Add an ability to load values in Debugger/Console on demand (PY-29468)

This commit is contained in:
Elizaveta Shashkova
2018-05-29 19:05:46 +03:00
parent 6afdfaedb5
commit 775bec79b8
13 changed files with 237 additions and 63 deletions
@@ -104,11 +104,21 @@ USE_LIB_COPY = SUPPORT_GEVENT and \
(IS_PY3K and sys.version_info[1] >= 3))
class ValuesPolicy:
SYNC = 0
ASYNC = 1
ON_DEMAND = 2
LOAD_VALUES_POLICY = ValuesPolicy.SYNC
if os.getenv('PYDEVD_LOAD_VALUES_ASYNC', 'False') == 'True':
LOAD_VALUES_POLICY = ValuesPolicy.ASYNC
if os.getenv('PYDEVD_LOAD_VALUES_ON_DEMAND', 'False') == 'True':
LOAD_VALUES_POLICY = ValuesPolicy.ON_DEMAND
DEFAULT_VALUES_DICT = {ValuesPolicy.ASYNC: "__pydevd_value_async", ValuesPolicy.ON_DEMAND: "__pydevd_value_on_demand"}
INTERACTIVE_MODE_AVAILABLE = sys.platform in ('darwin', 'win32') or os.getenv('DISPLAY') is not None
IS_PYCHARM = True
LOAD_VALUES_ASYNC = os.getenv('PYDEVD_LOAD_VALUES_ASYNC', 'False') == 'True'
DEFAULT_VALUE = "__pydevd_value_async"
ASYNC_EVAL_TIMEOUT_SEC = 60
NEXT_VALUE_SEPARATOR = "__pydev_val__"
BUILTINS_MODULE_NAME = '__builtin__' if IS_PY2 else 'builtins'
@@ -4,9 +4,7 @@ from _pydevd_bundle import pydevd_extension_utils
from _pydevd_bundle import pydevd_resolver
import sys
from _pydevd_bundle.pydevd_constants import dict_iter_items, dict_keys, IS_PY3K, \
BUILTINS_MODULE_NAME, MAXIMUM_VARIABLE_REPRESENTATION_SIZE, RETURN_VALUES_DICT, LOAD_VALUES_ASYNC, \
DEFAULT_VALUE
BUILTINS_MODULE_NAME, MAXIMUM_VARIABLE_REPRESENTATION_SIZE, RETURN_VALUES_DICT, LOAD_VALUES_POLICY, ValuesPolicy, DEFAULT_VALUES_DICT
from _pydev_bundle.pydev_imports import quote
from _pydevd_bundle.pydevd_extension_api import TypeResolveProvider, StrPresentationProvider
@@ -232,7 +230,7 @@ def is_builtin(x):
def should_evaluate_full_value(val):
return not LOAD_VALUES_ASYNC or (is_builtin(type(val)) and not isinstance(val, (list, tuple, dict)))
return LOAD_VALUES_POLICY == ValuesPolicy.SYNC or (is_builtin(type(val)) and not isinstance(val, (list, tuple, dict)))
def frame_vars_to_xml(frame_f_locals, hidden_ns=None):
@@ -289,7 +287,7 @@ def var_to_xml(val, name, doTrim=True, additional_in_xml='', evaluate_full_value
_type, typeName, resolver = get_type(v)
type_qualifier = getattr(_type, "__module__", "")
if not evaluate_full_value:
value = DEFAULT_VALUE
value = DEFAULT_VALUES_DICT[LOAD_VALUES_POLICY]
else:
try:
str_from_provider = _str_from_providers(v, _type, typeName)
@@ -6,6 +6,7 @@ import com.intellij.icons.AllIcons;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
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 org.jetbrains.annotations.NotNull;
@@ -29,7 +30,6 @@ public class PyDebugValue extends XNamedValue {
public static final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();
public static final String RETURN_VALUES_PREFIX = "__pydevd_ret_val_dict";
public static final String DEFAULT_VALUE_ASYNC = "__pydevd_value_async";
private @Nullable String myTempName = null;
private final @Nullable String myType;
@@ -40,12 +40,23 @@ public class PyDebugValue extends XNamedValue {
private final boolean myIsIPythonHidden;
private @Nullable PyDebugValue myParent;
private @Nullable String myId = null;
private boolean myLoadValueAsync;
private ValuesPolicy myLoadValuePolicy;
private @NotNull PyFrameAccessor myFrameAccessor;
private @Nullable PyVariableLocator myVariableLocator;
private volatile @Nullable XValueNode myLastNode = null;
private final boolean myErrorOnEval;
public enum ValuesPolicy {
SYNC, ASYNC, ON_DEMAND
}
private static final Map<String, ValuesPolicy> POLICY_DEFAULT_VALUES = ImmutableMap.of("__pydevd_value_async", ValuesPolicy.ASYNC,
"__pydevd_value_on_demand",
ValuesPolicy.ON_DEMAND);
public static final Map<ValuesPolicy, String> POLICY_ENV_VARS = ImmutableMap.of(ValuesPolicy.ASYNC, "PYDEVD_LOAD_VALUES_ASYNC",
ValuesPolicy.ON_DEMAND, "PYDEVD_LOAD_VALUES_ON_DEMAND");
public PyDebugValue(@NotNull final String name,
@Nullable final String type,
@Nullable String typeQualifier,
@@ -78,9 +89,9 @@ public class PyDebugValue extends XNamedValue {
myErrorOnEval = errorOnEval;
myParent = parent;
myFrameAccessor = frameAccessor;
myLoadValueAsync = false;
if (DEFAULT_VALUE_ASYNC.equals(myValue)) {
myLoadValueAsync = true;
myLoadValuePolicy = ValuesPolicy.SYNC;
if (POLICY_DEFAULT_VALUES.keySet().contains(myValue)) {
myLoadValuePolicy = POLICY_DEFAULT_VALUES.get(myValue);
setValue(" ");
}
}
@@ -88,7 +99,7 @@ public class PyDebugValue extends XNamedValue {
public PyDebugValue(@NotNull PyDebugValue value, @NotNull String newName) {
this(newName, value.getType(), value.getTypeQualifier(), value.getValue(), value.isContainer(), value.isReturnedVal(),
value.isIPythonHidden(), value.isErrorOnEval(), value.getParent(), value.getFrameAccessor());
setLoadValueAsync(value.isLoadValueAsync());
setLoadValuePolicy(value.getLoadValuePolicy());
setTempName(value.getTempName());
}
@@ -149,12 +160,12 @@ public class PyDebugValue extends XNamedValue {
return myParent == null ? this : myParent.getTopParent();
}
public boolean isLoadValueAsync() {
return myLoadValueAsync;
public ValuesPolicy getLoadValuePolicy() {
return myLoadValuePolicy;
}
public void setLoadValueAsync(boolean loadValueAsync) {
myLoadValueAsync = loadValueAsync;
public void setLoadValuePolicy(ValuesPolicy loadValueAsync) {
myLoadValuePolicy = loadValueAsync;
}
@Nullable
@@ -243,8 +254,22 @@ public class PyDebugValue extends XNamedValue {
node.setPresentation(getValueIcon(), myType, value, myContainer);
}
public void updateNodeValueAfterLoading(@NotNull XValueNode node, @NotNull String value, @NotNull String linkText) {
node.setPresentation(getValueIcon(), myType, value, myContainer);
public void updateNodeValueAfterLoading(@NotNull XValueNode node,
@NotNull String value,
@NotNull String linkText,
@Nullable String errorMessage) {
if (errorMessage != null) {
node.setPresentation(getValueIcon(), new XRegularValuePresentation(value, myType) {
@Override
public void renderValue(@NotNull XValueTextRenderer renderer) {
renderer.renderError(errorMessage);
}
}, myContainer);
}
else {
node.setPresentation(getValueIcon(), myType, value, myContainer);
}
if (isNumericContainer()) return; // do not update FullValueEvaluator not to break Array Viewer
if (value.length() >= MAX_VALUE) {
node.setFullValueEvaluator(new PyFullValueEvaluator(myFrameAccessor, getEvaluationExpression()));
@@ -274,11 +299,11 @@ public class PyDebugValue extends XNamedValue {
return new PyDebugCallback<String>() {
@Override
public void ok(String value) {
myLoadValueAsync = false;
myLoadValuePolicy = ValuesPolicy.SYNC;
myValue = value;
XValueNode node = myLastNode;
if (node != null && !node.isObsolete()) {
updateNodeValueAfterLoading(node, value, "");
updateNodeValueAfterLoading(node, value, "", null);
}
}
@@ -300,7 +325,7 @@ public class PyDebugValue extends XNamedValue {
XValue value = childrenList.getValue(i);
if (value instanceof PyDebugValue) {
PyDebugValue debugValue = (PyDebugValue)value;
if (debugValue.isLoadValueAsync()) {
if (debugValue.getLoadValuePolicy() == ValuesPolicy.ASYNC || debugValue.isNumericContainer()) {
variables.add(new PyFrameAccessor.PyAsyncValue<>(debugValue, debugValue.createDebugValueCallback()));
}
}
@@ -328,9 +353,12 @@ public class PyDebugValue extends XNamedValue {
if (value.length() >= MAX_VALUE) {
node.setFullValueEvaluator(new PyFullValueEvaluator(myFrameAccessor, treeName));
}
if (myLoadValueAsync) {
if (myLoadValuePolicy == ValuesPolicy.ASYNC) {
node.setFullValueEvaluator(new PyLoadingValueEvaluator("... Loading Value", myFrameAccessor, treeName));
}
else if (myLoadValuePolicy == ValuesPolicy.ON_DEMAND) {
node.setFullValueEvaluator(new PyOnDemandValueEvaluator("Show Value", myFrameAccessor, this, node));
}
return;
}
String linkText = "...View as " + postfix;
@@ -1,6 +1,7 @@
package com.jetbrains.python.debugger;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.frame.XCompositeNode;
import com.intellij.xdebugger.frame.XValueChildrenList;
import com.jetbrains.python.debugger.pydev.PyDebugCallback;
import org.jetbrains.annotations.NotNull;
@@ -44,6 +45,13 @@ public interface PyFrameAccessor {
return false;
}
default void setCurrentRootNode(@NotNull XCompositeNode node) {}
@Nullable
default XCompositeNode getCurrentRootNode() {
return null;
}
class PyAsyncValue<T> {
private final @NotNull PyDebugValue myDebugValue;
private final @NotNull PyDebugCallback<T> myCallback;
@@ -8,22 +8,22 @@ import org.jetbrains.annotations.NotNull;
* @author traff
*/
public class PyFullValueEvaluator extends XFullValueEvaluator {
private final PyFrameAccessor myDebugProcess;
private final String myExpression;
@NotNull protected final PyFrameAccessor myDebugProcess;
@NotNull protected final String myExpression;
/**
* @param linkText text of the link what will be appended to a variables tree node text
* @param debugProcess
* @param expression
*/
protected PyFullValueEvaluator(String linkText, PyFrameAccessor debugProcess, String expression) {
protected PyFullValueEvaluator(String linkText, @NotNull PyFrameAccessor debugProcess, @NotNull String expression) {
super(linkText);
myDebugProcess = debugProcess;
myExpression = expression;
}
protected PyFullValueEvaluator(PyFrameAccessor debugProcess, String expression) {
protected PyFullValueEvaluator(@NotNull PyFrameAccessor debugProcess, @NotNull String expression) {
myDebugProcess = debugProcess;
myExpression = expression;
}
@@ -32,7 +32,7 @@ public class PyFullValueEvaluator extends XFullValueEvaluator {
@Override
public void startEvaluation(@NotNull XFullValueEvaluationCallback callback) {
String expression = myExpression.trim();
if ("".equals(expression)) {
if (expression.isEmpty()) {
callback.evaluated("");
return;
}
@@ -0,0 +1,22 @@
// 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.intellij.xdebugger.frame.XValueNode
class PyOnDemandValueEvaluator(linkText: String,
debugProcess: PyFrameAccessor,
var debugValue: PyDebugValue,
var node: XValueNode) : PyFullValueEvaluator(linkText, debugProcess, debugValue.evaluationExpression) {
override fun startEvaluation(callback: XFullValueEvaluationCallback) {
node.setFullValueEvaluator(PyLoadingValueEvaluator("... Loading Value", myDebugProcess, myExpression))
callback.evaluated("... Loading Value")
val pyAsyncValue = PyFrameAccessor.PyAsyncValue<String>(debugValue, debugValue.createDebugValueCallback())
myDebugProcess.loadAsyncVariablesValues(listOf(pyAsyncValue))
}
override fun isShowValuePopup(): Boolean {
return false
}
}
@@ -31,6 +31,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.frame.XCompositeNode;
import com.intellij.xdebugger.frame.XValueChildrenList;
import com.intellij.xdebugger.frame.XValueNode;
import com.jetbrains.python.console.parsing.PythonConsoleData;
@@ -112,9 +113,11 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
private int myFullValueSeq = 0;
private final Map<Integer, List<PyFrameAccessor.PyAsyncValue<String>>> myCallbackHashMap = new ConcurrentHashMap<>();
private @Nullable PythonConsoleView myConsoleView;
@Nullable private PythonConsoleView myConsoleView;
private final List<PyFrameListener> myFrameListeners = ContainerUtil.createLockFreeCopyOnWriteList();
@Nullable private XCompositeNode myCurrentRootNode;
/**
* Initializes the xml-rpc communication.
*
@@ -629,7 +632,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
XValueNode node = value.getLastNode();
if (node != null && !node.isObsolete()) {
if (e.getMessage().startsWith("Timeout") || e.getMessage().startsWith("Console already exited")) {
value.updateNodeValueAfterLoading(node, " ", "Timeout Exceeded");
value.updateNodeValueAfterLoading(node, " ", "", PyVariableViewSettings.LOADING_TIMED_OUT);
}
else {
LOG.error(e);
@@ -677,6 +680,17 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
return new XValueChildrenList();
}
@Override
public void setCurrentRootNode(@NotNull XCompositeNode node) {
myCurrentRootNode = node;
}
@Override
@Nullable
public XCompositeNode getCurrentRootNode() {
return myCurrentRootNode;
}
@Override
public void changeVariable(PyDebugValue variable, String value) throws PyDebuggerException {
if (myClient != null) {
@@ -77,6 +77,7 @@ import com.jetbrains.python.PythonHelper;
import com.jetbrains.python.console.actions.ShowVarsAction;
import com.jetbrains.python.console.pydev.ConsoleCommunicationListener;
import com.jetbrains.python.debugger.PyDebugRunner;
import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.PyVariableViewSettings;
import com.jetbrains.python.debugger.settings.PyDebuggerSettings;
import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase;
@@ -207,7 +208,7 @@ public class PydevConsoleRunnerImpl implements PydevConsoleRunner {
DefaultActionGroup settings = new DefaultActionGroup("Settings", true);
settings.getTemplatePresentation().setIcon(AllIcons.General.GearPlain);
settings.add(new PyVariableViewSettings.SimplifiedView(null));
settings.add(new PyVariableViewSettings.AsyncView());
settings.add(new PyVariableViewSettings.VariablesPolicyGroup());
toolbarActions.add(settings);
@@ -1018,8 +1019,8 @@ public class PydevConsoleRunnerImpl implements PydevConsoleRunner {
myEnvironmentVariables = envs;
myEnvironmentVariables.putAll(consoleSettings.getEnvs());
PyDebuggerSettings debuggerSettings = PyDebuggerSettings.getInstance();
if (debuggerSettings.isLoadValuesAsync()) {
myEnvironmentVariables.put(PyVariableViewSettings.PYDEVD_LOAD_VALUES_ASYNC, "True");
if (debuggerSettings.getValuesPolicy() != PyDebugValue.ValuesPolicy.SYNC) {
myEnvironmentVariables.put(PyDebugValue.POLICY_ENV_VARS.get(debuggerSettings.getValuesPolicy()), "True");
}
}
@@ -101,6 +101,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
private PyReferrersLoader myReferrersProvider;
private final List<PyFrameListener> myFrameListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private boolean isCythonWarningShown = false;
@Nullable private XCompositeNode myCurrentRootNode;
public PyDebugProcess(@NotNull XDebugSession session,
@NotNull ServerSocket serverSocket,
@@ -451,7 +452,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
super.registerAdditionalActions(leftToolbar, topToolbar, settings);
settings.add(new WatchReturnValuesAction(this));
settings.add(new PyVariableViewSettings.SimplifiedView(this));
settings.add(new PyVariableViewSettings.AsyncView());
settings.add(new PyVariableViewSettings.VariablesPolicyGroup());
}
private static class WatchReturnValuesAction extends ToggleAction {
@@ -747,7 +748,8 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
XValueNode node = value.getLastNode();
if (node != null && !node.isObsolete()) {
if (e.getMessage().startsWith("Timeout")) {
value.updateNodeValueAfterLoading(node, " ", "Timeout Exceeded");
value.updateNodeValueAfterLoading(node, " ", "", PyVariableViewSettings.LOADING_TIMED_OUT);
PyVariableViewSettings.showWarningMessage(getCurrentRootNode());
}
else {
LOG.error(e);
@@ -830,6 +832,17 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
return PyDebugSupportUtils.canSaveToTemp(project, name);
}
@Override
public void setCurrentRootNode(@Nullable XCompositeNode currentRootNode) {
myCurrentRootNode = currentRootNode;
}
@Nullable
@Override
public XCompositeNode getCurrentRootNode() {
return myCurrentRootNode;
}
@NotNull
private PyStackFrame currentFrame() throws PyDebuggerException {
if (!isConnected()) {
@@ -333,8 +333,8 @@ public class PyDebugRunner extends GenericProgramRunner {
if (debuggerSettings.isLibrariesFilterEnabled()) {
environment.put(PYDEVD_FILTER_LIBRARIES, "True");
}
if (debuggerSettings.isLoadValuesAsync()) {
environment.put(PyVariableViewSettings.PYDEVD_LOAD_VALUES_ASYNC, "True");
if (debuggerSettings.getValuesPolicy() != PyDebugValue.ValuesPolicy.SYNC) {
environment.put(PyDebugValue.POLICY_ENV_VARS.get(debuggerSettings.getValuesPolicy()), "True");
}
PydevConsoleRunnerFactory.putIPythonEnvFlag(project, environment);
@@ -129,6 +129,7 @@ public class PyStackFrame extends XStackFrame {
@Override
public void computeChildren(@NotNull final XCompositeNode node) {
if (node.isObsolete()) return;
myDebugProcess.setCurrentRootNode(node);
ApplicationManager.getApplication().executeOnPooledThread(() -> {
try {
boolean cached = myDebugProcess.isCurrentFrameCached();
@@ -214,7 +215,7 @@ public class PyStackFrame extends XStackFrame {
node.addChildren(list, true);
}
@Nullable
@NotNull
@Override
public Icon getIcon() {
return AllIcons.Debugger.WatchLastReturnValue;
@@ -237,7 +238,7 @@ public class PyStackFrame extends XStackFrame {
node.addChildren(list, true);
}
@Nullable
@NotNull
@Override
public Icon getIcon() {
return PythonIcons.Python.Debug.SpecialVar;
@@ -258,10 +259,6 @@ public class PyStackFrame extends XStackFrame {
return myFrameInfo.getThreadId() + ":" + myFrameInfo.getId();
}
public String getFrameName() {
return myFrameInfo.getName();
}
protected XSourcePosition getPosition() {
return myPosition;
}
@@ -15,15 +15,23 @@
*/
package com.jetbrains.python.debugger;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.xdebugger.frame.XCompositeNode;
import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
import com.jetbrains.python.debugger.settings.PyDebuggerSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
public class PyVariableViewSettings {
public static final String PYDEVD_LOAD_VALUES_ASYNC = "PYDEVD_LOAD_VALUES_ASYNC";
public static final String LOADING_TIMED_OUT = "Loading timed out";
public static final String ON_DEMAND_LINK_TEXT = "Switch to loading on demand";
public static final String WARNING_MESSAGE = "The values of several variables couldn't be loaded ";
public static class SimplifiedView extends ToggleAction {
private final PyDebugProcess myProcess;
@@ -60,33 +68,107 @@ public class PyVariableViewSettings {
}
}
public static class AsyncView extends ToggleAction {
private final String myText;
private volatile boolean myLazyVariablesEvaluation;
public static void showWarningMessage(@Nullable final XCompositeNode node) {
if (node == null) return;
final PyDebuggerSettings debuggerSettings = PyDebuggerSettings.getInstance();
if (debuggerSettings.getValuesPolicy() == PyDebugValue.ValuesPolicy.ON_DEMAND) return;
public AsyncView() {
super("", "Load variable values asynchronously", null);
myLazyVariablesEvaluation = PyDebuggerSettings.getInstance().isLoadValuesAsync();
myText = "Load Values Asynchronously";
node.setMessage(
WARNING_MESSAGE, AllIcons.General.BalloonWarning, SimpleTextAttributes.REGULAR_ATTRIBUTES,
new XDebuggerTreeNodeHyperlink(ON_DEMAND_LINK_TEXT) {
private boolean linkClicked = false;
@Override
public void onClick(MouseEvent event) {
debuggerSettings.setValuesPolicy(PyDebugValue.ValuesPolicy.ON_DEMAND);
linkClicked = true;
}
@NotNull
@Override
public String getLinkText() {
if (linkClicked) {
return "";
}
else {
return ON_DEMAND_LINK_TEXT;
}
}
});
}
public static class VariablesPolicyGroup extends DefaultActionGroup {
@NotNull private final List<PolicyAction> myValuesPolicyActions = new ArrayList<>();
public VariablesPolicyGroup() {
super("Variables Loading Policy", true);
myValuesPolicyActions
.add(new PolicyAction("Synchronously", "Load variable values synchronously", PyDebugValue.ValuesPolicy.SYNC, this));
myValuesPolicyActions
.add(new PolicyAction("Asynchronously", "Load variable values asynchronously", PyDebugValue.ValuesPolicy.ASYNC, this));
myValuesPolicyActions
.add(new PolicyAction("On demand", "Load variable values on demand", PyDebugValue.ValuesPolicy.ON_DEMAND, this));
for (AnAction action : myValuesPolicyActions) {
add(action);
}
}
public void updatePolicyActions() {
final PyDebugValue.ValuesPolicy currentValuesPolicy = PyDebuggerSettings.getInstance().getValuesPolicy();
for (PolicyAction action : myValuesPolicyActions) {
action.setEnabled(currentValuesPolicy == action.getPolicy());
}
}
}
public static class PolicyAction extends ToggleAction {
@NotNull private final String myText;
@NotNull private final PyDebugValue.ValuesPolicy myPolicy;
@NotNull private final VariablesPolicyGroup myActionGroup;
private volatile boolean isEnabled;
public PolicyAction(@NotNull String text,
@NotNull String description,
@NotNull PyDebugValue.ValuesPolicy policy,
@NotNull VariablesPolicyGroup actionGroup) {
super("", description, null);
myText = text;
myPolicy = policy;
myActionGroup = actionGroup;
isEnabled = PyDebuggerSettings.getInstance().getValuesPolicy() == policy;
}
@Override
public void update(@NotNull final AnActionEvent e) {
super.update(e);
myActionGroup.updatePolicyActions();
final Presentation presentation = e.getPresentation();
presentation.setEnabled(true);
presentation.setText(myText);
}
@NotNull
public PyDebugValue.ValuesPolicy getPolicy() {
return myPolicy;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
@Override
public boolean isSelected(AnActionEvent e) {
return myLazyVariablesEvaluation;
return isEnabled;
}
@Override
public void setSelected(AnActionEvent e, boolean hide) {
myLazyVariablesEvaluation = hide;
PyDebuggerSettings.getInstance().setLoadValuesAsync(hide);
isEnabled = hide;
if (hide) {
PyDebuggerSettings.getInstance().setValuesPolicy(myPolicy);
}
myActionGroup.updatePolicyActions();
}
}
}
@@ -9,6 +9,7 @@ import com.intellij.util.SmartList;
import com.intellij.util.xmlb.XmlSerializerUtil;
import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
import com.intellij.xdebugger.settings.XDebuggerSettings;
import com.jetbrains.python.debugger.PyDebugValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,7 +27,7 @@ public class PyDebuggerSettings extends XDebuggerSettings<PyDebuggerSettings> im
public static final String FILTERS_DIVIDER = ";";
private boolean myWatchReturnValues = false;
private boolean mySimplifiedView = true;
private boolean myLoadValuesAsync = true;
private volatile PyDebugValue.ValuesPolicy myValuesPolicy = PyDebugValue.ValuesPolicy.ASYNC;
public PyDebuggerSettings() {
super("python");
@@ -49,12 +50,12 @@ public class PyDebuggerSettings extends XDebuggerSettings<PyDebuggerSettings> im
mySimplifiedView = simplifiedView;
}
public boolean isLoadValuesAsync() {
return myLoadValuesAsync;
public PyDebugValue.ValuesPolicy getValuesPolicy() {
return myValuesPolicy;
}
public void setLoadValuesAsync(boolean loadValuesAsync) {
myLoadValuesAsync = loadValuesAsync;
public void setValuesPolicy(PyDebugValue.ValuesPolicy valuesPolicy) {
myValuesPolicy = valuesPolicy;
}
public static PyDebuggerSettings getInstance() {