From 02a5ee5731d347dcde8ade4fdec2a4e918d7f3f2 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 16 Sep 2015 20:01:43 +0300 Subject: [PATCH] match slot names only once --- .../debugger/engine/JavaStackFrame.java | 13 ++-- .../expression/LocalVariableEvaluator.java | 14 ++--- .../impl/descriptors/data/ArgValueData.java | 8 ++- .../debugger/jdi/DecompiledLocalVariable.java | 38 ++++++++---- .../debugger/jdi/LocalVariablesUtil.java | 60 ++++++++++--------- .../watch/ArgumentValueDescriptorImpl.java | 23 +------ .../impl/watch/NodeDescriptorFactoryImpl.java | 4 +- 7 files changed, 81 insertions(+), 79 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java index 89e0af183275..3963d117e743 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java @@ -324,9 +324,11 @@ public class JavaStackFrame extends XStackFrame { children.add(new DummyMessageValueNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE.getLabel(), XDebuggerUIConstants.INFORMATION_MESSAGE_ICON)); // trying to collect values from variable slots try { - for (Map.Entry entry : LocalVariablesUtil.fetchValues(getStackFrameProxy()).entrySet()) { + for (Map.Entry entry : LocalVariablesUtil.fetchValues(getStackFrameProxy(), debugProcess).entrySet()) { DecompiledLocalVariable var = entry.getKey(); - children.add(createArgumentValue(var.getSlot(), entry.getValue(), var.isParam(), evaluationContext)); + children.add(JavaValue.create( + myNodeManager.getArgumentValueDescriptor(null, var.getSlot(), entry.getValue(), var.isParam(), var.getDisplayName()), + evaluationContext, myNodeManager)); } } catch (Exception ex) { @@ -389,13 +391,6 @@ public class JavaStackFrame extends XStackFrame { } } - private JavaValue createArgumentValue(int index, Value value, boolean isParam, EvaluationContextImpl evaluationContext) { - ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(null, index, value, isParam); - // setContext is required to calculate correct name - descriptor.setContext(evaluationContext); - return JavaValue.create(null, descriptor, evaluationContext, myNodeManager, true); - } - protected void superBuildVariables(final EvaluationContextImpl evaluationContext, XValueChildrenList children) throws EvaluateException { final StackFrameProxyImpl frame = getStackFrameProxy(); for (final LocalVariableProxyImpl local : frame.visibleVariables()) { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java index aec99ccbf7b8..13106ffc8eab 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java @@ -22,6 +22,7 @@ package com.intellij.debugger.engine.evaluation.expression; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.engine.DebugProcess; +import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; @@ -41,7 +42,6 @@ import com.intellij.psi.PsiVariable; import com.sun.jdi.*; import org.jetbrains.annotations.Nullable; -import java.util.Collection; import java.util.List; import java.util.Map; @@ -74,6 +74,7 @@ class LocalVariableEvaluator implements Evaluator { ThreadReferenceProxyImpl threadProxy = null; int lastFrameIndex = -1; PsiVariable variable = null; + DebugProcessImpl process = context.getDebugProcess(); boolean topFrame = true; @@ -82,7 +83,7 @@ class LocalVariableEvaluator implements Evaluator { LocalVariableProxyImpl local = frameProxy.visibleVariableByName(myLocalVariableName); if (local != null) { if (topFrame || - variable.equals(resolveVariable(frameProxy, myLocalVariableName, context.getProject(), context.getDebugProcess()))) { + variable.equals(resolveVariable(frameProxy, myLocalVariableName, context.getProject(), process))) { myEvaluatedVariable = local; myContext = context; return frameProxy.getValue(local); @@ -96,11 +97,10 @@ class LocalVariableEvaluator implements Evaluator { // try to look in slots try { - Map vars = LocalVariablesUtil.fetchValues(frameProxy); + Map vars = LocalVariablesUtil.fetchValues(frameProxy, process); for (Map.Entry entry : vars.entrySet()) { - Collection names = - LocalVariablesUtil.calcNames(new SimpleStackFrameContext(frameProxy, context.getDebugProcess()), entry.getKey().getSlot()); - if (names.contains(myLocalVariableName) || entry.getKey().getName().equals(myLocalVariableName)) { + DecompiledLocalVariable var = entry.getKey(); + if (var.getMatchedNames().contains(myLocalVariableName) || var.getDefaultName().equals(myLocalVariableName)) { return entry.getValue(); } } @@ -123,7 +123,7 @@ class LocalVariableEvaluator implements Evaluator { if (myCanScanFrames) { if (topFrame) { - variable = resolveVariable(frameProxy, myLocalVariableName, context.getProject(), context.getDebugProcess()); + variable = resolveVariable(frameProxy, myLocalVariableName, context.getProject(), process); if (variable == null) break; } if (threadProxy == null /* initialize it lazily */) { diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/descriptors/data/ArgValueData.java b/java/debugger/impl/src/com/intellij/debugger/impl/descriptors/data/ArgValueData.java index 159333bf7133..08240c8feccf 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/descriptors/data/ArgValueData.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/descriptors/data/ArgValueData.java @@ -19,21 +19,25 @@ import com.intellij.debugger.ui.impl.watch.ArgumentValueDescriptorImpl; import com.intellij.openapi.project.Project; import com.sun.jdi.Value; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class ArgValueData extends DescriptorData{ private final int myIndex; private final Value myValue; private final boolean myIsParam; + @Nullable + private final String myDisplayName; - public ArgValueData(int index, Value value, boolean isParam) { + public ArgValueData(int index, Value value, boolean isParam, @Nullable String displayName) { super(); myIndex = index; myValue = value; myIsParam = isParam; + myDisplayName = displayName; } protected ArgumentValueDescriptorImpl createDescriptorImpl(@NotNull Project project) { - return new ArgumentValueDescriptorImpl(project, myIndex, myValue, myIsParam); + return new ArgumentValueDescriptorImpl(project, myIndex, myValue, myIsParam, myDisplayName); } public boolean equals(Object object) { diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/DecompiledLocalVariable.java b/java/debugger/impl/src/com/intellij/debugger/jdi/DecompiledLocalVariable.java index 59dd07c3dc0e..bff5066eed86 100644 --- a/java/debugger/impl/src/com/intellij/debugger/jdi/DecompiledLocalVariable.java +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/DecompiledLocalVariable.java @@ -15,8 +15,11 @@ */ package com.intellij.debugger.jdi; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.Comparator; /** @@ -34,11 +37,13 @@ public class DecompiledLocalVariable{ private final int mySlot; private final String mySignature; private final boolean myIsParam; + private final Collection myMatchedNames; - public DecompiledLocalVariable(int slot, boolean isParam, @Nullable String signature) { + public DecompiledLocalVariable(int slot, boolean isParam, @Nullable String signature, @NotNull Collection names) { mySlot = slot; myIsParam = isParam; mySignature = signature; + myMatchedNames = names; } public int getSlot() { @@ -50,20 +55,33 @@ public class DecompiledLocalVariable{ return mySignature; } - public String getName() { - return getDefaultName(mySlot, myIsParam); - } - - public static String getDefaultName(int slot, boolean isParam) { - return isParam ? "arg_" + slot : "slot_" + slot; - } - public boolean isParam() { return myIsParam; } + @NotNull + public String getDefaultName() { + return myIsParam ? "arg_" + mySlot : "slot_" + mySlot; + } + + public String getDisplayName() { + String nameString = StringUtil.join(myMatchedNames, " | "); + if (myIsParam && myMatchedNames.size() == 1) { + return nameString; + } + else if (!myMatchedNames.isEmpty()) { + return nameString + ": " + getDefaultName(); + } + return getDefaultName(); + } + + @NotNull + public Collection getMatchedNames() { + return myMatchedNames; + } + @Override public String toString() { - return getName() + " (" + mySignature + ")"; + return getDisplayName() + " (slot " + mySlot + ", " + mySignature + ")"; } } diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/LocalVariablesUtil.java b/java/debugger/impl/src/com/intellij/debugger/jdi/LocalVariablesUtil.java index 88ddc2033656..f5757974ae46 100644 --- a/java/debugger/impl/src/com/intellij/debugger/jdi/LocalVariablesUtil.java +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/LocalVariablesUtil.java @@ -17,13 +17,16 @@ package com.intellij.debugger.jdi; import com.intellij.debugger.SourcePosition; import com.intellij.debugger.engine.ContextUtil; +import com.intellij.debugger.engine.DebugProcess; import com.intellij.debugger.engine.StackFrameContext; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.impl.DebuggerUtilsEx; +import com.intellij.debugger.impl.SimpleStackFrameContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Computable; import com.intellij.psi.*; +import com.intellij.util.containers.MultiMap; import com.sun.jdi.*; import org.jetbrains.annotations.NotNull; @@ -116,13 +119,17 @@ public class LocalVariablesUtil { ourInitializationOk = success; } - public static Map fetchValues(StackFrameProxyImpl frameProxy) throws Exception { + public static Map fetchValues(StackFrameProxyImpl frameProxy, DebugProcess process) throws Exception { Map map = new LinkedHashMap(); // LinkedHashMap for correct order + // gather code variables names + MultiMap namesMap = calcNames(new SimpleStackFrameContext(frameProxy, process)); + // first add arguments int slot = 0; for (Value value : frameProxy.getArgumentValues()) { - map.put(new DecompiledLocalVariable(slot++, true, null), value); + map.put(new DecompiledLocalVariable(slot, true, null, namesMap.get(slot)), value); + slot++; } if (!ourInitializationOk) { @@ -130,7 +137,7 @@ public class LocalVariablesUtil { } // now try to fetch stack values - List vars = collectVariablesFromBytecode(frameProxy); + List vars = collectVariablesFromBytecode(frameProxy, namesMap); StackFrame frame = frameProxy.getStackFrame(); int size = vars.size(); while (size > 0) { @@ -201,7 +208,8 @@ public class LocalVariablesUtil { } @NotNull - private static List collectVariablesFromBytecode(final StackFrameProxyImpl frame) throws EvaluateException { + private static List collectVariablesFromBytecode(StackFrameProxyImpl frame, + final MultiMap namesMap) throws EvaluateException { if (!frame.getVirtualMachine().canGetBytecodes()) { return Collections.emptyList(); } @@ -225,7 +233,7 @@ public class LocalVariablesUtil { if (slot >= firstLocalVariableSlot) { DecompiledLocalVariable variable = usedVars.get(slot); if (variable == null || !typeSignature.equals(variable.getSignature())) { - variable = new DecompiledLocalVariable(slot, false, typeSignature); + variable = new DecompiledLocalVariable(slot, false, typeSignature, namesMap.get(slot)); usedVars.put(slot, variable); } } @@ -250,49 +258,45 @@ public class LocalVariablesUtil { } @NotNull - public static Collection calcNames(@NotNull final StackFrameContext context, final int slotNumber) { - return ApplicationManager.getApplication().runReadAction(new Computable>() { + private static MultiMap calcNames(@NotNull final StackFrameContext context) { + return ApplicationManager.getApplication().runReadAction(new Computable>() { @Override - public Collection compute() { + public MultiMap compute() { SourcePosition position = ContextUtil.getSourcePosition(context); if (position != null) { PsiElement method = DebuggerUtilsEx.getContainingMethod(position.getElementAt()); if (method != null) { PsiParameterList params = DebuggerUtilsEx.getParameterList(method); if (params != null) { - if (slotNumber < params.getParametersCount()) { - return Collections.singleton(params.getParameters()[slotNumber].getName()); + MultiMap res = new MultiMap(); + for (int i = 0; i < params.getParametersCount(); i++) { + res.putValue(i, params.getParameters()[i].getName()); } - else { - PsiElement body = DebuggerUtilsEx.getBody(method); - if (body != null) { - Set res = new HashSet(); - try { - body.accept(new LocalVariableNameFinder(slotNumber, getFirstLocalsSlot(method), res)); - } - catch (Exception e) { - LOG.info(e); - } - return res; + PsiElement body = DebuggerUtilsEx.getBody(method); + if (body != null) { + try { + body.accept(new LocalVariableNameFinder(getFirstLocalsSlot(method), res)); + } + catch (Exception e) { + LOG.info(e); } } + return res; } } } - return Collections.emptyList(); + return MultiMap.empty(); } }); } private static class LocalVariableNameFinder extends JavaRecursiveElementVisitor { private final int myStartSlot; - private final Collection myNames; + private final MultiMap myNames; private int myCurrentSlotIndex; private final Stack myIndexStack; - private final int mySlotIndex; - public LocalVariableNameFinder(int slot, int startSlot, Set names) { - mySlotIndex = slot; + public LocalVariableNameFinder(int startSlot, MultiMap names) { myStartSlot = startSlot; myNames = names; myCurrentSlotIndex = myStartSlot; @@ -318,9 +322,7 @@ public class LocalVariablesUtil { } private void appendName(String varName) { - if (myCurrentSlotIndex == mySlotIndex) { - myNames.add(varName); - } + myNames.putValue(myCurrentSlotIndex, varName); } @Override diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java index bae4f126d017..d94c69efe377 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java @@ -20,10 +20,7 @@ import com.intellij.debugger.DebuggerContext; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.impl.PositionUtil; -import com.intellij.debugger.jdi.DecompiledLocalVariable; -import com.intellij.debugger.jdi.LocalVariablesUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiExpression; @@ -31,19 +28,17 @@ import com.intellij.util.IncorrectOperationException; import com.sun.jdi.PrimitiveValue; import com.sun.jdi.Value; -import java.util.Collection; - public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{ private final int myIndex; private final Value myValue; private String myName; private final boolean myIsParam; - public ArgumentValueDescriptorImpl(Project project, int index, Value value, boolean isParam) { - super(project); + public ArgumentValueDescriptorImpl(Project project, int index, Value value, boolean isParam, String displayName) { + super(project, value); myIndex = index; myValue = value; - myName = getDefaultName(); + myName = displayName; myIsParam = isParam; setLvalue(true); } @@ -58,21 +53,9 @@ public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{ } public Value calcValue(final EvaluationContextImpl evaluationContext) throws EvaluateException { - Collection names = LocalVariablesUtil.calcNames(evaluationContext, myIndex); - String nameString = StringUtil.join(names, " | "); - if (myIsParam && names.size() == 1) { - myName = nameString; - } - else if (!names.isEmpty()) { - myName = nameString + ": " + getDefaultName(); - } return myValue; } - private String getDefaultName() { - return DecompiledLocalVariable.getDefaultName(myIndex, myIsParam); - } - public String getName() { return myName; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorFactoryImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorFactoryImpl.java index f6a0120267ed..13eff617ed72 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorFactoryImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorFactoryImpl.java @@ -162,8 +162,8 @@ public class NodeDescriptorFactoryImpl implements NodeDescriptorFactory { return getDescriptor(parent, new LocalData((LocalVariableProxyImpl)local)); } - public ArgumentValueDescriptorImpl getArgumentValueDescriptor(NodeDescriptor parent, int index, Value value, boolean isParam) { - return getDescriptor(parent, new ArgValueData(index, value, isParam)); + public ArgumentValueDescriptorImpl getArgumentValueDescriptor(NodeDescriptor parent, int index, Value value, boolean isParam, String name) { + return getDescriptor(parent, new ArgValueData(index, value, isParam, name)); } public StackFrameDescriptorImpl getStackFrameDescriptor(@Nullable NodeDescriptorImpl parent, @NotNull StackFrameProxyImpl frameProxy) {