implement multinamespace translation:

creating classes altogether before namespaces
better implementation of NamespaceDeclarationTranslator
This commit is contained in:
Pavel Talanov
2012-02-21 17:40:15 +04:00
parent 6ca5b732de
commit af28455e5b
4 changed files with 79 additions and 44 deletions
@@ -39,8 +39,8 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
@Nullable
private JsStatement declarationsStatement = null;
public ClassDeclarationTranslator(@NotNull TranslationContext context,
@NotNull List<ClassDescriptor> descriptors) {
public ClassDeclarationTranslator(@NotNull List<ClassDescriptor> descriptors,
@NotNull TranslationContext context) {
super(context);
this.descriptors = descriptors;
this.localToGlobalClassName = new HashMap<JsName, JsName>();
@@ -3,15 +3,17 @@ package org.jetbrains.k2js.translate.declaration;
import com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
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.general.Translation;
import java.util.List;
import java.util.Set;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getAllNonNativeNamespaceDescriptors;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getAllClassesDefinedInNamespace;
/**
* @author Pavel Talanov
@@ -19,14 +21,76 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.getAllNonNativeNam
public final class NamespaceDeclarationTranslator extends AbstractTranslator {
public static List<JsStatement> translateFiles(@NotNull List<JetFile> files, @NotNull TranslationContext context) {
List<JsStatement> result = Lists.newArrayList();
for (NamespaceDescriptor namespaceDescriptor : getAllNonNativeNamespaceDescriptors(context.bindingContext(), files)) {
result.add(Translation.translateNamespace(namespaceDescriptor, context));
Set<NamespaceDescriptor> namespaceDescriptorSet = getAllNonNativeNamespaceDescriptors(context.bindingContext(), files);
return (new NamespaceDeclarationTranslator(Lists.newArrayList(namespaceDescriptorSet), context)).translate();
}
@NotNull
private final ClassDeclarationTranslator classDeclarationTranslator;
@NotNull
private final List<NamespaceDescriptor> namespaceDescriptors;
private NamespaceDeclarationTranslator(@NotNull List<NamespaceDescriptor> namespaceDescriptors,
@NotNull TranslationContext context) {
super(context);
this.namespaceDescriptors = namespaceDescriptors;
this.classDeclarationTranslator = new ClassDeclarationTranslator(getAllClasses(), context);
}
@NotNull
private List<ClassDescriptor> getAllClasses() {
List<ClassDescriptor> result = Lists.newArrayList();
for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) {
result.addAll(getAllClassesDefinedInNamespace(namespaceDescriptor));
}
return result;
}
private NamespaceDeclarationTranslator(@NotNull TranslationContext context) {
super(context);
//TODO: logic seems not so clear, may be a couple of extract method should help
@NotNull
private List<JsStatement> translate() {
classDeclarationTranslator.generateDeclarations();
List<JsStatement> result = Lists.newArrayList();
result.add(classDeclarationsStatement());
List<NamespaceTranslator> namespaceTranslators = getTranslatorsForNonEmptyNamespaces();
result.addAll(declarationStatements(namespaceTranslators));
result.addAll(initializeStatements(namespaceTranslators));
return result;
}
@NotNull
private JsStatement classDeclarationsStatement() {
return classDeclarationTranslator.getDeclarationsStatement();
}
@NotNull
private List<NamespaceTranslator> getTranslatorsForNonEmptyNamespaces() {
List<NamespaceTranslator> namespaceTranslators = Lists.newArrayList();
for (NamespaceDescriptor descriptor : namespaceDescriptors) {
NamespaceTranslator namespaceTranslator =
new NamespaceTranslator(descriptor, classDeclarationTranslator, context());
if (!namespaceTranslator.isNamespaceEmpty()) {
namespaceTranslators.add(namespaceTranslator);
}
}
return namespaceTranslators;
}
@NotNull
private List<JsStatement> declarationStatements(@NotNull List<NamespaceTranslator> namespaceTranslators) {
List<JsStatement> result = Lists.newArrayList();
for (NamespaceTranslator translator : namespaceTranslators) {
result.add(translator.getDeclarationStatement());
}
return result;
}
@NotNull
private List<JsStatement> initializeStatements(@NotNull List<NamespaceTranslator> namespaceTranslators) {
List<JsStatement> result = Lists.newArrayList();
for (NamespaceTranslator translator : namespaceTranslators) {
result.add(translator.getInitializeStatement());
}
return result;
}
}
@@ -13,8 +13,6 @@ import org.jetbrains.k2js.translate.utils.BindingUtils;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getAllClassesDefinedInNamespace;
/**
* @author Pavel.Talanov
* <p/>
@@ -29,44 +27,24 @@ public final class NamespaceTranslator extends AbstractTranslator {
@NotNull
private final ClassDeclarationTranslator classDeclarationTranslator;
@NotNull
public static JsStatement translateNamespace(@NotNull NamespaceDescriptor namespace,
@NotNull TranslationContext context) {
return (new NamespaceTranslator(namespace, context)).translateNamespace();
}
private NamespaceTranslator(@NotNull NamespaceDescriptor descriptor, @NotNull TranslationContext context) {
/*package*/ NamespaceTranslator(@NotNull NamespaceDescriptor descriptor,
@NotNull ClassDeclarationTranslator classDeclarationTranslator,
@NotNull TranslationContext context) {
super(context.newDeclaration(descriptor));
this.descriptor = descriptor;
this.namespaceName = context.getNameForDescriptor(descriptor);
this.classDeclarationTranslator = new ClassDeclarationTranslator(context(),
getAllClassesDefinedInNamespace(descriptor));
}
@NotNull
public JsStatement translateNamespace() {
if (isNamespaceEmpty()) {
return program().getEmptyStmt();
}
classDeclarationTranslator.generateDeclarations();
return AstUtil.newBlock(classDeclarationsStatement(),
namespaceOwnDeclarationStatement(),
namespaceInitializeStatement());
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
private boolean isNamespaceEmpty() {
public boolean isNamespaceEmpty() {
return BindingUtils.getDeclarationsForNamespace(context().bindingContext(), descriptor).isEmpty();
}
@NotNull
private JsStatement classDeclarationsStatement() {
return classDeclarationTranslator.getDeclarationsStatement();
}
@NotNull
private JsStatement namespaceInitializeStatement() {
public JsStatement getInitializeStatement() {
JsNameRef initializeMethodReference = Namer.initializeMethodReference();
AstUtil.setQualifier(initializeMethodReference, namespaceName.makeRef());
return AstUtil.newInvocation(initializeMethodReference).makeStmt();
@@ -78,7 +56,7 @@ public final class NamespaceTranslator extends AbstractTranslator {
}
@NotNull
private JsStatement namespaceOwnDeclarationStatement() {
public JsStatement getDeclarationStatement() {
JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation();
addMemberDeclarations(namespaceDeclaration);
addClassesDeclarations(namespaceDeclaration);
@@ -14,7 +14,6 @@ import org.jetbrains.k2js.translate.context.StaticContext;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.declaration.ClassTranslator;
import org.jetbrains.k2js.translate.declaration.NamespaceDeclarationTranslator;
import org.jetbrains.k2js.translate.declaration.NamespaceTranslator;
import org.jetbrains.k2js.translate.expression.ExpressionVisitor;
import org.jetbrains.k2js.translate.expression.FunctionTranslator;
import org.jetbrains.k2js.translate.expression.PatternTranslator;
@@ -38,12 +37,6 @@ public final class Translation {
return FunctionTranslator.newInstance(function, context);
}
@NotNull
public static JsStatement translateNamespace(@NotNull NamespaceDescriptor namespace,
@NotNull TranslationContext context) {
return NamespaceTranslator.translateNamespace(namespace, context);
}
@NotNull
public static List<JsStatement> translateFiles(@NotNull List<JetFile> files, @NotNull TranslationContext context) {
return NamespaceDeclarationTranslator.translateFiles(files, context);