diff --git a/compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt b/compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt index a28080869ad..d9175424f8e 100644 --- a/compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt +++ b/compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt @@ -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 { diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ClassesTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ClassesTestGenerated.java index 77f4bf5b732..f58fcce933f 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ClassesTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ClassesTestGenerated.java @@ -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"); 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 fecb36fa1ef..bf630cde09a 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 @@ -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) diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DeclarationBodyVisitor.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DeclarationBodyVisitor.java index 9a626770c0e..b18f3796777 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DeclarationBodyVisitor.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DeclarationBodyVisitor.java @@ -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 { private final List staticResult; private final List enumEntryList = new SmartList(); - public DeclarationBodyVisitor(@NotNull List result, @NotNull List staticResult) { + @NotNull + private final JsScope scope; + + @Nullable + private List initializerStatements; + + public DeclarationBodyVisitor( + @NotNull List result, @NotNull List staticResult, + @NotNull JsScope scope + ) { this.result = result; this.staticResult = staticResult; + this.scope = scope; } @NotNull @@ -65,6 +74,15 @@ public class DeclarationBodyVisitor extends TranslatorVisitor { @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 { public Void visitSecondaryConstructor(@NotNull KtSecondaryConstructor constructor, TranslationContext data) { return null; } + + private void addInitializerStatement(@NotNull JsStatement statement) { + if (initializerStatements == null) { + initializerStatements = new ArrayList(); + JsFunction initializerFunction = new JsFunction(scope, new JsBlock(initializerStatements), "class initializer"); + staticResult.add(new JsPropertyInitializer(new JsNameRef("object_initializer$"), initializerFunction)); + } + initializerStatements.add(statement); + } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/FileDeclaration.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/FileDeclaration.kt index d4489cc5a2d..a05590303bd 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/FileDeclaration.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/FileDeclaration.kt @@ -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 = SmartList() -) : DeclarationBodyVisitor(initializers, SmartList()) { +) : DeclarationBodyVisitor(initializers, SmartList(), scope) { private val initializer = JsAstUtils.createFunctionWithEmptyBody(context.scope()) private val initializerContext = context.contextWithScope(initializer) diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/PackageTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/PackageTranslator.java index b9a99adc3d5..98a2988d6ea 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/PackageTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/PackageTranslator.java @@ -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); }