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 06198dc42e1..9ba6674669b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/stepping/KotlinSteppingCommandProvider.kt @@ -30,8 +30,8 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully 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.getLineNumber import org.jetbrains.kotlin.idea.core.refactoring.getLineStartOffset import org.jetbrains.kotlin.idea.util.DebuggerUtils import org.jetbrains.kotlin.psi.* @@ -61,25 +61,116 @@ public class KotlinSteppingCommandProvider: JvmSteppingCommandProvider() { val inlinedArguments = getInlinedArgumentsIfAny(sourcePosition) if (inlinedArguments.isEmpty()) return null + if (inlinedArguments.any { it.shouldNotUseStepOver(sourcePosition.elementAt) }) { + return null + } + + val additionalElementsToSkip = sourcePosition.elementAt.getAdditionalElementsToSkip() + + val containingFunction = sourcePosition.elementAt.getParentOfType(false) + val startLineNumber = containingFunction?.getLineNumber(true) ?: return null + val endLineNumber = containingFunction?.getLineNumber(false) ?: return null + val linesRange = startLineNumber + 1..endLineNumber + 1 val locations = computedReferenceType.allLineLocations() - val countOfLinesInFile = file.getLineCount() + .dropWhile { it != location } + .drop(1) + .filter { it.method() == location.method() && it.lineNumber() in linesRange } + .dropWhile { it.lineNumber() == location.lineNumber() } - val nextLine = sourcePosition.line + 2 /* +1 - because of locations are counted from 1 and +1 - because we want next line */ + for (locationAtLine in locations) { + val lineNumber = locationAtLine.lineNumber() + val lineStartOffset = file.getLineStartOffset(lineNumber - 1) ?: continue + if (inlinedArguments.any { it.textRange.contains(lineStartOffset) }) continue + if (additionalElementsToSkip.any { it.textRange.contains(lineStartOffset) }) continue - for (lineNumber in nextLine..countOfLinesInFile) { - val locationAtLine = locations.firstOrNull { it.lineNumber() == lineNumber } - if (locationAtLine != null) { - val lineStartOffset = file.getLineStartOffset(lineNumber - 1) ?: continue - if (inlinedArguments.any { it.textRange.contains(lineStartOffset) }) continue + val elementAt = file.findElementAt(lineStartOffset) ?: continue - val elementAt = file.findElementAt(lineStartOffset) - val xPosition = XSourcePositionImpl.createByElement(elementAt) ?: return null + val xPosition = XSourcePositionImpl.createByElement(elementAt) ?: return null + return suspendContext.debugProcess.createRunToCursorCommand(suspendContext, xPosition, ignoreBreakpoints) + } - return suspendContext.debugProcess.createRunToCursorCommand(suspendContext, xPosition, ignoreBreakpoints) + return suspendContext.debugProcess.createStepOutCommand(suspendContext)!! + } + + private fun PsiElement.getAdditionalElementsToSkip(): List { + val result = arrayListOf() + val ifParent = getParentOfType(false) + if (ifParent != null) { + if (ifParent.then?.textRange?.contains(this.textRange) ?: false) { + ifParent.elseKeyword?.let { result.add(it) } + ifParent.`else`?.let { result.add(it) } + } + } + val tryParent = getParentOfType(false) + if (tryParent != null) { + val catchClause = getParentOfType(false) + if (catchClause != null) { + result.addAll(tryParent.catchClauses.filter { it != catchClause }) } } - return null + val whenEntry = getParentOfType(false) + if (whenEntry != null) { + if (whenEntry.expression?.textRange?.contains(this.textRange) ?: false) { + val whenParent = whenEntry.getParentOfType(false) + if (whenParent != null) { + result.addAll(whenParent.entries.filter { it != whenEntry }) + } + } + } + + return result + } + + private fun PsiElement.shouldNotUseStepOver(elementAt: PsiElement): Boolean { + val ifParent = getParentOfType(false) + if (ifParent != null) { + // if (inlineFunCall()) {...} + if (ifParent.condition?.textRange?.contains(this.textRange) ?: false) { + return true + } + + /* + if (...) inlineFunCall() + else inlineFunCall() + */ + val ifParentElementAt = elementAt.getParentOfType(false) + if (ifParentElementAt == null) { + if (ifParent.then?.textRange?.contains(this.textRange) ?: false) { + return true + } + if (ifParent.`else`?.textRange?.contains(this.textRange) ?: false) { + return true + } + } + } + + val tryParent = getParentOfType(false) + if (tryParent != null) { + /* try { inlineFunCall() } + catch()... + */ + if (tryParent.tryBlock.textRange?.contains(this.textRange) ?: false) { + return true + } + } + + val whenEntry = getParentOfType(false) + if (whenEntry != null) { + // inlineFunCall -> ... + if (whenEntry.conditions.any { it.textRange.contains(this.textRange) } ) { + return true + } + + // 1 == 2 -> inlineFunCall() + if (whenEntry.expression?.textRange?.contains(this.textRange) ?: false) { + val parentEntryElementAt = elementAt.getParentOfType(false) ?: return true + return parentEntryElementAt == whenEntry && + whenEntry.conditions.any { it.textRange.contains(elementAt.textRange) } + } + } + + return false } override fun getStepOutCommand(suspendContext: SuspendContextImpl?, stepSize: Int): DebugProcessImpl.ResumeCommand? { @@ -231,12 +322,12 @@ public class KotlinSteppingCommandProvider: JvmSteppingCommandProvider() { startOffset++ } - if (topMostElement == null) return emptyList() + if (topMostElement !is JetElement) return emptyList() val start = topMostElement.startOffset val end = topMostElement.endOffset - return CodeInsightUtils. + val allInlinedArguments = CodeInsightUtils. findElementsOfClassInRange(file, start, end, JetFunctionLiteral::class.java, JetNamedFunction::class.java) .filter { JetPsiUtil.getParentCallIfPresent(it as JetExpression) != null } .filterIsInstance() @@ -244,5 +335,16 @@ public class KotlinSteppingCommandProvider: JvmSteppingCommandProvider() { val context = it.analyze(BodyResolveMode.PARTIAL) InlineUtil.isInlinedArgument(it, context, false) } + + // It is necessary to check range because of multiline assign + var linesRange = lineNumber..lineNumber + return allInlinedArguments.filter { + val parentCall = JetPsiUtil.getParentCallIfPresent(it)!! + val shouldInclude = parentCall.getLineNumber() in linesRange + if (shouldInclude) { + linesRange = Math.min(linesRange.start, it.getLineNumber())..Math.max(linesRange.end, it.getLineNumber(false)) + } + shouldInclude + } } -} \ No newline at end of file +} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt index 6bae03e8baf..3f48380a840 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt @@ -302,6 +302,10 @@ fun PsiFile.getLineEndOffset(line: Int): Int? { return PsiDocumentManager.getInstance(project).getDocument(this)?.getLineEndOffset(line) } +fun PsiElement.getLineNumber(start: Boolean = true): Int { + return PsiDocumentManager.getInstance(project).getDocument(this.containingFile)?.getLineNumber(if (start) this.startOffset else this.endOffset) ?: 0 +} + 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/stepOverIfWithInline.out b/idea/testData/debugger/tinyApp/outs/stepOverIfWithInline.out new file mode 100644 index 00000000000..327d7a605b2 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stepOverIfWithInline.out @@ -0,0 +1,28 @@ +LineBreakpoint created at stepOverIfWithInline.kt:5 +!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! stepOverIfWithInline.StepOverIfWithInlinePackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stepOverIfWithInline.kt:5 +stepOverIfWithInline.kt:7 +stepOverIfWithInline.kt:11 +stepOverIfWithInline.kt:7 +stepOverIfWithInline.kt:15 +stepOverIfWithInline.kt:18 +stepOverIfWithInline.kt:15 +stepOverIfWithInline.kt:21 +stepOverIfWithInline.kt:41 +stepOverIfWithInline.kt:21 +stepOverIfWithInline.kt:24 +stepOverIfWithInline.kt:25 +stepOverIfWithInline.kt:24 +stepOverIfWithInline.kt:28 +stepOverIfWithInline.kt:41 +stepOverIfWithInline.kt:28 +stepOverIfWithInline.kt:32 +stepOverIfWithInline.kt:41 +stepOverIfWithInline.kt:32 +stepOverIfWithInline.kt:36 +stepOverIfWithInline.kt:32 +stepOverIfWithInline.kt:38 +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/stepOverInlineFunctionInReturn.out b/idea/testData/debugger/tinyApp/outs/stepOverInlineFunctionInReturn.out new file mode 100644 index 00000000000..12b56897142 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stepOverInlineFunctionInReturn.out @@ -0,0 +1,10 @@ +LineBreakpoint created at stepOverInlineFunctionInReturn.kt:9 +!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! stepOverInlineFunctionInReturn.StepOverInlineFunctionInReturnPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stepOverInlineFunctionInReturn.kt:9 +stepOverInlineFunctionInReturn.kt:10 +stepOverInlineFunctionInReturn.kt:4 +stepOverInlineFunctionInReturn.kt:5 +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/stepOverInlinedLambda.out b/idea/testData/debugger/tinyApp/outs/stepOverInlinedLambda.out index 87f04ec36de..c6a207cb179 100644 --- a/idea/testData/debugger/tinyApp/outs/stepOverInlinedLambda.out +++ b/idea/testData/debugger/tinyApp/outs/stepOverInlinedLambda.out @@ -11,7 +11,8 @@ stepOverInlinedLambda.kt:19 stepOverInlinedLambda.kt:20 stepOverInlinedLambda.kt:23 stepOverInlinedLambda.kt:29 -stepOverInlinedLambda.kt:30 +stepOverInlinedLambda.kt:31 +stepOverInlinedLambda.kt:32 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/stepOverTryCatchWithInline.out b/idea/testData/debugger/tinyApp/outs/stepOverTryCatchWithInline.out new file mode 100644 index 00000000000..a9e883e3d78 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stepOverTryCatchWithInline.out @@ -0,0 +1,22 @@ +LineBreakpoint created at stepOverTryCatchWithInline.kt:14 +!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! stepOverTryCatchWithInline.StepOverTryCatchWithInlinePackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stepOverTryCatchWithInline.kt:14 +stepOverTryCatchWithInline.kt:16 +stepOverTryCatchWithInline.kt:17 +stepOverTryCatchWithInline.kt:48 +stepOverTryCatchWithInline.kt:17 +stepOverTryCatchWithInline.kt:24 +stepOverTryCatchWithInline.kt:25 +stepOverTryCatchWithInline.kt:28 +stepOverTryCatchWithInline.kt:35 +stepOverTryCatchWithInline.kt:36 +stepOverTryCatchWithInline.kt:48 +stepOverTryCatchWithInline.kt:36 +stepOverTryCatchWithInline.kt:39 +stepOverTryCatchWithInline.kt:43 +stepOverTryCatchWithInline.kt:8 +stepOverTryCatchWithInline.kt:10 +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/stepOverWhenInReturn.out b/idea/testData/debugger/tinyApp/outs/stepOverWhenInReturn.out new file mode 100644 index 00000000000..1012c1ff7ae --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stepOverWhenInReturn.out @@ -0,0 +1,13 @@ +LineBreakpoint created at stepOverWhenInReturn.kt:10 +!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! stepOverWhenInReturn.StepOverWhenInReturnPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stepOverWhenInReturn.kt:10 +stepOverWhenInReturn.kt:11 +stepOverWhenInReturn.kt:17 +stepOverWhenInReturn.kt:11 +stepOverWhenInReturn.kt:10 +stepOverWhenInReturn.kt:4 +stepOverWhenInReturn.kt:5 +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/stepOverWhenWithInline.out b/idea/testData/debugger/tinyApp/outs/stepOverWhenWithInline.out new file mode 100644 index 00000000000..826a3a84f22 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stepOverWhenWithInline.out @@ -0,0 +1,48 @@ +LineBreakpoint created at stepOverWhenWithInline.kt:5 +!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! stepOverWhenWithInline.StepOverWhenWithInlinePackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stepOverWhenWithInline.kt:5 +stepOverWhenWithInline.kt:8 +stepOverWhenWithInline.kt:9 +stepOverWhenWithInline.kt:83 +stepOverWhenWithInline.kt:9 +stepOverWhenWithInline.kt:7 +stepOverWhenWithInline.kt:14 +stepOverWhenWithInline.kt:17 +stepOverWhenWithInline.kt:18 +stepOverWhenWithInline.kt:13 +stepOverWhenWithInline.kt:26 +stepOverWhenWithInline.kt:83 +stepOverWhenWithInline.kt:26 +stepOverWhenWithInline.kt:27 +stepOverWhenWithInline.kt:83 +stepOverWhenWithInline.kt:27 +stepOverWhenWithInline.kt:25 +stepOverWhenWithInline.kt:32 +stepOverWhenWithInline.kt:34 +stepOverWhenWithInline.kt:83 +stepOverWhenWithInline.kt:34 +stepOverWhenWithInline.kt:32 +stepOverWhenWithInline.kt:38 +stepOverWhenWithInline.kt:43 +stepOverWhenWithInline.kt:38 +stepOverWhenWithInline.kt:51 +stepOverWhenWithInline.kt:52 +stepOverWhenWithInline.kt:83 +stepOverWhenWithInline.kt:52 +stepOverWhenWithInline.kt:51 +stepOverWhenWithInline.kt:58 +stepOverWhenWithInline.kt:83 +stepOverWhenWithInline.kt:58 +stepOverWhenWithInline.kt:57 +stepOverWhenWithInline.kt:64 +stepOverWhenWithInline.kt:65 +stepOverWhenWithInline.kt:63 +stepOverWhenWithInline.kt:76 +stepOverWhenWithInline.kt:83 +stepOverWhenWithInline.kt:76 +stepOverWhenWithInline.kt:75 +stepOverWhenWithInline.kt:80 +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/stepOverIfWithInline.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverIfWithInline.kt new file mode 100644 index 00000000000..ad8ef39ba47 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverIfWithInline.kt @@ -0,0 +1,47 @@ +package stepOverIfWithInline + +fun main(args: Array) { + //Breakpoint! + val prop = 1 + // False with braces + val a = if (1 > 2) { + foo { test(1) } + } + else { + foo { test(1) } + } + + // False without braces + val b = if (1 > 2) + foo { test(1) } + else + foo { test(1) } + + // One line + val c = if (1 > 2) foo { test(1) } else foo { test(1) } + + // Else on next line, false + val d = if (1 > 2) foo { test(1) } + else foo { test(1) } + + // Else on next line, true + val e = if (1 < 2) foo { test(1) } + else foo { test(1) } + + // Inline function call in condition + val f = if (foo { test(1) } > 2) { + foo { test(1) } + } + else { + foo { test(1) } + } +} + +inline fun foo(f: () -> Int): Int { + val a = 1 + return f() +} + +fun test(i: Int) = 1 + +// STEP_OVER: 30 \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlineFunctionInReturn.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlineFunctionInReturn.kt new file mode 100644 index 00000000000..48e33e692aa --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlineFunctionInReturn.kt @@ -0,0 +1,22 @@ +package stepOverInlineFunctionInReturn + +fun main(args: Array) { + f() +} + +fun f(): Int { + //Breakpoint! + val a = 1 + return foo { + test(2) + } +} + +inline fun foo(f: () -> Int): Int { + val a = 1 + return f() +} + +fun test(i: Int) = 1 + +// STEP_OVER: 4 \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlinedLambda.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlinedLambda.kt index 6c20cbb5dde..c95bc259323 100644 --- a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlinedLambda.kt +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlinedLambda.kt @@ -27,6 +27,8 @@ fun main(args: Array) { }) val b = foo { test(1) } + + foo(fun (){ test(1) }) } inline fun foo(f: () -> Unit) { @@ -47,4 +49,4 @@ class A { fun test(i: Int) = 1 -// STEP_OVER: 11 \ No newline at end of file +// STEP_OVER: 13 \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverTryCatchWithInline.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverTryCatchWithInline.kt new file mode 100644 index 00000000000..da3f0b9be2d --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverTryCatchWithInline.kt @@ -0,0 +1,54 @@ +package stepOverTryCatchWithInline + +fun main(args: Array) { + try { + bar() + } + catch(e: Exception) { + val a = 1 + } +} + +fun bar() { + //Breakpoint! + val prop = 1 + // Try + try { + foo { test(1) } + } + catch(e: Exception) { + foo { test(1) } + } + + // Many catch clauses + try { + throw IllegalStateException() + } + catch(e: IllegalStateException) { + foo { test(1) } + } + catch(e: Exception) { + foo { test(1) } + } + + // exception in lambda + try { + foo { throw IllegalStateException() } + } + catch(e: Exception) { + foo { test(1) } + } + + // Exception without catch + foo { throw IllegalStateException() } + val prop2 = 1 +} + +inline fun foo(f: () -> Int): Int { + val a = 1 + return f() +} + +fun test(i: Int) = 1 + +// STEP_OVER: 30 \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverWhenInReturn.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverWhenInReturn.kt new file mode 100644 index 00000000000..5104422d798 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverWhenInReturn.kt @@ -0,0 +1,23 @@ +package stepOverWhenInReturn + +fun main(args: Array) { + whenInReturn() +} + +fun whenInReturn(): Int { + val a = 1 + //Breakpoint! + return when(a) { + 1 -> foo { 1 } + else -> 3 + } +} + +inline fun foo(f: () -> Int): Int { + val a = 1 + return f() +} + +fun test(i: Int) = 1 + +// STEP_OVER: 6 \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverWhenWithInline.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverWhenWithInline.kt new file mode 100644 index 00000000000..2d53fac668e --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverWhenWithInline.kt @@ -0,0 +1,89 @@ +package stepOverWhenWithInline + +fun main(args: Array) { + //Breakpoint! + val prop = 1 + // Break after second + val a = when { + 1 > 2 -> foo { test(1) } + 2 > 1 -> foo { test(1) } + else -> foo { test(1) } + } + + val b = when { + 1 > 2 -> { + foo { test(1) } + } + 2 > 1 -> { + foo { test(1) } + } + else -> { + foo { test(1) } + } + } + + val c = when { + foo { test(1) } > 2 -> 1 + 2 > foo { test(1) } -> 2 + else -> foo { test(1) } + } + + // When with expression + val a1 = when(prop) { + 2 -> foo { test(1) } + 1 -> foo { test(1) } + else -> foo { test(1) } + } + + val b1 = when(prop) { + 2 -> { + foo { test(1) } + } + 1 -> { + foo { test(1) } + } + else -> { + foo { test(1) } + } + } + + // Break after first + val c1 = when(prop) { + foo { test(1) } -> 1 + foo { test(2) } -> 2 + else -> foo { test(1) } + } + + val a2 = when { + 2 > 1 -> foo { test(1) } + 1 > 2 -> foo { test(1) } + else -> foo { test(1) } + } + + val b2 = when { + 2 > 1 -> { + foo { test(1) } + } + 1 > 2 -> { + foo { test(1) } + } + else -> { + foo { test(1) } + } + } + + val c2 = when { + 2 > foo { test(1) } -> 2 + foo { test(1) } > 2 -> 1 + else -> foo { test(1) } + } +} + +inline fun foo(f: () -> Int): Int { + val a = 1 + return f() +} + +fun test(i: Int) = i + +// STEP_OVER: 50 \ 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 28003635e60..043cf887104 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java @@ -343,6 +343,18 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { doStepOverTest(fileName); } + @TestMetadata("stepOverIfWithInline.kt") + public void testStepOverIfWithInline() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverIfWithInline.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("stepOverInlineFunctionInReturn.kt") + public void testStepOverInlineFunctionInReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlineFunctionInReturn.kt"); + doStepOverTest(fileName); + } + @TestMetadata("stepOverInlinedLambda.kt") public void testStepOverInlinedLambda() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverInlinedLambda.kt"); @@ -360,6 +372,24 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverSimpleFun.kt"); doStepOverTest(fileName); } + + @TestMetadata("stepOverTryCatchWithInline.kt") + public void testStepOverTryCatchWithInline() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverTryCatchWithInline.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("stepOverWhenInReturn.kt") + public void testStepOverWhenInReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverWhenInReturn.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("stepOverWhenWithInline.kt") + public void testStepOverWhenWithInline() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stepOverWhenWithInline.kt"); + doStepOverTest(fileName); + } } @TestMetadata("idea/testData/debugger/tinyApp/src/stepping/filters")