IDEA-141134 Run to cursor does not work inside lambda
authorEgor.Ushakov <egor.ushakov@jetbrains.com>
Mon, 8 Jun 2015 09:05:07 +0000 (12:05 +0300)
committerEgor.Ushakov <egor.ushakov@jetbrains.com>
Mon, 8 Jun 2015 09:06:26 +0000 (12:06 +0300)
java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java
java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java
java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java
java/debugger/impl/src/com/intellij/debugger/engine/RemappedSourcePosition.java
java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java
java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java
java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java

index 52d9ab2ed75168fcd5fca1ef9bc64110d682507f..557d630ef8e9f51e1c8e3bc2852cb75efc09344c 100644 (file)
@@ -50,7 +50,6 @@ import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
@@ -61,8 +60,8 @@ import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.wm.ToolWindowId;
 import com.intellij.openapi.wm.impl.status.StatusBarUtil;
 import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.ui.classFilter.ClassFilter;
 import com.intellij.ui.classFilter.DebuggerClassFilterProvider;
@@ -74,6 +73,7 @@ import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashMap;
 import com.intellij.util.ui.UIUtil;
 import com.intellij.xdebugger.XDebugSession;
+import com.intellij.xdebugger.XSourcePosition;
 import com.intellij.xdebugger.impl.XDebugSessionImpl;
 import com.intellij.xdebugger.impl.actions.XDebuggerActions;
 import com.sun.jdi.*;
@@ -1569,11 +1569,11 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
     private final RunToCursorBreakpoint myRunToCursorBreakpoint;
     private final boolean myIgnoreBreakpoints;
 
-    private RunToCursorCommand(SuspendContextImpl suspendContext, Document document, int lineIndex, final boolean ignoreBreakpoints) {
+    private RunToCursorCommand(SuspendContextImpl suspendContext, @NotNull XSourcePosition position, final boolean ignoreBreakpoints) {
       super(suspendContext);
       myIgnoreBreakpoints = ignoreBreakpoints;
-      final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager();
-      myRunToCursorBreakpoint = breakpointManager.addRunToCursorBreakpoint(document, lineIndex, ignoreBreakpoints);
+      BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager();
+      myRunToCursorBreakpoint = breakpointManager.addRunToCursorBreakpoint(position, ignoreBreakpoints);
     }
 
     @Override
@@ -2035,13 +2035,15 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
     return new StepIntoCommand(suspendContext, ignoreFilters, smartStepFilter, stepSize);
   }
 
-  public ResumeCommand createRunToCursorCommand(SuspendContextImpl suspendContext, Document document, int lineIndex,
-                                                            final boolean ignoreBreakpoints)
+  public ResumeCommand createRunToCursorCommand(SuspendContextImpl suspendContext,
+                                                @NotNull XSourcePosition position,
+                                                boolean ignoreBreakpoints)
     throws EvaluateException {
-    RunToCursorCommand runToCursorCommand = new RunToCursorCommand(suspendContext, document, lineIndex, ignoreBreakpoints);
-    if(runToCursorCommand.myRunToCursorBreakpoint == null) {
-      final PsiFile psiFile = PsiDocumentManager.getInstance(getProject()).getPsiFile(document);
-      throw new EvaluateException(DebuggerBundle.message("error.running.to.cursor.no.executable.code", psiFile != null? psiFile.getName() : "<No File>", lineIndex), null);
+    RunToCursorCommand runToCursorCommand = new RunToCursorCommand(suspendContext, position, ignoreBreakpoints);
+    if (runToCursorCommand.myRunToCursorBreakpoint == null) {
+      PsiFile psiFile = PsiManager.getInstance(myProject).findFile(position.getFile());
+      throw new EvaluateException(DebuggerBundle.message("error.running.to.cursor.no.executable.code", psiFile != null? psiFile.getName() : "<No File>",
+                                                         position.getLine()), null);
     }
     return runToCursorCommand;
   }
index 30f778c159c6d796f4522f3945a12bec48e35445..23aceb88dd3a218f05cfac0906ce3a44ee9bfc1b 100644 (file)
@@ -253,8 +253,7 @@ public class JavaDebugProcess extends XDebugProcess {
 
   @Override
   public void runToPosition(@NotNull XSourcePosition position) {
-    Document document = FileDocumentManager.getInstance().getDocument(position.getFile());
-    myJavaSession.runToCursor(document, position.getLine(), false);
+    myJavaSession.runToCursor(position, false);
   }
 
   @NotNull
index 00acfce7396ab27611324a3cc8d463739d739af6..40fc9e5f203bf6c9e145577009883ee5071cfd2a 100644 (file)
@@ -150,7 +150,7 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
       }
     }
 
-    Method method = location.method();
+    final Method method = location.method();
 
     if (psiFile instanceof PsiCompiledElement || lineNumber < 0) {
       final String methodSignature = method.signature();
@@ -195,7 +195,12 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
             return LambdaMethodFilter.getLambdaOrdinal(o1.method().name()) - LambdaMethodFilter.getLambdaOrdinal(o2.method().name());
           }
         });
-        lambdaOrdinal = lambdas.indexOf(location);
+        lambdaOrdinal = ContainerUtil.indexOf(lambdas, new Condition<Location>() {
+          @Override
+          public boolean value(Location location) {
+            return location.method().equals(method);
+          }
+        });
       }
     }
     return new JavaSourcePosition(sourcePosition, location.declaringType(), method, lambdaOrdinal);
@@ -226,10 +231,9 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
         else if ((method instanceof PsiMethod && myExpectedMethodName.equals(((PsiMethod)method).getName()))) {
           if (insideBody(element, ((PsiMethod)method).getBody())) return element;
         }
-        //else if (method instanceof PsiLambdaExpression && (myLambdaOrdinal < 0 || myLambdaOrdinal == lambdaOrdinal)
-        //         && LambdaMethodFilter.isLambdaName(myExpectedMethodName)) {
-        //  if (insideBody(element, ((PsiLambdaExpression)method).getBody())) return element;
-        //}
+        else if (method instanceof PsiLambdaExpression && LambdaMethodFilter.isLambdaName(myExpectedMethodName)) {
+          if (insideBody(element, ((PsiLambdaExpression)method).getBody())) return element;
+        }
       }
       return null;
     }
index 79ce07d524a28928eaebfa959f34317dfdec5504..8fb462314bd9db0e82af5ffb0e31edad009aafc9 100644 (file)
@@ -40,29 +40,27 @@ abstract class RemappedSourcePosition extends SourcePosition {
 
   @Override
   public PsiElement getElementAt() {
+    checkRemap();
     return myDelegate.getElementAt();
   }
 
   @Override
   public int getLine() {
-    int line = myDelegate.getLine();
+    checkRemap();
+    return myDelegate.getLine();
+  }
+
+  private void checkRemap() {
     if (!myMapped) {
       myMapped = true;
       myDelegate = mapDelegate(myDelegate);
-      return myDelegate.getLine();
     }
-    return line;
   }
 
   @Override
   public int getOffset() {
-    int offset = myDelegate.getOffset(); //document loaded here
-    if (!myMapped) {
-      myMapped = true;
-      myDelegate = mapDelegate(myDelegate);
-      return myDelegate.getOffset();
-    }
-    return offset;
+    checkRemap();
+    return myDelegate.getOffset();
   }
 
   public abstract SourcePosition mapDelegate(SourcePosition original);
index 56299754bc26327f8d5231e43929dcf791a4b98a..cf471b99592d6b35c8cf6ce2c890201e68289d80 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -59,6 +59,7 @@ import com.intellij.util.TimeoutUtil;
 import com.intellij.util.ui.UIUtil;
 import com.intellij.xdebugger.AbstractDebuggerSession;
 import com.intellij.xdebugger.XDebugSession;
+import com.intellij.xdebugger.XSourcePosition;
 import com.intellij.xdebugger.impl.actions.XDebuggerActions;
 import com.intellij.xdebugger.impl.evaluate.quick.common.ValueLookupManager;
 import com.sun.jdi.ObjectCollectedException;
@@ -295,9 +296,9 @@ public class DebuggerSession implements AbstractDebuggerSession {
     stepInto(ignoreFilters, smartStepFilter, StepRequest.STEP_LINE);
   }
 
-  public void runToCursor(Document document, int line, final boolean ignoreBreakpoints) {
+  public void runToCursor(@NotNull XSourcePosition position, final boolean ignoreBreakpoints) {
     try {
-      DebugProcessImpl.ResumeCommand runToCursorCommand = myDebugProcess.createRunToCursorCommand(getSuspendContext(), document, line, ignoreBreakpoints);
+      DebugProcessImpl.ResumeCommand runToCursorCommand = myDebugProcess.createRunToCursorCommand(getSuspendContext(), position, ignoreBreakpoints);
       mySteppingThroughThreads.add(runToCursorCommand.getContextThread());
       resumeAction(runToCursorCommand, EVENT_STEP);
     }
index 07fef8cc5f2cd0568fde3e59e8345159d6705c8e..9da20781369efd9ac7fc9694e44bc76b02ec4077 100644 (file)
@@ -51,6 +51,7 @@ import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.xdebugger.XDebuggerManager;
 import com.intellij.xdebugger.XDebuggerUtil;
+import com.intellij.xdebugger.XSourcePosition;
 import com.intellij.xdebugger.breakpoints.*;
 import com.intellij.xdebugger.impl.DebuggerSupport;
 import com.intellij.xdebugger.impl.XDebugSessionImpl;
@@ -186,8 +187,8 @@ public class BreakpointManager {
   }
 
   @Nullable
-  public RunToCursorBreakpoint addRunToCursorBreakpoint(Document document, int lineIndex, final boolean ignoreBreakpoints) {
-    return RunToCursorBreakpoint.create(myProject, document, lineIndex, ignoreBreakpoints);
+  public RunToCursorBreakpoint addRunToCursorBreakpoint(@NotNull XSourcePosition position, final boolean ignoreBreakpoints) {
+    return RunToCursorBreakpoint.create(myProject, position, ignoreBreakpoints);
   }
 
   @Nullable
index c970d691595b086ee48bff6cfba4540fd42fc896..52af16623eb7807ae04460a9a504105864b26816 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,12 +17,15 @@ package com.intellij.debugger.ui.breakpoints;
 
 import com.intellij.debugger.SourcePosition;
 import com.intellij.debugger.engine.DebugProcessImpl;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Computable;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.xdebugger.XSourcePosition;
+import com.sun.jdi.Location;
+import com.sun.jdi.ReferenceType;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -116,17 +119,33 @@ public class RunToCursorBreakpoint extends LineBreakpoint {
     return false;  // always enabled
   }
 
-  @Nullable
-  protected static RunToCursorBreakpoint create(@NotNull Project project, @NotNull Document document, int lineIndex, boolean restoreBreakpoints) {
-    VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
-    if (virtualFile == null) {
-      return null;
-    }
-
-    PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
-    SourcePosition pos = SourcePosition.createFromLine(psiFile, lineIndex);
+  @Override
+  protected boolean acceptLocation(final DebugProcessImpl debugProcess, ReferenceType classType, final Location loc) {
+    if (!super.acceptLocation(debugProcess, classType, loc)) return false;
+    return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+      @Override
+      public Boolean compute() {
+        PsiElement expectedElement = myCustomPosition.getElementAt();
+        if (expectedElement != null) {
+          SourcePosition position = debugProcess.getPositionManager().getSourcePosition(loc);
+          if (position != null) {
+            PsiElement currentElement = position.getElementAt();
+            if (currentElement != null) {
+              NavigatablePsiElement expectedMethod = PsiTreeUtil.getParentOfType(expectedElement, PsiMethod.class, PsiLambdaExpression.class);
+              NavigatablePsiElement currentMethod = PsiTreeUtil.getParentOfType(currentElement, PsiMethod.class, PsiLambdaExpression.class);
+              return Comparing.equal(expectedMethod, currentMethod);
+            }
+          }
+        }
+        return true;
+      }
+    });
+  }
 
-    return new RunToCursorBreakpoint(project, pos, restoreBreakpoints);
+  @Nullable
+  protected static RunToCursorBreakpoint create(@NotNull Project project, @NotNull XSourcePosition position, boolean restoreBreakpoints) {
+    PsiFile psiFile = PsiManager.getInstance(project).findFile(position.getFile());
+    return new RunToCursorBreakpoint(project, SourcePosition.createFromOffset(psiFile, position.getOffset()), restoreBreakpoints);
   }
 
   @Override
index ce8c831a75f3d50019c76813b5c9f9397b94ebc0..5e5ae92513845c07b21291e68cdcaa57a7b406d3 100644 (file)
@@ -245,7 +245,7 @@ public abstract class SourcePosition implements Navigatable{
           }
 
           PsiElement element = null;
-          int offset = startOffset;
+          int offset = getOffset();
           while (true) {
             final CharSequence charsSequence = document.getCharsSequence();
             for (; offset < charsSequence.length(); offset++) {
index c8c81f08882cd843afa4ada4c04025914a6b4919..cc2ba00f239fdbd9f025c8e9b441f177869d356d 100644 (file)
@@ -187,9 +187,9 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
     if (editor == null) return null;
 
     final Document document = editor.getDocument();
-    final int line = editor.getCaretModel().getLogicalPosition().line;
+    int offset = editor.getCaretModel().getOffset();
     VirtualFile file = FileDocumentManager.getInstance().getFile(document);
-    return XSourcePositionImpl.create(file, line);
+    return XSourcePositionImpl.createByOffset(file, offset);
   }
 
   @NotNull