From df0a2180155237df7814acaa56f3b1bf9b625423 Mon Sep 17 00:00:00 2001 From: develar Date: Thu, 22 Aug 2013 19:35:55 +0400 Subject: [PATCH] JS backend: generate ref for not public api open classes as ref to internal class pool (_c var), but not to namespace definition. (cherry picked from commit fa3db43) --- .../k2js/translate/context/Namer.java | 2 +- .../ClassDeclarationTranslator.java | 35 ++++++++++++++++--- .../checkImplementationCharacteristics.kt | 8 +++-- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java index dcea37d62d6..bec1d782a2e 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java @@ -47,7 +47,7 @@ public final class Namer { private static final String SUPER_METHOD_NAME = "super_init"; private static final String ROOT_NAMESPACE = "_"; private static final String RECEIVER_PARAMETER_NAME = "$receiver"; - private static final String CLASSES_OBJECT_NAME = "classes"; + private static final String CLASSES_OBJECT_NAME = "_c"; private static final String THROW_NPE_FUN_NAME = "throwNPE"; private static final String CLASS_OBJECT_GETTER = "object$"; private static final String CLASS_OBJECT_INITIALIZER = "object_initializer$"; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java index 1b098238386..c79e8d9ec00 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java @@ -19,16 +19,17 @@ package org.jetbrains.k2js.translate.declaration; import com.google.dart.compiler.backend.js.ast.*; import com.intellij.util.SmartList; import gnu.trove.THashMap; +import gnu.trove.THashSet; import gnu.trove.TObjectObjectProcedure; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.Modality; import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.utils.DFS; -import org.jetbrains.k2js.translate.LabelGenerator; import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; @@ -47,7 +48,7 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor * Generates a big block where are all the classes(objects representing them) are created. */ public final class ClassDeclarationTranslator extends AbstractTranslator { - private final LabelGenerator localLabelGenerator = new LabelGenerator('c'); + private final THashSet nameClashGuard = new THashSet(); @NotNull private final THashMap openClassDescriptorToItem = new THashMap(); @@ -201,7 +202,28 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { }); } - @NotNull + private String createNameForClass(ClassDescriptor descriptor) { + String suggestedName = descriptor.getName().asString(); + String name = suggestedName; + DeclarationDescriptor containing = descriptor; + while (!nameClashGuard.add(name)) { + containing = containing.getContainingDeclaration(); + assert containing != null; + name = suggestedName + '_' + containing.getName().asString(); + } + return name; + } + + @Nullable + public JsNameRef getQualifiedReference(ClassDescriptor descriptor) { + if (descriptor.getModality() != Modality.FINAL) { + //noinspection ConstantConditions + return classDescriptorToQualifiedLabel.get(descriptor, null); + } + return null; + } + + @Nullable public JsPropertyInitializer translate(@NotNull JetClassOrObject declaration, TranslationContext context) { ClassDescriptor descriptor = getClassDescriptor(context().bindingContext(), declaration); JsExpression value; @@ -209,7 +231,7 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { value = new ClassTranslator(declaration, classDescriptorToQualifiedLabel, context).translate(); } else { - String label = localLabelGenerator.generate(); + String label = createNameForClass(descriptor); JsName name = dummyFunction.getScope().declareName(label); JsNameRef qualifiedLabel = openClassDescriptorToQualifiedLabel.get(descriptor); if (qualifiedLabel == null) { @@ -227,6 +249,11 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { openClassDescriptorToItem.put(descriptor, item); value = qualifiedLabel; + + // not public api classes referenced to internal var _c + if (!descriptor.getVisibility().isPublicAPI()) { + return null; + } } return InitializerUtils.createPropertyInitializer(descriptor, value, context()); diff --git a/js/js.translator/testFiles/trait/cases/checkImplementationCharacteristics.kt b/js/js.translator/testFiles/trait/cases/checkImplementationCharacteristics.kt index 53e007dd011..213039896eb 100644 --- a/js/js.translator/testFiles/trait/cases/checkImplementationCharacteristics.kt +++ b/js/js.translator/testFiles/trait/cases/checkImplementationCharacteristics.kt @@ -1,9 +1,9 @@ package foo -trait A { +public trait A { fun foo() {} } -trait B : A { +public trait B : A { fun boo() {} } @@ -12,7 +12,6 @@ native val undefined: Any = noImpl native class Function(vararg args: String) val hasProp = Function("obj, prop", "return obj[prop] !== undefined") as ((Any, String)->Boolean) -val PREFIX = "Kotlin.modules.JS_TESTS.foo" fun box(): String { val a = object: A {} @@ -24,6 +23,9 @@ fun box(): String { if (!hasProp(b, "foo")) return "B hasn't foo" if (!hasProp(b, "boo")) return "B hasn't boo" + val PREFIX = "Kotlin.modules.JS_TESTS.foo" + if (eval("$PREFIX.A") == null) return "$PREFIX.A not found" + if (eval("$PREFIX.B") == null) return "$PREFIX.B not found" if (eval("$PREFIX.A === $PREFIX.B") as Boolean) return "A and B refer to the same object" return "OK"