diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java index a565ad1713a..67758a7904a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java @@ -221,7 +221,7 @@ public class MethodInliner { if (invokeCall.lambdaInfo.getFunctionDescriptor().getValueParameters().isEmpty()) { // There won't be no parameters processing and line call can be left without actual instructions. - // Note: if function is called on the line with other instructions like 1 + foo() no will still be generated. + // Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated. visitInsn(Opcodes.NOP); } diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerClassNameProvider.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerClassNameProvider.kt index 8dc4c43a8b1..cff44ea3622 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerClassNameProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerClassNameProvider.kt @@ -47,6 +47,7 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall @@ -119,7 +120,12 @@ class DebuggerClassNameProvider(val myDebugProcess: DebugProcess, val scopes: Li when { element is KtFunctionLiteral -> { val asmType = CodegenBinding.asmTypeForAnonymousClass(typeMapper.bindingContext, element) - return CachedClassNames(asmType.internalName) + val className = asmType.internalName + + val inlineCallClassPatterns = inlineCallClassPatterns(typeMapper, element) + val names = listOf(className) + inlineCallClassPatterns + + return CachedClassNames(names) } element is KtAnonymousInitializer -> { // Class-object initializer @@ -159,14 +165,46 @@ class DebuggerClassNameProvider(val myDebugProcess: DebugProcess, val scopes: Li val inlinedCalls = findInlinedCalls(element, typeMapper.bindingContext) if (parentInternalName == null) return CachedClassNames(inlinedCalls) - return CachedClassNames(listOf(parentInternalName) + inlinedCalls) + val inlineCallPatterns = if (parent != null) inlineCallClassPatterns(typeMapper, parent) else emptyList() + return CachedClassNames((listOf(parentInternalName) + inlinedCalls + inlineCallPatterns).filterNotNull()) } } return CachedClassNames(getClassNameForFile(file)) } + private fun inlineCallClassPatterns(typeMapper: KotlinTypeMapper, element: KtElement): List { + val context = typeMapper.bindingContext + + val (inlineCall, functionLiteral) = runReadAction { + element.parents.filterIsInstance().map { + val lambdaExpression = it.parent as? KtLambdaExpression ?: return@map null + val ktCallExpression = + lambdaExpression.typedParent()?.typedParent()?.typedParent() ?: + lambdaExpression.typedParent()?.typedParent() ?: + return@map null + + ktCallExpression to it + }.lastOrNull { + it != null && isInlineCall(context, it.component1()) + } + } ?: return emptyList() + + val lexicalScope = context[BindingContext.LEXICAL_SCOPE, inlineCall] ?: return emptyList() + + val resolvedCall = runReadAction { inlineCall.getResolvedCall(context) } ?: return emptyList() + val inlineFunctionName = resolvedCall.resultingDescriptor.name + + val originalInternalClassName = CodegenBinding.asmTypeForAnonymousClass(typeMapper.bindingContext, functionLiteral).internalName + val ownerDescriptorName = lexicalScope.ownerDescriptor.name + + val mangledInternalClassName = originalInternalClassName.funPrefix() + (if (ownerDescriptorName.isSpecial) "\$\$special\$" else "$") + + InlineCodegenUtil.INLINE_TRANSFORMATION_SUFFIX + "$" + inlineFunctionName + + return listOf("$mangledInternalClassName*") + } + private fun getClassNameForClass(klass: KtClassOrObject, typeMapper: KotlinTypeMapper) = klass.readAction { getJvmInternalNameForImpl(typeMapper, it) } private fun getClassNameForFile(file: KtFile) = file.readAction { NoResolveFileClassesProvider.getFileClassInternalName(it) } @@ -329,14 +367,32 @@ class DebuggerClassNameProvider(val myDebugProcess: DebugProcess, val scopes: Li } private fun getArgumentExpression(it: ValueArgument) = (it.getArgumentExpression() as? KtLambdaExpression)?.functionLiteral ?: it.getArgumentExpression() +} - private fun String.substringIndex(): String { - if (lastIndexOf("$") < 0) return this +private fun isInlineCall(context: BindingContext, expr: KtCallExpression): Boolean { + val resolvedCall = expr.getResolvedCall(context) ?: return false + return InlineUtil.isInline(resolvedCall.resultingDescriptor) +} - val suffix = substringAfterLast("$") - if (suffix.all(Char::isDigit)) { - return substringBeforeLast("$") + "$" - } - return this +private inline fun PsiElement.typedParent(): T? = getStrictParentOfType() + +private fun String.funPrefix(): String { + if (lastIndexOf("$") < 0) return this + + val trimmed = trimEnd { it == '$' || it.isDigit() } // Can accidentally trim end of function name if it ends with a number + val nextDollarIndex = indexOf('$', startIndex = trimmed.length - 1) + + if (nextDollarIndex < 0) return this + + return this.substring(0, nextDollarIndex) +} + +private fun String.substringIndex(): String { + if (lastIndexOf("$") < 0) return this + + val suffix = substringAfterLast("$") + if (suffix.all(Char::isDigit)) { + return substringBeforeLast("$") + "$" } + return this } \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/outs/stopInInlineCallLocalFunLambda.out b/idea/testData/debugger/tinyApp/outs/stopInInlineCallLocalFunLambda.out new file mode 100644 index 00000000000..48c861b4adc --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInInlineCallLocalFunLambda.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInInlineCallLocalFunLambda.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! stopInInlineCallLocalFunLambda.StopInInlineCallLocalFunLambdaKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInInlineCallLocalFunLambda.kt:9 +stopInInlineCallLocalFunLambda.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/stopInInlinedInSpecialNamedFun.out b/idea/testData/debugger/tinyApp/outs/stopInInlinedInSpecialNamedFun.out new file mode 100644 index 00000000000..b6b202db518 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInInlinedInSpecialNamedFun.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInInlinedInSpecialNamedFun.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! stopInInlinedInSpecialNamedFun.StopInInlinedInSpecialNamedFunKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInInlinedInSpecialNamedFun.kt:10 +stopInInlinedInSpecialNamedFun.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/outs/stopInInlinedInSpecialNamedFunWithGet.out b/idea/testData/debugger/tinyApp/outs/stopInInlinedInSpecialNamedFunWithGet.out new file mode 100644 index 00000000000..20c7cc73ddd --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInInlinedInSpecialNamedFunWithGet.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInInlinedInSpecialNamedFunWithGet.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! stopInInlinedInSpecialNamedFunWithGet.StopInInlinedInSpecialNamedFunWithGetKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInInlinedInSpecialNamedFunWithGet.kt:10 +stopInInlinedInSpecialNamedFunWithGet.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/outs/stopInLambdaInlineCallLambda.out b/idea/testData/debugger/tinyApp/outs/stopInLambdaInlineCallLambda.out new file mode 100644 index 00000000000..899a10708a7 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInLambdaInlineCallLambda.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInLambdaInlineCallLambda.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! stopInLambdaInlineCallLambda.StopInLambdaInlineCallLambdaKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInLambdaInlineCallLambda.kt:9 +stopInLambdaInlineCallLambda.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/stopInLocalFunInlineCallLambda.out b/idea/testData/debugger/tinyApp/outs/stopInLocalFunInlineCallLambda.out new file mode 100644 index 00000000000..51bf7614524 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInLocalFunInlineCallLambda.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInLocalFunInlineCallLambda.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! stopInLocalFunInlineCallLambda.StopInLocalFunInlineCallLambdaKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInLocalFunInlineCallLambda.kt:9 +stopInLocalFunInlineCallLambda.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/stopInNonInlinedLambdaInInlineCallWithClosure.out b/idea/testData/debugger/tinyApp/outs/stopInNonInlinedLambdaInInlineCallWithClosure.out new file mode 100644 index 00000000000..4de293afe56 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInNonInlinedLambdaInInlineCallWithClosure.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInNonInlinedLambdaInInlineCallWithClosure.kt:8 +!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! stopInNonInlinedLambdaInInlineCallWithClosure.StopInNonInlinedLambdaInInlineCallWithClosureKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInNonInlinedLambdaInInlineCallWithClosure.kt:8 +stopInNonInlinedLambdaInInlineCallWithClosure.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/stopInNonInlinedLambdaInInlineCallWithoutClosure.out b/idea/testData/debugger/tinyApp/outs/stopInNonInlinedLambdaInInlineCallWithoutClosure.out new file mode 100644 index 00000000000..80a8f5c7169 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInNonInlinedLambdaInInlineCallWithoutClosure.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInNonInlinedLambdaInInlineCallWithoutClosure.kt:8 +!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! stopInNonInlinedLambdaInInlineCallWithoutClosure.StopInNonInlinedLambdaInInlineCallWithoutClosureKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInNonInlinedLambdaInInlineCallWithoutClosure.kt:8 +stopInNonInlinedLambdaInInlineCallWithoutClosure.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/stopInObjectLiteralInInlineCallNoClosure.out b/idea/testData/debugger/tinyApp/outs/stopInObjectLiteralInInlineCallNoClosure.out new file mode 100644 index 00000000000..2a28b78dcd1 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInObjectLiteralInInlineCallNoClosure.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInObjectLiteralInInlineCallNoClosure.kt:12 +!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! stopInObjectLiteralInInlineCallNoClosure.StopInObjectLiteralInInlineCallNoClosureKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInObjectLiteralInInlineCallNoClosure.kt:12 +stopInObjectLiteralInInlineCallNoClosure.kt:13 +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/stopInObjectLiteralInInlineCallWithClosure.out b/idea/testData/debugger/tinyApp/outs/stopInObjectLiteralInInlineCallWithClosure.out new file mode 100644 index 00000000000..a8b60b1cb79 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stopInObjectLiteralInInlineCallWithClosure.out @@ -0,0 +1,8 @@ +LineBreakpoint created at stopInObjectLiteralInInlineCallWithClosure.kt:12 +!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! stopInObjectLiteralInInlineCallWithClosure.StopInObjectLiteralInInlineCallWithClosureKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stopInObjectLiteralInInlineCallWithClosure.kt:12 +stopInObjectLiteralInInlineCallWithClosure.kt:13 +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/stopInInlineCallLocalFunLambda.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlineCallLocalFunLambda.kt new file mode 100644 index 00000000000..83ac623190c --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlineCallLocalFunLambda.kt @@ -0,0 +1,21 @@ +package stopInInlineCallLocalFunLambda + +fun main(args: Array) { + var prop = 1 + inlineFun { + fun local() { + { + //Breakpoint! + foo(12) + }() + } + + local() + } +} + +inline fun inlineFun(f: () -> Unit) { + f() +} + +fun foo(a: Any) {} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlinedInSpecialNamedFun.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlinedInSpecialNamedFun.kt new file mode 100644 index 00000000000..ba12fce6139 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlinedInSpecialNamedFun.kt @@ -0,0 +1,24 @@ +package stopInInlinedInSpecialNamedFun + +// KT-12470 + +class Foo(bar: Bar) { + init { + with(bar) { + { + //Breakpoint! + nop() + nop() + }() + } + } + + fun nop() {} +} + +fun main(args: Array) { + Foo(Bar()) +} + +class Bar + diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlinedInSpecialNamedFunWithGet.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlinedInSpecialNamedFunWithGet.kt new file mode 100644 index 00000000000..8f137c6f973 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlinedInSpecialNamedFunWithGet.kt @@ -0,0 +1,28 @@ +package stopInInlinedInSpecialNamedFunWithGet + +// KT-12470 + +class Foo(bar: Bar) { + init { + with(bar) { + get { + //Breakpoint! + nop() + nop() + } + } + } + + private fun nop() {} +} + +fun main(args: Array) { + Foo(Bar()) +} + +class Bar +class BarContext + +inline fun Bar.get(noinline body: BarContext.() -> Unit) { + BarContext().body() +} diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLambdaInlineCallLambda.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLambdaInlineCallLambda.kt new file mode 100644 index 00000000000..e7bbf0676b7 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLambdaInlineCallLambda.kt @@ -0,0 +1,19 @@ +package stopInLambdaInlineCallLambda + +fun main(args: Array) { + var prop = 1 + { + inlineFun { + { + //Breakpoint! + foo(12) + }() + } + }() +} + +inline fun inlineFun(f: () -> Unit) { + f() +} + +fun foo(a: Any) {} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLocalFunInlineCallLambda.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLocalFunInlineCallLambda.kt new file mode 100644 index 00000000000..901a0ea0cce --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLocalFunInlineCallLambda.kt @@ -0,0 +1,21 @@ +package stopInLocalFunInlineCallLambda + +fun main(args: Array) { + var prop = 1 + fun local() { + inlineFun { + { + //Breakpoint! + foo(12) + }() + } + } + + local() +} + +inline fun inlineFun(f: () -> Unit) { + f() +} + +fun foo(a: Any) {} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInNonInlinedLambdaInInlineCallWithClosure.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInNonInlinedLambdaInInlineCallWithClosure.kt new file mode 100644 index 00000000000..23e176ba51d --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInNonInlinedLambdaInInlineCallWithClosure.kt @@ -0,0 +1,22 @@ +package stopInNonInlinedLambdaInInlineCallWithClosure + +fun main(args: Array) { + var prop = 1 + inlineFun { + notInlineFun { + //Breakpoint! + foo(prop) + foo(prop) + } + } +} + +inline fun inlineFun(f: () -> Unit) { + f() +} + +fun notInlineFun(f: () -> Unit) { + f() +} + +fun foo(a: Any) {} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInNonInlinedLambdaInInlineCallWithoutClosure.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInNonInlinedLambdaInInlineCallWithoutClosure.kt new file mode 100644 index 00000000000..3a9ff9276ca --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInNonInlinedLambdaInInlineCallWithoutClosure.kt @@ -0,0 +1,21 @@ +package stopInNonInlinedLambdaInInlineCallWithoutClosure + +fun main(args: Array) { + var prop = 1 + inlineFun { + notInlineFun { + //Breakpoint! + foo(12) + } + } +} + +inline fun inlineFun(f: () -> Unit) { + f() +} + +fun notInlineFun(f: () -> Unit) { + f() +} + +fun foo(a: Any) {} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInObjectLiteralInInlineCallNoClosure.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInObjectLiteralInInlineCallNoClosure.kt new file mode 100644 index 00000000000..20aade7f078 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInObjectLiteralInInlineCallNoClosure.kt @@ -0,0 +1,23 @@ +package stopInObjectLiteralInInlineCallNoClosure + +// KT-12734 + +fun main(args: Array) { + val a = 12 + + inlineF { + val s = object: () -> Unit { + override fun invoke() { + //Breakpoint! + nop() + nop() + } + } + + s() + } +} + +inline fun inlineF(block: () -> R): R = block() + +fun nop() {} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInObjectLiteralInInlineCallWithClosure.kt b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInObjectLiteralInInlineCallWithClosure.kt new file mode 100644 index 00000000000..e88d1703419 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInObjectLiteralInInlineCallWithClosure.kt @@ -0,0 +1,23 @@ +package stopInObjectLiteralInInlineCallWithClosure + +// KT-12734 + +fun main(args: Array) { + val a = 12 + + inlineF { + val s = object: () -> Unit { + override fun invoke() { + //Breakpoint! + nop(a) + nop(a) + } + } + + s() + } +} + +inline fun inlineF(block: () -> R): R = block() + +fun nop(a: Any) {} \ 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 44f29fdc67b..3b32c17a20f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java @@ -704,6 +704,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { doStepOverTest(fileName); } + @TestMetadata("stopInInlineCallLocalFunLambda.kt") + public void testStopInInlineCallLocalFunLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlineCallLocalFunLambda.kt"); + doStepOverTest(fileName); + } + @TestMetadata("stopInInlineFunDex.kt") public void testStopInInlineFunDex() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlineFunDex.kt"); @@ -722,11 +728,59 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { doStepOverTest(fileName); } + @TestMetadata("stopInInlinedInSpecialNamedFun.kt") + public void testStopInInlinedInSpecialNamedFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlinedInSpecialNamedFun.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("stopInInlinedInSpecialNamedFunWithGet.kt") + public void testStopInInlinedInSpecialNamedFunWithGet() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlinedInSpecialNamedFunWithGet.kt"); + doStepOverTest(fileName); + } + @TestMetadata("stopInLabdaOfCrossinlineCalledInAnonymous.kt") public void testStopInLabdaOfCrossinlineCalledInAnonymous() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLabdaOfCrossinlineCalledInAnonymous.kt"); doStepOverTest(fileName); } + + @TestMetadata("stopInLambdaInlineCallLambda.kt") + public void testStopInLambdaInlineCallLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLambdaInlineCallLambda.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("stopInLocalFunInlineCallLambda.kt") + public void testStopInLocalFunInlineCallLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLocalFunInlineCallLambda.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("stopInNonInlinedLambdaInInlineCallWithClosure.kt") + public void testStopInNonInlinedLambdaInInlineCallWithClosure() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInNonInlinedLambdaInInlineCallWithClosure.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("stopInNonInlinedLambdaInInlineCallWithoutClosure.kt") + public void testStopInNonInlinedLambdaInInlineCallWithoutClosure() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInNonInlinedLambdaInInlineCallWithoutClosure.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("stopInObjectLiteralInInlineCallNoClosure.kt") + public void testStopInObjectLiteralInInlineCallNoClosure() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInObjectLiteralInInlineCallNoClosure.kt"); + doStepOverTest(fileName); + } + + @TestMetadata("stopInObjectLiteralInInlineCallWithClosure.kt") + public void testStopInObjectLiteralInInlineCallWithClosure() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInObjectLiteralInInlineCallWithClosure.kt"); + doStepOverTest(fileName); + } } @TestMetadata("idea/testData/debugger/tinyApp/src/stepping/filters")