From ff3c0a20a097207c19390bc2e9547ce2a99d4aa6 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Thu, 15 Mar 2012 22:26:59 +0400 Subject: [PATCH] Support a simple case with nested namespaces. --- .../ClassDeclarationTranslator.java | 7 +- .../NamespaceDeclarationTranslator.java | 7 +- .../declaration/NamespaceTranslator.java | 40 +++++++---- .../k2js/translate/utils/BindingUtils.java | 32 +-------- .../k2js/translate/utils/DescriptorUtils.java | 67 ++++++++++++++++--- .../translate/utils/PartiallyOrderedSet.java | 2 +- js/js.translator/testFiles/kotlin_lib.js | 1 - 7 files changed, 95 insertions(+), 61 deletions(-) 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 e05d86dc588..9d100fb7f29 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 @@ -16,6 +16,7 @@ package org.jetbrains.k2js.translate.declaration; +import com.google.common.collect.Lists; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; @@ -150,10 +151,10 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { } @NotNull - public JsObjectLiteral classDeclarationsForNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { - JsObjectLiteral result = new JsObjectLiteral(); + public List classDeclarationsForNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { + List result = Lists.newArrayList(); for (ClassDescriptor classDescriptor : getAllClassesDefinedInNamespace(namespaceDescriptor)) { - result.getPropertyInitializers().add(getClassNameToClassObject(classDescriptor)); + result.add(getClassNameToClassObject(classDescriptor)); } return result; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java index 39aee435ea4..f4cda6ca969 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java @@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; +import org.jetbrains.k2js.translate.utils.DescriptorUtils; import java.util.List; import java.util.Set; @@ -90,10 +91,8 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { private List getTranslatorsForNonEmptyNamespaces() { List namespaceTranslators = Lists.newArrayList(); for (NamespaceDescriptor descriptor : namespaceDescriptors) { - NamespaceTranslator namespaceTranslator = - new NamespaceTranslator(descriptor, classDeclarationTranslator, context()); - if (!namespaceTranslator.isNamespaceEmpty()) { - namespaceTranslators.add(namespaceTranslator); + if (!DescriptorUtils.isNamespaceEmpty(descriptor)) { + namespaceTranslators.add(new NamespaceTranslator(descriptor, classDeclarationTranslator, context())); } } return namespaceTranslators; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java index 15c14d3d363..201a0b79c01 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java @@ -16,6 +16,7 @@ package org.jetbrains.k2js.translate.declaration; +import com.google.common.collect.Lists; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; @@ -24,7 +25,7 @@ import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.Translation; -import org.jetbrains.k2js.translate.utils.BindingUtils; +import org.jetbrains.k2js.translate.utils.DescriptorUtils; import java.util.ArrayList; import java.util.List; @@ -54,12 +55,6 @@ public final class NamespaceTranslator extends AbstractTranslator { this.classDeclarationTranslator = classDeclarationTranslator; } - //TODO: at the moment this check is very ineffective, possible solution is to cash the result of getDFN - // other solution is to determine it's not affecting performance :D - public boolean isNamespaceEmpty() { - return BindingUtils.getDeclarationsForNamespace(bindingContext(), descriptor).isEmpty(); - } - @NotNull public JsStatement getInitializeStatement() { @@ -76,18 +71,35 @@ public final class NamespaceTranslator extends AbstractTranslator { @NotNull public JsStatement getDeclarationStatement() { JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation(); - addMemberDeclarations(namespaceDeclaration); - addClassesDeclarations(namespaceDeclaration); + namespaceDeclaration.getArguments().add(translateNamespaceMemberDeclarations()); + namespaceDeclaration.getArguments().add(getClassesAndNestedNamespaces()); return newVar(namespaceName, namespaceDeclaration); } - private void addClassesDeclarations(@NotNull JsInvocation namespaceDeclaration) { - namespaceDeclaration.getArguments().add(classDeclarationTranslator.classDeclarationsForNamespace(descriptor)); + @NotNull + private JsObjectLiteral getClassesAndNestedNamespaces() { + JsObjectLiteral classesAndNestedNamespaces = new JsObjectLiteral(); + classesAndNestedNamespaces.getPropertyInitializers() + .addAll(getClassesDefined()); + classesAndNestedNamespaces.getPropertyInitializers() + .addAll(getNestedNamespaceDeclarations()); + return classesAndNestedNamespaces; } - private void addMemberDeclarations(@NotNull JsInvocation jsNamespace) { - JsObjectLiteral jsClassDescription = translateNamespaceMemberDeclarations(); - jsNamespace.getArguments().add(jsClassDescription); + @NotNull + private List getClassesDefined() { + return classDeclarationTranslator.classDeclarationsForNamespace(descriptor); + } + + @NotNull + private List getNestedNamespaceDeclarations() { + List result = Lists.newArrayList(); + List nestedNamespaces = DescriptorUtils.getNestedNamespaces(descriptor); + for (NamespaceDescriptor nestedNamespace : nestedNamespaces) { + JsName nameForDescriptor = context().getNameForDescriptor(nestedNamespace); + result.add(new JsPropertyInitializer(nameForDescriptor.makeRef(), nameForDescriptor.makeRef())); + } + return result; } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index 70821648f5e..7c7248c0640 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -97,11 +97,7 @@ public final class BindingUtils { public static List getDeclarationsForNamespace(@NotNull BindingContext bindingContext, @NotNull NamespaceDescriptor namespace) { List declarations = new ArrayList(); - for (DeclarationDescriptor descriptor : namespace.getMemberScope().getAllDescriptors()) { - if (AnnotationsUtils.isPredefinedObject(descriptor)) { - continue; - } - //TODO: + for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespace)) { if (descriptor instanceof NamespaceDescriptor) { continue; } @@ -199,27 +195,6 @@ public final class BindingUtils { return !superClassDescriptor.equals(JetStandardClasses.getAny()); } - - //TODO: refactor duplication - //TODO: check where we use these, suspicious - public static boolean isOwnedByNamespace(@NotNull DeclarationDescriptor descriptor) { - if (descriptor instanceof ConstructorDescriptor) { - DeclarationDescriptor classDescriptor = descriptor.getContainingDeclaration(); - assert classDescriptor != null; - return isOwnedByNamespace(classDescriptor); - } - return (descriptor.getContainingDeclaration() instanceof NamespaceDescriptor); - } - - public static boolean isOwnedByClass(@NotNull DeclarationDescriptor descriptor) { - if (descriptor instanceof ConstructorDescriptor) { - DeclarationDescriptor classDescriptor = descriptor.getContainingDeclaration(); - assert classDescriptor != null; - return isOwnedByClass(classDescriptor); - } - return (descriptor.getContainingDeclaration() instanceof ClassDescriptor); - } - @NotNull public static ResolvedCall getResolvedCall(@NotNull BindingContext context, @NotNull JetExpression expression) { @@ -321,7 +296,7 @@ public final class BindingUtils { for (JetFile file : files) { NamespaceDescriptor namespaceDescriptor = getNamespaceDescriptor(context, file); if (!AnnotationsUtils.isPredefinedObject(namespaceDescriptor)) { - descriptorSet.add(namespaceDescriptor); + descriptorSet.addAll(getNamespaceDescriptorHierarchy(namespaceDescriptor)); } } return descriptorSet; @@ -338,8 +313,7 @@ public final class BindingUtils { @NotNull public static ResolvedCall getResolvedCallForArrayAccess(@NotNull BindingContext context, @NotNull JetArrayAccessExpression arrayAccessExpression, - boolean isGet - ) { + boolean isGet) { ResolvedCall resolvedCall = context.get(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/DescriptorUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/DescriptorUtils.java index 2e81d7fe3e6..f47adab3ed9 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/DescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/DescriptorUtils.java @@ -81,13 +81,9 @@ public final class DescriptorUtils { @NotNull public static PropertyDescriptor getPropertyByName(@NotNull JetScope scope, @NotNull String name) { - VariableDescriptor variable = scope.getLocalVariable(name); - if (variable == null) { - variable = scope.getPropertyByFieldReference("$" + name); - } Set variables = scope.getProperties(name); assert variables.size() == 1 : "Actual size: " + variables.size(); - variable = variables.iterator().next(); + VariableDescriptor variable = variables.iterator().next(); PropertyDescriptor descriptor = (PropertyDescriptor) variable; assert descriptor != null : "Must have a descriptor."; return descriptor; @@ -208,10 +204,7 @@ public final class DescriptorUtils { @NotNull public static List getAllClassesDefinedInNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { List classDescriptors = Lists.newArrayList(); - for (DeclarationDescriptor descriptor : namespaceDescriptor.getMemberScope().getAllDescriptors()) { - if (AnnotationsUtils.isPredefinedObject(descriptor)) { - continue; - } + for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) { if (descriptor instanceof ClassDescriptor) { classDescriptors.add((ClassDescriptor) descriptor); } @@ -219,6 +212,17 @@ public final class DescriptorUtils { return classDescriptors; } + @NotNull + public static List getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor) { + List result = Lists.newArrayList(); + for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) { + if (descriptor instanceof NamespaceDescriptor) { + result.add((NamespaceDescriptor) descriptor); + } + } + return result; + } + @Nullable public static FunctionDescriptor getOverriddenDescriptor(@NotNull FunctionDescriptor functionDescriptor) { Set overriddenDescriptors = functionDescriptor.getOverriddenDescriptors(); @@ -242,4 +246,49 @@ public final class DescriptorUtils { // return functionDescriptor; // } // } + + @NotNull + public static List getContainedDescriptorsWhichAreNotPredefined + (@NotNull NamespaceDescriptor namespace) { + List result = Lists.newArrayList(); + for (DeclarationDescriptor descriptor : namespace.getMemberScope().getAllDescriptors()) { + if (!AnnotationsUtils.isPredefinedObject(descriptor)) { + result.add(descriptor); + } + } + return result; + } + + //TODO: at the moment this check is very ineffective + public static boolean isNamespaceEmpty(@NotNull NamespaceDescriptor namespace) { + List containedDescriptors = getContainedDescriptorsWhichAreNotPredefined(namespace); + for (DeclarationDescriptor descriptor : containedDescriptors) { + if (descriptor instanceof NamespaceDescriptor) { + if (!isNamespaceEmpty((NamespaceDescriptor) descriptor)) { + return false; + } + } + else { + return false; + } + } + return true; + } + + @NotNull + public static List getNamespaceDescriptorHierarchy(@NotNull NamespaceDescriptor namespaceDescriptor) { + List result = Lists.newArrayList(namespaceDescriptor); + NamespaceDescriptor current = namespaceDescriptor; + while (!current.getName().equals("")) { + result.add(current); + if (current.getContainingDeclaration() instanceof NamespaceDescriptor) { + current = (NamespaceDescriptor) current.getContainingDeclaration(); + assert current != null; + } + else { + break; + } + } + return result; + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/PartiallyOrderedSet.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/PartiallyOrderedSet.java index 86d1f90a473..79be5ba4890 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/PartiallyOrderedSet.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/PartiallyOrderedSet.java @@ -45,7 +45,7 @@ public final class PartiallyOrderedSet { } public interface Order { - boolean firstDependsOnSecond(@NotNull Element first, @NotNull Element Second); + boolean firstDependsOnSecond(@NotNull Element first, @NotNull Element second); } @NotNull diff --git a/js/js.translator/testFiles/kotlin_lib.js b/js/js.translator/testFiles/kotlin_lib.js index 82ad77cca64..8c2b828a74a 100644 --- a/js/js.translator/testFiles/kotlin_lib.js +++ b/js/js.translator/testFiles/kotlin_lib.js @@ -233,7 +233,6 @@ var Kotlin; } function create() { - var result = {}; for (var i = 0, length = arguments.length; i < length; i++) { add(result, arguments[i]);