diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ArrayAction.java similarity index 61% rename from java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java rename to java/debugger/impl/src/com/intellij/debugger/actions/ArrayAction.java index 437affb2e09f..48ec49125cae 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ArrayAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.intellij.debugger.actions; import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.JavaValue; +import com.intellij.debugger.engine.SuspendContextImpl; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.settings.ArrayRendererConfigurable; @@ -24,16 +25,26 @@ import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl; import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; import com.intellij.debugger.ui.tree.render.*; +import com.intellij.debugger.ui.tree.render.Renderer; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.frame.XValue; +import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; +import com.intellij.xdebugger.impl.ui.XDebuggerExpressionEditor; import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.debugger.JavaDebuggerEditorsProvider; -public class AdjustArrayRangeAction extends DebuggerAction { +import javax.swing.*; +import java.util.List; + +public abstract class ArrayAction extends DebuggerAction { @Override public void actionPerformed(AnActionEvent e) { DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(e.getDataContext()); @@ -43,8 +54,6 @@ public class AdjustArrayRangeAction extends DebuggerAction { return; } - final Project project = debuggerContext.getProject(); - final XValueNodeImpl node = XDebuggerTreeActionBase.getSelectedNode(e.getDataContext()); if (node == null) { return; @@ -67,22 +76,20 @@ public class AdjustArrayRangeAction extends DebuggerAction { //if (index > 0) { // title = title + " " + label.substring(index); //} - String title = node.getName(); - final ArrayRenderer clonedRenderer = renderer.clone(); - clonedRenderer.setForced(true); - if (ShowSettingsUtil.getInstance().editConfigurable(project, new NamedArrayConfigurable(title, clonedRenderer))) { + ArrayRenderer newRenderer = createNewRenderer(renderer, debuggerContext.getProject(), node.getName()); + if (newRenderer != null) { debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(debuggerContext.getSuspendContext()) { @Override - public void contextAction() throws Exception { + public void contextAction(@NotNull SuspendContextImpl suspendContext) throws Exception { final Renderer lastRenderer = descriptor.getLastRenderer(); if (lastRenderer instanceof ArrayRenderer) { - ((JavaValue)container).setRenderer(clonedRenderer, node); + ((JavaValue)container).setRenderer(newRenderer, node); } else if (lastRenderer instanceof CompoundNodeRenderer) { final CompoundNodeRenderer compoundRenderer = (CompoundNodeRenderer)lastRenderer; final ChildrenRenderer childrenRenderer = compoundRenderer.getChildrenRenderer(); if (childrenRenderer instanceof ExpressionChildrenRenderer) { - ExpressionChildrenRenderer.setPreferableChildrenRenderer(descriptor, clonedRenderer); + ExpressionChildrenRenderer.setPreferableChildrenRenderer(descriptor, newRenderer); ((JavaValue)container).reBuild(node); } } @@ -91,18 +98,17 @@ public class AdjustArrayRangeAction extends DebuggerAction { } } + @Nullable + protected abstract ArrayRenderer createNewRenderer(ArrayRenderer original, Project project, String title); + @Override public void update(AnActionEvent e) { boolean enable = false; - XValueNodeImpl node = XDebuggerTreeActionBase.getSelectedNode(e.getDataContext()); - if (node != null) { - XValue container = node.getValueContainer(); - if (container instanceof JavaValue) { - ValueDescriptorImpl descriptor = ((JavaValue)container).getDescriptor(); - enable = getArrayRenderer(descriptor) != null; - } + List values = ViewAsGroup.getSelectedValues(e); + if (values.size() == 1) { + enable = getArrayRenderer(values.get(0).getDescriptor()) != null; } - e.getPresentation().setVisible(enable); + e.getPresentation().setEnabledAndVisible(enable); } @Nullable @@ -152,4 +158,59 @@ public class AdjustArrayRangeAction extends DebuggerAction { return null; } } + + private static class AdjustArrayRangeAction extends ArrayAction { + @Override + protected ArrayRenderer createNewRenderer(ArrayRenderer original, Project project, String title) { + ArrayRenderer clonedRenderer = original.clone(); + clonedRenderer.setForced(true); + if (ShowSettingsUtil.getInstance().editConfigurable(project, new NamedArrayConfigurable(title, clonedRenderer))) { + return clonedRenderer; + } + return null; + } + } + + private static class FilterArrayAction extends ArrayAction { + @Nullable + @Override + protected ArrayRenderer createNewRenderer(ArrayRenderer original, Project project, String title) { + ExpressionDialog dialog = + new ExpressionDialog(project, original instanceof ArrayRenderer.Filtered ? ((ArrayRenderer.Filtered)original).getExpression() + : XExpressionImpl.EMPTY_EXPRESSION); + if (dialog.showAndGet()) { + return new ArrayRenderer.Filtered(dialog.getExpression()); + } + return null; + } + + private static class ExpressionDialog extends DialogWrapper { + private final XDebuggerExpressionEditor myEditor; + + public ExpressionDialog(@NotNull Project project, XExpression expression) { + super(project); + myEditor = new XDebuggerExpressionEditor(project, new JavaDebuggerEditorsProvider(), "filter", null, + expression, false, true, false); + + setTitle("Filter"); + init(); + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + return myEditor.getComponent(); + } + + @Nullable + @Override + public JComponent getPreferredFocusedComponent() { + return myEditor.getPreferredFocusedComponent(); + } + + XExpression getExpression() { + return myEditor.getExpression(); + } + } + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java index 2f930f100f12..e98e0754a9ca 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java @@ -20,6 +20,9 @@ import com.intellij.debugger.DebuggerContext; import com.intellij.debugger.engine.DebuggerManagerThreadImpl; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContext; +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.engine.evaluation.TextWithImportsImpl; +import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.settings.ViewsGeneralSettings; import com.intellij.debugger.ui.impl.watch.ArrayElementDescriptorImpl; import com.intellij.debugger.ui.impl.watch.NodeManagerImpl; @@ -33,11 +36,13 @@ import com.intellij.openapi.util.DefaultJDOMExternalizer; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.CommonClassNames; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiExpression; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.IncorrectOperationException; +import com.intellij.xdebugger.XExpression; import com.sun.jdi.ArrayReference; import com.sun.jdi.ArrayType; import com.sun.jdi.Type; @@ -189,4 +194,75 @@ public class ArrayRenderer extends NodeRendererImpl{ public boolean isApplicable(Type type) { return type instanceof ArrayType; } + + public static class Filtered extends ArrayRenderer { + private final XExpression myExpression; + + public Filtered(XExpression expression) { + myExpression = expression; + } + + public XExpression getExpression() { + return myExpression; + } + + @Override + public void buildChildren(Value value, ChildrenBuilder builder, EvaluationContext evaluationContext) { + DebuggerManagerThreadImpl.assertIsManagerThread(); + NodeManagerImpl nodeManager = (NodeManagerImpl)builder.getNodeManager(); + NodeDescriptorFactory descriptorFactory = builder.getDescriptorManager(); + + builder.initChildrenArrayRenderer(this); + + if (ENTRIES_LIMIT > END_INDEX - START_INDEX + 1) { + ENTRIES_LIMIT = END_INDEX - START_INDEX; + } + + if (ENTRIES_LIMIT <= 0) { + ENTRIES_LIMIT = 1; + } + + ArrayReference array = (ArrayReference)value; + int arrayLength = array.length(); + if (arrayLength > 0) { + CachedEvaluator cachedEvaluator = new CachedEvaluator() { + @Override + protected String getClassName() { + return CommonClassNames.JAVA_LANG_OBJECT; + } + }; + cachedEvaluator.setReferenceExpression(TextWithImportsImpl.fromXExpression(myExpression)); + + int added = 0; + if (arrayLength - 1 >= START_INDEX) { + for (int idx = START_INDEX; idx < arrayLength; idx++) { + try { + if (DebuggerUtilsEx.evaluateBoolean(cachedEvaluator.getEvaluator(evaluationContext.getProject()), + (EvaluationContextImpl)evaluationContext.createEvaluationContext(array.getValue(idx)))) { + + DebuggerTreeNode arrayItemNode = + nodeManager + .createNode(descriptorFactory.getArrayItemDescriptor(builder.getParentDescriptor(), array, idx), evaluationContext); + + builder.addChildren(Collections.singletonList(arrayItemNode), false); + added++; + //if (added > ENTRIES_LIMIT) { + // break; + //} + } + } + catch (EvaluateException e) { + builder.addChildren(Collections.singletonList(nodeManager.createMessageNode(e.getMessage())), false); + } + } + } + + builder.addChildren(Collections.emptyList(), true); + + //if (added != 0 && END_INDEX < arrayLength - 1) { + // builder.setRemaining(arrayLength - 1 - END_INDEX); + //} + } + } + } } diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 8a00a00164e3..1db5418420c7 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -1052,6 +1052,7 @@ action.XDebugger.ToggleSortValues.description=Sort values alphabetically in debu group.XDebugger.settings.text=Settings action.Debugger.AdjustArrayRange.text=Adjust Range... +action.Debugger.FilterArray.text=Filter... action.Debugger.Inspect.text=Inspect action.Debugger.CopyValue.text=Copy Value action.Debugger.ViewEditText.text=View/Edit Text diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index 855a912153e2..7eda79209731 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -185,7 +185,10 @@ - + + + +