[debugger] IDEA-349254 Fixes

- handle suspend thread policy correctly
- close all popups when the process is terminated

GitOrigin-RevId: f2de849da195effa418f78d55f56301b1e31c15b
This commit is contained in:
Alexander Kuznetsov
2024-10-14 17:27:11 +00:00
committed by intellij-monorepo-bot
parent 1051ef13e9
commit f386cee9cc
@@ -2,6 +2,7 @@
package com.intellij.debugger.collections.visualizer
import com.intellij.debugger.JavaDebuggerBundle
import com.intellij.debugger.engine.DebugProcess
import com.intellij.debugger.engine.DebugProcessListener
import com.intellij.debugger.engine.FullValueEvaluatorProvider
import com.intellij.debugger.engine.SuspendContext
@@ -13,6 +14,7 @@ import com.intellij.openapi.ui.FrameWrapper
import com.intellij.platform.util.coroutines.childScope
import com.intellij.xdebugger.frame.XFullValueEvaluator
import com.intellij.xdebugger.impl.ui.CustomComponentEvaluator
import com.sun.jdi.request.EventRequest
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import java.awt.event.MouseEvent
@@ -20,8 +22,11 @@ import javax.swing.JComponent
class CollectionVisualizerEvaluator(private val visualizer: CollectionVisualizer) : FullValueEvaluatorProvider {
override fun getFullValueEvaluator(evaluationContext: EvaluationContextImpl, valueDescriptor: ValueDescriptorImpl): XFullValueEvaluator? {
val thread = evaluationContext.suspendContext.thread
val threadName = thread?.name() ?: "<unknown thread>"
val presenterName = valueDescriptor.type?.name() ?: "<unknown name>"
val scope = evaluationContext.managerThread.coroutineScope.childScope("Collection presentation for $presenterName")
val mainScopeName = "Collection presentation for $presenterName (thread $threadName)"
val scope = evaluationContext.managerThread.coroutineScope.childScope(mainScopeName)
return object : CustomComponentEvaluator("CoVi") {
override fun startEvaluation(callback: XFullValueEvaluationCallback) {
@@ -40,7 +45,7 @@ class CollectionVisualizerEvaluator(private val visualizer: CollectionVisualizer
title = JavaDebuggerBundle.message("debugger.collection.visualizer.title"),
component,
// don't cancel the whole scope when the window is closed -- otherwise it wouldn't be possible to reopen
scope.childScope("Collection presentation for $presenterName (limited to a window)"),
scope.childScope("$mainScopeName (limited to a window)"),
)
frame.apply {
disposeOnResume(evaluationContext, scope)
@@ -57,9 +62,27 @@ class CollectionVisualizerEvaluator(private val visualizer: CollectionVisualizer
) {
evaluationContext.debugProcess.addDebugProcessListener(object : DebugProcessListener {
override fun resumed(suspendContext: SuspendContext?) {
if (affectedByResume(suspendContext)) {
close()
scope.cancel()
}
}
override fun processDetached(process: DebugProcess, closedByUser: Boolean) {
close()
scope.cancel()
}
// maximum conservatism -- better close more popups than make them leak
private fun affectedByResume(suspendContext: SuspendContext?): Boolean {
if (suspendContext == null) return true
if (evaluationContext.suspendContext.suspendPolicy == EventRequest.SUSPEND_ALL) {
return true
}
val visualizerRelatedThread = evaluationContext.suspendContext.thread ?: return true
val resumeOnThread = suspendContext.thread ?: return true
return visualizerRelatedThread === resumeOnThread
}
})
}