KT-11030 Make copy method of local data classes to copy captured variables

This commit is contained in:
Alexey Andreev
2016-03-23 16:04:09 +03:00
parent a21b5ad4e6
commit a74c613ec5
2 changed files with 28 additions and 16 deletions
@@ -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 }
}
@@ -33,6 +33,7 @@ import java.util.List;
class JsDataClassGenerator extends DataClassMethodGenerator {
private final TranslationContext context;
private final List<? super JsPropertyInitializer> output;
private final List<JsName> closureFieldNames = new ArrayList<JsName>();
JsDataClassGenerator(KtClassOrObject klass, TranslationContext context, List<? super JsPropertyInitializer> 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<JsExpression> constructorArguments = new ArrayList<JsExpression>(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());