String (@NonNls String text) { StringBuilder builder = new StringBuilder(text.length()); text = text.replaceAll("(\\S[ \\t\\x0B\\f\\r]+)(at\\s+)", "$1\n$2"); text = text.replaceAll("(\\\\n|\\\\r|\\\\t)+(at\\s+)", "\n$2"); String[] lines = text.split("\n"); boolean first = true; boolean inAuxInfo = false; for (final String line : lines) { //noinspection HardCodedStringLiteral if (!inAuxInfo && (line.startsWith("JNI global references") || line.trim().equals("Heap"))) { builder.append("\n"); inAuxInfo = true; } if (inAuxInfo) { builder.append(trimSuffix(line)).append("\n"); continue; } if (line.startsWith("at breakpoint")) { // possible thread status mixed with "at ..." builder.append(" ").append(trimSuffix(line)); continue; } if (!first && (mustHaveNewLineBefore(line) || StringUtil.endsWith(builder, ")"))) { if (!StringUtil.endsWith(builder, "\n")) builder.append("\n"); if (line.startsWith("\"")) builder.append("\n"); // Additional line break for thread names } first = false; int i = builder.lastIndexOf("\n"); CharSequence lastLine = i == -1 ? builder : builder.subSequence(i + 1, builder.length()); if (!line.matches("\\s+.*") && lastLine.length() > 0) { if (lastLine.toString().matches("\\s*at") //separate 'at' from filename || ContainerUtil.or(IMPORTANT_THREAD_DUMP_WORDS, word -> line.startsWith(word))) { builder.append(" "); } } builder.append(trimSuffix(line)); } return builder.toString(); }