IDEA-126257 JDK 1.8: Debugger doesn't show variables *outside* lambda - better check...
authorEgor.Ushakov <egor.ushakov@jetbrains.com>
Fri, 14 Aug 2015 14:22:06 +0000 (17:22 +0300)
committerEgor.Ushakov <egor.ushakov@jetbrains.com>
Fri, 14 Aug 2015 14:23:28 +0000 (17:23 +0300)
java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java
java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java

index 5523463d8359b0251f99865cc535f3d2c7144b49..abc33f354eb9969c16beed9ec9a1900f8cbeee20 100644 (file)
@@ -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);
index 2fc76a81c778e7f1b386d29de19bd2289a3f78d2..4ac0d804db655cd817b77c4a8365e3b19595fbc8 100644 (file)
 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;