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;
class C {
@@ -37,12 +37,6 @@ public class ClassesTestGenerated extends AbstractClassesTest {
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")
public void ignoredClassObjectToString() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/classObjectToString.kt");
@@ -131,6 +125,12 @@ public class ClassesTestGenerated extends AbstractClassesTest {
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")
public void testClassObjectField() throws Exception {
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 delegationTranslator = DelegationTranslator(classDeclaration, nonConstructorContext)
translatePropertiesAsConstructorParameters(nonConstructorContext, properties)
val bodyVisitor = DeclarationBodyVisitor(properties, staticProperties)
val bodyVisitor = DeclarationBodyVisitor(properties, staticProperties, scope)
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
delegationTranslator.generateDelegated(properties)
@@ -19,10 +19,8 @@ package org.jetbrains.kotlin.js.translate.declaration;
import com.google.dart.compiler.backend.js.ast.*;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.Modality;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.Translation;
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.types.KotlinType;
import java.util.ArrayList;
import java.util.List;
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> 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.staticResult = staticResult;
this.scope = scope;
}
@NotNull
@@ -65,6 +74,15 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
@Override
public Void visitClassOrObject(@NotNull KtClassOrObject declaration, TranslationContext context) {
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;
}
@@ -115,4 +133,13 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
public Void visitSecondaryConstructor(@NotNull KtSecondaryConstructor constructor, TranslationContext data) {
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.JsPropertyInitializer
import com.google.dart.compiler.backend.js.ast.JsScope
import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.js.translate.context.TranslationContext
@@ -30,8 +31,9 @@ import org.jetbrains.kotlin.psi.*
class FileDeclarationVisitor(
val context: TranslationContext,
scope: JsScope,
initializers: List<JsPropertyInitializer> = SmartList()
) : DeclarationBodyVisitor(initializers, SmartList()) {
) : DeclarationBodyVisitor(initializers, SmartList(), scope) {
private val initializer = JsAstUtils.createFunctionWithEmptyBody(context.scope())
private val initializerContext = context.contextWithScope(initializer)
@@ -45,7 +45,7 @@ final class PackageTranslator extends AbstractTranslator {
DefinitionPlace definitionPlace = new DefinitionPlace((JsObjectScope) scope, reference, properties);
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);
}