mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
match slot names only once
This commit is contained in:
@@ -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<DecompiledLocalVariable, Value> entry : LocalVariablesUtil.fetchValues(getStackFrameProxy()).entrySet()) {
|
||||
for (Map.Entry<DecompiledLocalVariable, Value> 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()) {
|
||||
|
||||
+7
-7
@@ -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<DecompiledLocalVariable, Value> vars = LocalVariablesUtil.fetchValues(frameProxy);
|
||||
Map<DecompiledLocalVariable, Value> vars = LocalVariablesUtil.fetchValues(frameProxy, process);
|
||||
for (Map.Entry<DecompiledLocalVariable, Value> entry : vars.entrySet()) {
|
||||
Collection<String> 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 */) {
|
||||
|
||||
+6
-2
@@ -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<ArgumentValueDescriptorImpl>{
|
||||
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) {
|
||||
|
||||
@@ -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<String> myMatchedNames;
|
||||
|
||||
public DecompiledLocalVariable(int slot, boolean isParam, @Nullable String signature) {
|
||||
public DecompiledLocalVariable(int slot, boolean isParam, @Nullable String signature, @NotNull Collection<String> 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<String> getMatchedNames() {
|
||||
return myMatchedNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName() + " (" + mySignature + ")";
|
||||
return getDisplayName() + " (slot " + mySlot + ", " + mySignature + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<DecompiledLocalVariable, Value> fetchValues(StackFrameProxyImpl frameProxy) throws Exception {
|
||||
public static Map<DecompiledLocalVariable, Value> fetchValues(StackFrameProxyImpl frameProxy, DebugProcess process) throws Exception {
|
||||
Map<DecompiledLocalVariable, Value> map = new LinkedHashMap<DecompiledLocalVariable, Value>(); // LinkedHashMap for correct order
|
||||
|
||||
// gather code variables names
|
||||
MultiMap<Integer, String> 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<DecompiledLocalVariable> vars = collectVariablesFromBytecode(frameProxy);
|
||||
List<DecompiledLocalVariable> 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<DecompiledLocalVariable> collectVariablesFromBytecode(final StackFrameProxyImpl frame) throws EvaluateException {
|
||||
private static List<DecompiledLocalVariable> collectVariablesFromBytecode(StackFrameProxyImpl frame,
|
||||
final MultiMap<Integer, String> 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<String> calcNames(@NotNull final StackFrameContext context, final int slotNumber) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Collection<String>>() {
|
||||
private static MultiMap<Integer, String> calcNames(@NotNull final StackFrameContext context) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<MultiMap<Integer, String>>() {
|
||||
@Override
|
||||
public Collection<String> compute() {
|
||||
public MultiMap<Integer, String> 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<Integer, String> res = new MultiMap<Integer, String>();
|
||||
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<String> res = new HashSet<String>();
|
||||
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<String> myNames;
|
||||
private final MultiMap<Integer, String> myNames;
|
||||
private int myCurrentSlotIndex;
|
||||
private final Stack<Integer> myIndexStack;
|
||||
private final int mySlotIndex;
|
||||
|
||||
public LocalVariableNameFinder(int slot, int startSlot, Set<String> names) {
|
||||
mySlotIndex = slot;
|
||||
public LocalVariableNameFinder(int startSlot, MultiMap<Integer, String> 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
|
||||
|
||||
+3
-20
@@ -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<String> 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;
|
||||
}
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user