mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-186342 [rd][debugger] Async Stack Traces as a frontend action
GitOrigin-RevId: 4d62f3552baf3dfa7645708b6d1c5833761c3272
This commit is contained in:
committed by
intellij-monorepo-bot
parent
287c4ec997
commit
a9ba23fd11
+6
@@ -2,6 +2,7 @@
|
||||
package com.intellij.java.debugger.impl.backend
|
||||
|
||||
import com.intellij.debugger.actions.ThreadDumpAction
|
||||
import com.intellij.debugger.engine.AsyncStacksUtils
|
||||
import com.intellij.debugger.engine.JavaDebugProcess
|
||||
import com.intellij.debugger.engine.executeOnDMT
|
||||
import com.intellij.execution.filters.ExceptionFilters
|
||||
@@ -52,6 +53,11 @@ internal class BackendJavaDebuggerSessionApi : JavaDebuggerSessionApi {
|
||||
}
|
||||
return JavaThreadDumpResponseDto(channelDeferred.await(), ExceptionFilters.getFilters(session.searchScope))
|
||||
}
|
||||
|
||||
override suspend fun setAsyncStacksEnabled(sessionId: XDebugSessionId, state: Boolean) {
|
||||
val session = sessionId.findValue() ?: return
|
||||
AsyncStacksUtils.setAsyncStacksEnabled(session, state)
|
||||
}
|
||||
}
|
||||
|
||||
private fun truncateIfNeeded(allDumpItems: List<DumpItem>, maxItems: Int): Pair<List<DumpItem>, Int> {
|
||||
|
||||
@@ -290,10 +290,6 @@
|
||||
<add-to-group group-id="XDebugger.ValueGroup" anchor="last"/>
|
||||
</action>
|
||||
|
||||
<action id="Debugger.AsyncStacks" class="com.intellij.debugger.actions.AsyncStacksToggleAction">
|
||||
<add-to-group group-id="XDebugger.Frames.Tree.Popup"/>
|
||||
<add-to-group group-id="XDebugger.Frames.Tree.Popup.Frontend"/>
|
||||
</action>
|
||||
<action id="Debugger.SwitchToTheNextContext" class="com.intellij.debugger.actions.SwitchToTheNextContextAction"/>
|
||||
<action id="Debugger.CallTracer" class="com.intellij.debugger.ui.breakpoints.CallTracer$CallTracerToggleAction"
|
||||
icon="AllIcons.Debugger.Db_set_breakpoint">
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
// 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.debugger.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.project.DumbAwareToggleAction
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil
|
||||
|
||||
class AsyncStacksToggleAction : DumbAwareToggleAction() {
|
||||
override fun isSelected(e: AnActionEvent): Boolean {
|
||||
return ASYNC_STACKS_ENABLED.get(DebuggerUIUtil.getSessionData(e), true)
|
||||
}
|
||||
|
||||
override fun setSelected(e: AnActionEvent, state: Boolean) {
|
||||
ASYNC_STACKS_ENABLED.set(DebuggerUIUtil.getSessionData(e), state)
|
||||
DebuggerUIUtil.getSessionProxy(e)?.apply {
|
||||
if (isSuspended) {
|
||||
rebuildViews()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
super.update(e)
|
||||
e.presentation.isEnabledAndVisible = DebuggerAction.isInJavaSession(e)
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
return ActionUpdateThread.BGT
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val ASYNC_STACKS_ENABLED = Key.create<Boolean>("ASYNC_STACKS_ENABLED")
|
||||
|
||||
@JvmStatic
|
||||
fun isAsyncStacksEnabled(session: XDebugSessionImpl): Boolean {
|
||||
return ASYNC_STACKS_ENABLED.get(session.sessionData, true)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setAsyncStacksEnabled(session: XDebugSessionImpl, state: Boolean) {
|
||||
ASYNC_STACKS_ENABLED.set(session.sessionData, state)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,9 @@ import com.intellij.platform.eel.provider.utils.EelPathUtils;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.SlowOperations;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.sun.jdi.*;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.intellij.build.BuildDependenciesJps;
|
||||
@@ -56,6 +58,17 @@ public final class AsyncStacksUtils {
|
||||
public static final String CAPTURE_STORAGE_CLASS_NAME = "com.intellij.rt.debugger.agent.CaptureStorage";
|
||||
public static final String CAPTURE_AGENT_CLASS_NAME = "com.intellij.rt.debugger.agent.CaptureAgent";
|
||||
private static final String AGENT_JAR_NAME = "debugger-agent.jar";
|
||||
private static final Key<Boolean> ASYNC_STACKS_ENABLED = Key.create("ASYNC_STACKS_ENABLED");
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static Boolean isAsyncStacksEnabled(XDebugSessionImpl session) {
|
||||
return ASYNC_STACKS_ENABLED.get(session.getSessionData(), true);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void setAsyncStacksEnabled(XDebugSessionImpl session, Boolean state) {
|
||||
ASYNC_STACKS_ENABLED.set(session.getSessionData(), state);
|
||||
}
|
||||
|
||||
public static boolean isAgentEnabled() {
|
||||
return DebuggerSettings.getInstance().INSTRUMENTING_AGENT;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.intellij.debugger.engine;
|
||||
|
||||
import com.intellij.debugger.JavaDebuggerBundle;
|
||||
import com.intellij.debugger.actions.AsyncStacksToggleAction;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
|
||||
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
|
||||
@@ -356,8 +355,9 @@ public class JavaExecutionStack extends XExecutionStack {
|
||||
List<StackFrameItem> relatedStack = null;
|
||||
var creationStack = myCreationStack;
|
||||
XStackFrame topFrame = ContainerUtil.getFirstItem(frames);
|
||||
if (AsyncStacksToggleAction.isAsyncStacksEnabled(
|
||||
(XDebugSessionImpl)suspendContext.getDebugProcess().getXdebugProcess().getSession()) &&
|
||||
JavaDebugProcess xdebugProcess = suspendContext.getDebugProcess().getXdebugProcess();
|
||||
if (xdebugProcess != null &&
|
||||
AsyncStacksUtils.isAsyncStacksEnabled((XDebugSessionImpl)xdebugProcess.getSession()) &&
|
||||
topFrame instanceof JavaStackFrame frame) {
|
||||
if (creationStack == null) {
|
||||
creationStack = DebugUtilsKt.computeSafeIfAny(CreationStackTraceProvider.EP,
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
key="debugger.thread.dump.max.items.frontend"/>
|
||||
</extensions>
|
||||
<actions resource-bundle="messages.JavaDebuggerSharedBundle">
|
||||
<action id="Debugger.AsyncStacks" class="com.intellij.java.debugger.impl.shared.actions.AsyncStacksToggleAction">
|
||||
<add-to-group group-id="XDebugger.Frames.Tree.Popup"/>
|
||||
<add-to-group group-id="XDebugger.Frames.Tree.Popup.Frontend"/>
|
||||
</action>
|
||||
<action id="DumpThreads" class="com.intellij.java.debugger.impl.shared.actions.ThreadDumpAction" icon="AllIcons.Actions.Dump">
|
||||
<add-to-group group-id="DebuggingActionsGroup" anchor="last"/>
|
||||
<add-to-group group-id="XDebugger.ToolWindow.TopToolbar3.Extra"/>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
action.Debugger.AsyncStacks.text=Async Stack Traces
|
||||
action.DumpThreads.text=Get Thread Dump
|
||||
thread.dump.name=Dump {0}
|
||||
thread.dump=Thread Dump
|
||||
+1
@@ -15,6 +15,7 @@ class SharedJavaDebuggerSession(dto: JavaDebuggerSessionDto, private val cs: Cor
|
||||
|
||||
val isAttached: Boolean get() = isAttachedFlow.value
|
||||
|
||||
internal var isAsyncStacksEnabled: Boolean = true
|
||||
|
||||
fun close() {
|
||||
cs.cancel()
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.debugger.impl.shared.actions
|
||||
|
||||
import com.intellij.java.debugger.impl.shared.SharedJavaDebuggerManager
|
||||
import com.intellij.java.debugger.impl.shared.SharedJavaDebuggerSession
|
||||
import com.intellij.java.debugger.impl.shared.rpc.JavaDebuggerSessionApi
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.DumbAwareToggleAction
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.xdebugger.impl.frame.XDebugSessionProxy
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class AsyncStacksToggleAction : DumbAwareToggleAction(), ActionRemoteBehaviorSpecification.FrontendOtherwiseBackend {
|
||||
override fun isSelected(e: AnActionEvent): Boolean {
|
||||
return getJavaSession(e)?.isAsyncStacksEnabled ?: true
|
||||
}
|
||||
|
||||
override fun setSelected(e: AnActionEvent, state: Boolean) {
|
||||
getJavaSession(e)?.isAsyncStacksEnabled = state
|
||||
DebuggerUIUtil.getSessionProxy(e)?.apply {
|
||||
AsyncStackTraceActionCoroutineScope.getInstance(project).cs.launch {
|
||||
JavaDebuggerSessionApi.getInstance().setAsyncStacksEnabled(id, state)
|
||||
}
|
||||
if (isSuspended) {
|
||||
rebuildViews()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
super.update(e)
|
||||
e.presentation.isEnabledAndVisible = getJavaSession(e) != null
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
return ActionUpdateThread.BGT
|
||||
}
|
||||
}
|
||||
|
||||
private fun getJavaSession(e: AnActionEvent) = DebuggerUIUtil.getSessionProxy(e)?.let(::getJavaSession)
|
||||
|
||||
private fun getJavaSession(proxy: XDebugSessionProxy): SharedJavaDebuggerSession? = SharedJavaDebuggerManager.getInstance(proxy.project).getJavaSession(proxy.id)
|
||||
|
||||
@Suppress("OPT_IN_USAGE")
|
||||
@Service(Service.Level.PROJECT)
|
||||
internal class AsyncStackTraceActionCoroutineScope(val cs: CoroutineScope) {
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): AsyncStackTraceActionCoroutineScope = project.service()
|
||||
}
|
||||
}
|
||||
+2
@@ -22,6 +22,8 @@ interface JavaDebuggerSessionApi : RemoteApi<Unit> {
|
||||
|
||||
suspend fun dumpThreads(sessionId: XDebugSessionId, maxItems: Int = Int.MAX_VALUE, onlyPlatformThreads: Boolean): JavaThreadDumpResponseDto?
|
||||
|
||||
suspend fun setAsyncStacksEnabled(sessionId: XDebugSessionId, state: Boolean)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
suspend fun getInstance(): JavaDebuggerSessionApi {
|
||||
|
||||
@@ -319,7 +319,6 @@ action.Debugger.CreateRenderer.text=Create\u2026
|
||||
action.Debugger.CreateRenderer.XDebuggerTreePopup.text=Create Renderer
|
||||
action.Debugger.XDebuggerTextPopup.ShowAsObject.text=Show as Object
|
||||
action.Debugger.MuteRenderers.text=Mute Renderers
|
||||
action.Debugger.AsyncStacks.text=Async Stack Traces
|
||||
action.Debugger.SwitchToTheNextContext.text=Switch to the Next Stopped Breakpoint
|
||||
action.Debugger.CallTracer.text=Trace Calls
|
||||
action.Debugger.ReloadFile.text=Compile And Reload File
|
||||
|
||||
+3
-7
@@ -2,12 +2,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.debugger.coroutine
|
||||
|
||||
import com.intellij.debugger.actions.AsyncStacksToggleAction
|
||||
import com.intellij.debugger.engine.DebugProcessImpl
|
||||
import com.intellij.debugger.engine.DebuggerManagerThreadImpl
|
||||
import com.intellij.debugger.engine.MethodInvokeUtils
|
||||
import com.intellij.debugger.engine.SuspendContextImpl
|
||||
import com.intellij.debugger.engine.SuspendManagerUtil
|
||||
import com.intellij.debugger.engine.*
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx
|
||||
import com.intellij.debugger.impl.DebuggerUtilsImpl
|
||||
import com.intellij.debugger.impl.HelperClassNotAvailableException
|
||||
@@ -41,7 +36,8 @@ private class CoroutineStackFrameInterceptor : StackFrameInterceptor {
|
||||
DebuggerManagerThreadImpl.assertIsManagerThread()
|
||||
if (debugProcess.xdebugProcess?.session !is XDebugSessionImpl
|
||||
|| frame is SkipCoroutineStackFrameProxyImpl
|
||||
|| !AsyncStacksToggleAction.isAsyncStacksEnabled(debugProcess.xdebugProcess?.session as XDebugSessionImpl)) {
|
||||
|| !AsyncStacksUtils.isAsyncStacksEnabled(debugProcess.xdebugProcess?.session as XDebugSessionImpl)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
// skip -1 line in invokeSuspend and main
|
||||
|
||||
Reference in New Issue
Block a user