diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java index 5523463d8359..abc33f354eb9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java @@ -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); 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 2fc76a81c778..4ac0d804db65 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 @@ -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() { + @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;