JS backend: ensure enumerability for object literal properties.

Namespace lends annotation improved (root).

(cherry picked from commit 246c001)
This commit is contained in:
develar
2013-08-14 14:56:41 +04:00
committed by Zalim Bashorov
parent 0daf2c6a79
commit 481cee16c5
7 changed files with 61 additions and 59 deletions
@@ -35,6 +35,7 @@ import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator;
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.ArrayList;
import java.util.Collection;
@@ -200,14 +201,14 @@ public final class ClassTranslator extends AbstractTranslator {
}
else {
if (qualifiedReference != null) {
// about "prototype" -- see http://code.google.com/p/jsdoc-toolkit/wiki/TagLends
invocationArguments.add(new JsDocComment("lends", new JsNameRef("prototype", qualifiedReference)));
// about "prototype" - see http://code.google.com/p/jsdoc-toolkit/wiki/TagLends
invocationArguments.add(new JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, new JsNameRef("prototype", qualifiedReference)));
}
invocationArguments.add(new JsObjectLiteral(properties, true));
}
}
if (hasStaticProperties) {
invocationArguments.add(new JsDocComment("lends", qualifiedReference));
invocationArguments.add(new JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, qualifiedReference));
invocationArguments.add(new JsObjectLiteral(staticProperties, true));
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.declaration;
import com.google.dart.compiler.backend.js.ast.*;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -31,6 +32,7 @@ import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.*;
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 {
private final Iterable<JetFile> files;
@@ -99,23 +101,33 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
rootNamespace = (NamespaceDescriptor) rootNamespace.getContainingDeclaration();
}
List<JsExpression> args;
JsObjectLiteral rootNamespaceDefinition = new JsObjectLiteral(true);
if (context().isEcma5()) {
args = Arrays.<JsExpression>asList(JsLiteral.NULL, rootNamespaceDefinition);
descriptorToDefineInvocation.put(rootNamespace, createDefineInvocation(rootNamespace, null, rootNamespaceDefinition, context()));
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 {
args = Collections.<JsExpression>singletonList(rootNamespaceDefinition);
return Collections.<JsExpression>singletonList(members);
}
descriptorToDefineInvocation.put(rootNamespace, args);
return rootNamespaceDefinition;
}
private JsVar getDeclaration(@NotNull JsObjectLiteral rootNamespaceDefinition) {
JsExpression packageMapValue;
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 {
packageMapValue = rootNamespaceDefinition;
@@ -35,8 +35,6 @@ import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -130,18 +128,11 @@ final class NamespaceTranslator extends AbstractTranslator {
}
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) {
if (context().isEcma5()) {
return Arrays.asList(initializer == null ? JsLiteral.NULL : initializer,
new JsDocComment("lends", getQualifiedReference(context(), descriptor)),
members);
}
else {
return Collections.<JsExpression>singletonList(members);
}
return NamespaceDeclarationTranslator.createDefineInvocation(descriptor, initializer, members, context());
}
private JsPropertyInitializer getEntry(@NotNull NamespaceDescriptor descriptor, List<JsExpression> defineInvocation) {
@@ -154,7 +145,7 @@ final class NamespaceTranslator extends AbstractTranslator {
Map<NamespaceDescriptor, List<JsExpression>> descriptorToDeclarationPlace) {
List<JsExpression> parentDefineInvocation = descriptorToDeclarationPlace.get(parentDescriptor);
if (parentDefineInvocation != null) {
((JsObjectLiteral) parentDefineInvocation.get(context().isEcma5() ? 1 : 0)).getPropertyInitializers().add(entry);
getListFromPlace(parentDefineInvocation).add(entry);
return true;
}
return false;
@@ -19,9 +19,7 @@ package org.jetbrains.k2js.translate.initializer;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.Named;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
import org.jetbrains.jet.lang.psi.JetProperty;
@@ -72,16 +70,16 @@ public final class InitializerUtils {
) {
ClassDescriptor descriptor = getClassDescriptor(context.bindingContext(), declaration);
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;
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 {
expression = assignment(new JsNameRef(named.getName().asString(), JsLiteral.THIS), value);
expression = assignment(new JsNameRef(descriptor.getName().asString(), JsLiteral.THIS), value);
}
return expression.makeStmt();
}
@@ -101,8 +101,8 @@ public final class AnnotationsUtils {
}
ClassDescriptor containingClass = getContainingClass(descriptor);
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) {
@@ -39,6 +39,8 @@ public final class JsAstUtils {
private static final JsPropertyInitializer WRITABLE = new JsPropertyInitializer(new JsNameRef("writable"), JsLiteral.TRUE);
private static final JsPropertyInitializer ENUMERABLE = new JsPropertyInitializer(new JsNameRef("enumerable"), JsLiteral.TRUE);
public static final String LENDS_JS_DOC_TAG = "lends";
static {
JsNameRef globalObjectReference = new JsNameRef("Object");
DEFINE_PROPERTY.setQualifier(globalObjectReference);
@@ -228,20 +230,18 @@ public final class JsAstUtils {
}
@NotNull
public static JsInvocation defineProperty(@NotNull String name,
public static JsInvocation defineProperty(
@NotNull String name,
@NotNull JsObjectLiteral value,
@NotNull TranslationContext context) {
JsInvocation invocation = new JsInvocation(DEFINE_PROPERTY);
invocation.getArguments().add(JsLiteral.THIS);
invocation.getArguments().add(context.program().getStringLiteral(name));
invocation.getArguments().add(value);
return invocation;
@NotNull TranslationContext context
) {
return new JsInvocation(DEFINE_PROPERTY, JsLiteral.THIS, context.program().getStringLiteral(name), value);
}
@NotNull
public static JsStatement defineSimpleProperty(@NotNull String name, @NotNull JsExpression value, @NotNull TranslationContext context) {
if (context.isEcma5()) {
return defineProperty(name, createDataDescriptor(value, false), context).makeStmt();
return defineProperty(name, createDataDescriptor(value, false, false), context).makeStmt();
} else {
return assignment(new JsNameRef(name, JsLiteral.THIS), value).makeStmt();
}
@@ -250,41 +250,41 @@ public final class JsAstUtils {
@NotNull
public static JsObjectLiteral createPropertyDataDescriptor(@NotNull FunctionDescriptor descriptor,
@NotNull JsExpression value) {
return createPropertyDataDescriptor(descriptor.getModality().isOverridable(), descriptor, value);
return createPropertyDataDescriptor(descriptor, descriptor.getModality().isOverridable(), value);
}
@NotNull
public static JsObjectLiteral createDataDescriptor(@NotNull JsExpression value) {
return createDataDescriptor(value, false);
return createDataDescriptor(value, false, false);
}
@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();
dataDescriptor.getPropertyInitializers().add(new JsPropertyInitializer(VALUE, value));
if (writable) {
dataDescriptor.getPropertyInitializers().add(WRITABLE);
}
return dataDescriptor;
}
@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)) {
if (enumerable) {
dataDescriptor.getPropertyInitializers().add(ENUMERABLE);
}
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
public static JsFunction createPackage(@NotNull List<JsStatement> to, @NotNull JsScope scope) {
JsFunction packageBlockFunction = createFunctionWithEmptyBody(scope);
@@ -64,7 +64,7 @@ public final class TranslationUtils {
@NotNull
private static JsPropertyInitializer translateExtensionFunctionAsEcma5DataDescriptor(@NotNull JsFunction function,
@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);
}