[debugger] Support Customize representation in XThreadsView

IJPL-203827

GitOrigin-RevId: fe7389f780b798c0faa69295c45609ca4e1d2f14
This commit is contained in:
Maria Sokolova
2026-02-03 13:42:25 +00:00
committed by intellij-monorepo-bot
parent 2e35cd934b
commit 5886fc1dfc
2 changed files with 34 additions and 25 deletions
@@ -388,6 +388,7 @@
<action id="Debugger.CustomizeThreadsView" class="com.intellij.debugger.actions.CustomizeThreadsViewAction">
<add-to-group group-id="XDebugger.Frames.Tree.Popup" anchor="last"/>
<add-to-group group-id="XDebugger.Threads.View.Popup" anchor="last"/>
</action>
<action id="Debugger.EditFrameSource" class="com.intellij.debugger.actions.EditFrameSourceAction" use-shortcut-of="EditSource"/>
<action id="Debugger.FilterArray" class="com.intellij.debugger.actions.ArrayAction$FilterArrayAction">
@@ -8,7 +8,6 @@ import com.intellij.platform.debugger.impl.rpc.XDebugSessionApi
import com.intellij.platform.debugger.impl.shared.proxy.XDebugSessionProxy
import com.intellij.platform.debugger.impl.ui.DebuggerUIUtilShared
import com.intellij.ui.AutoScrollToSourceHandler
import com.intellij.ui.SimpleColoredComponent
import com.intellij.ui.SimpleTextAttributes
import com.intellij.util.concurrency.annotations.RequiresEdt
import com.intellij.xdebugger.XDebugSession
@@ -35,6 +34,7 @@ import kotlinx.coroutines.withContext
import org.jetbrains.annotations.ApiStatus
import java.awt.Component
import java.awt.event.HierarchyEvent
import javax.swing.Icon
import javax.swing.JPanel
@OptIn(FlowPreview::class)
@@ -145,6 +145,7 @@ class XThreadsView(project: Project, session: XDebugSessionProxy) : XDebugView()
override fun computeChildren(node: XCompositeNode) {
val container = object : XSuspendContext.XExecutionStackGroupContainer {
override fun errorOccurred(errorMessage: String) {
node.setMessage(errorMessage)
}
override fun addExecutionStack(executionStacks: List<XExecutionStack>, last: Boolean) {
@@ -190,45 +191,52 @@ class XThreadsView(project: Project, session: XDebugSessionProxy) : XDebugView()
override fun addStackFrames(stackFrames: List<XStackFrame>, last: Boolean) {
val children = XValueChildrenList()
stackFrames.forEach { children.add("", FrameValue(executionStack,it)) }
stackFrames.forEach { children.add("", FrameValue(executionStack,it, session)) }
node.addChildren(children, last)
}
})
}
override fun computePresentation(node: XValueNode, place: XValuePlace) {
node.setPresentation(executionStack.icon, XRegularValuePresentation(executionStack.displayName, null, ""), true)
}
private fun XCompositeNode.setMessage(text: String) {
// remove temporary loading message nodes
addChildren(XValueChildrenList.EMPTY, true)
setMessage(text, null, SimpleTextAttributes.GRAYED_ATTRIBUTES, null)
node.setEmptyValuePresentation(executionStack.icon)
}
}
class FrameValue(val executionStack: XExecutionStack, val frame : XStackFrame) : XValue() {
class FrameValue(val executionStack: XExecutionStack, val frame : XStackFrame, private val session: XDebugSessionProxy) : XValue() {
override fun computePresentation(node: XValueNode, place: XValuePlace) {
val component = SimpleColoredComponent()
frame.customizeTextPresentation(component)
node.setPresentation(component.icon, object : XValuePresentation() {
override fun getSeparator(): @NlsSafe String = ""
override fun renderValue(renderer: XValueTextRenderer) {
val i = component.iterator()
while (i.hasNext()) {
i.next()
val text = i.fragment
when (i.textAttributes) {
SimpleTextAttributes.GRAYED_ATTRIBUTES -> renderer.renderComment(text)
SimpleTextAttributes.ERROR_ATTRIBUTES -> renderer.renderError(text)
SimpleTextAttributes.REGULAR_ATTRIBUTES -> renderer.renderValue(text)
session.coroutineScope.launch {
frame.customizePresentation().collectLatest { presentation ->
node.setPresentation(presentation.icon, object : XValuePresentation() {
override fun getSeparator(): @NlsSafe String = ""
override fun renderValue(renderer: XValueTextRenderer) {
val fragments = presentation.fragments
fragments.forEach { (text, attr) ->
when(attr) {
SimpleTextAttributes.GRAYED_ATTRIBUTES,
SimpleTextAttributes.GRAY_ATTRIBUTES,
SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES,
-> renderer.renderComment(text)
SimpleTextAttributes.ERROR_ATTRIBUTES -> renderer.renderError(text)
else -> renderer.renderValue(text)
}
}
}
}
}, false)
}
}, false)
}
}
}
class XThreadsRootNode(tree: XDebuggerTree, session: XDebugSessionProxy) :
XValueContainerNode<ThreadsContainer>(tree, null, false, ThreadsContainer(session))
}
private fun XCompositeNode.setMessage(text: String) {
// remove temporary loading message nodes
addChildren(XValueChildrenList.EMPTY, true)
setMessage(text, null, SimpleTextAttributes.GRAYED_ATTRIBUTES, null)
}
private fun XValueNode.setEmptyValuePresentation(icon: Icon?) {
setPresentation(icon, XRegularValuePresentation("", null, ""), true)
}