Generate non-local destructuring declarations as properties
#KT-5620 Fixed #KT-15810 Fixed
This commit is contained in:
@@ -3439,6 +3439,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration);
|
||||
@@ -3481,7 +3497,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
else if (declaration instanceof KtTypeAlias) {
|
||||
genTypeAlias((KtTypeAlias) declaration);
|
||||
}
|
||||
else if (declaration instanceof KtDestructuringDeclarationEntry) {
|
||||
try {
|
||||
propertyCodegen.genDestructuringDeclaration((KtDestructuringDeclarationEntry) declaration);
|
||||
}
|
||||
catch (ProcessCanceledException | CompilationException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new CompilationException("Failed to generate destructuring declaration entry " + declaration.getName(), e, declaration);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown parameter: " + declaration);
|
||||
}
|
||||
@@ -466,6 +477,9 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
initializeProperty(codegen.invoke(), (KtProperty) declaration);
|
||||
}
|
||||
}
|
||||
else if (declaration instanceof KtDestructuringDeclaration) {
|
||||
codegen.invoke().initializeDestructuringDeclaration((KtDestructuringDeclaration) declaration, true);
|
||||
}
|
||||
else if (declaration instanceof KtAnonymousInitializer) {
|
||||
KtExpression body = ((KtAnonymousInitializer) declaration).getBody();
|
||||
if (body != null) {
|
||||
|
||||
@@ -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.
|
||||
@@ -105,6 +105,18 @@ public class PropertyCodegen {
|
||||
gen(property, propertyDescriptor, property.getGetter(), property.getSetter());
|
||||
}
|
||||
|
||||
public void genDestructuringDeclaration(@NotNull KtDestructuringDeclarationEntry entry) {
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, entry);
|
||||
if (!(variableDescriptor instanceof PropertyDescriptor)) {
|
||||
throw ExceptionLogger.logDescriptorNotFound(
|
||||
"Destructuring declaration entry" + entry.getName() + " should have a property descriptor: " + variableDescriptor, entry
|
||||
);
|
||||
}
|
||||
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
|
||||
genDestructuringDeclaration(entry, propertyDescriptor);
|
||||
}
|
||||
|
||||
public void generateInPackageFacade(@NotNull DeserializedPropertyDescriptor deserializedProperty) {
|
||||
assert context instanceof MultifileClassFacadeContext : "should be called only for generating facade: " + context;
|
||||
gen(null, deserializedProperty, null, null);
|
||||
@@ -129,6 +141,19 @@ public class PropertyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void genDestructuringDeclaration(
|
||||
@Nullable KtDestructuringDeclarationEntry entry,
|
||||
@NotNull PropertyDescriptor descriptor
|
||||
) {
|
||||
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DEFAULT_IMPLS
|
||||
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
|
||||
|
||||
genBackingFieldAndAnnotations(entry, descriptor, false);
|
||||
|
||||
generateGetter(entry, descriptor, null);
|
||||
generateSetter(entry, descriptor, null);
|
||||
}
|
||||
|
||||
private void genBackingFieldAndAnnotations(
|
||||
@Nullable KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter
|
||||
) {
|
||||
|
||||
@@ -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.
|
||||
@@ -228,6 +228,11 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
else if (declaration instanceof KtClassOrObject) {
|
||||
genClassOrObject((KtClassOrObject) declaration);
|
||||
}
|
||||
else if (declaration instanceof KtDestructuringDeclaration) {
|
||||
for (KtDestructuringDeclarationEntry entry : ((KtDestructuringDeclaration) declaration).getEntries()) {
|
||||
genSimpleMember(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,5 @@
|
||||
>>> val (a, b) = listOf(1, 2)
|
||||
>>> a
|
||||
1
|
||||
>>> b
|
||||
2
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user