IJPL-164393 Add freeze analyzer to "Analyze Stacktrace or Thread Dump" action

GitOrigin-RevId: e9f9d6527b1768b87f59b19e03df5456aadcf81e
This commit is contained in:
Maxim.Kolmakov
2024-10-18 08:07:38 +00:00
committed by intellij-monorepo-bot
parent 6e6b1ff11e
commit 5fa64dce4b
7 changed files with 79 additions and 17 deletions
@@ -810,6 +810,10 @@ f:com.intellij.task.impl.ProjectTaskManagerImpl
- a:getRequestedTasks(java.lang.Class):java.util.List
f:com.intellij.testIntegration.TestFinderHelper
- *s:navigateToTestImmediately(com.intellij.psi.PsiElement):Z
f:com.intellij.unscramble.AnalyzeStacktraceUtil
- *sf:EP_CONTENT_PROVIDER:com.intellij.openapi.extensions.ProjectExtensionPointName
*:com.intellij.unscramble.StacktraceTabContentProvider
- a:createRunTabDescriptor(com.intellij.openapi.project.Project,java.lang.String):com.intellij.execution.ui.RunContentDescriptor
*f:com.intellij.util.gist.GistAstMarker
- <init>(com.intellij.openapi.fileTypes.FileType,java.lang.String,kotlin.jvm.functions.Function1):V
- f:accepts(com.intellij.openapi.project.Project,com.intellij.openapi.vfs.VirtualFile):Z
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.concurrency.ThreadingAssertions;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,6 +37,9 @@ import static com.intellij.openapi.application.ex.ClipboardUtil.getTextInClipboa
public final class AnalyzeStacktraceUtil {
public static final ProjectExtensionPointName<Filter> EP_NAME = new ProjectExtensionPointName<>("com.intellij.analyzeStacktraceFilter");
@ApiStatus.Experimental
public static final ProjectExtensionPointName<StacktraceTabContentProvider> EP_CONTENT_PROVIDER =
new ProjectExtensionPointName<>("com.intellij.analyzeStacktraceRunContentProvider");
private AnalyzeStacktraceUtil() {
}
@@ -51,7 +55,10 @@ public final class AnalyzeStacktraceUtil {
JComponent createConsoleComponent(ConsoleView consoleView, DefaultActionGroup toolbarActions);
}
public static void addConsole(Project project, @Nullable ConsoleFactory consoleFactory, final @NlsContexts.TabTitle String tabTitle, String text) {
public static void addConsole(Project project,
@Nullable ConsoleFactory consoleFactory,
final @NlsContexts.TabTitle String tabTitle,
String text) {
addConsole(project, consoleFactory, tabTitle, text, null);
}
@@ -87,7 +94,14 @@ public final class AnalyzeStacktraceUtil {
if (withExecutor) {
final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
RunContentManager.getInstance(project).showRunContent(executor, descriptor);
RunContentManager runContentManager = RunContentManager.getInstance(project);
runContentManager.showRunContent(executor, descriptor);
for (@NotNull StacktraceTabContentProvider stacktraceRunContentProvider : EP_CONTENT_PROVIDER.getExtensions(project)) {
RunContentDescriptor contentDescriptor = stacktraceRunContentProvider.createRunTabDescriptor(project, text);
if (contentDescriptor == null) continue;
runContentManager.showRunContent(executor, contentDescriptor);
}
}
consoleView.allowHeavyFilters();
if (consoleFactory == null) {
@@ -108,7 +122,8 @@ public final class AnalyzeStacktraceUtil {
MyConsolePanel(ExecutionConsole consoleView, ActionGroup toolbarActions) {
super(new BorderLayout());
JPanel toolbarPanel = new JPanel(new BorderLayout());
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.ANALYZE_STACKTRACE_PANEL_TOOLBAR, toolbarActions, false);
ActionToolbar toolbar =
ActionManager.getInstance().createActionToolbar(ActionPlaces.ANALYZE_STACKTRACE_PANEL_TOOLBAR, toolbarActions, false);
toolbar.setTargetComponent(consoleView.getComponent());
toolbarPanel.add(toolbar.getComponent());
add(toolbarPanel, BorderLayout.WEST);
@@ -0,0 +1,12 @@
// 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;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
@ApiStatus.Experimental
public interface StacktraceTabContentProvider {
@Nullable RunContentDescriptor createRunTabDescriptor(Project project, String text);
}
@@ -605,6 +605,8 @@
</extensionPoint>
<extensionPoint name="analyzeStacktraceFilter" interface="com.intellij.execution.filters.Filter" area="IDEA_PROJECT" dynamic="true"/>
<extensionPoint name="analyzeStacktraceRunContentProvider" interface="com.intellij.unscramble.StacktraceTabContentProvider"
area="IDEA_PROJECT" dynamic="true"/>
<extensionPoint name="stacktrace.fold" beanClass="com.intellij.execution.console.CustomizableConsoleFoldingBean" dynamic="true"/>
<extensionPoint name="stacktrace.fold.line.modifier" interface="com.intellij.execution.console.ConsoleLineModifier" dynamic="true"/>
@@ -8,5 +8,7 @@
<extensions defaultExtensionNs="com.intellij">
<fileEditorProvider id="java-stacktrace-editor"
implementation="org.jetbrains.idea.devkit.stacktrace.editor.StackTraceEditorProvider"/>
<analyzeStacktraceRunContentProvider id="freeze-run-content"
implementation="org.jetbrains.idea.devkit.stacktrace.FreezeTabContentProvider"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,39 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.devkit.stacktrace
import com.intellij.execution.ui.RunContentDescriptor
import com.intellij.openapi.application.EDT
import com.intellij.openapi.project.Project
import com.intellij.platform.diagnostic.freezeAnalyzer.FreezeAnalyzer
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
import com.intellij.platform.ide.progress.withBackgroundProgress
import com.intellij.unscramble.StacktraceTabContentProvider
import com.intellij.unscramble.AnalyzeStacktraceUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jetbrains.idea.devkit.DevKitIcons
object FreezeDescriptor {
suspend fun getFreezeRunDescriptor(text: String, project: Project): RunContentDescriptor? = withContext(Dispatchers.Default) {
withBackgroundProgress(project, DevKitStackTraceBundle.message("progress.title.freeze.analysis")) {
FreezeAnalyzer.analyzeFreeze(text)?.let { result ->
withContext(Dispatchers.EDT) {
AnalyzeStacktraceUtil.addConsole(
project, null,
DevKitStackTraceBundle.message("tab.title.freeze.analyzer"),
"${result.message}\n${result.additionalMessage ?: ""}\n======= Stack Trace: ========= \n${result.threads.joinToString { it -> it.stackTrace }}",
DevKitIcons.Freeze, false
)
}
}
}
}
}
class FreezeTabContentProvider : StacktraceTabContentProvider {
override fun createRunTabDescriptor(project: Project, text: String): RunContentDescriptor? {
return runWithModalProgressBlocking(project, DevKitStackTraceBundle.message("progress.title.freeze.analysis")) {
FreezeDescriptor.getFreezeRunDescriptor(text, project)
}
}
}
@@ -14,14 +14,12 @@ import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.UserDataHolderBase
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.wm.ToolWindow
import com.intellij.platform.diagnostic.freezeAnalyzer.FreezeAnalyzer
import com.intellij.platform.ide.progress.withBackgroundProgress
import com.intellij.threadDumpParser.ThreadDumpParser.parse
import com.intellij.ui.content.Content
import com.intellij.ui.content.ContentFactory.getInstance
import com.intellij.ui.content.ContentManager
import com.intellij.ui.content.TabbedPaneContentUI
import com.intellij.unscramble.AnalyzeStacktraceUtil
import com.intellij.unscramble.UnscrambleUtils.addConsole
import com.intellij.util.concurrency.annotations.RequiresEdt
import kotlinx.coroutines.*
@@ -30,8 +28,8 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.debounce
import org.jetbrains.idea.devkit.DevKitIcons
import org.jetbrains.idea.devkit.stacktrace.DevKitStackTraceBundle
import org.jetbrains.idea.devkit.stacktrace.FreezeDescriptor
import org.jetbrains.idea.devkit.stacktrace.util.StackTracePluginScope
import java.awt.BorderLayout
import java.beans.PropertyChangeListener
@@ -120,17 +118,7 @@ class StackTraceFileEditor(private val project: Project, private val file: Virtu
}
private suspend fun addFreezeAnalysisContent(contentManager: ContentManager) {
withContext(Dispatchers.Default) {
withBackgroundProgress(project, DevKitStackTraceBundle.message("progress.title.freeze.analysis")) {
FreezeAnalyzer.analyzeFreeze(document.text)
}
}?.let { result ->
val freezeDescriptor = AnalyzeStacktraceUtil.addConsole(
project, null,
DevKitStackTraceBundle.message("tab.title.freeze.analyzer"),
"${result.message}\n${result.additionalMessage ?: ""}\n======= Stack Trace: ========= \n${result.threads.joinToString { it -> it.stackTrace }}",
DevKitIcons.Freeze, false
)
FreezeDescriptor.getFreezeRunDescriptor(document.text, project)?.let { freezeDescriptor ->
contentManager.addContent(createNewContent(freezeDescriptor).apply {
executionId = freezeDescriptor.executionId
component = freezeDescriptor.component