From 0096f2668cba29fea051a800b19963cea943d840 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Wed, 9 Sep 2015 11:50:14 +0300 Subject: [PATCH] Fix step over if there isn't any inlined arguments --- .../stepping/KotlinSteppingCommandProvider.kt | 42 ++++++++++++------- .../idea/refactoring/jetRefactoringUtil.kt | 6 ++- .../tinyApp/outs/stepOverSimpleFun.out | 8 ++++ .../stepping/stepOver/stepOverSimpleFun.kt | 26 ++++++++++++ .../debugger/KotlinSteppingTestGenerated.java | 6 +++ 5 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 idea/testData/debugger/tinyApp/outs/stepOverSimpleFun.out create mode 100644 idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverSimpleFun.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt index b8f491ce8dd..06198dc42e1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt @@ -21,6 +21,7 @@ import com.intellij.debugger.engine.DebugProcessImpl import com.intellij.debugger.engine.SuspendContextImpl import com.intellij.debugger.engine.events.DebuggerCommandImpl import com.intellij.debugger.impl.JvmSteppingCommandProvider +import com.intellij.psi.PsiElement import com.intellij.util.concurrency.Semaphore import com.intellij.xdebugger.impl.XSourcePositionImpl import com.sun.jdi.Location @@ -30,6 +31,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils import org.jetbrains.kotlin.idea.core.refactoring.getLineCount +import org.jetbrains.kotlin.idea.core.refactoring.getLineEndOffset import org.jetbrains.kotlin.idea.core.refactoring.getLineStartOffset import org.jetbrains.kotlin.idea.util.DebuggerUtils import org.jetbrains.kotlin.psi.* @@ -56,7 +58,8 @@ public class KotlinSteppingCommandProvider: JvmSteppingCommandProvider() { val file = sourcePosition.file as? JetFile ?: return null - val inlinedArguments = getInlinedArgumentsIfAny(sourcePosition) ?: return null + val inlinedArguments = getInlinedArgumentsIfAny(sourcePosition) + if (inlinedArguments.isEmpty()) return null val locations = computedReferenceType.allLineLocations() val countOfLinesInFile = file.getLineCount() @@ -96,7 +99,7 @@ public class KotlinSteppingCommandProvider: JvmSteppingCommandProvider() { val nextLineLocations = locations.dropWhile { it.lineNumber() != location.lineNumber() }.filter { it.method() == location.method() } val inlineFunction = getInlineFunctionsIfAny(file, lineStartOffset) - if (inlineFunction != null) { + if (inlineFunction.isNotEmpty()) { val xPosition = suspendContext.getXPositionForStepOutFromInlineFunction(nextLineLocations, inlineFunction) ?: return null return suspendContext.debugProcess.createRunToCursorCommand(suspendContext, xPosition, true) } @@ -152,12 +155,12 @@ public class KotlinSteppingCommandProvider: JvmSteppingCommandProvider() { return null } - private fun getInlineFunctionsIfAny(file: JetFile, offset: Int): List? { - val elementAt = file.findElementAt(offset) ?: return null - val containingFunction = elementAt.getParentOfType(false) ?: return null + private fun getInlineFunctionsIfAny(file: JetFile, offset: Int): List { + val elementAt = file.findElementAt(offset) ?: return emptyList() + val containingFunction = elementAt.getParentOfType(false) ?: return emptyList() val descriptor = containingFunction.resolveToDescriptor() - if (!InlineUtil.isInline(descriptor)) return null + if (!InlineUtil.isInline(descriptor)) return emptyList() val inlineFunctionsCalls = DebuggerUtils.analyzeElementWithInline( containingFunction.getResolutionFacade(), @@ -211,16 +214,27 @@ public class KotlinSteppingCommandProvider: JvmSteppingCommandProvider() { return result } - private fun getInlinedArgumentsIfAny(sourcePosition: SourcePosition): List? { - val file = sourcePosition.file as? JetFile ?: return null + private fun getInlinedArgumentsIfAny(sourcePosition: SourcePosition): List { + val file = sourcePosition.file as? JetFile ?: return emptyList() val lineNumber = sourcePosition.line - val elementAt = CodeInsightUtils.getTopmostElementAtOffset( - sourcePosition.elementAt, - file.getLineStartOffset(lineNumber) ?: sourcePosition.elementAt.startOffset - ) ?: return null + var elementAt = sourcePosition.elementAt - val start = elementAt.startOffset - val end = elementAt.endOffset + var startOffset = file.getLineStartOffset(lineNumber) ?: elementAt.startOffset + var endOffset = file.getLineEndOffset(lineNumber) ?: elementAt.endOffset + + var topMostElement: PsiElement? = null + while (topMostElement !is JetElement && startOffset < endOffset) { + elementAt = file.findElementAt(startOffset) + if (elementAt != null) { + topMostElement = CodeInsightUtils.getTopmostElementAtOffset(elementAt, startOffset) + } + startOffset++ + } + + if (topMostElement == null) return emptyList() + + val start = topMostElement.startOffset + val end = topMostElement.endOffset return CodeInsightUtils. findElementsOfClassInRange(file, start, end, JetFunctionLiteral::class.java, JetNamedFunction::class.java) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt index 5df35ce0ffe..25643b82358 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt @@ -280,7 +280,7 @@ public class SelectionAwareScopeHighlighter(val editor: Editor) { } fun PsiFile.getLineStartOffset(line: Int): Int? { - val doc = this.let { file -> PsiDocumentManager.getInstance(getProject()).getDocument(file) } + val doc = PsiDocumentManager.getInstance(project).getDocument(this) if (doc != null) { val startOffset = doc.getLineStartOffset(line) val element = findElementAt(startOffset) ?: return startOffset @@ -291,6 +291,10 @@ fun PsiFile.getLineStartOffset(line: Int): Int? { return null } +fun PsiFile.getLineEndOffset(line: Int): Int? { + return PsiDocumentManager.getInstance(project).getDocument(this)?.getLineEndOffset(line) +} + fun PsiElement.getLineCount(): Int { val doc = getContainingFile()?.let { file -> PsiDocumentManager.getInstance(getProject()).getDocument(file) } if (doc != null) { diff --git a/idea/testData/debugger/tinyApp/outs/stepOverSimpleFun.out b/idea/testData/debugger/tinyApp/outs/stepOverSimpleFun.out new file mode 100644 index 00000000000..9c42be37172 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stepOverSimpleFun.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stepOverSimpleFun.kt:11 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! stepOverSimpleFun.StepOverSimpleFunPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stepOverSimpleFun.kt:11 +stepOverSimpleFun.kt:4 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverSimpleFun.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverSimpleFun.kt new file mode 100644 index 00000000000..849358ab5ef --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverSimpleFun.kt @@ -0,0 +1,26 @@ +package stepOverSimpleFun + +fun main(args: Array) { + foo(1) + val a = 1 +} + +fun foo(i: Int): Int { + if (i > 0) { + //Breakpoint! + return 1 + } + return 1 +} + +// Do not remove: kotlin strata should be available for this test +inline fun f(p: () -> Unit) { + val b = 1 + p() +} + +fun f2() { + f { + val b = 1 + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java index 5d48fd2fe35..a61cb27d9a4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java @@ -348,6 +348,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlinedLambdaStdlib.kt"); doStepOverTest(fileName); } + + @TestMetadata("stepOverSimpleFun.kt") + public void testStepOverSimpleFun() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverSimpleFun.kt"); + doStepOverTest(fileName); + } } @TestMetadata("idea/testData/debugger/tinyApp/src/stepping/filters")