diff --git a/java/debugger/backend/BUILD.bazel b/java/debugger/backend/BUILD.bazel
index 01ccfb495e84..59100486a84c 100644
--- a/java/debugger/backend/BUILD.bazel
+++ b/java/debugger/backend/BUILD.bazel
@@ -33,6 +33,8 @@ jvm_library(
"//java/execution/openapi:java-execution",
"//platform/xdebugger-impl/shared",
"//platform/xdebugger-impl/rpc",
+ "//platform/projectModel-api:projectModel",
+ "//platform/util/jdom",
],
runtime_deps = [":backend_resources"]
)
diff --git a/java/debugger/backend/intellij.java.debugger.impl.backend.iml b/java/debugger/backend/intellij.java.debugger.impl.backend.iml
index 39b4d597c380..bcd169a6251e 100644
--- a/java/debugger/backend/intellij.java.debugger.impl.backend.iml
+++ b/java/debugger/backend/intellij.java.debugger.impl.backend.iml
@@ -53,5 +53,7 @@
+
+
\ No newline at end of file
diff --git a/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerManagerApi.kt b/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerManagerApi.kt
index 8fa171b9f438..3435a9ee9aaf 100644
--- a/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerManagerApi.kt
+++ b/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerManagerApi.kt
@@ -1,6 +1,7 @@
// 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.backend
+import com.intellij.debugger.actions.MuteRendererUtils
import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.JavaDebugProcess
import com.intellij.debugger.impl.DebuggerSession
@@ -21,9 +22,12 @@ internal class BackendJavaDebuggerManagerApi : JavaDebuggerManagerApi {
val javaProcess = debuggerSession.process
val sessionStateFlow = debuggerSession.sessionStateFlow
+ val renderersFlow = MuteRendererUtils.getOrCreateFlow(xSession.sessionData)
return JavaDebuggerSessionDto(
initialState = getJavaSessionState(debuggerSession, javaProcess),
stateFlow = sessionStateFlow.map { getJavaSessionState(debuggerSession, javaProcess) }.toRpc(),
+ areRenderersMutedInitial = renderersFlow.value,
+ areRenderersMutedFlow = renderersFlow.toRpc(),
)
}
}
diff --git a/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerSessionApi.kt b/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerSessionApi.kt
index 09ddd55fd7f5..69258cedc075 100644
--- a/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerSessionApi.kt
+++ b/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerSessionApi.kt
@@ -3,6 +3,7 @@ package com.intellij.java.debugger.impl.backend
import com.intellij.debugger.actions.*
import com.intellij.debugger.engine.*
+import com.intellij.debugger.settings.NodeRendererSettings
import com.intellij.execution.filters.ExceptionFilters
import com.intellij.ide.ui.icons.rpcId
import com.intellij.java.debugger.impl.shared.engine.NodeRendererId
@@ -87,6 +88,13 @@ internal class BackendJavaDebuggerSessionApi : JavaDebuggerSessionApi {
}
}
+ override suspend fun muteRenderers(sessionId: XDebugSessionId, state: Boolean) {
+ val xSession = sessionId.findValue() ?: return
+ val renderersFlow = MuteRendererUtils.getFlow(xSession.sessionData)
+ renderersFlow.value = state
+ NodeRendererSettings.getInstance().fireRenderersChanged()
+ }
+
override suspend fun resumeThread(executionStackId: XExecutionStackId) {
invokeThreadCommand(executionStackId, ThreadCommand.RESUME)
}
diff --git a/java/debugger/impl/resources/META-INF/java-debugger.xml b/java/debugger/impl/resources/META-INF/java-debugger.xml
index ce9944f5bf74..a071d1e4e620 100644
--- a/java/debugger/impl/resources/META-INF/java-debugger.xml
+++ b/java/debugger/impl/resources/META-INF/java-debugger.xml
@@ -294,8 +294,9 @@
-
+
+
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ForceOnDemandRenderersAction.kt b/java/debugger/impl/src/com/intellij/debugger/actions/ForceOnDemandRenderersAction.kt
deleted file mode 100644
index 7f17f07d208e..000000000000
--- a/java/debugger/impl/src/com/intellij/debugger/actions/ForceOnDemandRenderersAction.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2000-2020 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.debugger.actions
-
-import com.intellij.debugger.settings.NodeRendererSettings
-import com.intellij.openapi.actionSystem.ActionUpdateThread
-import com.intellij.openapi.actionSystem.AnActionEvent
-import com.intellij.openapi.actionSystem.ToggleAction
-import com.intellij.openapi.project.DumbAware
-import com.intellij.openapi.util.Key
-import com.intellij.xdebugger.impl.XDebugSessionImpl
-import com.intellij.xdebugger.impl.ui.DebuggerUIUtil
-
-class ForceOnDemandRenderersAction : ToggleAction(), DumbAware {
-
- override fun isSelected(e: AnActionEvent): Boolean {
- return RENDERERS_ONDEMAND_FORCED.get(DebuggerUIUtil.getSessionData(e), false)
- }
-
- override fun setSelected(e: AnActionEvent, state: Boolean) {
- RENDERERS_ONDEMAND_FORCED.set(DebuggerUIUtil.getSessionData(e), state)
- NodeRendererSettings.getInstance().fireRenderersChanged()
- }
-
- 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 RENDERERS_ONDEMAND_FORCED = Key.create("RENDERERS_ONDEMAND_FORCED")
-
- @JvmStatic
- fun isForcedOnDemand(session: XDebugSessionImpl): Boolean {
- return RENDERERS_ONDEMAND_FORCED.get(session.sessionData, false)
- }
- }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/MuteRendererUtils.kt b/java/debugger/impl/src/com/intellij/debugger/actions/MuteRendererUtils.kt
new file mode 100644
index 000000000000..b0c82ed2c320
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/MuteRendererUtils.kt
@@ -0,0 +1,26 @@
+// 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.debugger.actions
+
+import com.intellij.openapi.util.Key
+import com.intellij.openapi.util.getOrCreateUserData
+import com.intellij.xdebugger.impl.ui.XDebugSessionData
+import kotlinx.coroutines.flow.MutableStateFlow
+import org.jetbrains.annotations.ApiStatus
+
+@ApiStatus.Internal
+object MuteRendererUtils {
+ private val MUTE_RENDERERS_FLOW = Key.create>("MUTE_RENDERERS_FLOW")
+
+ fun getOrCreateFlow(sessionData: XDebugSessionData): MutableStateFlow {
+ return sessionData.getOrCreateUserData(MUTE_RENDERERS_FLOW) { MutableStateFlow(false) }
+ }
+
+ fun getFlow(sessionData: XDebugSessionData): MutableStateFlow {
+ return sessionData.getUserData(MUTE_RENDERERS_FLOW)!!
+ }
+
+ @JvmStatic
+ fun isMuted(sessionData: XDebugSessionData): Boolean {
+ return sessionData.getUserData(MUTE_RENDERERS_FLOW)?.value ?: false
+ }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.java
index 9dafbb1fe97e..bf5762d5b3e8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.java
@@ -1,7 +1,7 @@
// 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.debugger.ui.tree.render;
-import com.intellij.debugger.actions.ForceOnDemandRenderersAction;
+import com.intellij.debugger.actions.MuteRendererUtils;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.FullValueEvaluatorProvider;
import com.intellij.debugger.engine.JavaDebugProcess;
@@ -102,6 +102,6 @@ public interface OnDemandRenderer extends FullValueEvaluatorProvider {
static boolean isOnDemandForced(DebugProcessImpl debugProcess) {
JavaDebugProcess process = debugProcess.getXdebugProcess();
- return process != null && ForceOnDemandRenderersAction.isForcedOnDemand((XDebugSessionImpl)process.getSession());
+ return process != null && MuteRendererUtils.isMuted(((XDebugSessionImpl)process.getSession()).getSessionData());
}
}
diff --git a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/SharedJavaDebuggerSession.kt b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/SharedJavaDebuggerSession.kt
index 2b90f38a3220..898a063c4564 100644
--- a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/SharedJavaDebuggerSession.kt
+++ b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/SharedJavaDebuggerSession.kt
@@ -2,6 +2,8 @@
package com.intellij.java.debugger.impl.shared
import com.intellij.java.debugger.impl.shared.rpc.JavaDebuggerSessionDto
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.xdebugger.impl.ui.DebuggerUIUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.SharingStarted
@@ -12,13 +14,24 @@ import org.jetbrains.annotations.ApiStatus
class SharedJavaDebuggerSession(dto: JavaDebuggerSessionDto, private val cs: CoroutineScope) {
private val stateFlow = dto.stateFlow.toFlow()
.stateIn(cs, SharingStarted.Eagerly, dto.initialState)
+ private val areRenderersMutedFlow = dto.areRenderersMutedFlow.toFlow()
+ .stateIn(cs, SharingStarted.Eagerly, dto.areRenderersMutedInitial)
val isAttached: Boolean get() = stateFlow.value.isAttached
val isEvaluationPossible: Boolean get() = stateFlow.value.isEvaluationPossible
+ val areRenderersMuted: Boolean get() = areRenderersMutedFlow.value
internal var isAsyncStacksEnabled: Boolean = true
fun close() {
cs.cancel()
}
+
+ companion object {
+ fun findSession(e: AnActionEvent): SharedJavaDebuggerSession? {
+ val project = e.project ?: return null
+ val sessionProxy = DebuggerUIUtil.getSessionProxy(e) ?: return null
+ return SharedJavaDebuggerManager.getInstance(project).getJavaSession(sessionProxy.id)
+ }
+ }
}
diff --git a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/actions/MuteRenderersAction.kt b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/actions/MuteRenderersAction.kt
new file mode 100644
index 000000000000..59837aa5e5ab
--- /dev/null
+++ b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/actions/MuteRenderersAction.kt
@@ -0,0 +1,38 @@
+// 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.SharedJavaDebuggerSession
+import com.intellij.java.debugger.impl.shared.SharedJavaDebuggerSession.Companion
+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.ToggleAction
+import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification
+import com.intellij.openapi.project.DumbAware
+import com.intellij.xdebugger.impl.ui.DebuggerUIUtil
+import kotlinx.coroutines.launch
+
+internal class MuteRenderersAction : ToggleAction(), DumbAware, ActionRemoteBehaviorSpecification.FrontendOtherwiseBackend {
+
+ override fun isSelected(e: AnActionEvent): Boolean {
+ val javaSession = SharedJavaDebuggerSession.findSession(e) ?: return false
+ return javaSession.areRenderersMuted
+ }
+
+ override fun setSelected(e: AnActionEvent, state: Boolean) {
+ val session = DebuggerUIUtil.getSessionProxy(e) ?: return
+ session.coroutineScope.launch {
+ JavaDebuggerSessionApi.getInstance().muteRenderers(session.id, state)
+ }
+ }
+
+ override fun update(e: AnActionEvent) {
+ super.update(e)
+ val javaSession = Companion.findSession(e)
+ e.presentation.isEnabledAndVisible = javaSession != null
+ }
+
+ override fun getActionUpdateThread(): ActionUpdateThread {
+ return ActionUpdateThread.BGT
+ }
+}
\ No newline at end of file
diff --git a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerManagerApi.kt b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerManagerApi.kt
index 4173920a6b2a..153c8af778c6 100644
--- a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerManagerApi.kt
+++ b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerManagerApi.kt
@@ -28,6 +28,8 @@ interface JavaDebuggerManagerApi : RemoteApi {
data class JavaDebuggerSessionDto(
val initialState: JavaSessionState,
val stateFlow: RpcFlow,
+ val areRenderersMutedInitial: Boolean,
+ val areRenderersMutedFlow: RpcFlow,
)
@ApiStatus.Internal
diff --git a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerSessionApi.kt b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerSessionApi.kt
index 93509825d92b..008591e8fec7 100644
--- a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerSessionApi.kt
+++ b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerSessionApi.kt
@@ -38,6 +38,8 @@ interface JavaDebuggerSessionApi : RemoteApi {
suspend fun setRenderer(rendererId: NodeRendererId?, xValueIds: List)
+ suspend fun muteRenderers(sessionId: XDebugSessionId, state: Boolean)
+
companion object {
@JvmStatic
suspend fun getInstance(): JavaDebuggerSessionApi {