diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index c4e3acf11e0..d5869e937f6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -118,6 +118,8 @@ public class AsmUtil { // For non-inlined callable references ('kotlin.jvm.internal.CallableReference' has a 'receiver' field) public static final String BOUND_REFERENCE_RECEIVER = "receiver"; + public static final String LOCAL_FUNCTION_VARIABLE_PREFIX = "$fun$"; + private static final ImmutableMap primitiveTypeByAsmSort; private static final ImmutableMap primitiveTypeByBoxedType; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 4db53c6a9b8..5632271ba6f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1434,7 +1434,7 @@ public class ExpressionCodegen extends KtVisitor impleme String functionIndex = StringsKt.substringAfterLast(type.getInternalName(), '$', ""); assert !functionIndex.isEmpty(); - String localVariableName = "$fun$" + String localVariableName = AsmUtil.LOCAL_FUNCTION_VARIABLE_PREFIX + VariableAsmNameManglingUtils.mangleNameIfNeeded(functionDescriptor.getName().asString()) + "$" + functionIndex; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/VariableAsmNameManglingUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/VariableAsmNameManglingUtils.kt index 4dc07208fa6..9551dd2cf57 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/VariableAsmNameManglingUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/VariableAsmNameManglingUtils.kt @@ -10,11 +10,13 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.resolve.jvm.checkers.isValidDalvikCharacter +const val DESTRUCTURED_LAMBDA_ARGUMENT_VARIABLE_PREFIX = "\$dstr\$" + fun getNameForDestructuredParameterOrNull(valueParameterDescriptor: ValueParameterDescriptor): String? { val variables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(valueParameterDescriptor) ?: return null @Suppress("SpellCheckingInspection") - return "\$dstr\$" + variables.joinToString(separator = "$") { descriptor -> + return DESTRUCTURED_LAMBDA_ARGUMENT_VARIABLE_PREFIX + variables.joinToString(separator = "$") { descriptor -> val name = descriptor.name mangleNameIfNeeded( when { diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/KotlinStackFrame.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/KotlinStackFrame.kt index cc8befc9e14..8350dba2353 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/KotlinStackFrame.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/KotlinStackFrame.kt @@ -30,6 +30,7 @@ import com.sun.jdi.ReferenceType import com.sun.jdi.Type import com.sun.jdi.Value import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.DESTRUCTURED_LAMBDA_ARGUMENT_VARIABLE_PREFIX import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_PARAMETER_NAME import org.jetbrains.kotlin.codegen.inline.INLINE_FUN_VAR_SUFFIX import org.jetbrains.kotlin.codegen.inline.isFakeLocalVariableForInline @@ -206,6 +207,8 @@ class KotlinStackFrame(frame: StackFrameProxyImpl) : JavaStackFrame(StackFrameDe private fun isHidden(variable: LocalVariableProxyImpl, inlineDepth: Int): Boolean { val name = variable.name() return isFakeLocalVariableForInline(name) + || name.startsWith(DESTRUCTURED_LAMBDA_ARGUMENT_VARIABLE_PREFIX) + || name.startsWith(AsmUtil.LOCAL_FUNCTION_VARIABLE_PREFIX) || VariableFinder.getInlineDepth(variable.name()) != inlineDepth || name == CONTINUATION_VARIABLE_NAME } diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/lambdaParameterMangling.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/lambdaParameterMangling.kt new file mode 100644 index 00000000000..452ba28f760 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/lambdaParameterMangling.kt @@ -0,0 +1,20 @@ +package lambdaParameterMangling + +private data class Foo(val a: String, val b: Int) + +private fun foo(foo: Foo, block: (Foo) -> Unit) { + block(foo) +} + +fun main() { + foo(Foo("a", 5)) { (a, b) -> + //Breakpoint! + val c = 5 + } +} + +// SHOW_KOTLIN_VARIABLES +// PRINT_FRAME + +// EXPRESSION: a.length + b +// RESULT: 6: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/lambdaParameterMangling.out b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/lambdaParameterMangling.out new file mode 100644 index 00000000000..c05e4514f75 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/lambdaParameterMangling.out @@ -0,0 +1,14 @@ +LineBreakpoint created at lambdaParameterMangling.kt:12 +Run Java +Connected to the target VM +lambdaParameterMangling.kt:12 +Compile bytecode for a.length + b + frame = invoke:12, LambdaParameterManglingKt$main$1 {lambdaParameterMangling} + local = a: java.lang.String = a (sp = lambdaParameterMangling.kt, 10) + field = value: char[] = {char[1]@uniqueID} (sp = String.!EXT!) + element = 0 = 'a' 97 + field = hash: int = 0 (sp = String.!EXT!) + local = b: int = 5 (sp = lambdaParameterMangling.kt, 10) +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/localFunctionMangling.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/localFunctionMangling.kt new file mode 100644 index 00000000000..e8eb76a1ab8 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/localFunctionMangling.kt @@ -0,0 +1,14 @@ +package localFunctionMangling + +fun main() { + fun foo() {} + + //Breakpoint! + val a = 5 +} + +// SHOW_KOTLIN_VARIABLES +// PRINT_FRAME + +// EXPRESSION: 1 +// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/localFunctionMangling.out b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/localFunctionMangling.out new file mode 100644 index 00000000000..73cb3a56300 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/localFunctionMangling.out @@ -0,0 +1,9 @@ +LineBreakpoint created at localFunctionMangling.kt:7 +Run Java +Connected to the target VM +localFunctionMangling.kt:7 +Compile bytecode for 1 + frame = main:7, LocalFunctionManglingKt {localFunctionMangling} +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index da430e6654c..3b0824994c0 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -745,6 +745,16 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/hideSyntheticThis.kt"); } + @TestMetadata("lambdaParameterMangling.kt") + public void testLambdaParameterMangling() throws Exception { + runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/lambdaParameterMangling.kt"); + } + + @TestMetadata("localFunctionMangling.kt") + public void testLocalFunctionMangling() throws Exception { + runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/localFunctionMangling.kt"); + } + @TestMetadata("remapThis.kt") public void testRemapThis() throws Exception { runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/remapThis.kt");