IDEA-141134 Run to cursor does not work inside lambda

This commit is contained in:
Egor.Ushakov
2015-06-08 12:06:26 +03:00
parent 5668313966
commit 7655200f58
9 changed files with 77 additions and 53 deletions
@@ -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;
}
@@ -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
@@ -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;
}
@@ -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);
@@ -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);
}
@@ -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
@@ -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
}
@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;
}
});
}
@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);
return new RunToCursorBreakpoint(project, pos, restoreBreakpoints);
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
@@ -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++) {