From a9fcee098d8fe86108086c4e1b2e46a855e51196 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 20 Oct 2016 17:23:42 +0300 Subject: [PATCH] Support single-underscore named variables in JVM backend There are mainly two kind of changes: - skipping 'componentX' calls for destructuring entries named _ - fixing local variable table for them - skip entries for destructuring entries named _ - use $noName_ format for lambda parameters named _ #KT-3824 Fixed #KT-2783 Fixed --- .../codegen/ClosureGenerationStrategy.kt | 2 +- .../kotlin/codegen/ExpressionCodegen.java | 30 ++++++-- .../kotlin/codegen/FunctionCodegen.java | 17 ++++- .../jetbrains/kotlin/codegen/codegenUtil.kt | 2 + .../underscoreNames.kt | 34 ++++++++++ .../box/closures/underscoreParameters.kt | 3 + .../underscoreNames.kt | 9 +++ .../underscoreParameters.kt | 3 + .../codegen/box/multiDecl/UnderscoreNames.kt | 14 ++++ .../box/multiDecl/forRange/UnderscoreNames.kt | 43 ++++++++++++ .../UnderscoreNamesDontCallComponent.kt | 15 ++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 36 ++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 36 ++++++++++ ...CheckLocalVariablesTableTestGenerated.java | 6 ++ .../debugger/tinyApp/outs/underscoreNames.out | 68 +++++++++++++++++++ .../lambdas/underscoreNames.kt | 32 +++++++++ ...KotlinEvaluateExpressionTestGenerated.java | 6 ++ .../FunctionExpressionTestGenerated.java | 6 ++ 18 files changed, 355 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/checkLocalVariablesTable/underscoreNames.kt create mode 100644 compiler/testData/codegen/box/closures/underscoreParameters.kt create mode 100644 compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt create mode 100644 compiler/testData/codegen/box/functions/functionExpression/underscoreParameters.kt create mode 100644 compiler/testData/codegen/box/multiDecl/UnderscoreNames.kt create mode 100644 compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNames.kt create mode 100644 compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt create mode 100644 idea/testData/debugger/tinyApp/outs/underscoreNames.out create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/lambdas/underscoreNames.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureGenerationStrategy.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureGenerationStrategy.kt index 0c795e7e57d..20d901558b7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureGenerationStrategy.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureGenerationStrategy.kt @@ -44,7 +44,7 @@ class ClosureGenerationStrategy( for (parameterDescriptor in codegen.context.functionDescriptor.valueParameters) { if (parameterDescriptor !is ValueParameterDescriptorImpl.WithDestructuringDeclaration) continue - for (entry in parameterDescriptor.destructuringVariables) { + for (entry in parameterDescriptor.destructuringVariables.filterOutDescriptorsWithSpecialNames()) { codegen.myFrameMap.enter(entry, codegen.typeMapper.mapType(entry.type)) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 553dcdcac39..f08d659dbf9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -775,9 +775,19 @@ public class ExpressionCodegen extends KtVisitor impleme private void generateDestructuringDeclaration(@NotNull KtDestructuringDeclaration destructuringDeclaration) { final Label destructuringStartLabel = new Label(); - for (KtDestructuringDeclarationEntry variableDeclaration : destructuringDeclaration.getEntries()) { - final VariableDescriptor componentDescriptor = bindingContext.get(VARIABLE, variableDeclaration); + List componentDescriptors = + CollectionsKt.map( + destructuringDeclaration.getEntries(), + new Function1() { + @Override + public VariableDescriptor invoke(KtDestructuringDeclarationEntry entry) { + return getVariableDescriptorNotNull(entry); + } + } + ); + + for (final VariableDescriptor componentDescriptor : CodegenUtilKt.filterOutDescriptorsWithSpecialNames(componentDescriptors)) { @SuppressWarnings("ConstantConditions") final Type componentAsmType = asmType(componentDescriptor.getReturnType()); final int componentVarIndex = myFrameMap.enter(componentDescriptor, componentAsmType); scheduleLeaveVariable(new Runnable() { @@ -1957,8 +1967,10 @@ public class ExpressionCodegen extends KtVisitor impleme } private void putLocalVariableIntoFrameMap(@NotNull KtVariableDeclaration statement) { - VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement); - assert variableDescriptor != null : "Couldn't find variable declaration in binding context " + statement.getText(); + VariableDescriptor variableDescriptor = getVariableDescriptorNotNull(statement); + // Do not modify local variables table for variables like _ in val (_, y) = pair + // They always will have special name + if (variableDescriptor.getName().isSpecial()) return; Type type = getVariableType(variableDescriptor); int index = myFrameMap.enter(variableDescriptor, type); @@ -2004,6 +2016,10 @@ public class ExpressionCodegen extends KtVisitor impleme ) { final VariableDescriptor variableDescriptor = getVariableDescriptorNotNull(statement); + // Do not modify local variables table for variables like _ in val (_, y) = pair + // They always will have special name + if (variableDescriptor.getName().isSpecial()) return; + final Type type = getVariableType(variableDescriptor); final Label scopeStart = new Label(); @@ -3902,6 +3918,12 @@ public class ExpressionCodegen extends KtVisitor impleme ResolvedCall resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration); assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); Call call = makeFakeCall(receiver); + + VariableDescriptor variableDescriptor = getVariableDescriptorNotNull(variableDeclaration); + + // Do not call `componentX` for destructuring entry called _ + if (variableDescriptor.getName().isSpecial()) continue; + initializeLocalVariable(variableDeclaration, invokeFunction(call, resolvedCall, receiverStackValue)); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 71489b6daa4..56fec60af3e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -46,9 +46,11 @@ import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.KtElement; import org.jetbrains.kotlin.psi.KtFunction; import org.jetbrains.kotlin.psi.KtNamedFunction; +import org.jetbrains.kotlin.psi.KtParameter; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils; +import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt; import org.jetbrains.kotlin.resolve.constants.ArrayValue; import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.KClassValue; @@ -563,7 +565,7 @@ public class FunctionCodegen { parameterName = destructuringVariables == null - ? parameter.getName().asString() + ? computeParameterName(i, parameter) : "$" + joinParameterNames(destructuringVariables); } else { @@ -583,7 +585,7 @@ public class FunctionCodegen { List destructuringVariables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(parameter); if (destructuringVariables == null) continue; - for (VariableDescriptor entry : destructuringVariables) { + for (VariableDescriptor entry : CodegenUtilKt.filterOutDescriptorsWithSpecialNames(destructuringVariables)) { Type type = typeMapper.mapType(entry.getType()); mv.visitLocalVariable(entry.getName().asString(), type.getDescriptor(), null, methodBegin, methodEnd, shift); shift += type.getSize(); @@ -591,10 +593,21 @@ public class FunctionCodegen { } } + private static String computeParameterName(int i, ValueParameterDescriptor parameter) { + PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(parameter); + if (element instanceof KtParameter && UnderscoreUtilKt.isSingleUnderscore((KtParameter) element)) { + return "$noName_" + i; + } + + return parameter.getName().asString(); + } + private static String joinParameterNames(@NotNull List variables) { return org.jetbrains.kotlin.utils.StringsKt.join(CollectionsKt.map(variables, new Function1() { @Override public String invoke(VariableDescriptor descriptor) { + // stub for anonymous destructuring declaration entry + if (descriptor.getName().isSpecial()) return "$_$"; return descriptor.getName().asString(); } }), "_"); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt index a72d3080660..f36063fc792 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt @@ -255,3 +255,5 @@ private fun CallableDescriptor.isJvmStaticIn(predicate: (DeclarationDescriptor) } else -> predicate(containingDeclaration) && hasJvmStaticAnnotation() } + +fun Collection.filterOutDescriptorsWithSpecialNames() = filterNot { it.name.isSpecial } diff --git a/compiler/testData/checkLocalVariablesTable/underscoreNames.kt b/compiler/testData/checkLocalVariablesTable/underscoreNames.kt new file mode 100644 index 00000000000..29f8aced886 --- /dev/null +++ b/compiler/testData/checkLocalVariablesTable/underscoreNames.kt @@ -0,0 +1,34 @@ +data class A(val x: Double = 1.0, val y: String = "", val z: Char = '0') + +fun foo(a: A, block: (A, String, Int) -> String): String = block(a, "", 1) + +val arrayOfA: Array = Array(1) { A() } + +fun box() { + + foo(A()) { + (x, _, y), _, w -> + + val (a, _, c) = A() + val (_, `_`, d) = A() + + for ((_, q) in arrayOfA) { + + } + + "" + } +} + +// METHOD : UnderscoreNamesKt$box$1.invoke(LA;Ljava/lang/String;I)Ljava/lang/String; +// VARIABLE : NAME=q TYPE=Ljava/lang/String; INDEX=15 +// VARIABLE : NAME=d TYPE=C INDEX=11 +// VARIABLE : NAME=_ TYPE=Ljava/lang/String; INDEX=10 +// VARIABLE : NAME=c TYPE=C INDEX=9 +// VARIABLE : NAME=a TYPE=D INDEX=7 +// VARIABLE : NAME=this TYPE=LUnderscoreNamesKt$box$1; INDEX=0 +// VARIABLE : NAME=$x_$_$_y TYPE=LA; INDEX=1 +// VARIABLE : NAME=$noName_1 TYPE=Ljava/lang/String; INDEX=2 +// VARIABLE : NAME=w TYPE=I INDEX=3 +// VARIABLE : NAME=x TYPE=D INDEX=4 +// VARIABLE : NAME=y TYPE=C INDEX=6 diff --git a/compiler/testData/codegen/box/closures/underscoreParameters.kt b/compiler/testData/codegen/box/closures/underscoreParameters.kt new file mode 100644 index 00000000000..02b96fd24f0 --- /dev/null +++ b/compiler/testData/codegen/box/closures/underscoreParameters.kt @@ -0,0 +1,3 @@ +fun foo(block: (String, String, String) -> String): String = block("O", "fail", "K") + +fun box() = foo { x, _, y -> x + y } diff --git a/compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt b/compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt new file mode 100644 index 00000000000..8db07f7778e --- /dev/null +++ b/compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt @@ -0,0 +1,9 @@ +class A { + operator fun component1() = "O" + operator fun component2(): String = throw RuntimeException("fail 0") + operator fun component3() = "K" +} + +fun foo(a: A, block: (A) -> String): String = block(a) + +fun box() = foo(A()) { (x, _, y) -> x + y } diff --git a/compiler/testData/codegen/box/functions/functionExpression/underscoreParameters.kt b/compiler/testData/codegen/box/functions/functionExpression/underscoreParameters.kt new file mode 100644 index 00000000000..b25ca696000 --- /dev/null +++ b/compiler/testData/codegen/box/functions/functionExpression/underscoreParameters.kt @@ -0,0 +1,3 @@ +fun foo(block: (String, String, String) -> String): String = block("O", "fail", "K") + +fun box() = foo(fun(x: String, _: String, y: String) = x + y) diff --git a/compiler/testData/codegen/box/multiDecl/UnderscoreNames.kt b/compiler/testData/codegen/box/multiDecl/UnderscoreNames.kt new file mode 100644 index 00000000000..12dfc941fb6 --- /dev/null +++ b/compiler/testData/codegen/box/multiDecl/UnderscoreNames.kt @@ -0,0 +1,14 @@ +class A { + operator fun component1() = 1 + operator fun component2() = 2 +} + +fun box() : String { + val (_, b) = A() + + val (a, _) = A() + + val (`_`, c) = A() + + return if (a == 1 && b == 2 && _ == 1 && c == 2) "OK" else "fail" +} diff --git a/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNames.kt b/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNames.kt new file mode 100644 index 00000000000..ff9d07f1f46 --- /dev/null +++ b/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNames.kt @@ -0,0 +1,43 @@ +class Range(val from : C, val to: C) { + operator fun iterator() = It(from, to) +} + +class It(val from: C, val to: C) { + var c = from.i + + operator fun next(): C { + val next = C(c) + c++ + return next + } + + operator fun hasNext(): Boolean = c <= to.i +} + +class C(val i : Int) { + operator fun component1() = i + 1 + operator fun component2() = i + 2 + operator fun rangeTo(c: C) = Range(this, c) +} + +fun doTest(): String { + var s = "" + for ((a, _) in C(0)..C(2)) { + s += "$a;" + } + + for ((_, b) in C(1)..C(3)) { + s += "$b;" + } + + for ((_, `_`) in C(2)..C(4)) { + s += "$_;" + } + + return s +} + +fun box(): String { + val s = doTest() + return if (s == "1;2;3;3;4;5;4;5;6;") "OK" else "fail: $s" +} diff --git a/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt b/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt new file mode 100644 index 00000000000..644125c9809 --- /dev/null +++ b/compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt @@ -0,0 +1,15 @@ +class A { + operator fun component1() = "O" + operator fun component2(): String = throw RuntimeException("fail 0") + operator fun component3() = "K" +} + +fun box(): String { + val aA = Array(1) { A() } + + for ((x, _, z) in aA) { + return x + z + } + + return "OK" +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 6c2a28d650d..a682babdfda 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -3445,6 +3445,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("underscoreParameters.kt") + public void testUnderscoreParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/closures/underscoreParameters.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/codegen/box/closures/captureOuterProperty") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -5776,6 +5782,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("underscoreNames.kt") + public void testUnderscoreNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt"); + doTest(fileName); + } + @TestMetadata("withIndexed.kt") public void testWithIndexed() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/destructuringDeclInLambdaParam/withIndexed.kt"); @@ -7238,6 +7250,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/functionExpression/functionLiteralExpression.kt"); doTest(fileName); } + + @TestMetadata("underscoreParameters.kt") + public void testUnderscoreParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/functionExpression/underscoreParameters.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/functions/invoke") @@ -9043,6 +9061,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("UnderscoreNames.kt") + public void testUnderscoreNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiDecl/UnderscoreNames.kt"); + doTest(fileName); + } + @TestMetadata("ValCapturedInFunctionLiteral.kt") public void testValCapturedInFunctionLiteral() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiDecl/ValCapturedInFunctionLiteral.kt"); @@ -9189,6 +9213,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("UnderscoreNames.kt") + public void testUnderscoreNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNames.kt"); + doTest(fileName); + } + + @TestMetadata("UnderscoreNamesDontCallComponent.kt") + public void testUnderscoreNamesDontCallComponent() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/codegen/box/multiDecl/forRange/explicitRangeTo") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d7ef0d53a4a..eea9876b504 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -3445,6 +3445,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("underscoreParameters.kt") + public void testUnderscoreParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/closures/underscoreParameters.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/codegen/box/closures/captureOuterProperty") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -5776,6 +5782,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("underscoreNames.kt") + public void testUnderscoreNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/destructuringDeclInLambdaParam/underscoreNames.kt"); + doTest(fileName); + } + @TestMetadata("withIndexed.kt") public void testWithIndexed() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/destructuringDeclInLambdaParam/withIndexed.kt"); @@ -7238,6 +7250,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/functionExpression/functionLiteralExpression.kt"); doTest(fileName); } + + @TestMetadata("underscoreParameters.kt") + public void testUnderscoreParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/functionExpression/underscoreParameters.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/functions/invoke") @@ -9043,6 +9061,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("UnderscoreNames.kt") + public void testUnderscoreNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiDecl/UnderscoreNames.kt"); + doTest(fileName); + } + @TestMetadata("ValCapturedInFunctionLiteral.kt") public void testValCapturedInFunctionLiteral() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiDecl/ValCapturedInFunctionLiteral.kt"); @@ -9189,6 +9213,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("UnderscoreNames.kt") + public void testUnderscoreNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNames.kt"); + doTest(fileName); + } + + @TestMetadata("UnderscoreNamesDontCallComponent.kt") + public void testUnderscoreNamesDontCallComponent() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/multiDecl/forRange/UnderscoreNamesDontCallComponent.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/codegen/box/multiDecl/forRange/explicitRangeTo") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CheckLocalVariablesTableTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CheckLocalVariablesTableTestGenerated.java index 1c79d312805..b3324ccfa44 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CheckLocalVariablesTableTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CheckLocalVariablesTableTestGenerated.java @@ -118,4 +118,10 @@ public class CheckLocalVariablesTableTestGenerated extends AbstractCheckLocalVar String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/checkLocalVariablesTable/localFun.kt"); doTest(fileName); } + + @TestMetadata("underscoreNames.kt") + public void testUnderscoreNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/checkLocalVariablesTable/underscoreNames.kt"); + doTest(fileName); + } } diff --git a/idea/testData/debugger/tinyApp/outs/underscoreNames.out b/idea/testData/debugger/tinyApp/outs/underscoreNames.out new file mode 100644 index 00000000000..8255ec155d2 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/underscoreNames.out @@ -0,0 +1,68 @@ +LineBreakpoint created at underscoreNames.kt:18 lambdaOrdinal = 1 +!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! underscoreNames.UnderscoreNamesKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +underscoreNames.kt:18 +Compile bytecode for x +Compile bytecode for y +package underscoreNames +data class A(val x: Double = 1.0, val y: String = "", val z: Char = '0') + +fun foo(a: A, block: (A, String, Int) -> String): String = block(a, "", 1) + +val arrayOfA: Array = Array(1) { A() } + +fun main(args: Array) { + + foo(A()) { + (x, _, y), _, w -> + + val (a, _, c) = A() + val (_, `_`, d) = A() + + for ((_, q) in arrayOfA) { + //Breakpoint! (lambdaOrdinal = 1) + println(q) + } + + "" + } +} + +// PRINT_FRAME + +// EXPRESSION: x +// RESULT: 1.0: D + +// EXPRESSION: y +// RESULT: 48: C + + +Compile bytecode for arrayOfA + frame = invoke:18, UnderscoreNamesKt$main$1 {underscoreNames} + this = this = {underscoreNames.UnderscoreNamesKt$main$1@uniqueID}Function3 + field = arity: int = 3 (sp = Lambda.!EXT!) + local = $x_$_$_y: underscoreNames.A = {underscoreNames.A@uniqueID}A(x=1.0, y=, z=0) (sp = null) + field = x: double = 1.0 (sp = underscoreNames.kt, 2) + field = y: java.lang.String = (sp = underscoreNames.kt, 2) + field = value: char[] = {char[0]@uniqueID} (sp = String.!EXT!) + field = hash: int = 0 (sp = String.!EXT!) + field = z: char = '0' 48 (sp = underscoreNames.kt, 2) + local = $noName_1: java.lang.String = (sp = null) + field = value: char[] = {char[0]@uniqueID} (sp = String.!EXT!) + field = hash: int = 0 (sp = String.!EXT!) + local = w: int = 1 (sp = underscoreNames.kt, 11) + local = x: double = 1.0 (sp = underscoreNames.kt, 11) + local = y: char = '0' 48 (sp = underscoreNames.kt, 11) + local = a: double = 1.0 (sp = underscoreNames.kt, 13) + local = c: char = '0' 48 (sp = underscoreNames.kt, 13) + local = _: java.lang.String = (sp = underscoreNames.kt, 14) + field = value: char[] = {char[0]@uniqueID} (sp = String.!EXT!) + field = hash: int = 0 (sp = String.!EXT!) + local = d: char = '0' 48 (sp = underscoreNames.kt, 14) + local = q: java.lang.String = (sp = underscoreNames.kt, 16) + field = value: char[] = {char[0]@uniqueID} (sp = String.!EXT!) + field = hash: int = 0 (sp = String.!EXT!) +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/evaluate/singleBreakpoint/lambdas/underscoreNames.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/lambdas/underscoreNames.kt new file mode 100644 index 00000000000..17ad6a09e7f --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/lambdas/underscoreNames.kt @@ -0,0 +1,32 @@ +package underscoreNames +data class A(val x: Double = 1.0, val y: String = "", val z: Char = '0') + +fun foo(a: A, block: (A, String, Int) -> String): String = block(a, "", 1) + +val arrayOfA: Array = Array(1) { A() } + +fun main(args: Array) { + + foo(A()) { + (x, _, y), _, w -> + + val (a, _, c) = A() + val (_, `_`, d) = A() + + for ((_, q) in arrayOfA) { + //Breakpoint! (lambdaOrdinal = 1) + println(q) + } + + "" + } +} + +// PRINT_FRAME + +// EXPRESSION: x +// RESULT: 1.0: D + +// EXPRESSION: y +// RESULT: 48: C + 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 fd577f7ed1e..e32dfb14f4a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -842,6 +842,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/lambdas/twoLambdasOnOneLineSecond.kt"); doSingleBreakpointTest(fileName); } + + @TestMetadata("underscoreNames.kt") + public void testUnderscoreNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/lambdas/underscoreNames.kt"); + doSingleBreakpointTest(fileName); + } } @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/renderer") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/FunctionExpressionTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/FunctionExpressionTestGenerated.java index dad7a2fe872..0add8d45138 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/FunctionExpressionTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/FunctionExpressionTestGenerated.java @@ -52,4 +52,10 @@ public class FunctionExpressionTestGenerated extends AbstractFunctionExpressionT String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/functionExpression/functionLiteralExpression.kt"); doTest(fileName); } + + @TestMetadata("underscoreParameters.kt") + public void testUnderscoreParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/functionExpression/underscoreParameters.kt"); + doTest(fileName); + } }