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)
This commit is contained in:
@@ -47,7 +47,7 @@ public final class Namer {
|
|||||||
private static final String SUPER_METHOD_NAME = "super_init";
|
private static final String SUPER_METHOD_NAME = "super_init";
|
||||||
private static final String ROOT_NAMESPACE = "_";
|
private static final String ROOT_NAMESPACE = "_";
|
||||||
private static final String RECEIVER_PARAMETER_NAME = "$receiver";
|
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 THROW_NPE_FUN_NAME = "throwNPE";
|
||||||
private static final String CLASS_OBJECT_GETTER = "object$";
|
private static final String CLASS_OBJECT_GETTER = "object$";
|
||||||
private static final String CLASS_OBJECT_INITIALIZER = "object_initializer$";
|
private static final String CLASS_OBJECT_INITIALIZER = "object_initializer$";
|
||||||
|
|||||||
+31
-4
@@ -19,16 +19,17 @@ package org.jetbrains.k2js.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 gnu.trove.THashMap;
|
import gnu.trove.THashMap;
|
||||||
|
import gnu.trove.THashSet;
|
||||||
import gnu.trove.TObjectObjectProcedure;
|
import gnu.trove.TObjectObjectProcedure;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
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.descriptors.Modality;
|
||||||
import org.jetbrains.jet.lang.psi.JetClass;
|
import org.jetbrains.jet.lang.psi.JetClass;
|
||||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.utils.DFS;
|
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.Namer;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
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.
|
* Generates a big block where are all the classes(objects representing them) are created.
|
||||||
*/
|
*/
|
||||||
public final class ClassDeclarationTranslator extends AbstractTranslator {
|
public final class ClassDeclarationTranslator extends AbstractTranslator {
|
||||||
private final LabelGenerator localLabelGenerator = new LabelGenerator('c');
|
private final THashSet<String> nameClashGuard = new THashSet<String>();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final THashMap<ClassDescriptor, OpenClassInfo> openClassDescriptorToItem = new THashMap<ClassDescriptor, OpenClassInfo>();
|
private final THashMap<ClassDescriptor, OpenClassInfo> openClassDescriptorToItem = new THashMap<ClassDescriptor, OpenClassInfo>();
|
||||||
@@ -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) {
|
public JsPropertyInitializer translate(@NotNull JetClassOrObject declaration, TranslationContext context) {
|
||||||
ClassDescriptor descriptor = getClassDescriptor(context().bindingContext(), declaration);
|
ClassDescriptor descriptor = getClassDescriptor(context().bindingContext(), declaration);
|
||||||
JsExpression value;
|
JsExpression value;
|
||||||
@@ -209,7 +231,7 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
|
|||||||
value = new ClassTranslator(declaration, classDescriptorToQualifiedLabel, context).translate();
|
value = new ClassTranslator(declaration, classDescriptorToQualifiedLabel, context).translate();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String label = localLabelGenerator.generate();
|
String label = createNameForClass(descriptor);
|
||||||
JsName name = dummyFunction.getScope().declareName(label);
|
JsName name = dummyFunction.getScope().declareName(label);
|
||||||
JsNameRef qualifiedLabel = openClassDescriptorToQualifiedLabel.get(descriptor);
|
JsNameRef qualifiedLabel = openClassDescriptorToQualifiedLabel.get(descriptor);
|
||||||
if (qualifiedLabel == null) {
|
if (qualifiedLabel == null) {
|
||||||
@@ -227,6 +249,11 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
|
|||||||
openClassDescriptorToItem.put(descriptor, item);
|
openClassDescriptorToItem.put(descriptor, item);
|
||||||
|
|
||||||
value = qualifiedLabel;
|
value = qualifiedLabel;
|
||||||
|
|
||||||
|
// not public api classes referenced to internal var _c
|
||||||
|
if (!descriptor.getVisibility().isPublicAPI()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return InitializerUtils.createPropertyInitializer(descriptor, value, context());
|
return InitializerUtils.createPropertyInitializer(descriptor, value, context());
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package foo
|
package foo
|
||||||
|
|
||||||
trait A {
|
public trait A {
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
}
|
}
|
||||||
trait B : A {
|
public trait B : A {
|
||||||
fun boo() {}
|
fun boo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,7 +12,6 @@ native val undefined: Any = noImpl
|
|||||||
native class Function(vararg args: String)
|
native class Function(vararg args: String)
|
||||||
|
|
||||||
val hasProp = Function("obj, prop", "return obj[prop] !== undefined") as ((Any, String)->Boolean)
|
val hasProp = Function("obj, prop", "return obj[prop] !== undefined") as ((Any, String)->Boolean)
|
||||||
val PREFIX = "Kotlin.modules.JS_TESTS.foo"
|
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val a = object: A {}
|
val a = object: A {}
|
||||||
@@ -24,6 +23,9 @@ fun box(): String {
|
|||||||
if (!hasProp(b, "foo")) return "B hasn't foo"
|
if (!hasProp(b, "foo")) return "B hasn't foo"
|
||||||
if (!hasProp(b, "boo")) return "B hasn't boo"
|
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"
|
if (eval("$PREFIX.A === $PREFIX.B") as Boolean) return "A and B refer to the same object"
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
|
|||||||
Reference in New Issue
Block a user