From cd139bd5fd45545208488e05390f2ee5d83e301c Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Sun, 3 Nov 2013 21:54:22 +0100 Subject: [PATCH] ensure smart step into methods, whose first statement's line has no executable instructions mapped --- .../engine/AnonymousClassMethodFilter.java | 30 +++++++++++-------- .../engine/BreakpointStepMethodFilter.java | 5 ++++ .../debugger/engine/LambdaMethodFilter.java | 11 +++---- .../ui/breakpoints/StepIntoBreakpoint.java | 8 ++--- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/AnonymousClassMethodFilter.java b/java/debugger/impl/src/com/intellij/debugger/engine/AnonymousClassMethodFilter.java index 7d78cdb258cd..7f8436b3de69 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/AnonymousClassMethodFilter.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/AnonymousClassMethodFilter.java @@ -28,10 +28,25 @@ import org.jetbrains.annotations.Nullable; public class AnonymousClassMethodFilter extends BasicStepMethodFilter implements BreakpointStepMethodFilter{ @Nullable private final SourcePosition myBreakpointPosition; + private final int myLastStatementLine; public AnonymousClassMethodFilter(PsiMethod psiMethod) { super(psiMethod); - myBreakpointPosition = calcBreakpointPosition(psiMethod.getBody()); + SourcePosition firstStatementPosition = null; + SourcePosition lastStatementPosition = null; + final PsiCodeBlock body = psiMethod.getBody(); + if (body != null) { + final PsiStatement[] statements = body.getStatements(); + if (statements.length > 0) { + firstStatementPosition = SourcePosition.createFromElement(statements[0]); + if (firstStatementPosition != null) { + final PsiStatement lastStatement = statements[statements.length - 1]; + lastStatementPosition = SourcePosition.createFromOffset(firstStatementPosition.getFile(), lastStatement.getTextRange().getEndOffset()); + } + } + } + myBreakpointPosition = firstStatementPosition; + myLastStatementLine = lastStatementPosition != null? lastStatementPosition.getLine() : -1; } @Nullable @@ -39,16 +54,7 @@ public class AnonymousClassMethodFilter extends BasicStepMethodFilter implements return myBreakpointPosition; } - private static SourcePosition calcBreakpointPosition(final PsiCodeBlock body) { - if (body == null) { - return null; - } - final PsiStatement[] statements = body.getStatements(); - if (statements.length == 0) { - return null; - } - final PsiStatement firstStatement = statements[0]; - return SourcePosition.createFromElement(firstStatement); + public int getLastStatementLine() { + return myLastStatementLine; } - } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/BreakpointStepMethodFilter.java b/java/debugger/impl/src/com/intellij/debugger/engine/BreakpointStepMethodFilter.java index adfe975b8398..9c142ef2c0b6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/BreakpointStepMethodFilter.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/BreakpointStepMethodFilter.java @@ -25,4 +25,9 @@ import org.jetbrains.annotations.Nullable; public interface BreakpointStepMethodFilter extends MethodFilter{ @Nullable SourcePosition getBreakpointPosition(); + + /** + * @return a zero-based line number of the last lambda statement, or -1 if not available + */ + int getLastStatementLine(); } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/LambdaMethodFilter.java b/java/debugger/impl/src/com/intellij/debugger/engine/LambdaMethodFilter.java index 32669347eb81..b1aade45d096 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/LambdaMethodFilter.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/LambdaMethodFilter.java @@ -45,11 +45,11 @@ public class LambdaMethodFilter implements BreakpointStepMethodFilter{ final PsiElement body = lambda.getBody(); if (body instanceof PsiCodeBlock) { final PsiStatement[] statements = ((PsiCodeBlock)body).getStatements(); - final int statementCount = statements.length; - if (statementCount > 0) { + if (statements.length > 0) { firstStatementPosition = SourcePosition.createFromElement(statements[0]); - if (statementCount > 1) { - lastStatementPosition = SourcePosition.createFromElement(statements[statementCount - 1]); + if (firstStatementPosition != null) { + final PsiStatement lastStatement = statements[statements.length - 1]; + lastStatementPosition = SourcePosition.createFromOffset(firstStatementPosition.getFile(), lastStatement.getTextRange().getEndOffset()); } } } @@ -69,9 +69,6 @@ public class LambdaMethodFilter implements BreakpointStepMethodFilter{ return myFirstStatementPosition; } - /** - * @return a zero-based line number of the last lambda statement, or -1 if not available - */ public int getLastStatementLine() { return myLastStatementLine; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StepIntoBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StepIntoBreakpoint.java index afb5a684ffdd..6e39e5ac1d29 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StepIntoBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StepIntoBreakpoint.java @@ -55,10 +55,10 @@ public class StepIntoBreakpoint extends RunToCursorBreakpoint { final SourcePosition startPosition = getSourcePosition(); List locations = positionManager.locationsOfLine(classType, startPosition); - if (locations.isEmpty() && myFilter instanceof LambdaMethodFilter) { - // sometimes first statements are mapped to some weird line number, - // so if lambda spans for more than one lines, try get some locations from these lines - final int lastLine = ((LambdaMethodFilter)myFilter).getLastStatementLine(); + if (locations.isEmpty()) { + // sometimes first statements are mapped to some weird line number, or there are no executable instructions at first statement's line + // so if lambda or method body spans for more than one lines, try get some locations from these lines + final int lastLine = myFilter.getLastStatementLine(); if (lastLine >= 0) { int nextLine = startPosition.getLine() + 1; while (nextLine <= lastLine && locations.isEmpty()) {