mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[debugger] IDEA-363334 Add watch pause/resume actions in context menu
GitOrigin-RevId: 7098d56696ca46262057bc0ed50b2e74252e25f7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0c86aab5ba
commit
ea4944f46a
@@ -1350,6 +1350,8 @@ action.XDebugger.EditWatch.text=Edit\u2026
|
||||
action.XDebugger.CopyWatch.text=Duplicate Watch
|
||||
action.XDebugger.MoveWatchUp.text=Move Watch Up
|
||||
action.XDebugger.MoveWatchDown.text=Move Watch Down
|
||||
action.XDebugger.PauseWatch.text=Pause Watch
|
||||
action.XDebugger.ResumeWatch.text=Resume Watch
|
||||
action.XDebugger.SeparateWatches.text=Separate Watches
|
||||
action.XDebugger.ToggleEvaluateExpressionField.text=Show Evaluate Expression Field
|
||||
action.XDebugger.PreviewTab.text=Open Files in Preview Tab
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<action id="XDebugger.MoveWatchDown" class="com.intellij.xdebugger.impl.frame.actions.XMoveWatchDown" use-shortcut-of="MoveLineDown"/>
|
||||
<action id="XDebugger.SeparateWatches" class="com.intellij.xdebugger.impl.frame.actions.XSeparateWatchesAndVariables"
|
||||
icon="AllIcons.Debugger.Watch"/>
|
||||
<action id="XDebugger.PauseWatch" class="com.intellij.xdebugger.impl.frame.actions.XPauseWatchAction"/>
|
||||
<action id="XDebugger.ToggleEvaluateExpressionField" class="com.intellij.xdebugger.impl.frame.actions.XToggleEvaluateExpressionFieldAction"/>
|
||||
<action id="XDebugger.RemoveAllWatches" class="com.intellij.xdebugger.impl.frame.actions.XRemoveAllWatchesAction"/>
|
||||
<action id="XDebugger.MuteBreakpoints" class="com.intellij.xdebugger.impl.actions.MuteBreakpointAction"
|
||||
@@ -152,6 +153,7 @@
|
||||
<reference ref="XDebugger.RemoveWatch"/>
|
||||
<reference ref="XDebugger.RemoveAllWatches"/>
|
||||
<reference ref="XDebugger.EditWatch"/>
|
||||
<reference ref="XDebugger.PauseWatch"/>
|
||||
<separator/>
|
||||
<reference ref="XDebugger.ValueGroup"/>
|
||||
</group>
|
||||
|
||||
@@ -296,6 +296,8 @@ memory.view.instances.warning.not.all.loaded=Not all instances will be loaded (o
|
||||
debugger.inline.watches.group.name=Inline Watches
|
||||
debugger.inline.watches.edit.watch.expression.text=Edit Watch Expression
|
||||
debugger.inline.watches.popup.action.add.as.inline.watch=Add as Inline Watch
|
||||
xdebugger.evaluate.paused.watch=\u2026 Evaluate
|
||||
xdebugger.watch.is.paused.message=The watch is paused
|
||||
|
||||
debug.toolwindow.empty.text.0=To debug your code, do one of the following:
|
||||
debug.toolwindow.empty.text.1=\u2013 Click the Run icon in the editor gutter
|
||||
|
||||
@@ -1583,6 +1583,7 @@ c:com.intellij.xdebugger.impl.ui.tree.nodes.WatchNodeImpl
|
||||
- getEvaluationOrigin():com.intellij.xdebugger.impl.ui.tree.nodes.XEvaluationOrigin
|
||||
- getExpression():com.intellij.xdebugger.XExpression
|
||||
- getValueContainer():com.intellij.xdebugger.frame.XValue
|
||||
- getXWatch():com.intellij.xdebugger.impl.XWatch
|
||||
- ps:renderName(com.intellij.xdebugger.XExpression):java.lang.String
|
||||
- p:shouldUpdateInlineDebuggerData():Z
|
||||
c:com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// 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.frame.actions
|
||||
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.idea.ActionsBundle
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.xdebugger.frame.XValuePlace
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView
|
||||
import com.intellij.xdebugger.impl.frame.actions.XWatchesTreeActionBase.getSelectedNodes
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNodeImpl
|
||||
|
||||
private class XPauseWatchAction : XWatchesTreeActionBase() {
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT
|
||||
|
||||
override fun isEnabled(e: AnActionEvent, tree: XDebuggerTree): Boolean {
|
||||
val selectedNode = getSelectedWatchNode(tree) ?: return false
|
||||
return selectedNode.xWatch.canBePaused
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
super.update(e)
|
||||
e.presentation.isVisible = e.presentation.isEnabled
|
||||
if (e.presentation.isEnabled) {
|
||||
val tree = XDebuggerTree.getTree(e) ?: return
|
||||
val node = getSelectedWatchNode(tree) ?: return
|
||||
val paused = node.xWatch.isPaused
|
||||
e.presentation.text =
|
||||
if (paused) ActionsBundle.message("action.XDebugger.ResumeWatch.text")
|
||||
else ActionsBundle.message("action.XDebugger.PauseWatch.text")
|
||||
e.presentation.icon = if (paused) AllIcons.Toolwindows.ToolWindowRun else AllIcons.Actions.Pause
|
||||
}
|
||||
}
|
||||
|
||||
override fun perform(e: AnActionEvent, tree: XDebuggerTree, watchesView: XWatchesView) {
|
||||
val node = getSelectedWatchNode(tree) ?: return
|
||||
val paused = node.xWatch.isPaused
|
||||
node.xWatch.isPaused = !paused
|
||||
if (!paused) {
|
||||
// only update icon, keep calculated value
|
||||
node.setPresentation(AllIcons.Actions.Pause, node.valuePresentation!!, !node.isLeaf)
|
||||
}
|
||||
else {
|
||||
// resume watch, trigger value evaluation
|
||||
node.valueContainer.computePresentation(node, XValuePlace.TREE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectedWatchNode(tree: XDebuggerTree): WatchNodeImpl? =
|
||||
getSelectedNodes(tree, WatchNodeImpl::class.java).singleOrNull()
|
||||
+56
-1
@@ -5,6 +5,7 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.xdebugger.Obsolescent;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XExpression;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
|
||||
import com.intellij.xdebugger.evaluation.XInstanceEvaluator;
|
||||
@@ -15,11 +16,14 @@ 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.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.concurrency.Promises;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class WatchNodeImpl extends XValueNodeImpl implements WatchNode {
|
||||
private final XWatch myWatch;
|
||||
|
||||
@@ -46,7 +50,7 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode {
|
||||
this(tree, parent, new XAlwaysEvaluatedWatch(expression), null, null, value);
|
||||
}
|
||||
|
||||
XWatch getWatch() {
|
||||
public XWatch getXWatch() {
|
||||
return myWatch;
|
||||
}
|
||||
|
||||
@@ -99,6 +103,7 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode {
|
||||
private final XDebuggerTree myTree;
|
||||
private final XStackFrame myStackFrame;
|
||||
private volatile XValue myValue;
|
||||
private final AtomicBoolean myEvaluateRequested = new AtomicBoolean(false);
|
||||
|
||||
XWatchValue(XWatch watch, XDebuggerTree tree, XStackFrame stackFrame) {
|
||||
super(watch.getExpression().getExpression());
|
||||
@@ -116,6 +121,11 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode {
|
||||
|
||||
@Override
|
||||
public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
|
||||
clearPausedLink(node);
|
||||
if (myWatch.isPaused() && !myEvaluateRequested.getAndSet(false)) {
|
||||
showPausedPresentation(node, place);
|
||||
return;
|
||||
}
|
||||
if (myStackFrame != null) {
|
||||
if (myTree.isShowing() || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
XDebuggerEvaluator evaluator = myStackFrame.getEvaluator();
|
||||
@@ -132,6 +142,18 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode {
|
||||
node.setPresentation(AllIcons.Debugger.Db_watch, EMPTY_PRESENTATION, false);
|
||||
}
|
||||
|
||||
private void clearPausedLink(@NotNull XValueNode node) {
|
||||
if (node instanceof XValueNodeImpl xValueNode
|
||||
&& xValueNode.getFullValueEvaluator() instanceof EvaluateLink) {
|
||||
xValueNode.clearFullValueEvaluator();
|
||||
}
|
||||
}
|
||||
|
||||
private void showPausedPresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
|
||||
node.setPresentation(AllIcons.Actions.Pause, PAUSED_PRESENTATION, false);
|
||||
node.setFullValueEvaluator(new EvaluateLink(node, place));
|
||||
}
|
||||
|
||||
private class MyEvaluationCallback extends XEvaluationCallbackBase implements XEvaluationCallbackWithOrigin, Obsolescent {
|
||||
@NotNull private final XValueNode myNode;
|
||||
@NotNull private final XValuePlace myPlace;
|
||||
@@ -240,5 +262,38 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode {
|
||||
public XReferrersProvider getReferrersProvider() {
|
||||
return myValue != null ? myValue.getReferrersProvider() : null;
|
||||
}
|
||||
|
||||
private class EvaluateLink extends XFullValueEvaluator {
|
||||
private final @NotNull XValueNode myNode;
|
||||
private final @NotNull XValuePlace myPlace;
|
||||
|
||||
private EvaluateLink(@NotNull XValueNode node, @NotNull XValuePlace place) {
|
||||
super(XDebuggerBundle.message("xdebugger.evaluate.paused.watch"));
|
||||
myNode = node;
|
||||
myPlace = place;
|
||||
setShowValuePopup(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEvaluation(@NotNull XFullValueEvaluationCallback callback) {
|
||||
callback.evaluated("");
|
||||
myEvaluateRequested.set(true);
|
||||
computePresentation(myNode, myPlace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static final XValuePresentation PAUSED_PRESENTATION = new XValuePresentation() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getSeparator() {
|
||||
return " ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderValue(@NotNull XValueTextRenderer renderer) {
|
||||
renderer.renderComment(XDebuggerBundle.message("xdebugger.watch.is.paused.message"));
|
||||
}
|
||||
};
|
||||
}
|
||||
+1
-1
@@ -165,7 +165,7 @@ public class WatchesRootNode extends XValueContainerNode<XValueContainer> {
|
||||
return StreamEx.of(getWatchChildren())
|
||||
.select(WatchNodeImpl.class)
|
||||
.filter(node -> !(node instanceof ResultNode))
|
||||
.map(WatchNodeImpl::getWatch)
|
||||
.map(WatchNodeImpl::getXWatch)
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user