From a74c613ec5c24cb894822512d84c198c066af574 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Wed, 23 Mar 2016 16:04:09 +0300 Subject: [PATCH] KT-11030 Make copy method of local data classes to copy captured variables --- .../translate/declaration/ClassTranslator.kt | 34 ++++++++++--------- .../declaration/JsDataClassGenerator.java | 10 ++++++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt index a8d0847bebb..23b07db952b 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt @@ -95,10 +95,6 @@ class ClassTranslator private constructor( bodyVisitor.traverseContainer(classDeclaration, context) delegationTranslator.generateDelegated(properties) - if (descriptor.isData) { - JsDataClassGenerator(classDeclaration, context, properties).generate() - } - if (isEnumClass(descriptor)) { val enumEntries = JsObjectLiteral(bodyVisitor.enumEntryList, true) val function = simpleReturnFunction(context.getScopeForDescriptor(descriptor), enumEntries) @@ -107,6 +103,24 @@ class ClassTranslator private constructor( generatedBridgeMethods(properties) + val dataClassGenerator = JsDataClassGenerator(classDeclaration, context, properties) + val tracker = context.usageTracker() + if (tracker != null && initializer != null && tracker.hasCapturedExceptContaining()) { + val captured = tracker.capturedDescriptorToJsName + val keysAsList = captured.keys.toList() + for ((i, key) in keysAsList.withIndex()) { + val name = captured[key]!! + initializer.parameters.add(i, JsParameter(name)) + initializer.body.statements.add(i, JsAstUtils.defineSimpleProperty(name.ident, name.makeRef())) + dataClassGenerator.addClosureVariable(name) + } + context.putLocalClassClosure(descriptor, keysAsList) + } + + if (descriptor.isData) { + dataClassGenerator.generate() + } + val hasStaticProperties = !staticProperties.isEmpty() if (!properties.isEmpty() || hasStaticProperties) { if (properties.isEmpty()) { @@ -123,18 +137,6 @@ class ClassTranslator private constructor( invocationArguments.add(JsObjectLiteral(staticProperties, true)) } - val tracker = context.usageTracker() - if (tracker != null && initializer != null && tracker.hasCapturedExceptContaining()) { - val captured = tracker.capturedDescriptorToJsName - val keysAsList = captured.keys.toList() - for ((i, key) in keysAsList.withIndex()) { - val name = captured[key]!! - initializer.parameters.add(i, JsParameter(name)) - initializer.body.statements.add(i, JsAstUtils.defineSimpleProperty(name.ident, name.makeRef())) - } - context.putLocalClassClosure(descriptor, keysAsList) - } - if (initializer != null && initializer.body.isEmpty) { invocationArguments.replaceAll { if (it == initializer) JsLiteral.NULL else it } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/JsDataClassGenerator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/JsDataClassGenerator.java index 512eb973d4c..55c6466b940 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/JsDataClassGenerator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/JsDataClassGenerator.java @@ -33,6 +33,7 @@ import java.util.List; class JsDataClassGenerator extends DataClassMethodGenerator { private final TranslationContext context; private final List output; + private final List closureFieldNames = new ArrayList(); JsDataClassGenerator(KtClassOrObject klass, TranslationContext context, List output) { super(klass, context.bindingContext()); @@ -40,6 +41,10 @@ class JsDataClassGenerator extends DataClassMethodGenerator { this.output = output; } + public void addClosureVariable(@NotNull JsName name) { + closureFieldNames.add(name); + } + @Override public void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull ValueParameterDescriptor parameter) { JsFunction functionObject = generateJsMethod(function); @@ -55,6 +60,11 @@ class JsDataClassGenerator extends DataClassMethodGenerator { assert function.getValueParameters().size() == constructorParameters.size(); List constructorArguments = new ArrayList(constructorParameters.size()); + + for (JsName closureFieldName : closureFieldNames) { + constructorArguments.add(propertyAccessor(JsLiteral.THIS, closureFieldName.getIdent())); + } + for (int i = 0; i < constructorParameters.size(); i++) { KtParameter constructorParam = constructorParameters.get(i); JsName paramName = funScope.declareName(constructorParam.getName());