IDEA-126257 JDK 1.8: Debugger doesn't show variables *outside* lambda - better check for found variable

This commit is contained in:
Egor.Ushakov
2015-08-14 17:23:28 +03:00
parent f8f1e4f512
commit 51853ca9a2
2 changed files with 46 additions and 23 deletions
@@ -628,7 +628,9 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
final String localName = psiVar.getName();
PsiClass variableClass = getContainingClass(psiVar);
if (getContextPsiClass() == null || getContextPsiClass().equals(variableClass)) {
final LocalVariableEvaluator localVarEvaluator = new LocalVariableEvaluator(localName, ContextUtil.isJspImplicit(element));
PsiElement method = PsiTreeUtil.getContextOfType(expression, PsiMethod.class, PsiLambdaExpression.class);
boolean canScanFrames = method instanceof PsiLambdaExpression || ContextUtil.isJspImplicit(element);
LocalVariableEvaluator localVarEvaluator = new LocalVariableEvaluator(localName, canScanFrames);
if (psiVar instanceof PsiParameter) {
final PsiParameter param = (PsiParameter)psiVar;
final PsiParameterList paramList = PsiTreeUtil.getParentOfType(param, PsiParameterList.class, true);
@@ -21,18 +21,27 @@
package com.intellij.debugger.engine.evaluation.expression;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.engine.LambdaMethodFilter;
import com.intellij.debugger.engine.DebugProcess;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.jdi.StackFrameProxy;
import com.intellij.debugger.impl.PositionUtil;
import com.intellij.debugger.impl.SimpleStackFrameContext;
import com.intellij.debugger.jdi.LocalVariableProxyImpl;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.ui.impl.watch.LocalVariableDescriptorImpl;
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiVariable;
import com.sun.jdi.*;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -42,12 +51,12 @@ class LocalVariableEvaluator implements Evaluator {
private final String myLocalVariableName;
private EvaluationContextImpl myContext;
private LocalVariableProxyImpl myEvaluatedVariable;
private final boolean myIsJspSpecial;
private final boolean myCanScanFrames;
private int myParameterIndex = -1;
public LocalVariableEvaluator(String localVariableName, boolean isJspSpecial) {
public LocalVariableEvaluator(String localVariableName, boolean canScanFrames) {
myLocalVariableName = localVariableName;
myIsJspSpecial = isJspSpecial;
myCanScanFrames = canScanFrames;
}
public void setParameterIndex(int parameterIndex) {
@@ -64,23 +73,27 @@ class LocalVariableEvaluator implements Evaluator {
try {
ThreadReferenceProxyImpl threadProxy = null;
int lastFrameIndex = -1;
PsiVariable variable = null;
boolean anotherFrame = false;
boolean topFrame = true;
while (true) {
try {
LocalVariableProxyImpl local = frameProxy.visibleVariableByName(myLocalVariableName);
if (local != null) {
myEvaluatedVariable = local;
myContext = context;
return frameProxy.getValue(local);
if (topFrame ||
variable.equals(resolveVariable(frameProxy, myLocalVariableName, context.getProject(), context.getDebugProcess()))) {
myEvaluatedVariable = local;
myContext = context;
return frameProxy.getValue(local);
}
}
}
catch (EvaluateException e) {
if (!(e.getCause() instanceof AbsentInformationException)) {
throw e;
}
if (!anotherFrame) {
if (topFrame) {
if (myParameterIndex < 0) {
throw e;
}
@@ -92,7 +105,11 @@ class LocalVariableEvaluator implements Evaluator {
}
}
if (anotherFrame || needToSwitchFrames(frameProxy)) {
if (myCanScanFrames) {
if (topFrame) {
variable = resolveVariable(frameProxy, myLocalVariableName, context.getProject(), context.getDebugProcess());
if (variable == null) break;
}
if (threadProxy == null /* initialize it lazily */) {
threadProxy = frameProxy.threadProxy();
lastFrameIndex = threadProxy.frameCount() - 1;
@@ -101,7 +118,7 @@ class LocalVariableEvaluator implements Evaluator {
if (currentFrameIndex < lastFrameIndex) {
frameProxy = threadProxy.frame(currentFrameIndex + 1);
if (frameProxy != null) {
anotherFrame = true;
topFrame = false;
continue;
}
}
@@ -118,17 +135,6 @@ class LocalVariableEvaluator implements Evaluator {
}
}
private boolean needToSwitchFrames(StackFrameProxyImpl frameProxy) {
if (myIsJspSpecial) return true;
try {
Location location = frameProxy.location();
if (location == null) return false;
return LambdaMethodFilter.isLambdaName(location.method().name());
}
catch (EvaluateException ignored) {}
return false;
}
@Override
public Modifier getModifier() {
Modifier modifier = null;
@@ -176,6 +182,21 @@ class LocalVariableEvaluator implements Evaluator {
return modifier;
}
@Nullable
private static PsiVariable resolveVariable(final StackFrameProxy frame,
final String name,
final Project project,
final DebugProcess process) {
return ApplicationManager.getApplication().runReadAction(new Computable<PsiVariable>() {
@Override
public PsiVariable compute() {
PsiElement place = PositionUtil.getContextElement(new SimpleStackFrameContext(frame, process));
if (place == null) return null;
return JavaPsiFacade.getInstance(project).getResolveHelper().resolveReferencedVariable(name, place);
}
});
}
@Override
public String toString() {
return myLocalVariableName;