mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-8118 Add hex and binary integer renderers to Python debugger and console
GitOrigin-RevId: 8295632e227e7a68a37ceffcc34551d4cc606281
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d825cd0866
commit
64e1a276b7
@@ -2,6 +2,7 @@ package com.jetbrains.python.debugger;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -9,6 +10,7 @@ import com.intellij.xdebugger.frame.*;
|
||||
import com.intellij.xdebugger.frame.presentation.XRegularValuePresentation;
|
||||
import com.jetbrains.python.debugger.pydev.PyDebugCallback;
|
||||
import com.jetbrains.python.debugger.pydev.PyVariableLocator;
|
||||
import com.jetbrains.python.debugger.render.PyNodeRenderer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -51,6 +53,8 @@ public class PyDebugValue extends XNamedValue {
|
||||
private int myOffset;
|
||||
private int myCollectionLength = -1;
|
||||
|
||||
private @NotNull PyDebugValueDescriptor myDescriptor = new PyDebugValueDescriptor();
|
||||
|
||||
public enum ValuesPolicy {
|
||||
SYNC, ASYNC, ON_DEMAND
|
||||
}
|
||||
@@ -336,6 +340,7 @@ public class PyDebugValue extends XNamedValue {
|
||||
if (value.length() >= MAX_VALUE) {
|
||||
value = value.substring(0, MAX_VALUE);
|
||||
}
|
||||
value = applyRendererIfApplicable(value);
|
||||
setElementPresentation(node, value);
|
||||
}
|
||||
|
||||
@@ -456,6 +461,9 @@ public class PyDebugValue extends XNamedValue {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
try {
|
||||
XValueChildrenList values = myFrameAccessor.loadVariable(this);
|
||||
|
||||
restoreChildrenRenderers(values);
|
||||
|
||||
if (!node.isObsolete()) {
|
||||
updateLengthIfIsCollection(values);
|
||||
|
||||
@@ -655,4 +663,49 @@ public class PyDebugValue extends XNamedValue {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDebugValueDescriptor getDescriptor() {
|
||||
return myDescriptor;
|
||||
}
|
||||
|
||||
public void setDescriptor(@NotNull PyDebugValueDescriptor descriptor) {
|
||||
myDescriptor = descriptor;
|
||||
}
|
||||
|
||||
private void restoreChildrenRenderers(XValueChildrenList values) {
|
||||
PyDebugValueDescriptor descriptor = getDescriptor();
|
||||
Map<String, PyDebugValueDescriptor> childrenDescriptors = descriptor.getChildrenDescriptors();
|
||||
|
||||
if (childrenDescriptors == null) {
|
||||
childrenDescriptors = Maps.newHashMap();
|
||||
descriptor.setChildrenDescriptors(childrenDescriptors);
|
||||
}
|
||||
|
||||
if (values == null) return;
|
||||
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
if (values.getValue(i) instanceof PyDebugValue) {
|
||||
PyDebugValue value = (PyDebugValue) values.getValue(i);
|
||||
descriptor = childrenDescriptors.getOrDefault(value.getName(), null);
|
||||
if (descriptor == null) {
|
||||
descriptor = new PyDebugValueDescriptor();
|
||||
childrenDescriptors.put(value.getName(), descriptor);
|
||||
}
|
||||
value.setDescriptor(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String applyRendererIfApplicable(String value) {
|
||||
final PyNodeRenderer renderer = getDescriptor().getRenderer();
|
||||
final String type = getType();
|
||||
if (renderer == null || type == null) return value;
|
||||
if (renderer.isApplicable(type)) {
|
||||
return renderer.render(value);
|
||||
}
|
||||
else {
|
||||
getDescriptor().setRenderer(null);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2000-2019 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.jetbrains.python.debugger;
|
||||
|
||||
import com.jetbrains.python.debugger.render.PyNodeRenderer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class PyDebugValueDescriptor {
|
||||
|
||||
@Nullable private PyNodeRenderer myRenderer;
|
||||
|
||||
/**
|
||||
* Because of the variables and recreated every time we make a step in the debugger,
|
||||
* we have to save the variable children's descriptors to restore them when updating
|
||||
* the debugger variable view. Note that even if there is no renderer associated
|
||||
* with a {@link PyDebugValue} instance, it still maintains a value descriptor
|
||||
* to preserve access to its children renderers. Otherwise, it will be impossible to
|
||||
* reach them during the renderers' restoration process.
|
||||
*/
|
||||
@Nullable private Map<String, PyDebugValueDescriptor> myChildrenDescriptors;
|
||||
|
||||
@Nullable
|
||||
public PyNodeRenderer getRenderer() {
|
||||
return myRenderer;
|
||||
}
|
||||
|
||||
public void setRenderer(@Nullable PyNodeRenderer renderer) {
|
||||
myRenderer = renderer;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<String, PyDebugValueDescriptor> getChildrenDescriptors() {
|
||||
return myChildrenDescriptors;
|
||||
}
|
||||
|
||||
public void setChildrenDescriptors(@Nullable Map<String, PyDebugValueDescriptor> childrenDescriptors) {
|
||||
myChildrenDescriptors = childrenDescriptors;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2000-2019 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.jetbrains.python.debugger.render;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
public abstract class AbstractIntegerRenderer implements PyNodeRenderer {
|
||||
|
||||
private static final ImmutableSet<String> mySupportedTypes = ImmutableSet.of("int");
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(String type) {
|
||||
return type != null && mySupportedTypes.contains(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2000-2019 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.jetbrains.python.debugger.render;
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class BinaryRenderer extends AbstractIntegerRenderer {
|
||||
|
||||
private static final String myName = "Binary";
|
||||
|
||||
@Override
|
||||
public @NonNls String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String render(@NotNull String value) {
|
||||
final String prefix = value.startsWith("-") ? "-0b" : "0b";
|
||||
return prefix + new BigInteger(value).abs().toString(2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2000-2019 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.jetbrains.python.debugger.render;
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DecimalRenderer extends AbstractIntegerRenderer {
|
||||
|
||||
private static final String myName = "Decimal";
|
||||
|
||||
@Override
|
||||
public @NonNls String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String render(@NotNull String value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2000-2019 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.jetbrains.python.debugger.render;
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class HexRenderer extends AbstractIntegerRenderer {
|
||||
|
||||
private static final String myName = "Hex";
|
||||
|
||||
@Override
|
||||
public @NonNls String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull @NonNls String render(@NotNull String value) {
|
||||
final String prefix = value.startsWith("-") ? "-0x" : "0x";
|
||||
return prefix + new BigInteger(value).abs().toString(16).toUpperCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright 2000-2019 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.jetbrains.python.debugger.render;
|
||||
|
||||
public interface PyNodeRenderer {
|
||||
|
||||
String getName();
|
||||
|
||||
String render(String value);
|
||||
|
||||
boolean isApplicable(String type);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2000-2019 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.jetbrains.python.debugger.render;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PyNodeRendererManager {
|
||||
|
||||
private static final PyNodeRendererManager INSTANCE = new PyNodeRendererManager();
|
||||
|
||||
private final List<PyNodeRenderer> myAvailableRenderers = new ArrayList<>();
|
||||
|
||||
private PyNodeRendererManager() {
|
||||
myAvailableRenderers.add(new BinaryRenderer());
|
||||
myAvailableRenderers.add(new DecimalRenderer());
|
||||
myAvailableRenderers.add(new HexRenderer());
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public static PyNodeRendererManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public List<PyNodeRenderer> getAvailableRenderers() {
|
||||
return new ArrayList<>(myAvailableRenderers);
|
||||
}
|
||||
}
|
||||
@@ -827,6 +827,10 @@
|
||||
<add-to-group group-id="XDebugger.ValueGroup" anchor="after" relative-to-action="Debugger.AddToWatch"/>
|
||||
</action>
|
||||
|
||||
<action id="PyDebugger.ViewAsGroup" class="com.jetbrains.python.debugger.actions.ViewAsGroup" text="View as">
|
||||
<add-to-group group-id="XDebugger.ValueGroup" anchor="last" />
|
||||
</action>
|
||||
|
||||
<action id="PyConvertModuleToPackage" class="com.jetbrains.python.refactoring.convertModulePackage.PyConvertModuleToPackageAction"
|
||||
text="Convert to Python Package"
|
||||
description="Create package with the same name and move content of the module to its __init__.py">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2019 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.jetbrains.python.console;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.execution.console.LanguageConsoleImpl;
|
||||
import com.intellij.execution.filters.OpenFileHyperlinkInfo;
|
||||
import com.intellij.execution.impl.ConsoleViewUtil;
|
||||
@@ -40,6 +41,7 @@ import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.console.completion.PythonConsoleAutopopupBlockingHandler;
|
||||
import com.jetbrains.python.console.pydev.ConsoleCommunication;
|
||||
import com.jetbrains.python.console.pydev.ConsoleCommunicationListener;
|
||||
import com.jetbrains.python.debugger.PyDebugValueDescriptor;
|
||||
import com.jetbrains.python.debugger.PyDebuggerEditorsProvider;
|
||||
import com.jetbrains.python.debugger.PyStackFrame;
|
||||
import com.jetbrains.python.debugger.PyStackFrameInfo;
|
||||
@@ -54,6 +56,7 @@ import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -77,6 +80,8 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable
|
||||
private boolean isShowVars;
|
||||
@Nullable private String mySdkHomePath;
|
||||
|
||||
private final Map<String, Map<String, PyDebugValueDescriptor>> myDescriptorsCache = Maps.newConcurrentMap();
|
||||
|
||||
/**
|
||||
* @param testMode this console will be used to display test output and should support TC messages
|
||||
*/
|
||||
@@ -364,6 +369,7 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable
|
||||
|
||||
public void showVariables(PydevConsoleCommunication consoleCommunication) {
|
||||
PyStackFrame stackFrame = new PyStackFrame(getProject(), consoleCommunication, new PyStackFrameInfo("", "", "", null), null);
|
||||
stackFrame.restoreChildrenDescriptors(myDescriptorsCache);
|
||||
final XStandaloneVariablesView view = new XStandaloneVariablesView(getProject(), new PyDebuggerEditorsProvider(), stackFrame);
|
||||
consoleCommunication.addCommunicationListener(new ConsoleCommunicationListener() {
|
||||
@Override
|
||||
|
||||
@@ -111,6 +111,8 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
|
||||
private boolean isCythonWarningShown = false;
|
||||
@Nullable private XCompositeNode myCurrentRootNode;
|
||||
|
||||
private final Map<String, Map<String, PyDebugValueDescriptor>> myDescriptorsCache = Maps.newConcurrentMap();
|
||||
|
||||
public PyDebugProcess(@NotNull XDebugSession session,
|
||||
@NotNull ServerSocket serverSocket,
|
||||
@NotNull ExecutionConsole executionConsole,
|
||||
@@ -1066,8 +1068,10 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
|
||||
}
|
||||
|
||||
public PyStackFrame createStackFrame(PyStackFrameInfo frameInfo) {
|
||||
return new PyStackFrame(getSession().getProject(), this, frameInfo,
|
||||
getPositionConverter().convertFromPython(frameInfo.getPosition(), frameInfo.getName()));
|
||||
final PyStackFrame frame = new PyStackFrame(getSession().getProject(), this, frameInfo,
|
||||
getPositionConverter().convertFromPython(frameInfo.getPosition(), frameInfo.getName()));
|
||||
frame.restoreChildrenDescriptors(myDescriptorsCache);
|
||||
return frame;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2018 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.jetbrains.python.debugger;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
@@ -48,6 +49,8 @@ public class PyStackFrame extends XStackFrame {
|
||||
private final PyStackFrameInfo myFrameInfo;
|
||||
private final XSourcePosition myPosition;
|
||||
|
||||
private @Nullable Map<String, PyDebugValueDescriptor> myChildrenDescriptors;
|
||||
|
||||
public PyStackFrame(@NotNull Project project,
|
||||
@NotNull final PyFrameAccessor debugProcess,
|
||||
@NotNull final PyStackFrameInfo frameInfo, XSourcePosition position) {
|
||||
@@ -146,6 +149,9 @@ public class PyStackFrame extends XStackFrame {
|
||||
String name = children.getName(i);
|
||||
if (value instanceof PyDebugValue) {
|
||||
PyDebugValue pyValue = (PyDebugValue)value;
|
||||
|
||||
restoreValueDescriptor(pyValue);
|
||||
|
||||
if (pyValue.isReturnedVal() && debuggerSettings.isWatchReturnValues()) {
|
||||
returnedValues.put(name, value);
|
||||
}
|
||||
@@ -209,4 +215,26 @@ public class PyStackFrame extends XStackFrame {
|
||||
protected XSourcePosition getPosition() {
|
||||
return myPosition;
|
||||
}
|
||||
|
||||
public void setChildrenDescriptors(@Nullable Map<String, PyDebugValueDescriptor> childrenDescriptors) {
|
||||
myChildrenDescriptors = childrenDescriptors;
|
||||
}
|
||||
|
||||
public void restoreChildrenDescriptors(@NotNull Map<String, Map<String, PyDebugValueDescriptor>> descriptorsCache) {
|
||||
final String threadFrameId = getThreadFrameId();
|
||||
final Map<String, PyDebugValueDescriptor> childrenDescriptors = descriptorsCache.getOrDefault(threadFrameId, Maps.newHashMap());
|
||||
setChildrenDescriptors(childrenDescriptors);
|
||||
descriptorsCache.put(threadFrameId, childrenDescriptors);
|
||||
}
|
||||
|
||||
private void restoreValueDescriptor(PyDebugValue value) {
|
||||
if (myChildrenDescriptors != null) {
|
||||
PyDebugValueDescriptor descriptor = myChildrenDescriptors.getOrDefault(value.getName(), null);
|
||||
if (descriptor == null) {
|
||||
descriptor = new PyDebugValueDescriptor();
|
||||
myChildrenDescriptors.put(value.getName(), descriptor);
|
||||
}
|
||||
value.setDescriptor(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright 2000-2019 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.jetbrains.python.debugger.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import com.jetbrains.python.debugger.PyDebugValue;
|
||||
import com.jetbrains.python.debugger.render.DecimalRenderer;
|
||||
import com.jetbrains.python.debugger.render.PyNodeRenderer;
|
||||
import com.jetbrains.python.debugger.render.PyNodeRendererManager;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ViewAsGroup extends ActionGroup implements DumbAware {
|
||||
|
||||
private static final AnAction[] myChildren;
|
||||
|
||||
static {
|
||||
final List<AnAction> children = new ArrayList<>();
|
||||
for (PyNodeRenderer renderer : PyNodeRendererManager.getInstance().getAvailableRenderers()) {
|
||||
children.add(new RendererAction(renderer));
|
||||
}
|
||||
myChildren = children.toArray(EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
private static class RendererAction extends ToggleAction {
|
||||
|
||||
private final PyNodeRenderer myPyNodeRenderer;
|
||||
|
||||
private RendererAction(PyNodeRenderer pyNodeRenderer) {
|
||||
super(pyNodeRenderer.getName());
|
||||
myPyNodeRenderer = pyNodeRenderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(@NotNull AnActionEvent e) {
|
||||
final List<PyDebugValue> values = getSelectedValues(e);
|
||||
|
||||
if (values.isEmpty()) return false;
|
||||
|
||||
if (values.size() == 1) {
|
||||
PyNodeRenderer renderer = values.get(0).getDescriptor().getRenderer();
|
||||
return renderer == null ? myPyNodeRenderer instanceof DecimalRenderer : renderer == myPyNodeRenderer;
|
||||
}
|
||||
|
||||
boolean allRenderersAreTheSame = values.stream().map(value -> value.getDescriptor().getRenderer()).distinct().count() == 1;
|
||||
|
||||
if (allRenderersAreTheSame) {
|
||||
if (values.get(0).getDescriptor().getRenderer() == myPyNodeRenderer
|
||||
|| (values.get(0).getDescriptor().getRenderer() == null && myPyNodeRenderer instanceof DecimalRenderer)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(@NotNull AnActionEvent e, boolean state) {
|
||||
if (!state) return;
|
||||
|
||||
final List<XValueNodeImpl> selectedNodes = XDebuggerTreeActionBase.getSelectedNodes(e.getDataContext());
|
||||
|
||||
for (XValueNodeImpl node : selectedNodes) {
|
||||
PyDebugValue value = (PyDebugValue) node.getValueContainer();
|
||||
value.getDescriptor().setRenderer(myPyNodeRenderer);
|
||||
if (value.getValue() == null) continue;
|
||||
String lbl = value.getDescriptor().getRenderer() != null ? value.getDescriptor().
|
||||
getRenderer().render(value.getValue()) : value.getValue();
|
||||
if (lbl != null) {
|
||||
node.setPresentation(node.getIcon(), value.getType(), lbl, node.getChildCount() != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PyNodeRenderer getRenderer() {
|
||||
return myPyNodeRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
public ViewAsGroup() {
|
||||
super(null, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AnAction[] getChildren(@Nullable AnActionEvent e) {
|
||||
if (e == null) return EMPTY_ARRAY;
|
||||
|
||||
final List<PyDebugValue> values = getSelectedValues(e);
|
||||
|
||||
if (values.isEmpty()) return EMPTY_ARRAY;
|
||||
|
||||
for (PyDebugValue value : values) {
|
||||
for (AnAction child : myChildren) {
|
||||
if (!((RendererAction)child).getRenderer().isApplicable(value.getType())) return EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
return myChildren;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hideIfNoVisibleChildren() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PyDebugValue> getSelectedValues(AnActionEvent e) {
|
||||
return StreamEx.of(XDebuggerTreeActionBase.getSelectedNodes(e.getDataContext()))
|
||||
.map(XValueNodeImpl::getValueContainer)
|
||||
.select(PyDebugValue.class)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user