Support a simple case with nested namespaces.

This commit is contained in:
Pavel V. Talanov
2012-03-15 22:26:59 +04:00
parent 452bbdce4d
commit ff3c0a20a0
7 changed files with 95 additions and 61 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.k2js.translate.declaration; 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.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil; import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -150,10 +151,10 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
} }
@NotNull @NotNull
public JsObjectLiteral classDeclarationsForNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { public List<JsPropertyInitializer> classDeclarationsForNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
JsObjectLiteral result = new JsObjectLiteral(); List<JsPropertyInitializer> result = Lists.newArrayList();
for (ClassDescriptor classDescriptor : getAllClassesDefinedInNamespace(namespaceDescriptor)) { for (ClassDescriptor classDescriptor : getAllClassesDefinedInNamespace(namespaceDescriptor)) {
result.getPropertyInitializers().add(getClassNameToClassObject(classDescriptor)); result.add(getClassNameToClassObject(classDescriptor));
} }
return result; return result;
} }
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
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;
import org.jetbrains.k2js.translate.utils.DescriptorUtils;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -90,10 +91,8 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
private List<NamespaceTranslator> getTranslatorsForNonEmptyNamespaces() { private List<NamespaceTranslator> getTranslatorsForNonEmptyNamespaces() {
List<NamespaceTranslator> namespaceTranslators = Lists.newArrayList(); List<NamespaceTranslator> namespaceTranslators = Lists.newArrayList();
for (NamespaceDescriptor descriptor : namespaceDescriptors) { for (NamespaceDescriptor descriptor : namespaceDescriptors) {
NamespaceTranslator namespaceTranslator = if (!DescriptorUtils.isNamespaceEmpty(descriptor)) {
new NamespaceTranslator(descriptor, classDeclarationTranslator, context()); namespaceTranslators.add(new NamespaceTranslator(descriptor, classDeclarationTranslator, context()));
if (!namespaceTranslator.isNamespaceEmpty()) {
namespaceTranslators.add(namespaceTranslator);
} }
} }
return namespaceTranslators; return namespaceTranslators;
@@ -16,6 +16,7 @@
package org.jetbrains.k2js.translate.declaration; 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.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil; import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull; 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.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation; 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.ArrayList;
import java.util.List; import java.util.List;
@@ -54,12 +55,6 @@ public final class NamespaceTranslator extends AbstractTranslator {
this.classDeclarationTranslator = classDeclarationTranslator; 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 @NotNull
public JsStatement getInitializeStatement() { public JsStatement getInitializeStatement() {
@@ -76,18 +71,35 @@ public final class NamespaceTranslator extends AbstractTranslator {
@NotNull @NotNull
public JsStatement getDeclarationStatement() { public JsStatement getDeclarationStatement() {
JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation(); JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation();
addMemberDeclarations(namespaceDeclaration); namespaceDeclaration.getArguments().add(translateNamespaceMemberDeclarations());
addClassesDeclarations(namespaceDeclaration); namespaceDeclaration.getArguments().add(getClassesAndNestedNamespaces());
return newVar(namespaceName, namespaceDeclaration); return newVar(namespaceName, namespaceDeclaration);
} }
private void addClassesDeclarations(@NotNull JsInvocation namespaceDeclaration) { @NotNull
namespaceDeclaration.getArguments().add(classDeclarationTranslator.classDeclarationsForNamespace(descriptor)); private JsObjectLiteral getClassesAndNestedNamespaces() {
JsObjectLiteral classesAndNestedNamespaces = new JsObjectLiteral();
classesAndNestedNamespaces.getPropertyInitializers()
.addAll(getClassesDefined());
classesAndNestedNamespaces.getPropertyInitializers()
.addAll(getNestedNamespaceDeclarations());
return classesAndNestedNamespaces;
} }
private void addMemberDeclarations(@NotNull JsInvocation jsNamespace) { @NotNull
JsObjectLiteral jsClassDescription = translateNamespaceMemberDeclarations(); private List<JsPropertyInitializer> getClassesDefined() {
jsNamespace.getArguments().add(jsClassDescription); return classDeclarationTranslator.classDeclarationsForNamespace(descriptor);
}
@NotNull
private List<JsPropertyInitializer> getNestedNamespaceDeclarations() {
List<JsPropertyInitializer> result = Lists.newArrayList();
List<NamespaceDescriptor> nestedNamespaces = DescriptorUtils.getNestedNamespaces(descriptor);
for (NamespaceDescriptor nestedNamespace : nestedNamespaces) {
JsName nameForDescriptor = context().getNameForDescriptor(nestedNamespace);
result.add(new JsPropertyInitializer(nameForDescriptor.makeRef(), nameForDescriptor.makeRef()));
}
return result;
} }
@NotNull @NotNull
@@ -97,11 +97,7 @@ public final class BindingUtils {
public static List<JetDeclaration> getDeclarationsForNamespace(@NotNull BindingContext bindingContext, public static List<JetDeclaration> getDeclarationsForNamespace(@NotNull BindingContext bindingContext,
@NotNull NamespaceDescriptor namespace) { @NotNull NamespaceDescriptor namespace) {
List<JetDeclaration> declarations = new ArrayList<JetDeclaration>(); List<JetDeclaration> declarations = new ArrayList<JetDeclaration>();
for (DeclarationDescriptor descriptor : namespace.getMemberScope().getAllDescriptors()) { for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespace)) {
if (AnnotationsUtils.isPredefinedObject(descriptor)) {
continue;
}
//TODO:
if (descriptor instanceof NamespaceDescriptor) { if (descriptor instanceof NamespaceDescriptor) {
continue; continue;
} }
@@ -199,27 +195,6 @@ public final class BindingUtils {
return !superClassDescriptor.equals(JetStandardClasses.getAny()); 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 @NotNull
public static ResolvedCall<?> getResolvedCall(@NotNull BindingContext context, public static ResolvedCall<?> getResolvedCall(@NotNull BindingContext context,
@NotNull JetExpression expression) { @NotNull JetExpression expression) {
@@ -321,7 +296,7 @@ public final class BindingUtils {
for (JetFile file : files) { for (JetFile file : files) {
NamespaceDescriptor namespaceDescriptor = getNamespaceDescriptor(context, file); NamespaceDescriptor namespaceDescriptor = getNamespaceDescriptor(context, file);
if (!AnnotationsUtils.isPredefinedObject(namespaceDescriptor)) { if (!AnnotationsUtils.isPredefinedObject(namespaceDescriptor)) {
descriptorSet.add(namespaceDescriptor); descriptorSet.addAll(getNamespaceDescriptorHierarchy(namespaceDescriptor));
} }
} }
return descriptorSet; return descriptorSet;
@@ -338,8 +313,7 @@ public final class BindingUtils {
@NotNull @NotNull
public static ResolvedCall<FunctionDescriptor> getResolvedCallForArrayAccess(@NotNull BindingContext context, public static ResolvedCall<FunctionDescriptor> getResolvedCallForArrayAccess(@NotNull BindingContext context,
@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetArrayAccessExpression arrayAccessExpression,
boolean isGet boolean isGet) {
) {
ResolvedCall<FunctionDescriptor> resolvedCall = context.get(isGet ResolvedCall<FunctionDescriptor> resolvedCall = context.get(isGet
? INDEXED_LVALUE_GET ? INDEXED_LVALUE_GET
: INDEXED_LVALUE_SET, arrayAccessExpression); : INDEXED_LVALUE_SET, arrayAccessExpression);
@@ -81,13 +81,9 @@ public final class DescriptorUtils {
@NotNull @NotNull
public static PropertyDescriptor getPropertyByName(@NotNull JetScope scope, public static PropertyDescriptor getPropertyByName(@NotNull JetScope scope,
@NotNull String name) { @NotNull String name) {
VariableDescriptor variable = scope.getLocalVariable(name);
if (variable == null) {
variable = scope.getPropertyByFieldReference("$" + name);
}
Set<VariableDescriptor> variables = scope.getProperties(name); Set<VariableDescriptor> variables = scope.getProperties(name);
assert variables.size() == 1 : "Actual size: " + variables.size(); assert variables.size() == 1 : "Actual size: " + variables.size();
variable = variables.iterator().next(); VariableDescriptor variable = variables.iterator().next();
PropertyDescriptor descriptor = (PropertyDescriptor) variable; PropertyDescriptor descriptor = (PropertyDescriptor) variable;
assert descriptor != null : "Must have a descriptor."; assert descriptor != null : "Must have a descriptor.";
return descriptor; return descriptor;
@@ -208,10 +204,7 @@ public final class DescriptorUtils {
@NotNull @NotNull
public static List<ClassDescriptor> getAllClassesDefinedInNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { public static List<ClassDescriptor> getAllClassesDefinedInNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
List<ClassDescriptor> classDescriptors = Lists.newArrayList(); List<ClassDescriptor> classDescriptors = Lists.newArrayList();
for (DeclarationDescriptor descriptor : namespaceDescriptor.getMemberScope().getAllDescriptors()) { for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) {
if (AnnotationsUtils.isPredefinedObject(descriptor)) {
continue;
}
if (descriptor instanceof ClassDescriptor) { if (descriptor instanceof ClassDescriptor) {
classDescriptors.add((ClassDescriptor) descriptor); classDescriptors.add((ClassDescriptor) descriptor);
} }
@@ -219,6 +212,17 @@ public final class DescriptorUtils {
return classDescriptors; return classDescriptors;
} }
@NotNull
public static List<NamespaceDescriptor> getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor) {
List<NamespaceDescriptor> result = Lists.newArrayList();
for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) {
if (descriptor instanceof NamespaceDescriptor) {
result.add((NamespaceDescriptor) descriptor);
}
}
return result;
}
@Nullable @Nullable
public static FunctionDescriptor getOverriddenDescriptor(@NotNull FunctionDescriptor functionDescriptor) { public static FunctionDescriptor getOverriddenDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
Set<? extends FunctionDescriptor> overriddenDescriptors = functionDescriptor.getOverriddenDescriptors(); Set<? extends FunctionDescriptor> overriddenDescriptors = functionDescriptor.getOverriddenDescriptors();
@@ -242,4 +246,49 @@ public final class DescriptorUtils {
// return functionDescriptor; // return functionDescriptor;
// } // }
// } // }
@NotNull
public static List<DeclarationDescriptor> getContainedDescriptorsWhichAreNotPredefined
(@NotNull NamespaceDescriptor namespace) {
List<DeclarationDescriptor> 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<DeclarationDescriptor> 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<NamespaceDescriptor> getNamespaceDescriptorHierarchy(@NotNull NamespaceDescriptor namespaceDescriptor) {
List<NamespaceDescriptor> result = Lists.newArrayList(namespaceDescriptor);
NamespaceDescriptor current = namespaceDescriptor;
while (!current.getName().equals("<root>")) {
result.add(current);
if (current.getContainingDeclaration() instanceof NamespaceDescriptor) {
current = (NamespaceDescriptor) current.getContainingDeclaration();
assert current != null;
}
else {
break;
}
}
return result;
}
} }
@@ -45,7 +45,7 @@ public final class PartiallyOrderedSet<Element> {
} }
public interface Order<Element> { public interface Order<Element> {
boolean firstDependsOnSecond(@NotNull Element first, @NotNull Element Second); boolean firstDependsOnSecond(@NotNull Element first, @NotNull Element second);
} }
@NotNull @NotNull
-1
View File
@@ -233,7 +233,6 @@ var Kotlin;
} }
function create() { function create() {
var result = {}; var result = {};
for (var i = 0, length = arguments.length; i < length; i++) { for (var i = 0, length = arguments.length; i < length; i++) {
add(result, arguments[i]); add(result, arguments[i]);