mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-13 15:52:01 +07:00
Extract threadDump parser to a separate module
GitOrigin-RevId: c9d9890c5bf10e57b0aa77bb8f5c9ca7451c723e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
20c62c2d7e
commit
e3d0d48018
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -789,6 +789,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/testFramework/ui/intellij.platform.testFramework.ui.iml" filepath="$PROJECT_DIR$/platform/testFramework/ui/intellij.platform.testFramework.ui.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/testRunner/intellij.platform.testRunner.iml" filepath="$PROJECT_DIR$/platform/testRunner/intellij.platform.testRunner.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/platform-tests/intellij.platform.tests.iml" filepath="$PROJECT_DIR$/platform/platform-tests/intellij.platform.tests.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/threadDumpParser/intellij.platform.threadDumpParser.iml" filepath="$PROJECT_DIR$/platform/threadDumpParser/intellij.platform.threadDumpParser.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/tips-of-the-day/intellij.platform.tips.iml" filepath="$PROJECT_DIR$/platform/tips-of-the-day/intellij.platform.tips.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/tracing-ide/intellij.platform.tracing.ide.iml" filepath="$PROJECT_DIR$/platform/tracing-ide/intellij.platform.tracing.ide.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/tracing/intellij.platform.tracing.rt.iml" filepath="$PROJECT_DIR$/platform/tracing/intellij.platform.tracing.rt.iml" />
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
<orderEntry type="library" name="kotlinx-serialization-core" level="project" />
|
||||
<orderEntry type="library" name="kotlinx-serialization-json" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util.coroutines" />
|
||||
<orderEntry type="module" module-name="intellij.platform.threadDumpParser" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.unscramble.ThreadDumpPanel;
|
||||
import com.intellij.unscramble.ThreadState;
|
||||
import com.intellij.threadDumpParser.ThreadState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -17,8 +17,8 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.unscramble.ThreadDumpParser;
|
||||
import com.intellij.unscramble.ThreadState;
|
||||
import com.intellij.threadDumpParser.ThreadDumpParser;
|
||||
import com.intellij.threadDumpParser.ThreadState;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.sun.jdi.*;
|
||||
|
||||
@@ -45,7 +45,7 @@ import com.intellij.ui.classFilter.ClassFilter;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.viewModel.extraction.ToolWindowContentExtractor;
|
||||
import com.intellij.unscramble.ThreadDumpPanel;
|
||||
import com.intellij.unscramble.ThreadState;
|
||||
import com.intellij.threadDumpParser.ThreadState;
|
||||
import com.intellij.util.DocumentUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.ThreeState;
|
||||
|
||||
@@ -15,7 +15,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.unscramble.ThreadState;
|
||||
import com.intellij.threadDumpParser.ThreadState;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.ui.MessageCategory;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.util.io.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util.jdom" />
|
||||
<orderEntry type="module" module-name="intellij.platform.threadDumpParser" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -36,8 +36,8 @@ import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.unscramble.AnalyzeStacktraceUtil;
|
||||
import com.intellij.unscramble.ThreadDumpConsoleFactory;
|
||||
import com.intellij.unscramble.ThreadDumpParser;
|
||||
import com.intellij.unscramble.ThreadState;
|
||||
import com.intellij.threadDumpParser.ThreadDumpParser;
|
||||
import com.intellij.threadDumpParser.ThreadState;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.TimeoutUtil;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.markdown.utils" />
|
||||
<orderEntry type="library" name="jetbrains.markdown" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.threadDumpParser" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.unscramble;
|
||||
import com.intellij.execution.ui.ConsoleView;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.threadDumpParser.ThreadState;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
@@ -26,6 +26,8 @@ import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.threadDumpParser.ThreadOperation;
|
||||
import com.intellij.threadDumpParser.ThreadState;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||
<orderEntry type="module" module-name="intellij.java.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.threadDumpParser" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -20,6 +20,8 @@ import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.configurable.VcsContentAnnotationConfigurable;
|
||||
import com.intellij.threadDumpParser.ThreadDumpParser;
|
||||
import com.intellij.threadDumpParser.ThreadState;
|
||||
import com.intellij.ui.GuiUtils;
|
||||
import com.intellij.ui.SimpleListCellRenderer;
|
||||
import com.intellij.ui.TextFieldWithHistory;
|
||||
@@ -45,7 +47,6 @@ public class UnscrambleDialog extends DialogWrapper {
|
||||
private static final @NonNls String PROPERTY_LOG_FILE_LAST_URL = "UNSCRAMBLE_LOG_FILE_LAST_URL";
|
||||
private static final @NonNls String PROPERTY_UNSCRAMBLER_NAME_USED = "UNSCRAMBLER_NAME_USED";
|
||||
private static final Condition<ThreadState> DEADLOCK_CONDITION = state -> state.isDeadlocked();
|
||||
private static final String[] IMPORTANT_THREAD_DUMP_WORDS = ContainerUtil.ar("tid", "nid", "wait", "parking", "prio", "os_prio", "java");
|
||||
|
||||
private final Project myProject;
|
||||
private JPanel myEditorPanel;
|
||||
@@ -279,77 +280,10 @@ public class UnscrambleDialog extends DialogWrapper {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e){
|
||||
String text = myStacktraceEditorPanel.getText();
|
||||
myStacktraceEditorPanel.setText(normalizeText(text));
|
||||
myStacktraceEditorPanel.setText(ThreadDumpParser.normalizeText(text));
|
||||
}
|
||||
}
|
||||
|
||||
public static String normalizeText(@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();
|
||||
}
|
||||
|
||||
private static String trimSuffix(final String line) {
|
||||
int len = line.length();
|
||||
|
||||
while ((0 < len) && (line.charAt(len-1) <= ' ')) {
|
||||
len--;
|
||||
}
|
||||
return (len < line.length()) ? line.substring(0, len) : line;
|
||||
}
|
||||
|
||||
private static boolean mustHaveNewLineBefore(String line) {
|
||||
final int nonWs = CharArrayUtil.shiftForward(line, 0, " \t");
|
||||
if (nonWs < line.length()) {
|
||||
line = line.substring(nonWs);
|
||||
}
|
||||
|
||||
if (line.startsWith("at")) return true; // Start of the new stack frame entry
|
||||
if (line.startsWith("Caused")) return true; // Caused by message
|
||||
if (line.startsWith("- locked")) return true; // "Locked a monitor" logging
|
||||
if (line.startsWith("- waiting")) return true; // "Waiting for monitor" logging
|
||||
if (line.startsWith("- parking to wait")) return true;
|
||||
if (line.startsWith("java.lang.Thread.State")) return true;
|
||||
if (line.startsWith("\"")) return true; // Start of the new thread (thread name)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
if (myConfigurable != null && myConfigurable.isModified()) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.threadDumpParser.ThreadDumpParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
@@ -35,7 +36,7 @@ class UnscrambleListener extends ClipboardAnalyzeListener {
|
||||
|
||||
@Override
|
||||
public boolean canHandle(@NotNull String value) {
|
||||
value = UnscrambleDialog.normalizeText(value);
|
||||
value = ThreadDumpParser.normalizeText(value);
|
||||
int linesCount = 0;
|
||||
for (String line : value.split("\n")) {
|
||||
line = line.trim();
|
||||
|
||||
0
platform/threadDumpParser/api-dump.txt
Normal file
0
platform/threadDumpParser/api-dump.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||
<orderEntry type="library" scope="TEST" name="JUnit3" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.tools.ide.metrics.benchmark" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,8 +1,11 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.unscramble;
|
||||
package com.intellij.threadDumpParser;
|
||||
|
||||
import com.intellij.diagnostic.EventCountDumper;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -14,7 +17,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
import static com.intellij.diagnostic.CoroutineDumperKt.isCoroutineDumpHeader;
|
||||
|
||||
|
||||
@ApiStatus.Internal
|
||||
public final class ThreadDumpParser {
|
||||
private static final Pattern ourThreadStartPattern = Pattern.compile("^\"(.+)\".+(prio=\\d+ (?:os_prio=[^\\s]+ )?.*tid=[^\\s]+ nid=[^\\s]+|[Ii][Dd]=\\d+) ([^\\[]+)");
|
||||
private static final Pattern ourForcedThreadStartPattern = Pattern.compile("^Thread (\\d+): \\(state = (.+)\\)");
|
||||
@@ -30,6 +33,8 @@ public final class ThreadDumpParser {
|
||||
private static final String AT_JAVA_LANG_OBJECT_WAIT = "at java.lang.Object.wait(";
|
||||
private static final Pattern ourLockedOwnableSynchronizersPattern = Pattern.compile("- <(0x[\\da-f]+)> \\(.*\\)");
|
||||
|
||||
private static final String[] IMPORTANT_THREAD_DUMP_WORDS = ContainerUtil.ar("tid", "nid", "wait", "parking", "prio", "os_prio", "java");
|
||||
|
||||
|
||||
private ThreadDumpParser() {
|
||||
}
|
||||
@@ -263,4 +268,72 @@ public final class ThreadDumpParser {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String normalizeText(@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();
|
||||
}
|
||||
|
||||
private static boolean mustHaveNewLineBefore(String line) {
|
||||
final int nonWs = CharArrayUtil.shiftForward(line, 0, " \t");
|
||||
if (nonWs < line.length()) {
|
||||
line = line.substring(nonWs);
|
||||
}
|
||||
|
||||
if (line.startsWith("at")) return true; // Start of the new stack frame entry
|
||||
if (line.startsWith("Caused")) return true; // Caused by message
|
||||
if (line.startsWith("- locked")) return true; // "Locked a monitor" logging
|
||||
if (line.startsWith("- waiting")) return true; // "Waiting for monitor" logging
|
||||
if (line.startsWith("- parking to wait")) return true;
|
||||
if (line.startsWith("java.lang.Thread.State")) return true;
|
||||
if (line.startsWith("\"")) return true; // Start of the new thread (thread name)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String trimSuffix(final String line) {
|
||||
int len = line.length();
|
||||
|
||||
while ((0 < len) && (line.charAt(len - 1) <= ' ')) {
|
||||
len--;
|
||||
}
|
||||
return (len < line.length()) ? line.substring(0, len) : line;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.unscramble;
|
||||
package com.intellij.threadDumpParser;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public enum ThreadOperation {
|
||||
Socket("socket operation"), IO("I/O");
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.unscramble;
|
||||
package com.intellij.threadDumpParser;
|
||||
|
||||
import com.intellij.diagnostic.ThreadDumper;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class ThreadState {
|
||||
private final String myName;
|
||||
private final String myState;
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.unscramble;
|
||||
package com.intellij.threadDumpParser;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -165,7 +165,7 @@ public class NormalizeTextTest extends TestCase {
|
||||
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
|
||||
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
|
||||
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)""");
|
||||
assertEquals(2, ThreadDumpParser.parse(UnscrambleDialog.normalizeText(text)).size());
|
||||
assertEquals(2, ThreadDumpParser.parse(ThreadDumpParser.normalizeText(text)).size());
|
||||
}
|
||||
|
||||
public void testJsonEscapes() {
|
||||
@@ -182,6 +182,6 @@ public class NormalizeTextTest extends TestCase {
|
||||
}
|
||||
|
||||
private static void doTest(@NonNls String stackTrace, @NonNls String expected) {
|
||||
assertEquals(expected, UnscrambleDialog.normalizeText(stackTrace));
|
||||
assertEquals(expected, ThreadDumpParser.normalizeText(stackTrace));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.unscramble;
|
||||
package com.intellij.threadDumpParser;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.tools.ide.metrics.benchmark.Benchmark;
|
||||
Reference in New Issue
Block a user