diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt index a634a30136f..b9c7b3ab7d7 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt @@ -5,12 +5,10 @@ package org.jetbrains.kotlin.backend.jvm.lower +import com.intellij.lang.jvm.source.JvmDeclarationSearch import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.ir.copyTo -import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor -import org.jetbrains.kotlin.backend.common.ir.isSuspend -import org.jetbrains.kotlin.backend.common.ir.moveBodyTo +import org.jetbrains.kotlin.backend.common.ir.* import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase @@ -29,12 +27,12 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -43,6 +41,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames +import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin internal val suspendLambdaPhase = makeIrFilePhase( ::SuspendLambdaLowering, @@ -191,7 +190,7 @@ private class SuspendLambdaLowering(context: JvmBackendContext) : SuspendLowerin } val invokeSuspend = addInvokeSuspendForLambda(function, suspendLambda, parametersFields) if (function.capturesCrossinline()) { - addInvokeSuspendForInlineForLambda(invokeSuspend) + addInvokeSuspendForInlineLambda(invokeSuspend) } if (createToOverride != null) { addInvokeCallingCreate(addCreate(constructor, createToOverride, parametersFields), invokeSuspend, invokeToOverride) @@ -209,19 +208,37 @@ private class SuspendLambdaLowering(context: JvmBackendContext) : SuspendLowerin it.valueParameters[0].type.isKotlinResult() } return addFunctionOverride(superMethod, irFunction.startOffset, irFunction.endOffset).apply { - body = irFunction.moveBodyTo(this, mapOf())?.transform(object : IrElementTransformerVoid() { - override fun visitGetValue(expression: IrGetValue): IrExpression { - val parameter = (expression.symbol.owner as? IrValueParameter)?.takeIf { it.parent == irFunction } - ?: return expression - val field = fields[parameter.index + if (irFunction.extensionReceiverParameter != null) 1 else 0] + val localVals: List = fields.mapIndexed { index, field -> + buildVariable( + parent = this, + startOffset = UNDEFINED_OFFSET, + endOffset = UNDEFINED_OFFSET, + origin = IrDeclarationOrigin.DEFINED, + name = field.name, + type = field.type + ).apply { val receiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter!!.symbol) - return IrGetFieldImpl(expression.startOffset, expression.endOffset, field.symbol, field.type, receiver) + val initializerBlock = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.type) + initializerBlock.statements += IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.symbol, field.type, receiver) + initializer = initializerBlock } - }, null) + } + + body = irFunction.moveBodyTo(this, mapOf())?.let { body -> + body.transform(object : IrElementTransformerVoid() { + override fun visitGetValue(expression: IrGetValue): IrExpression { + val parameter = (expression.symbol.owner as? IrValueParameter)?.takeIf { it.parent == irFunction } + ?: return expression + val lvar = localVals[parameter.index + if (irFunction.extensionReceiverParameter != null) 1 else 0] + return IrGetValueImpl(expression.startOffset, expression.endOffset, lvar.symbol) + } + }, null) + context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET, localVals + body.statements) + } } } - private fun IrClass.addInvokeSuspendForInlineForLambda(invokeSuspend: IrSimpleFunction): IrSimpleFunction { + private fun IrClass.addInvokeSuspendForInlineLambda(invokeSuspend: IrSimpleFunction): IrSimpleFunction { return addFunction( INVOKE_SUSPEND_METHOD_NAME + FOR_INLINE_SUFFIX, context.irBuiltIns.anyNType, diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/dataClass.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/dataClass.kt index 55270f96d5d..b4e53b487cf 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/dataClass.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/dataClass.kt @@ -11,21 +11,10 @@ suspend fun foo(data: Data, body: suspend (Data) -> Unit) { body(data) } -// Parameters (including anonymous destructuring parameters) are moved to fields in the Continuation class for the suspend lambda class. -// However, in non-IR, the fields are first stored in local variables, and they are not read directly (even for destructuring components). -// In IR, the fields are directly read from. - // METHOD : DataClassKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; -// JVM_TEMPLATES // VARIABLE : NAME=$dstr$x_param$y_param TYPE=LData; INDEX=2 // VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3 // VARIABLE : NAME=y_param TYPE=I INDEX=4 // VARIABLE : NAME=this TYPE=LDataClassKt$test$2; INDEX=0 // VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=1 - -// JVM_IR_TEMPLATES -// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=2 -// VARIABLE : NAME=y_param TYPE=I INDEX=3 -// VARIABLE : NAME=this TYPE=LDataClassKt$test$2; INDEX=0 -// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=1 diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/extensionComponents.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/extensionComponents.kt index 329c7a95838..0b83d31d4af 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/extensionComponents.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/extensionComponents.kt @@ -22,10 +22,6 @@ suspend fun test() = B.bar() // Local function bodies (i.e., `A.component3()`) are in a separate class (implementing FunctionN) for non-IR, and are static methods // in the enclosing class for IR. Therefore the ordinal in the suspend lambda class name is different for non-IR (`$3`) vs IR (e.g., `$2`). // -// Parameters (including anonymous destructuring parameters) are moved to fields in the Continuation class for the suspend lambda class. -// However, in non-IR, the fields are first stored in local variables, and they are not read directly (even for destructuring components). -// In IR, the fields are directly read from. - // JVM_TEMPLATES // METHOD : ExtensionComponentsKt$bar$3.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; // VARIABLE : NAME=$dstr$x_param$y_param$z_param TYPE=LA; INDEX=2 @@ -37,6 +33,7 @@ suspend fun test() = B.bar() // JVM_IR_TEMPLATES // METHOD : ExtensionComponentsKt$bar$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +// VARIABLE : NAME=$dstr$x_param$y_param$z_param TYPE=LA; INDEX=2 // VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=2 // VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=3 // VARIABLE : NAME=z_param TYPE=I INDEX=4 diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/generic.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/generic.kt index 128ad21f6ba..506636165ed 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/generic.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/generic.kt @@ -8,21 +8,10 @@ suspend fun test() = foo(A("OK", 1)) { (x_param, y_param) -> x_param + (y_param.toString()) } -// Parameters (including anonymous destructuring parameters) are moved to fields in the Continuation class for the suspend lambda class. -// However, in non-IR, the fields are first stored in local variables, and they are not read directly (even for destructuring components). -// In IR, the fields are directly read from. - // METHOD : GenericKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; -// JVM_TEMPLATES // VARIABLE : NAME=$dstr$x_param$y_param TYPE=LA; INDEX=2 // VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3 // VARIABLE : NAME=y_param TYPE=I INDEX=4 // VARIABLE : NAME=this TYPE=LGenericKt$test$2; INDEX=0 -// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=1 - -// JVM_IR_TEMPLATES -// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=2 -// VARIABLE : NAME=y_param TYPE=I INDEX=3 -// VARIABLE : NAME=this TYPE=LGenericKt$test$2; INDEX=0 -// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=1 +// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=1 \ No newline at end of file diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/otherParameters.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/otherParameters.kt index 6e9909a9254..94e6de609fa 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/otherParameters.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/otherParameters.kt @@ -7,13 +7,8 @@ suspend fun test() = foo(A("O", "K")) { i_param, (x_param, y_param), v_param -> i_param.toString() + x_param + y_param + v_param } -// Parameters (including anonymous destructuring parameters) are moved to fields in the Continuation class for the suspend lambda class. -// However, in non-IR, the fields are first stored in local variables, and they are not read directly (even for destructuring components). -// In IR, the fields are directly read from. - // METHOD : OtherParametersKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; -// JVM_TEMPLATES // VARIABLE : NAME=i_param TYPE=I INDEX=2 // VARIABLE : NAME=$dstr$x_param$y_param TYPE=LA; INDEX=3 // VARIABLE : NAME=v_param TYPE=Ljava/lang/String; INDEX=4 @@ -21,9 +16,3 @@ suspend fun test() = foo(A("O", "K")) { i_param, (x_param, y_param), v_param -> // VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=6 // VARIABLE : NAME=this TYPE=LOtherParametersKt$test$2; INDEX=0 // VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=1 - -// JVM_IR_TEMPLATES -// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=2 -// VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=3 -// VARIABLE : NAME=this TYPE=LOtherParametersKt$test$2; INDEX=0 -// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=1 diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt index 3572a208fe1..964126eeb98 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt @@ -11,9 +11,7 @@ suspend fun foo(data: Data, body: suspend Long.(String, Data, Int) -> Unit) { 1L.body("OK", data, 1) } -// Parameters (including anonymous destructuring parameters) are moved to fields in the Continuation class for the suspend lambda class. -// However, in non-IR, the fields are first stored in local variables, and they are not read directly (even for destructuring components). -// In IR, the fields are directly read from. +// The JVM and IR backend differ in naming scheme of captured receiver paramters in suspend lambdas // METHOD : ParametersKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; @@ -28,7 +26,11 @@ suspend fun foo(data: Data, body: suspend Long.(String, Data, Int) -> Unit) { // VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=1 // JVM_IR_TEMPLATES -// VARIABLE : NAME=x TYPE=Ljava/lang/String; INDEX=2 -// VARIABLE : NAME=z TYPE=I INDEX=3 -// VARIABLE : NAME=this TYPE=LParametersKt$test$2; INDEX=0 -// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=1 +// VARIABLE : NAME=$dstr$x$_u24__u24$z TYPE=LData; INDEX=* +// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=* +// VARIABLE : NAME=i TYPE=I INDEX=* +// VARIABLE : NAME=p$ TYPE=J INDEX=* +// VARIABLE : NAME=str TYPE=Ljava/lang/String; INDEX=* +// VARIABLE : NAME=this TYPE=LParametersKt$test$2; INDEX=* +// VARIABLE : NAME=x TYPE=Ljava/lang/String; INDEX=* +// VARIABLE : NAME=z TYPE=I INDEX=* \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/coroutines/debug/localVariableCorrectLabel.kt b/compiler/testData/codegen/bytecodeText/coroutines/debug/localVariableCorrectLabel.kt index cb2b95ee703..b10d4d2438d 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/debug/localVariableCorrectLabel.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/debug/localVariableCorrectLabel.kt @@ -14,14 +14,12 @@ fun main(args: Array) { @BuilderInference suspend fun SequenceScope.awaitSeq(): Int = 42 -// label numbers differ in BEs -// JVM_TEMPLATES // 1 LOCALVARIABLE a I L[0-9]+ L18 -// 1 LINENUMBER 9 L19 /* TODO: JVM_IR does not generate LINENUMBER at the end of the lambda */ -// JVM_IR_TEMPLATES -// 1 LOCALVARIABLE a I L[0-9]+ L16 +// JVM_TEMPLATES +// 1 LINENUMBER 9 L19 + // IGNORE_BACKEND_FIR: JVM_IR diff --git a/compiler/testData/debug/localVariables/suspend/underscoreNames.kt b/compiler/testData/debug/localVariables/suspend/underscoreNames.kt index 728452ff7c3..1fc7379a13e 100644 --- a/compiler/testData/debug/localVariables/suspend/underscoreNames.kt +++ b/compiler/testData/debug/localVariables/suspend/underscoreNames.kt @@ -13,13 +13,8 @@ suspend fun box() = foo(A()) { (x_param, _, y_param) -> x_param + y_param } -// Parameters (including anonymous destructuring parameters) are moved to fields in the Continuation class for the suspend lambda class. -// However, in non-IR, the fields are first stored in local variables, and they are not read directly (even for destructuring components). -// In IR, the fields are directly read from. +// TODO: The backends disagree on the local variables in invoke/invokeSuspend methods -// The local variable for destructuring suspend lambda arguments, in this case -// `$dstr$x_param$_u24__u24$y_param`, is moved to a field in the IR backend, -// so does not figure in the LVT. // LOCAL VARIABLES // test.kt:12 box: $completion:kotlin.coroutines.Continuation=helpers.ResultContinuation @@ -41,16 +36,14 @@ suspend fun box() = foo(A()) { (x_param, _, y_param) -> // LOCAL VARIABLES // test.kt:12 invokeSuspend: // test.kt:5 component1: +// test.kt:12 invokeSuspend: $result:java.lang.Object=kotlin.Unit, $dstr$x_param$_u24__u24$y_param:A=A +// test.kt:7 component3: // LOCAL VARIABLES JVM // test.kt:12 invokeSuspend: $result:java.lang.Object=kotlin.Unit, $dstr$x_param$_u24__u24$y_param:A=A -// test.kt:7 component3: -// test.kt:12 invokeSuspend: $result:java.lang.Object=kotlin.Unit, $dstr$x_param$_u24__u24$y_param:A=A // LOCAL VARIABLES JVM_IR -// test.kt:12 invokeSuspend: $result:java.lang.Object=kotlin.Unit -// test.kt:7 component3: -// test.kt:12 invokeSuspend: $result:java.lang.Object=kotlin.Unit, x_param:java.lang.String="O":java.lang.String +// test.kt:12 invokeSuspend: $result:java.lang.Object=kotlin.Unit, $dstr$x_param$_u24__u24$y_param:A=A, x_param:java.lang.String="O":java.lang.String // LOCAL VARIABLES // test.kt:13 invokeSuspend: $result:java.lang.Object=kotlin.Unit, x_param:java.lang.String="O":java.lang.String, y_param:java.lang.String="K":java.lang.String diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/IrKotlinEvaluateExpressionTestGenerated.java b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/IrKotlinEvaluateExpressionTestGenerated.java index 00163b02c65..8b7ec2a5965 100644 --- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/IrKotlinEvaluateExpressionTestGenerated.java +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/IrKotlinEvaluateExpressionTestGenerated.java @@ -606,6 +606,11 @@ public class IrKotlinEvaluateExpressionTestGenerated extends AbstractIrKotlinEva runTest("idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/anyUpdateVariable.kt"); } + @TestMetadata("capturedReceiverName.kt") + public void testCapturedReceiverName() throws Exception { + runTest("idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/capturedReceiverName.kt"); + } + @TestMetadata("primitivesCoertion.kt") public void testPrimitivesCoertion() throws Exception { runTest("idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/primitivesCoertion.kt"); diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinEvaluateExpressionTestGenerated.java b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinEvaluateExpressionTestGenerated.java index 075e1da6b92..56165e49bf9 100644 --- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinEvaluateExpressionTestGenerated.java @@ -605,6 +605,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat runTest("idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/anyUpdateVariable.kt"); } + @TestMetadata("capturedReceiverName.kt") + public void testCapturedReceiverName() throws Exception { + runTest("idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/capturedReceiverName.kt"); + } + @TestMetadata("primitivesCoertion.kt") public void testPrimitivesCoertion() throws Exception { runTest("idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/primitivesCoertion.kt"); diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/capturedReceiverName.kt b/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/capturedReceiverName.kt new file mode 100644 index 00000000000..a6b90312804 --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/capturedReceiverName.kt @@ -0,0 +1,40 @@ +package capturedReceiverName + +import kotlin.sequences.* +import kotlin.coroutines.* + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(object : Continuation{ + override val context: CoroutineContext + get() = EmptyCoroutineContext + + override fun resumeWith(result: Result) { + result.getOrThrow() + } + }) +} + +fun main(args: Array) { + builder { + var s = "OK" + s = strChanger(s) { character -> + //Breakpoint! + character != 'a' // (2) + } + println(s) + } +} + +suspend fun strChanger(str: String, pred: suspend (Char) -> Boolean): String { + var result = "" + str.forEach { + if (pred(it)) { + result += it + } + } + return result +} + +// EXPRESSION: character +// RESULT: 79: C +// 79.toChar() == 'O' \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/capturedReceiverName.out b/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/capturedReceiverName.out new file mode 100644 index 00000000000..4370c48eaf0 --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/coroutines/capturedReceiverName.out @@ -0,0 +1,10 @@ +LineBreakpoint created at capturedReceiverName.kt:22 +Run Java +Connected to the target VM +capturedReceiverName.kt:22 +Compile bytecode for character +capturedReceiverName.kt:22 +Disconnected from the target VM + +Process finished with exit code 0 +OK