From 0c86aab5baa8555896c63d7300b3203353c0a2a7 Mon Sep 17 00:00:00 2001 From: Maksim Zuev Date: Wed, 18 Dec 2024 14:41:17 +0100 Subject: [PATCH] [debugger] IDEA-363334 Introduce watch entity to reuse between session suspend GitOrigin-RevId: fb44201c4af61542065f6374158f81d74ad0a6dd --- .../xdebugger-impl/api-dump-unreviewed.txt | 23 ++++++ .../impl/XDebuggerWatchesManager.java | 31 ++++++-- .../src/com/intellij/xdebugger/impl/XWatch.kt | 36 +++++++++ .../xdebugger/impl/frame/XVariablesView.java | 3 +- .../impl/frame/XWatchesViewImpl.java | 22 +++--- .../impl/inline/InlineWatchesRootNode.java | 36 +++++++-- .../impl/ui/tree/nodes/WatchNodeImpl.java | 56 +++++++------- .../impl/ui/tree/nodes/WatchesRootNode.java | 77 +++++++++++++++---- 8 files changed, 212 insertions(+), 72 deletions(-) create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XWatch.kt diff --git a/platform/xdebugger-impl/api-dump-unreviewed.txt b/platform/xdebugger-impl/api-dump-unreviewed.txt index 6c9a91f67893..faf0b26d440c 100644 --- a/platform/xdebugger-impl/api-dump-unreviewed.txt +++ b/platform/xdebugger-impl/api-dump-unreviewed.txt @@ -146,6 +146,13 @@ f:com.intellij.xdebugger.impl.InlayRunToCursorEditorListener - f:reshowInlayRunToCursor(com.intellij.openapi.editor.Editor):V f:com.intellij.xdebugger.impl.InlayRunToCursorEditorListener$Companion - f:isInlayRunToCursorEnabled():Z +f:com.intellij.xdebugger.impl.XAlwaysEvaluatedWatch +- com.intellij.xdebugger.impl.XWatch +- (com.intellij.xdebugger.XExpression):V +- getCanBePaused():Z +- getExpression():com.intellij.xdebugger.XExpression +- isPaused():Z +- setPaused(Z):V a:com.intellij.xdebugger.impl.XDebugProcessConfiguratorStarter - com.intellij.xdebugger.XDebugProcessStarter - ():V @@ -202,6 +209,18 @@ a:com.intellij.xdebugger.impl.XSourcePositionImpl - s:createByOffset(com.intellij.openapi.vfs.VirtualFile,I):com.intellij.xdebugger.impl.XSourcePositionImpl - createNavigatable(com.intellij.openapi.project.Project):com.intellij.pom.Navigatable - getFile():com.intellij.openapi.vfs.VirtualFile +com.intellij.xdebugger.impl.XWatch +- a:getCanBePaused():Z +- a:getExpression():com.intellij.xdebugger.XExpression +- a:isPaused():Z +- a:setPaused(Z):V +f:com.intellij.xdebugger.impl.XWatchImpl +- com.intellij.xdebugger.impl.XWatch +- (com.intellij.xdebugger.XExpression):V +- getCanBePaused():Z +- getExpression():com.intellij.xdebugger.XExpression +- isPaused():Z +- setPaused(Z):V c:com.intellij.xdebugger.impl.actions.AttachToProcessAction - com.intellij.xdebugger.impl.actions.AttachToProcessActionBase - ():V @@ -844,6 +863,7 @@ f:com.intellij.xdebugger.impl.inline.InlineWatch - f:updatePosition():Z c:com.intellij.xdebugger.impl.inline.InlineWatchesRootNode - com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode +- (com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.frame.XWatchesView,java.lang.String,com.intellij.xdebugger.frame.XStackFrame,Z):V - (com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.frame.XWatchesView,java.util.List,java.util.List,com.intellij.xdebugger.frame.XStackFrame,Z):V - addInlineWatchExpression(com.intellij.xdebugger.frame.XStackFrame,com.intellij.xdebugger.impl.inline.InlineWatch,I,Z):V - clearChildren():V @@ -1557,6 +1577,7 @@ c:com.intellij.xdebugger.impl.ui.tree.nodes.WatchNodeImpl - com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode - (com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode,com.intellij.xdebugger.XExpression,com.intellij.xdebugger.frame.XStackFrame):V - p:(com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode,com.intellij.xdebugger.XExpression,com.intellij.xdebugger.frame.XNamedValue):V +- (com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode,com.intellij.xdebugger.impl.XWatch,com.intellij.xdebugger.frame.XStackFrame,java.lang.String,com.intellij.xdebugger.frame.XValue):V - computePresentationIfNeeded():V - p:evaluated():V - getEvaluationOrigin():com.intellij.xdebugger.impl.ui.tree.nodes.XEvaluationOrigin @@ -1566,6 +1587,7 @@ c:com.intellij.xdebugger.impl.ui.tree.nodes.WatchNodeImpl - p:shouldUpdateInlineDebuggerData():Z c:com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode - com.intellij.xdebugger.impl.ui.tree.nodes.XValueContainerNode +- (com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.frame.XWatchesView,java.lang.String,com.intellij.xdebugger.frame.XStackFrame,Z):V - (com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.frame.XWatchesView,java.util.List,com.intellij.xdebugger.frame.XStackFrame,Z):V - (com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.frame.XWatchesView,com.intellij.xdebugger.XExpression[]):V - addNewWatch():V @@ -1578,6 +1600,7 @@ c:com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode - getLoadedChildren():java.util.List - getWatchChildren():java.util.List - getWatchExpressions():java.util.List +- getWatches():java.util.List - headerNodesCount():I - moveDown(com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode):V - moveUp(com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode):V diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java index 94191a19ade2..d35e106f6ded 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java @@ -19,7 +19,6 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import com.intellij.xdebugger.*; -import com.intellij.xdebugger.impl.breakpoints.XExpressionState; import com.intellij.xdebugger.impl.inline.InlineWatch; import com.intellij.xdebugger.impl.inline.InlineWatchInplaceEditor; import com.intellij.xdebugger.impl.inline.XInlineWatchesView; @@ -38,7 +37,7 @@ public final class XDebuggerWatchesManager { /** * Maps run configuration to a list of watches. */ - private final Map> watches = new ConcurrentHashMap<>(); + private final Map> watches = new ConcurrentHashMap<>(); /** * Maps file URL to a set of inline watches. */ @@ -59,16 +58,33 @@ public final class XDebuggerWatchesManager { myInlinesUpdateQueue = MergingUpdateQueue.Companion.edtMergingUpdateQueue("XInlineWatches", 300, coroutineScope); } - public @NotNull List getWatches(String configurationName) { + public @NotNull List getWatchEntries(String configurationName) { return ContainerUtil.notNullize(watches.get(configurationName)); } + public void setWatchEntries(@NotNull String configurationName, @NotNull List watchList) { + if (watchList.isEmpty()) { + watches.remove(configurationName); + } + else { + watches.put(configurationName, watchList); + } + } + + public @NotNull List getWatches(String configurationName) { + return ContainerUtil.map(ContainerUtil.notNullize(watches.get(configurationName)), XWatch::getExpression); + } + + /** + * @deprecated Use {@link XDebuggerWatchesManager#setWatchEntries(String, List)} instead + */ + @Deprecated public void setWatches(@NotNull String configurationName, @NotNull List expressions) { if (expressions.isEmpty()) { watches.remove(configurationName); } else { - watches.put(configurationName, expressions); + watches.put(configurationName, ContainerUtil.map(expressions, XWatchImpl::new)); } } @@ -80,7 +96,7 @@ public final class XDebuggerWatchesManager { public @NotNull WatchesManagerState saveState(@NotNull WatchesManagerState state) { List expressions = state.getExpressions(); expressions.clear(); - watches.forEach((key, value) -> expressions.add(new ConfigurationState(key, value))); + watches.forEach((key, value) -> expressions.add(new ConfigurationState(key, ContainerUtil.map(value, XWatch::getExpression)))); List inlineExpressionStates = state.getInlineExpressionStates(); inlineExpressionStates.clear(); inlineWatches.values().stream() @@ -103,7 +119,10 @@ public final class XDebuggerWatchesManager { for (ConfigurationState configurationState : state.getExpressions()) { List expressionStates = configurationState.getExpressionStates(); if (!ContainerUtil.isEmpty(expressionStates)) { - watches.put(configurationState.getName(), ContainerUtil.mapNotNull(expressionStates, XExpressionState::toXExpression)); + watches.put(configurationState.getName(), ContainerUtil.mapNotNull(expressionStates, watchState -> { + XExpression expression = watchState.toXExpression(); + return expression == null ? null : new XWatchImpl(expression); + })); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XWatch.kt b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XWatch.kt new file mode 100644 index 000000000000..0a823b5e97b6 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XWatch.kt @@ -0,0 +1,36 @@ +// 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.xdebugger.impl + +import com.intellij.xdebugger.XExpression + +/** + * Watch entity represents an expression to be evaluated with an additional state. + * + * This entity is used through the whole session and can be used between sessions via serialization performed by [XDebuggerWatchesManager]. + */ +interface XWatch { + val expression: XExpression + val canBePaused: Boolean + + var isPaused: Boolean +} + +/** + * A watch whose evaluation can be paused due to improper context or side effects. + */ +class XWatchImpl(override val expression: XExpression) : XWatch { + override val canBePaused: Boolean get() = true + override var isPaused: Boolean = false +} + +/** + * A watch that does not have an ability to be paused. + * + * For example, evaluation result, inline watches. + */ +class XAlwaysEvaluatedWatch(override val expression: XExpression) : XWatch { + override val canBePaused: Boolean get() = false + override var isPaused: Boolean + get() = false + set(value) = error("isPaused is not modifiable for AlwaysEvaluatedWatch") +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java index a1fb65248e1b..847711432ed9 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java @@ -88,8 +88,9 @@ public class XVariablesView extends XVariablesViewBase { super.dispose(); } + @ApiStatus.Internal @Nullable - protected final XDebugSessionImpl getSession() { + public final XDebugSessionImpl getSession() { return mySession.get(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java index 15453c66b805..9d8155c99357 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java @@ -38,10 +38,7 @@ import com.intellij.util.ui.tree.TreeUtil; import com.intellij.xdebugger.*; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.frame.XStackFrame; -import com.intellij.xdebugger.impl.XDebugSessionImpl; -import com.intellij.xdebugger.impl.XDebuggerManagerImpl; -import com.intellij.xdebugger.impl.XDebuggerUtilImpl; -import com.intellij.xdebugger.impl.XDebuggerWatchesManager; +import com.intellij.xdebugger.impl.*; import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; import com.intellij.xdebugger.impl.evaluate.DebuggerEvaluationStatisticsCollector; @@ -447,19 +444,14 @@ public class XWatchesViewImpl extends XVariablesView implements DnDNativeTarget, @Override protected XValueContainerNode doCreateNewRootNode(@Nullable XStackFrame stackFrame) { if (inlineWatchesEnabled) { - myRootNode = new InlineWatchesRootNode(getTree(), this, getExpressions(), getInlineExpressions(), stackFrame, myWatchesInVariables); + myRootNode = new InlineWatchesRootNode(getTree(), this, myConfigurationName, stackFrame, myWatchesInVariables); } else { - myRootNode = new WatchesRootNode(getTree(), this, getExpressions(), stackFrame, myWatchesInVariables); + myRootNode = new WatchesRootNode(getTree(), this, myConfigurationName, stackFrame, myWatchesInVariables); } return myRootNode; } - @NotNull - private List getInlineExpressions() { - return getWatchesManager().getInlineWatches(); - } - private XDebuggerWatchesManager getWatchesManager() { return ((XDebuggerManagerImpl)XDebuggerManager.getInstance(getTree().getProject())) .getWatchesManager(); @@ -523,6 +515,10 @@ public class XWatchesViewImpl extends XVariablesView implements DnDNativeTarget, } } + /** + * @deprecated Use {@link XDebuggerWatchesManager#getWatches(String)} directly + */ + @Deprecated @NotNull protected List getExpressions() { return getWatchesManager().getWatches(myConfigurationName); @@ -590,8 +586,8 @@ public class XWatchesViewImpl extends XVariablesView implements DnDNativeTarget, } public void updateSessionData() { - List watchExpressions = myRootNode.getWatchExpressions(); - getWatchesManager().setWatches(myConfigurationName, watchExpressions); + List watches = myRootNode.getWatches(); + getWatchesManager().setWatchEntries(myConfigurationName, watches); } @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/inline/InlineWatchesRootNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/inline/InlineWatchesRootNode.java index c1b93c74927b..b64b68e5f61b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/inline/InlineWatchesRootNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/inline/InlineWatchesRootNode.java @@ -4,9 +4,12 @@ package com.intellij.xdebugger.impl.inline; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.xdebugger.XDebuggerBundle; +import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.frame.*; +import com.intellij.xdebugger.impl.XDebuggerManagerImpl; import com.intellij.xdebugger.impl.frame.WatchInplaceEditor; +import com.intellij.xdebugger.impl.frame.XVariablesView; import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.*; @@ -18,20 +21,34 @@ import javax.swing.tree.TreeNode; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; public class InlineWatchesRootNode extends WatchesRootNode { private final @NotNull XWatchesView myWatchesView; private final XValueGroupNodeImpl myInlinesRootNode; private final InlinesGroup myInlinesGroup; + /** + * @deprecated Use {@link InlineWatchesRootNode#InlineWatchesRootNode(XDebuggerTree, XWatchesView, String, XStackFrame, boolean)} instead + */ + @Deprecated + public InlineWatchesRootNode(@NotNull XDebuggerTree tree, + @NotNull XWatchesView watchesView, + @NotNull List regularWatchesExpressions, + @NotNull List inlineWatchesExpressions, + @Nullable XStackFrame stackFrame, + boolean watchesInVariables) { + this(tree, watchesView, + Objects.requireNonNull(((XVariablesView)watchesView).getSession()).getSessionData().getConfigurationName(), + stackFrame, watchesInVariables); + } public InlineWatchesRootNode(@NotNull XDebuggerTree tree, - @NotNull XWatchesView watchesView, - @NotNull List regularWatchesExpressions, - @NotNull List inlineWatchesExpressions, - @Nullable XStackFrame stackFrame, - boolean watchesInVariables) { - super(tree, watchesView, regularWatchesExpressions, stackFrame, watchesInVariables); + @NotNull XWatchesView watchesView, + @NotNull String configurationName, + @Nullable XStackFrame stackFrame, + boolean watchesInVariables) { + super(tree, watchesView, configurationName, stackFrame, watchesInVariables); myWatchesView = watchesView; myInlinesGroup = new InlinesGroup(XDebuggerBundle.message("debugger.inline.watches.group.name"), true); myInlinesRootNode = new XValueGroupNodeImpl(tree, this, myInlinesGroup) { @@ -40,8 +57,11 @@ public class InlineWatchesRootNode extends WatchesRootNode { return myInlinesGroup.getChildren(); } }; - for (InlineWatch watchExpression : inlineWatchesExpressions) { - myInlinesGroup.getChildren().add(new InlineWatchNodeImpl(myTree, myInlinesRootNode, watchExpression, stackFrame)); + List inlineWatches = ((XDebuggerManagerImpl)XDebuggerManager.getInstance(tree.getProject())) + .getWatchesManager().getInlineWatches(); + + for (InlineWatch inlineWatch : inlineWatches) { + myInlinesGroup.getChildren().add(new InlineWatchNodeImpl(myTree, myInlinesRootNode, inlineWatch, stackFrame)); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java index 5f33e957e91d..60536c2abe63 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java @@ -11,6 +11,8 @@ import com.intellij.xdebugger.evaluation.XInstanceEvaluator; import com.intellij.xdebugger.frame.*; import com.intellij.xdebugger.frame.presentation.XErrorValuePresentation; import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.XAlwaysEvaluatedWatch; +import com.intellij.xdebugger.impl.XWatch; import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import org.jetbrains.annotations.NotNull; @@ -19,35 +21,33 @@ import org.jetbrains.concurrency.Promise; import org.jetbrains.concurrency.Promises; public class WatchNodeImpl extends XValueNodeImpl implements WatchNode { - private final XExpression myExpression; + private final XWatch myWatch; + + public WatchNodeImpl(@NotNull XDebuggerTree tree, + @NotNull XDebuggerTreeNode parent, + @NotNull XWatch watch, + @Nullable XStackFrame stackFrame, + @Nullable String name, + @Nullable XValue value) { + super(tree, parent, + name == null ? renderName(watch.getExpression()) : name, + value == null ? new XWatchValue(watch, tree, stackFrame) : value); + myWatch = watch; + } public WatchNodeImpl(@NotNull XDebuggerTree tree, @NotNull WatchesRootNode parent, @NotNull XExpression expression, @Nullable XStackFrame stackFrame) { - this(tree, parent, expression, stackFrame, renderName(expression)); - } - - WatchNodeImpl(@NotNull XDebuggerTree tree, - @NotNull WatchesRootNode parent, - @NotNull XExpression expression, - @Nullable XStackFrame stackFrame, - @NotNull String name) { - this(tree, parent, expression, name, new XWatchValue(expression, tree, stackFrame)); - } - - WatchNodeImpl(@NotNull XDebuggerTree tree, - @NotNull WatchesRootNode parent, - @NotNull XExpression expression, - @NotNull String name, - @NotNull XValue value) { - super(tree, parent, name, value); - myExpression = expression; + this(tree, parent, new XAlwaysEvaluatedWatch(expression), stackFrame, null, null); } protected WatchNodeImpl(XDebuggerTree tree, XDebuggerTreeNode parent, XExpression expression, XNamedValue value) { - super(tree, parent, renderName(expression), value); - myExpression = expression; + this(tree, parent, new XAlwaysEvaluatedWatch(expression), null, null, value); + } + + XWatch getWatch() { + return myWatch; } protected static String renderName(XExpression expression) { @@ -59,7 +59,7 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode { @Override @NotNull public XExpression getExpression() { - return myExpression; + return myWatch.getExpression(); } @NotNull @@ -95,14 +95,14 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode { } private static class XWatchValue extends XNamedValue { - private final XExpression myExpression; + private final XWatch myWatch; private final XDebuggerTree myTree; private final XStackFrame myStackFrame; private volatile XValue myValue; - XWatchValue(XExpression expression, XDebuggerTree tree, XStackFrame stackFrame) { - super(expression.getExpression()); - myExpression = expression; + XWatchValue(XWatch watch, XDebuggerTree tree, XStackFrame stackFrame) { + super(watch.getExpression().getExpression()); + myWatch = watch; myTree = tree; myStackFrame = stackFrame; } @@ -120,7 +120,7 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode { if (myTree.isShowing() || ApplicationManager.getApplication().isUnitTestMode()) { XDebuggerEvaluator evaluator = myStackFrame.getEvaluator(); if (evaluator != null) { - evaluator.evaluate(myExpression, new MyEvaluationCallback(node, place), myStackFrame.getSourcePosition()); + evaluator.evaluate(myWatch.getExpression(), new MyEvaluationCallback(node, place), myStackFrame.getSourcePosition()); return; } } @@ -190,7 +190,7 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode { @Override @NotNull public Promise calculateEvaluationExpression() { - return Promises.resolvedPromise(myExpression); + return Promises.resolvedPromise(myWatch.getExpression()); } @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java index ce7699f9bc4a..767edd72bebe 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java @@ -11,9 +11,14 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerBundle; +import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.frame.*; import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.XAlwaysEvaluatedWatch; +import com.intellij.xdebugger.impl.XDebuggerManagerImpl; +import com.intellij.xdebugger.impl.XWatch; +import com.intellij.xdebugger.impl.XWatchImpl; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; import com.intellij.xdebugger.impl.frame.WatchInplaceEditor; import com.intellij.xdebugger.impl.frame.XDebugView; @@ -66,7 +71,10 @@ public class WatchesRootNode extends XValueContainerNode { } } - @SuppressWarnings("unused") + /** + * @deprecated Use {@link WatchesRootNode#WatchesRootNode(XDebuggerTree, XWatchesView, String, XStackFrame, boolean)} instead + */ + @Deprecated // required for com.google.gct.core public WatchesRootNode(@NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView, @@ -74,27 +82,52 @@ public class WatchesRootNode extends XValueContainerNode { this(tree, watchesView, Arrays.asList(expressions), null, false); } + /** + * @deprecated Use {@link WatchesRootNode#WatchesRootNode(XDebuggerTree, XWatchesView, String, XStackFrame, boolean)} instead + */ + @Deprecated public WatchesRootNode(@NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView, @NotNull List expressions, @Nullable XStackFrame stackFrame, boolean watchesInVariables) { + this(tree, watchesView, ContainerUtil.map(expressions, XAlwaysEvaluatedWatch::new), stackFrame, watchesInVariables, false); + } + + public WatchesRootNode(@NotNull XDebuggerTree tree, + @NotNull XWatchesView watchesView, + @NotNull String configurationName, + @Nullable XStackFrame stackFrame, + boolean watchesInVariables) { + this(tree, watchesView, + ((XDebuggerManagerImpl)XDebuggerManager.getInstance(tree.getProject())).getWatchesManager().getWatchEntries(configurationName), + stackFrame, watchesInVariables, false); + } + + private WatchesRootNode(@NotNull XDebuggerTree tree, + @NotNull XWatchesView watchesView, + @NotNull List watches, + @Nullable XStackFrame stackFrame, + boolean watchesInVariables, + @SuppressWarnings("unused") boolean avoidSignatureClash) { super(tree, null, false, new RootContainerNode(stackFrame, watchesInVariables)); myWatchesView = watchesView; myChildren = new ArrayList<>(); + copyEvaluationResultFromOldRoot(tree, stackFrame); + + for (XWatch watch : watches) { + myChildren.add(new WatchNodeImpl(myTree, this, watch, stackFrame, null, null)); + } + } + + private void copyEvaluationResultFromOldRoot(@NotNull XDebuggerTree tree, @Nullable XStackFrame stackFrame) { // copy evaluation result by default - if (stackFrame != null) { - XDebuggerTreeNode root = tree.getRoot(); - if (root instanceof WatchesRootNode) { - StreamEx.of(((WatchesRootNode)root).myChildren) - .select(ResultNode.class) - .findFirst() - .ifPresent(node -> myChildren.add(new ResultNode(myTree, this, node.getExpression(), node.getValueContainer()))); - } - } - for (XExpression watchExpression : expressions) { - myChildren.add(new WatchNodeImpl(myTree, this, watchExpression, stackFrame)); - } + if (stackFrame == null) return; + if (!(tree.getRoot() instanceof WatchesRootNode watchesRootNode)) return; + StreamEx.of(watchesRootNode.myChildren) + .select(ResultNode.class) + .findFirst() + .ifPresent(node -> myChildren.add(new ResultNode(myTree, this, node.getExpression(), node.getValueContainer()))); } @NotNull @@ -117,6 +150,10 @@ public class WatchesRootNode extends XValueContainerNode { return myChildren; } + /** + * @deprecated Use {@link WatchesRootNode#getWatches()} instead. + */ + @Deprecated public List getWatchExpressions() { return StreamEx.of(getWatchChildren()) .filter(node -> !(node instanceof ResultNode)) @@ -124,6 +161,14 @@ public class WatchesRootNode extends XValueContainerNode { .toList(); } + public List getWatches() { + return StreamEx.of(getWatchChildren()) + .select(WatchNodeImpl.class) + .filter(node -> !(node instanceof ResultNode)) + .map(WatchNodeImpl::getWatch) + .toList(); + } + @Override public void clearChildren() { super.clearChildren(); @@ -139,14 +184,14 @@ public class WatchesRootNode extends XValueContainerNode { @NotNull WatchesRootNode parent, @NotNull XExpression expression, @Nullable XStackFrame stackFrame) { - super(tree, parent, expression, stackFrame, XDebuggerBundle.message("debugger.result.node.name")); + super(tree, parent, new XAlwaysEvaluatedWatch(expression), stackFrame, XDebuggerBundle.message("debugger.result.node.name"), null); } ResultNode(@NotNull XDebuggerTree tree, @NotNull WatchesRootNode parent, @NotNull XExpression expression, @NotNull XValue value) { - super(tree, parent, expression, XDebuggerBundle.message("debugger.result.node.name"), value); + super(tree, parent, new XAlwaysEvaluatedWatch(expression), null, XDebuggerBundle.message("debugger.result.node.name"), value); } @Override @@ -195,7 +240,7 @@ public class WatchesRootNode extends XValueContainerNode { @NotNull XExpression expression, int index, boolean navigateToWatchNode) { - WatchNodeImpl message = new WatchNodeImpl(myTree, this, expression, stackFrame); + WatchNodeImpl message = new WatchNodeImpl(myTree, this, new XWatchImpl(expression), stackFrame, null, null); if (index < 0 || index > myChildren.size()) { index = myChildren.size(); }