[debugger] IDEA-363334 Introduce watch entity to reuse between session suspend

GitOrigin-RevId: fb44201c4af61542065f6374158f81d74ad0a6dd
This commit is contained in:
Maksim Zuev
2024-12-20 19:00:22 +00:00
committed by intellij-monorepo-bot
parent d804c73e1f
commit 0c86aab5ba
8 changed files with 212 additions and 72 deletions
@@ -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
- <init>(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
- <init>():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
- <init>(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
- <init>():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
- <init>(com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.frame.XWatchesView,java.lang.String,com.intellij.xdebugger.frame.XStackFrame,Z):V
- <init>(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
- <init>(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:<init>(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
- <init>(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
- <init>(com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.frame.XWatchesView,java.lang.String,com.intellij.xdebugger.frame.XStackFrame,Z):V
- <init>(com.intellij.xdebugger.impl.ui.tree.XDebuggerTree,com.intellij.xdebugger.impl.frame.XWatchesView,java.util.List,com.intellij.xdebugger.frame.XStackFrame,Z):V
- <init>(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
@@ -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<String, List<XExpression>> watches = new ConcurrentHashMap<>();
private final Map<String, List<XWatch>> 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<XExpression> getWatches(String configurationName) {
public @NotNull List<XWatch> getWatchEntries(String configurationName) {
return ContainerUtil.notNullize(watches.get(configurationName));
}
public void setWatchEntries(@NotNull String configurationName, @NotNull List<XWatch> watchList) {
if (watchList.isEmpty()) {
watches.remove(configurationName);
}
else {
watches.put(configurationName, watchList);
}
}
public @NotNull List<XExpression> 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<XExpression> 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<ConfigurationState> 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<InlineWatchState> inlineExpressionStates = state.getInlineExpressionStates();
inlineExpressionStates.clear();
inlineWatches.values().stream()
@@ -103,7 +119,10 @@ public final class XDebuggerWatchesManager {
for (ConfigurationState configurationState : state.getExpressions()) {
List<WatchState> 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);
}));
}
}
@@ -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")
}
@@ -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();
}
@@ -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<InlineWatch> 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<XExpression> getExpressions() {
return getWatchesManager().getWatches(myConfigurationName);
@@ -590,8 +586,8 @@ public class XWatchesViewImpl extends XVariablesView implements DnDNativeTarget,
}
public void updateSessionData() {
List<XExpression> watchExpressions = myRootNode.getWatchExpressions();
getWatchesManager().setWatches(myConfigurationName, watchExpressions);
List<XWatch> watches = myRootNode.getWatches();
getWatchesManager().setWatchEntries(myConfigurationName, watches);
}
@Override
@@ -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<XExpression> regularWatchesExpressions,
@NotNull List<InlineWatch> 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<XExpression> regularWatchesExpressions,
@NotNull List<InlineWatch> 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<InlineWatch> inlineWatches = ((XDebuggerManagerImpl)XDebuggerManager.getInstance(tree.getProject()))
.getWatchesManager().getInlineWatches();
for (InlineWatch inlineWatch : inlineWatches) {
myInlinesGroup.getChildren().add(new InlineWatchNodeImpl(myTree, myInlinesRootNode, inlineWatch, stackFrame));
}
}
@@ -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<XExpression> calculateEvaluationExpression() {
return Promises.resolvedPromise(myExpression);
return Promises.resolvedPromise(myWatch.getExpression());
}
@Override
@@ -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<XValueContainer> {
}
}
@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<XValueContainer> {
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<? extends XExpression> 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<? extends XWatch> 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<XValueContainer> {
return myChildren;
}
/**
* @deprecated Use {@link WatchesRootNode#getWatches()} instead.
*/
@Deprecated
public List<XExpression> getWatchExpressions() {
return StreamEx.of(getWatchChildren())
.filter(node -> !(node instanceof ResultNode))
@@ -124,6 +161,14 @@ public class WatchesRootNode extends XValueContainerNode<XValueContainer> {
.toList();
}
public List<XWatch> 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<XValueContainer> {
@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<XValueContainer> {
@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();
}