From 47f2386212740b0ab7086f13fdfa996667c2bd5e Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 24 May 2017 17:32:11 +0300 Subject: [PATCH] Generate non-local destructuring declarations as properties #KT-5620 Fixed #KT-15810 Fixed --- .../kotlin/codegen/ExpressionCodegen.java | 34 +++++++++++++++++-- .../kotlin/codegen/MemberCodegen.java | 16 ++++++++- .../kotlin/codegen/PropertyCodegen.java | 27 ++++++++++++++- .../kotlin/codegen/ScriptCodegen.java | 7 +++- .../script/destructuringDeclaration.kts | 10 ++++++ .../repl/destructuringDeclaration.repl | 5 +++ .../codegen/ScriptCodegenTestGenerated.java | 6 ++++ .../repl/ReplInterpreterTestGenerated.java | 6 ++++ 8 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/script/destructuringDeclaration.kts create mode 100644 compiler/testData/repl/destructuringDeclaration.repl diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 1702599ce8c..7a6b13cb8b2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -3439,6 +3439,13 @@ public class ExpressionCodegen extends KtVisitor impleme @Override public StackValue visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration multiDeclaration, StackValue receiver) { + return initializeDestructuringDeclaration(multiDeclaration, false); + } + + public StackValue initializeDestructuringDeclaration( + @NotNull KtDestructuringDeclaration multiDeclaration, + boolean asProperty + ) { KtExpression initializer = multiDeclaration.getInitializer(); if (initializer == null) return StackValue.none(); @@ -3455,7 +3462,7 @@ public class ExpressionCodegen extends KtVisitor impleme v.store(tempVarIndex, initializerAsmType); StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType); - initializeDestructuringDeclarationVariables(multiDeclaration, initializerAsReceiver, local); + initializeDestructuringDeclarationVariables(multiDeclaration, initializerAsReceiver, local, asProperty); if (initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) { v.aconst(null); @@ -3470,6 +3477,15 @@ public class ExpressionCodegen extends KtVisitor impleme @NotNull KtDestructuringDeclaration destructuringDeclaration, @NotNull ReceiverValue receiver, @NotNull StackValue receiverStackValue + ) { + initializeDestructuringDeclarationVariables(destructuringDeclaration, receiver, receiverStackValue, false); + } + + private void initializeDestructuringDeclarationVariables( + @NotNull KtDestructuringDeclaration destructuringDeclaration, + @NotNull ReceiverValue receiver, + @NotNull StackValue receiverStackValue, + boolean asProperty ) { for (KtDestructuringDeclarationEntry variableDeclaration : destructuringDeclaration.getEntries()) { ResolvedCall resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration); @@ -3481,7 +3497,21 @@ public class ExpressionCodegen extends KtVisitor impleme // Do not call `componentX` for destructuring entry called _ if (variableDescriptor.getName().isSpecial()) continue; - initializeLocalVariable(variableDeclaration, invokeFunction(call, resolvedCall, receiverStackValue)); + if (asProperty && variableDescriptor instanceof PropertyDescriptor) { + StackValue.Property propertyValue = intermediateValueForProperty( + (PropertyDescriptor) variableDescriptor, + true, + false, + null, + true, + StackValue.LOCAL_0, + null); + + propertyValue.store(invokeFunction(call, resolvedCall, receiverStackValue), v); + } + else { + initializeLocalVariable(variableDeclaration, invokeFunction(call, resolvedCall, receiverStackValue)); + } } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 8d820bdd37b..4c1d7902afd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. + * Copyright 2010-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -216,6 +216,17 @@ public abstract class MemberCodegen { else if (declaration instanceof KtClassOrObject) { genClassOrObject((KtClassOrObject) declaration); } + else if (declaration instanceof KtDestructuringDeclaration) { + for (KtDestructuringDeclarationEntry entry : ((KtDestructuringDeclaration) declaration).getEntries()) { + genSimpleMember(entry); + } + } } } } diff --git a/compiler/testData/codegen/script/destructuringDeclaration.kts b/compiler/testData/codegen/script/destructuringDeclaration.kts new file mode 100644 index 00000000000..d488272d78a --- /dev/null +++ b/compiler/testData/codegen/script/destructuringDeclaration.kts @@ -0,0 +1,10 @@ +val (abc, def) = A() + +val rv = abc + def + +class A { + operator fun component1() = 123 + operator fun component2() = 2 +} + +// expected: rv: 125 \ No newline at end of file diff --git a/compiler/testData/repl/destructuringDeclaration.repl b/compiler/testData/repl/destructuringDeclaration.repl new file mode 100644 index 00000000000..dc609753e48 --- /dev/null +++ b/compiler/testData/repl/destructuringDeclaration.repl @@ -0,0 +1,5 @@ +>>> val (a, b) = listOf(1, 2) +>>> a +1 +>>> b +2 diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java index 85e2c4f3ae5..8f6f23d6e1f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ScriptCodegenTestGenerated.java @@ -48,6 +48,12 @@ public class ScriptCodegenTestGenerated extends AbstractScriptCodegenTest { doTest(fileName); } + @TestMetadata("destructuringDeclaration.kts") + public void testDestructuringDeclaration() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/destructuringDeclaration.kts"); + doTest(fileName); + } + @TestMetadata("empty.kts") public void testEmpty() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/empty.kts"); diff --git a/compiler/tests/org/jetbrains/kotlin/repl/ReplInterpreterTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/repl/ReplInterpreterTestGenerated.java index e9ce6ca731d..adccff222b1 100644 --- a/compiler/tests/org/jetbrains/kotlin/repl/ReplInterpreterTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/repl/ReplInterpreterTestGenerated.java @@ -48,6 +48,12 @@ public class ReplInterpreterTestGenerated extends AbstractReplInterpreterTest { doTest(fileName); } + @TestMetadata("destructuringDeclaration.repl") + public void testDestructuringDeclaration() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/destructuringDeclaration.repl"); + doTest(fileName); + } + @TestMetadata("empty.repl") public void testEmpty() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/empty.repl");