From 7655200f58293e5a30bf8b3cbb29ebadae374564 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Mon, 8 Jun 2015 12:05:07 +0300 Subject: [PATCH] IDEA-141134 Run to cursor does not work inside lambda --- .../debugger/engine/DebugProcessImpl.java | 24 +++++---- .../debugger/engine/JavaDebugProcess.java | 3 +- .../debugger/engine/PositionManagerImpl.java | 16 +++--- .../engine/RemappedSourcePosition.java | 18 +++---- .../debugger/impl/DebuggerSession.java | 7 +-- .../ui/breakpoints/BreakpointManager.java | 5 +- .../ui/breakpoints/RunToCursorBreakpoint.java | 51 +++++++++++++------ .../com/intellij/debugger/SourcePosition.java | 2 +- .../xdebugger/impl/XDebuggerUtilImpl.java | 4 +- 9 files changed, 77 insertions(+), 53 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 52d9ab2ed751..557d630ef8e9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -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() : "", 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() : "", + position.getLine()), null); } return runToCursorCommand; } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java index 30f778c159c6..23aceb88dd3a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java @@ -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 diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index 00acfce7396a..40fc9e5f203b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -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() { + @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; } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/RemappedSourcePosition.java b/java/debugger/impl/src/com/intellij/debugger/engine/RemappedSourcePosition.java index 79ce07d524a2..8fb462314bd9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/RemappedSourcePosition.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/RemappedSourcePosition.java @@ -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); diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java index 56299754bc26..cf471b99592d 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java @@ -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); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java index 07fef8cc5f2c..9da20781369e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java @@ -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 diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java index c970d691595b..52af16623eb7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java @@ -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() { + @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 diff --git a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java index ce8c831a75f3..5e5ae9251384 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java +++ b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java @@ -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++) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java index c8c81f08882c..cc2ba00f239f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java @@ -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