KT-11086 Treat initializer of a companion object as a class initializer

This commit is contained in:
Alexey Andreev
2016-05-17 12:49:05 +03:00
parent c5eaea846d
commit f0ee52faaf
6 changed files with 43 additions and 17 deletions
@@ -1,6 +1,3 @@
// Enable for JS when it supports initializer of companion objects.
// TARGET_BACKEND: JVM
// see https://youtrack.jetbrains.com/issue/KT-11086
var global = 0; var global = 0;
class C { class C {
@@ -37,12 +37,6 @@ public class ClassesTestGenerated extends AbstractClassesTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("classObjectAsStaticInitializer.kt")
public void ignoredClassObjectAsStaticInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt");
doTest(fileName);
}
@TestMetadata("classObjectToString.kt") @TestMetadata("classObjectToString.kt")
public void ignoredClassObjectToString() throws Exception { public void ignoredClassObjectToString() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/classObjectToString.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/classObjectToString.kt");
@@ -131,6 +125,12 @@ public class ClassesTestGenerated extends AbstractClassesTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("classObjectAsStaticInitializer.kt")
public void testClassObjectAsStaticInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt");
doTest(fileName);
}
@TestMetadata("classObjectField.kt") @TestMetadata("classObjectField.kt")
public void testClassObjectField() throws Exception { public void testClassObjectField() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/classObjectField.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/classObjectField.kt");
@@ -90,7 +90,7 @@ class ClassTranslator private constructor(
val nonConstructorContext = context.innerWithUsageTracker(scope, descriptor) val nonConstructorContext = context.innerWithUsageTracker(scope, descriptor)
val delegationTranslator = DelegationTranslator(classDeclaration, nonConstructorContext) val delegationTranslator = DelegationTranslator(classDeclaration, nonConstructorContext)
translatePropertiesAsConstructorParameters(nonConstructorContext, properties) translatePropertiesAsConstructorParameters(nonConstructorContext, properties)
val bodyVisitor = DeclarationBodyVisitor(properties, staticProperties) val bodyVisitor = DeclarationBodyVisitor(properties, staticProperties, scope)
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext) bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
delegationTranslator.generateDelegated(properties) delegationTranslator.generateDelegated(properties)
@@ -19,10 +19,8 @@ package org.jetbrains.kotlin.js.translate.declaration;
import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.*;
import com.intellij.util.SmartList; import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.Modality;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.Translation; import org.jetbrains.kotlin.js.translate.general.Translation;
import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor; import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor;
@@ -32,6 +30,7 @@ import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor; import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor;
@@ -43,9 +42,19 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
private final List<JsPropertyInitializer> staticResult; private final List<JsPropertyInitializer> staticResult;
private final List<JsPropertyInitializer> enumEntryList = new SmartList<JsPropertyInitializer>(); private final List<JsPropertyInitializer> enumEntryList = new SmartList<JsPropertyInitializer>();
public DeclarationBodyVisitor(@NotNull List<JsPropertyInitializer> result, @NotNull List<JsPropertyInitializer> staticResult) { @NotNull
private final JsScope scope;
@Nullable
private List<JsStatement> initializerStatements;
public DeclarationBodyVisitor(
@NotNull List<JsPropertyInitializer> result, @NotNull List<JsPropertyInitializer> staticResult,
@NotNull JsScope scope
) {
this.result = result; this.result = result;
this.staticResult = staticResult; this.staticResult = staticResult;
this.scope = scope;
} }
@NotNull @NotNull
@@ -65,6 +74,15 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
@Override @Override
public Void visitClassOrObject(@NotNull KtClassOrObject declaration, TranslationContext context) { public Void visitClassOrObject(@NotNull KtClassOrObject declaration, TranslationContext context) {
staticResult.addAll(ClassTranslator.translate(declaration, context).getProperties()); staticResult.addAll(ClassTranslator.translate(declaration, context).getProperties());
if (declaration instanceof KtObjectDeclaration) {
KtObjectDeclaration objectDeclaration = (KtObjectDeclaration) declaration;
if (objectDeclaration.isCompanion()) {
DeclarationDescriptor descriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), declaration);
addInitializerStatement(context.getQualifiedReference(descriptor).makeStmt());
}
}
return null; return null;
} }
@@ -115,4 +133,13 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
public Void visitSecondaryConstructor(@NotNull KtSecondaryConstructor constructor, TranslationContext data) { public Void visitSecondaryConstructor(@NotNull KtSecondaryConstructor constructor, TranslationContext data) {
return null; return null;
} }
private void addInitializerStatement(@NotNull JsStatement statement) {
if (initializerStatements == null) {
initializerStatements = new ArrayList<JsStatement>();
JsFunction initializerFunction = new JsFunction(scope, new JsBlock(initializerStatements), "class initializer");
staticResult.add(new JsPropertyInitializer(new JsNameRef("object_initializer$"), initializerFunction));
}
initializerStatements.add(statement);
}
} }
@@ -17,6 +17,7 @@ package org.jetbrains.kotlin.js.translate.declaration
import com.google.dart.compiler.backend.js.ast.JsFunction import com.google.dart.compiler.backend.js.ast.JsFunction
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer
import com.google.dart.compiler.backend.js.ast.JsScope
import com.intellij.util.SmartList import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.context.TranslationContext
@@ -30,8 +31,9 @@ import org.jetbrains.kotlin.psi.*
class FileDeclarationVisitor( class FileDeclarationVisitor(
val context: TranslationContext, val context: TranslationContext,
scope: JsScope,
initializers: List<JsPropertyInitializer> = SmartList() initializers: List<JsPropertyInitializer> = SmartList()
) : DeclarationBodyVisitor(initializers, SmartList()) { ) : DeclarationBodyVisitor(initializers, SmartList(), scope) {
private val initializer = JsAstUtils.createFunctionWithEmptyBody(context.scope()) private val initializer = JsAstUtils.createFunctionWithEmptyBody(context.scope())
private val initializerContext = context.contextWithScope(initializer) private val initializerContext = context.contextWithScope(initializer)
@@ -45,7 +45,7 @@ final class PackageTranslator extends AbstractTranslator {
DefinitionPlace definitionPlace = new DefinitionPlace((JsObjectScope) scope, reference, properties); DefinitionPlace definitionPlace = new DefinitionPlace((JsObjectScope) scope, reference, properties);
TranslationContext newContext = context.newDeclaration(descriptor, definitionPlace); TranslationContext newContext = context.newDeclaration(descriptor, definitionPlace);
FileDeclarationVisitor visitor = new FileDeclarationVisitor(newContext, definitionPlace.getProperties()); FileDeclarationVisitor visitor = new FileDeclarationVisitor(newContext, scope, definitionPlace.getProperties());
return new PackageTranslator(descriptor, newContext, visitor); return new PackageTranslator(descriptor, newContext, visitor);
} }