JS backend: ensure enumerability for object literal properties.
Namespace lends annotation improved (root). (cherry picked from commit 246c001)
This commit is contained in:
@@ -35,6 +35,7 @@ import org.jetbrains.k2js.translate.context.TranslationContext;
|
|||||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator;
|
import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator;
|
||||||
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
|
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
|
||||||
|
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -200,14 +201,14 @@ public final class ClassTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (qualifiedReference != null) {
|
if (qualifiedReference != null) {
|
||||||
// about "prototype" -- see http://code.google.com/p/jsdoc-toolkit/wiki/TagLends
|
// about "prototype" - see http://code.google.com/p/jsdoc-toolkit/wiki/TagLends
|
||||||
invocationArguments.add(new JsDocComment("lends", new JsNameRef("prototype", qualifiedReference)));
|
invocationArguments.add(new JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, new JsNameRef("prototype", qualifiedReference)));
|
||||||
}
|
}
|
||||||
invocationArguments.add(new JsObjectLiteral(properties, true));
|
invocationArguments.add(new JsObjectLiteral(properties, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasStaticProperties) {
|
if (hasStaticProperties) {
|
||||||
invocationArguments.add(new JsDocComment("lends", qualifiedReference));
|
invocationArguments.add(new JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, qualifiedReference));
|
||||||
invocationArguments.add(new JsObjectLiteral(staticProperties, true));
|
invocationArguments.add(new JsObjectLiteral(staticProperties, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-8
@@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.declaration;
|
|||||||
import com.google.dart.compiler.backend.js.ast.*;
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
import gnu.trove.THashMap;
|
import gnu.trove.THashMap;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -31,6 +32,7 @@ import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
|
import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
|
||||||
|
import static org.jetbrains.k2js.translate.utils.TranslationUtils.getQualifiedReference;
|
||||||
|
|
||||||
public final class NamespaceDeclarationTranslator extends AbstractTranslator {
|
public final class NamespaceDeclarationTranslator extends AbstractTranslator {
|
||||||
private final Iterable<JetFile> files;
|
private final Iterable<JetFile> files;
|
||||||
@@ -99,23 +101,33 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
|
|||||||
rootNamespace = (NamespaceDescriptor) rootNamespace.getContainingDeclaration();
|
rootNamespace = (NamespaceDescriptor) rootNamespace.getContainingDeclaration();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<JsExpression> args;
|
|
||||||
JsObjectLiteral rootNamespaceDefinition = new JsObjectLiteral(true);
|
JsObjectLiteral rootNamespaceDefinition = new JsObjectLiteral(true);
|
||||||
if (context().isEcma5()) {
|
descriptorToDefineInvocation.put(rootNamespace, createDefineInvocation(rootNamespace, null, rootNamespaceDefinition, context()));
|
||||||
args = Arrays.<JsExpression>asList(JsLiteral.NULL, rootNamespaceDefinition);
|
return rootNamespaceDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<JsExpression> createDefineInvocation(
|
||||||
|
@NotNull NamespaceDescriptor descriptor,
|
||||||
|
@Nullable JsExpression initializer,
|
||||||
|
@NotNull JsObjectLiteral members,
|
||||||
|
@NotNull TranslationContext context
|
||||||
|
) {
|
||||||
|
if (context.isEcma5()) {
|
||||||
|
return Arrays.asList(initializer == null ? JsLiteral.NULL : initializer,
|
||||||
|
new JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, getQualifiedReference(context, descriptor)),
|
||||||
|
members);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
args = Collections.<JsExpression>singletonList(rootNamespaceDefinition);
|
return Collections.<JsExpression>singletonList(members);
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptorToDefineInvocation.put(rootNamespace, args);
|
|
||||||
return rootNamespaceDefinition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsVar getDeclaration(@NotNull JsObjectLiteral rootNamespaceDefinition) {
|
private JsVar getDeclaration(@NotNull JsObjectLiteral rootNamespaceDefinition) {
|
||||||
JsExpression packageMapValue;
|
JsExpression packageMapValue;
|
||||||
if (context().isEcma5()) {
|
if (context().isEcma5()) {
|
||||||
packageMapValue = new JsInvocation(JsAstUtils.CREATE_OBJECT, JsLiteral.NULL, rootNamespaceDefinition);
|
packageMapValue = new JsInvocation(JsAstUtils.CREATE_OBJECT, JsLiteral.NULL,
|
||||||
|
new JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, Namer.getRootNamespaceName()),
|
||||||
|
rootNamespaceDefinition);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
packageMapValue = rootNamespaceDefinition;
|
packageMapValue = rootNamespaceDefinition;
|
||||||
|
|||||||
+3
-12
@@ -35,8 +35,6 @@ import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
|
|||||||
import org.jetbrains.k2js.translate.utils.BindingUtils;
|
import org.jetbrains.k2js.translate.utils.BindingUtils;
|
||||||
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -130,18 +128,11 @@ final class NamespaceTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<JsPropertyInitializer> getListFromPlace(List<JsExpression> defineInvocation) {
|
private List<JsPropertyInitializer> getListFromPlace(List<JsExpression> defineInvocation) {
|
||||||
return ((JsObjectLiteral) defineInvocation.get(context().isEcma5() ? 1 : 0)).getPropertyInitializers();
|
return ((JsObjectLiteral) defineInvocation.get(context().isEcma5() ? 2 : 0)).getPropertyInitializers();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<JsExpression> createDefineInvocation(@Nullable JsExpression initializer, @NotNull JsObjectLiteral members) {
|
private List<JsExpression> createDefineInvocation(@Nullable JsExpression initializer, @NotNull JsObjectLiteral members) {
|
||||||
if (context().isEcma5()) {
|
return NamespaceDeclarationTranslator.createDefineInvocation(descriptor, initializer, members, context());
|
||||||
return Arrays.asList(initializer == null ? JsLiteral.NULL : initializer,
|
|
||||||
new JsDocComment("lends", getQualifiedReference(context(), descriptor)),
|
|
||||||
members);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Collections.<JsExpression>singletonList(members);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsPropertyInitializer getEntry(@NotNull NamespaceDescriptor descriptor, List<JsExpression> defineInvocation) {
|
private JsPropertyInitializer getEntry(@NotNull NamespaceDescriptor descriptor, List<JsExpression> defineInvocation) {
|
||||||
@@ -154,7 +145,7 @@ final class NamespaceTranslator extends AbstractTranslator {
|
|||||||
Map<NamespaceDescriptor, List<JsExpression>> descriptorToDeclarationPlace) {
|
Map<NamespaceDescriptor, List<JsExpression>> descriptorToDeclarationPlace) {
|
||||||
List<JsExpression> parentDefineInvocation = descriptorToDeclarationPlace.get(parentDescriptor);
|
List<JsExpression> parentDefineInvocation = descriptorToDeclarationPlace.get(parentDescriptor);
|
||||||
if (parentDefineInvocation != null) {
|
if (parentDefineInvocation != null) {
|
||||||
((JsObjectLiteral) parentDefineInvocation.get(context().isEcma5() ? 1 : 0)).getPropertyInitializers().add(entry);
|
getListFromPlace(parentDefineInvocation).add(entry);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ package org.jetbrains.k2js.translate.initializer;
|
|||||||
import com.google.dart.compiler.backend.js.ast.*;
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
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.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.Named;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
|
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
|
||||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||||
@@ -72,16 +70,16 @@ public final class InitializerUtils {
|
|||||||
) {
|
) {
|
||||||
ClassDescriptor descriptor = getClassDescriptor(context.bindingContext(), declaration);
|
ClassDescriptor descriptor = getClassDescriptor(context.bindingContext(), declaration);
|
||||||
JsExpression value = ClassTranslator.generateObjectLiteral(declaration, descriptor, context);
|
JsExpression value = ClassTranslator.generateObjectLiteral(declaration, descriptor, context);
|
||||||
initializers.add(create(descriptor, value, context));
|
initializers.add(create(descriptor, !(descriptor.getContainingDeclaration() instanceof NamespaceDescriptor), value, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JsStatement create(Named named, JsExpression value, TranslationContext context) {
|
private static JsStatement create(DeclarationDescriptor descriptor, boolean enumerable, JsExpression value, TranslationContext context) {
|
||||||
JsExpression expression;
|
JsExpression expression;
|
||||||
if (context.isEcma5()) {
|
if (context.isEcma5()) {
|
||||||
expression = JsAstUtils.defineProperty(named.getName().asString(), JsAstUtils.createDataDescriptor(value), context);
|
expression = JsAstUtils.defineProperty(descriptor.getName().asString(), JsAstUtils.createDataDescriptor(value, false, enumerable), context);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
expression = assignment(new JsNameRef(named.getName().asString(), JsLiteral.THIS), value);
|
expression = assignment(new JsNameRef(descriptor.getName().asString(), JsLiteral.THIS), value);
|
||||||
}
|
}
|
||||||
return expression.makeStmt();
|
return expression.makeStmt();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ public final class AnnotationsUtils {
|
|||||||
}
|
}
|
||||||
ClassDescriptor containingClass = getContainingClass(descriptor);
|
ClassDescriptor containingClass = getContainingClass(descriptor);
|
||||||
return containingClass != null &&
|
return containingClass != null &&
|
||||||
(getAnnotationByName(containingClass, ENUMERABLE) != null ||
|
((containingClass.getKind().equals(ClassKind.OBJECT) && containingClass.getName().isSpecial()) ||
|
||||||
(containingClass.getKind().equals(ClassKind.OBJECT) && containingClass.getName().isSpecial()));
|
getAnnotationByName(containingClass, ENUMERABLE) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isLibraryObject(@NotNull DeclarationDescriptor descriptor) {
|
public static boolean isLibraryObject(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ public final class JsAstUtils {
|
|||||||
private static final JsPropertyInitializer WRITABLE = new JsPropertyInitializer(new JsNameRef("writable"), JsLiteral.TRUE);
|
private static final JsPropertyInitializer WRITABLE = new JsPropertyInitializer(new JsNameRef("writable"), JsLiteral.TRUE);
|
||||||
private static final JsPropertyInitializer ENUMERABLE = new JsPropertyInitializer(new JsNameRef("enumerable"), JsLiteral.TRUE);
|
private static final JsPropertyInitializer ENUMERABLE = new JsPropertyInitializer(new JsNameRef("enumerable"), JsLiteral.TRUE);
|
||||||
|
|
||||||
|
public static final String LENDS_JS_DOC_TAG = "lends";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
JsNameRef globalObjectReference = new JsNameRef("Object");
|
JsNameRef globalObjectReference = new JsNameRef("Object");
|
||||||
DEFINE_PROPERTY.setQualifier(globalObjectReference);
|
DEFINE_PROPERTY.setQualifier(globalObjectReference);
|
||||||
@@ -228,20 +230,18 @@ public final class JsAstUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsInvocation defineProperty(@NotNull String name,
|
public static JsInvocation defineProperty(
|
||||||
|
@NotNull String name,
|
||||||
@NotNull JsObjectLiteral value,
|
@NotNull JsObjectLiteral value,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context
|
||||||
JsInvocation invocation = new JsInvocation(DEFINE_PROPERTY);
|
) {
|
||||||
invocation.getArguments().add(JsLiteral.THIS);
|
return new JsInvocation(DEFINE_PROPERTY, JsLiteral.THIS, context.program().getStringLiteral(name), value);
|
||||||
invocation.getArguments().add(context.program().getStringLiteral(name));
|
|
||||||
invocation.getArguments().add(value);
|
|
||||||
return invocation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsStatement defineSimpleProperty(@NotNull String name, @NotNull JsExpression value, @NotNull TranslationContext context) {
|
public static JsStatement defineSimpleProperty(@NotNull String name, @NotNull JsExpression value, @NotNull TranslationContext context) {
|
||||||
if (context.isEcma5()) {
|
if (context.isEcma5()) {
|
||||||
return defineProperty(name, createDataDescriptor(value, false), context).makeStmt();
|
return defineProperty(name, createDataDescriptor(value, false, false), context).makeStmt();
|
||||||
} else {
|
} else {
|
||||||
return assignment(new JsNameRef(name, JsLiteral.THIS), value).makeStmt();
|
return assignment(new JsNameRef(name, JsLiteral.THIS), value).makeStmt();
|
||||||
}
|
}
|
||||||
@@ -250,41 +250,41 @@ public final class JsAstUtils {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static JsObjectLiteral createPropertyDataDescriptor(@NotNull FunctionDescriptor descriptor,
|
public static JsObjectLiteral createPropertyDataDescriptor(@NotNull FunctionDescriptor descriptor,
|
||||||
@NotNull JsExpression value) {
|
@NotNull JsExpression value) {
|
||||||
return createPropertyDataDescriptor(descriptor.getModality().isOverridable(), descriptor, value);
|
return createPropertyDataDescriptor(descriptor, descriptor.getModality().isOverridable(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsObjectLiteral createDataDescriptor(@NotNull JsExpression value) {
|
public static JsObjectLiteral createDataDescriptor(@NotNull JsExpression value) {
|
||||||
return createDataDescriptor(value, false);
|
return createDataDescriptor(value, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsObjectLiteral createDataDescriptor(@NotNull JsExpression value, boolean writable) {
|
public static JsObjectLiteral createDataDescriptor(@NotNull JsExpression value, boolean writable, boolean enumerable) {
|
||||||
JsObjectLiteral dataDescriptor = new JsObjectLiteral();
|
JsObjectLiteral dataDescriptor = new JsObjectLiteral();
|
||||||
dataDescriptor.getPropertyInitializers().add(new JsPropertyInitializer(VALUE, value));
|
dataDescriptor.getPropertyInitializers().add(new JsPropertyInitializer(VALUE, value));
|
||||||
if (writable) {
|
if (writable) {
|
||||||
dataDescriptor.getPropertyInitializers().add(WRITABLE);
|
dataDescriptor.getPropertyInitializers().add(WRITABLE);
|
||||||
}
|
}
|
||||||
return dataDescriptor;
|
if (enumerable) {
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JsObjectLiteral createPropertyDataDescriptor(@NotNull PropertyDescriptor descriptor,
|
|
||||||
@NotNull JsExpression value) {
|
|
||||||
return createPropertyDataDescriptor(descriptor.isVar() || descriptor.getModality() == Modality.OPEN, descriptor, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static JsObjectLiteral createPropertyDataDescriptor(boolean writable,
|
|
||||||
@NotNull DeclarationDescriptor descriptor,
|
|
||||||
@NotNull JsExpression value) {
|
|
||||||
JsObjectLiteral dataDescriptor = createDataDescriptor(value, writable);
|
|
||||||
if (AnnotationsUtils.isEnumerable(descriptor)) {
|
|
||||||
dataDescriptor.getPropertyInitializers().add(ENUMERABLE);
|
dataDescriptor.getPropertyInitializers().add(ENUMERABLE);
|
||||||
}
|
}
|
||||||
return dataDescriptor;
|
return dataDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JsObjectLiteral createPropertyDataDescriptor(@NotNull PropertyDescriptor descriptor, @NotNull JsExpression value) {
|
||||||
|
return createPropertyDataDescriptor(descriptor, descriptor.isVar() || descriptor.getModality() == Modality.OPEN, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static JsObjectLiteral createPropertyDataDescriptor(
|
||||||
|
@NotNull DeclarationDescriptor descriptor,
|
||||||
|
boolean writable,
|
||||||
|
@NotNull JsExpression value
|
||||||
|
) {
|
||||||
|
return createDataDescriptor(value, writable, AnnotationsUtils.isEnumerable(descriptor));
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsFunction createPackage(@NotNull List<JsStatement> to, @NotNull JsScope scope) {
|
public static JsFunction createPackage(@NotNull List<JsStatement> to, @NotNull JsScope scope) {
|
||||||
JsFunction packageBlockFunction = createFunctionWithEmptyBody(scope);
|
JsFunction packageBlockFunction = createFunctionWithEmptyBody(scope);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public final class TranslationUtils {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private static JsPropertyInitializer translateExtensionFunctionAsEcma5DataDescriptor(@NotNull JsFunction function,
|
private static JsPropertyInitializer translateExtensionFunctionAsEcma5DataDescriptor(@NotNull JsFunction function,
|
||||||
@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
|
@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
|
||||||
JsObjectLiteral meta = createDataDescriptor(function, descriptor.getModality().isOverridable());
|
JsObjectLiteral meta = createDataDescriptor(function, descriptor.getModality().isOverridable(), false);
|
||||||
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta);
|
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user