diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/DebuggerSteppingHelper.java b/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/DebuggerSteppingHelper.java index 6d6a04daf61..5a29581705c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/DebuggerSteppingHelper.java +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/DebuggerSteppingHelper.java @@ -105,7 +105,7 @@ public class DebuggerSteppingHelper { try { StackFrameProxyImpl frameProxy = suspendContext.getFrameProxy(); if (frameProxy != null) { - Action action = KotlinSteppingCommandProviderKt.getStepOutPosition( + Action action = KotlinSteppingCommandProviderKt.getStepOutAction( frameProxy.location(), suspendContext, inlineFunctions, 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 b68c2827064..0710f7d64b1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt @@ -347,10 +347,25 @@ fun getStepOverPosition( } } + fun isBackEdgeLocation(): Boolean { + val previousSuitableLocation = computedReferenceType.allLineLocations().reversed() + .dropWhile { it != location } + .drop(1) + .filter(::isLocationSuitable) + .dropWhile { it.lineNumber() == location.lineNumber() } + .firstOrNull() + + return previousSuitableLocation != null && previousSuitableLocation.lineNumber() > location.lineNumber() + } + + if (isBackEdgeLocation()) { + return Action.STEP_OVER() + } + val locations = computedReferenceType.allLineLocations() .dropWhile { it != location } .drop(1) - .filter { isLocationSuitable(it) } + .filter(::isLocationSuitable) .dropWhile { it.lineNumber() == location.lineNumber() } for (locationAtLine in locations) { @@ -378,7 +393,7 @@ fun getStepOverPosition( return Action.STEP_OVER() } -fun getStepOutPosition( +fun getStepOutAction( location: Location, suspendContext: SuspendContextImpl, inlineFunctions: List, diff --git a/idea/testData/debugger/tinyApp/outs/asIterableInFor.out b/idea/testData/debugger/tinyApp/outs/asIterableInFor.out new file mode 100644 index 00000000000..4554c86e3d6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/asIterableInFor.out @@ -0,0 +1,11 @@ +LineBreakpoint created at asIterableInFor.kt:7 +!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! asIterableInFor.AsIterableInForKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +asIterableInFor.kt:7 +asIterableInFor.kt:8 +asIterableInFor.kt:9 +asIterableInFor.kt:8 +asIterableInFor.kt:9 +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/outs/inlineCallInForRangeExpression.out b/idea/testData/debugger/tinyApp/outs/inlineCallInForRangeExpression.out new file mode 100644 index 00000000000..99d30a814fe --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/inlineCallInForRangeExpression.out @@ -0,0 +1,13 @@ +LineBreakpoint created at inlineCallInForRangeExpression.kt:7 +!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! inlineCallInForRangeExpression.InlineCallInForRangeExpressionKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +inlineCallInForRangeExpression.kt:7 +inlineCallInForRangeExpression.kt:8 +inlineCallInForRangeExpression.kt:9 +inlineCallInForRangeExpression.kt:8 +inlineCallInForRangeExpression.kt:9 +inlineCallInForRangeExpression.kt:8 +inlineCallInForRangeExpression.kt:11 +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/asIterableInFor.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/asIterableInFor.kt new file mode 100644 index 00000000000..bf404fe9e7f --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/asIterableInFor.kt @@ -0,0 +1,15 @@ +package asIterableInFor + +fun nonInline(p: T): T = p + +fun main(args: Array) { + //Breakpoint! + val list = listOf("a", "b", "c") + for (element in list.asIterable()) { + nonInline(element) + } +} + +// STEP_OVER: 4 + +// Tests that last line will be "9", no "11". See KT-13534. diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/inlineCallInForRangeExpression.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/inlineCallInForRangeExpression.kt new file mode 100644 index 00000000000..8550bf90d06 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/inlineCallInForRangeExpression.kt @@ -0,0 +1,15 @@ +package inlineCallInForRangeExpression + +fun nonInline(p: T) = p + +fun main(args: Array) { + //Breakpoint! + nonInline(12) + for (e in range()) { + nonInline(e) + } +} + +inline fun range() = 1..2 + +// STEP_OVER: 6 \ 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 06f4f8b613c..f64fdaa7fce 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java @@ -373,6 +373,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/stepping/stepOver"), Pattern.compile("^([^.]+)\\.kt$"), true); } + @TestMetadata("asIterableInFor.kt") + public void testAsIterableInFor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/asIterableInFor.kt"); + doStepOverTest(fileName); + } + @TestMetadata("dexInlineInClass.kt") public void testDexInlineInClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/dexInlineInClass.kt"); @@ -403,6 +409,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { doStepOverTest(fileName); } + @TestMetadata("inlineCallInForRangeExpression.kt") + public void testInlineCallInForRangeExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/inlineCallInForRangeExpression.kt"); + doStepOverTest(fileName); + } + @TestMetadata("inlineFunctionSameLines.kt") public void testInlineFunctionSameLines() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/inlineFunctionSameLines.kt");