From ba767e72052083386a8b4f10c4d9dfc3bfec1ec0 Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Tue, 29 Nov 2011 17:29:32 +0400 Subject: [PATCH] Reworked ExtractionVisitor into Declaration visitor. --- .../k2js/declarations/DeclarationContext.java | 46 ++++++ .../k2js/declarations/DeclarationVisitor.java | 139 ++++++++++++++++++ .../k2js/declarations/Declarations.java | 54 +++++-- .../k2js/declarations/ExtractionVisitor.java | 130 ---------------- .../k2js/translate/general/Translation.java | 5 +- .../reference/ReferenceTranslator.java | 1 + 6 files changed, 230 insertions(+), 145 deletions(-) create mode 100644 translator/src/org/jetbrains/k2js/declarations/DeclarationContext.java create mode 100644 translator/src/org/jetbrains/k2js/declarations/DeclarationVisitor.java delete mode 100644 translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java diff --git a/translator/src/org/jetbrains/k2js/declarations/DeclarationContext.java b/translator/src/org/jetbrains/k2js/declarations/DeclarationContext.java new file mode 100644 index 00000000000..d553d21a74c --- /dev/null +++ b/translator/src/org/jetbrains/k2js/declarations/DeclarationContext.java @@ -0,0 +1,46 @@ +package org.jetbrains.k2js.declarations; + +import com.google.dart.compiler.backend.js.ast.JsName; +import com.google.dart.compiler.backend.js.ast.JsNameRef; +import com.google.dart.compiler.backend.js.ast.JsScope; +import com.google.dart.compiler.util.AstUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class DeclarationContext { + + @NotNull + public static DeclarationContext rootContext(@NotNull JsScope scope, @Nullable JsNameRef qualifier) { + return new DeclarationContext(scope, qualifier); + } + + @NotNull + private final JsScope scope; + + @Nullable + private final JsNameRef qualifier; + + private DeclarationContext(@NotNull JsScope scope, @Nullable JsNameRef qualifier) { + this.scope = scope; + this.qualifier = qualifier; + } + + @NotNull + public JsScope getScope() { + return scope; + } + + @Nullable + public JsNameRef getQualifier() { + return qualifier; + } + + @NotNull + public DeclarationContext innerDeclaration(@NotNull JsScope declarationScope, @NotNull JsName declarationName) { + JsNameRef reference = declarationName.makeRef(); + if (qualifier != null) { + AstUtil.setQualifier(reference, qualifier); + } + return new DeclarationContext(declarationScope, reference); + } +} \ No newline at end of file diff --git a/translator/src/org/jetbrains/k2js/declarations/DeclarationVisitor.java b/translator/src/org/jetbrains/k2js/declarations/DeclarationVisitor.java new file mode 100644 index 00000000000..b4de4eb32a3 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/declarations/DeclarationVisitor.java @@ -0,0 +1,139 @@ +package org.jetbrains.k2js.declarations; + +import com.google.dart.compiler.backend.js.ast.JsName; +import com.google.dart.compiler.backend.js.ast.JsScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.k2js.translate.utils.Namer; + +/** + * @author Talanov Pavel + */ +public final class DeclarationVisitor extends DeclarationDescriptorVisitor { + + @NotNull + private final Declarations declarations; + + /*package*/ DeclarationVisitor(@NotNull Declarations declarations) { + this.declarations = declarations; + } + + @Override + public Void visitClassDescriptor(@NotNull ClassDescriptor descriptor, @NotNull DeclarationContext context) { + DeclarationContext classContext = declareClass(descriptor, context); + declareClassConstructor(descriptor, context); + declareClassMembers(descriptor, classContext); + return null; + } + + @NotNull + private DeclarationContext declareClass(@NotNull ClassDescriptor descriptor, + @NotNull DeclarationContext context) { + JsScope classScope = declareScope(descriptor, context, "class " + descriptor.getName()); + JsName className = declareName(descriptor, context); + return context.innerDeclaration(classScope, className); + } + + private JsScope declareScope(@NotNull DeclarationDescriptor descriptor, @NotNull DeclarationContext context, + @NotNull String scopeName) { + JsScope classScope = new JsScope(context.getScope(), scopeName); + declarations.putScope(descriptor, classScope); + return classScope; + } + + @NotNull + private JsName declareName(@NotNull DeclarationDescriptor descriptor, @NotNull DeclarationContext context, + @NotNull String name) { + JsName jsName = context.getScope().declareName(name); + declarations.putName(descriptor, jsName); + declarations.putQualifier(descriptor, context.getQualifier()); + return jsName; + } + + @NotNull + private JsName declareName(@NotNull DeclarationDescriptor descriptor, + @NotNull DeclarationContext context) { + return declareName(descriptor, context, descriptor.getName()); + } + + private void declareClassMembers(@NotNull ClassDescriptor descriptor, @NotNull DeclarationContext context) { + for (DeclarationDescriptor memberDescriptor : + descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { + memberDescriptor.accept(this, context); + } + } + + private void declareClassConstructor(@NotNull ClassDescriptor descriptor, @NotNull DeclarationContext context) { + for (ConstructorDescriptor constructorDescriptor : descriptor.getConstructors()) { + constructorDescriptor.accept(this, context); + } + } + + @Override + public Void visitConstructorDescriptor(@NotNull ConstructorDescriptor descriptor, + @NotNull DeclarationContext context) { + JsName alreadyDeclaredClassName = declarations.getName(descriptor.getContainingDeclaration()); + declarations.putName(descriptor, alreadyDeclaredClassName); + return null; + } + + @Override + public Void visitFunctionDescriptor(@NotNull FunctionDescriptor descriptor, @NotNull DeclarationContext context) { + declareName(descriptor, context); + declareScope(descriptor, context, "function " + descriptor.getName()); + return null; + } + + @Override + public Void visitPropertyDescriptor(@NotNull PropertyDescriptor descriptor, @NotNull DeclarationContext context) { + String propertyName = descriptor.getName(); + String backingFieldName = Namer.getKotlinBackingFieldName(propertyName); + declareName(descriptor, context, backingFieldName); + extractAccessor(descriptor.getGetter(), true, propertyName, context); + if (descriptor.isVar()) { + extractAccessor(descriptor.getSetter(), false, propertyName, context); + } + return null; + } + + public void extractAccessor(@Nullable PropertyAccessorDescriptor descriptor, boolean isGetter, + @NotNull String propertyName, @NotNull DeclarationContext context) { + assert descriptor != null : "Accessor descriptor should not be null"; + String accessorName = Namer.getNameForAccessor(propertyName, isGetter); + declareName(descriptor, context, accessorName); + declareScope(descriptor, context, (isGetter ? "getter " : "setter ") + propertyName); + } + + @Override + public Void visitNamespaceDescriptor(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) { + DeclarationContext namespaceContext = extractNamespaceDeclaration(descriptor, context); + visitMemberDeclarations(descriptor, namespaceContext); + return null; + } + + @NotNull + private DeclarationContext extractNamespaceDeclaration(@NotNull NamespaceDescriptor descriptor, + @NotNull DeclarationContext context) { + JsName namespaceName = declareName(descriptor, context, nameForNamespace(descriptor)); + JsScope namespaceScope = declareScope(descriptor, context, "namespace " + namespaceName.getIdent()); + return context.innerDeclaration(namespaceScope, namespaceName); + } + + @NotNull + private String nameForNamespace(@NotNull NamespaceDescriptor descriptor) { + String name = descriptor.getName(); + if (name.equals("")) { + return "Anonymous"; + } + return name; + } + + private void visitMemberDeclarations(@NotNull NamespaceDescriptor descriptor, @NotNull DeclarationContext context) { + for (DeclarationDescriptor memberDescriptor : + descriptor.getMemberScope().getAllDescriptors()) { + memberDescriptor.accept(this, context); + } + } + +} diff --git a/translator/src/org/jetbrains/k2js/declarations/Declarations.java b/translator/src/org/jetbrains/k2js/declarations/Declarations.java index 4aa19b139ce..2e41e2b4f57 100644 --- a/translator/src/org/jetbrains/k2js/declarations/Declarations.java +++ b/translator/src/org/jetbrains/k2js/declarations/Declarations.java @@ -1,9 +1,12 @@ package org.jetbrains.k2js.declarations; import com.google.dart.compiler.backend.js.ast.JsName; +import com.google.dart.compiler.backend.js.ast.JsNameRef; import com.google.dart.compiler.backend.js.ast.JsScope; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.types.JetStandardLibrary; import java.util.HashMap; import java.util.Map; @@ -12,46 +15,69 @@ import java.util.Map; * @author Talanov Pavel */ public final class Declarations { - private final Map descriptorToScopeMap - = new HashMap(); - private final Map descriptorToNameMap - = new HashMap(); - - private Declarations() { + @NotNull + private final Map descriptorToScopeMap = new HashMap(); + @NotNull + private final Map descriptorToNameMap = new HashMap(); + @NotNull + private final Map descriptorToQualifierMap = new HashMap(); + @NotNull + private final JsScope rootScope; + private Declarations(@NotNull JsScope scope) { + this.rootScope = scope; } @NotNull - static public Declarations extractDeclarations(@NotNull DeclarationDescriptor descriptor, JsScope rootScope) { - Declarations declarations = new Declarations(); - ExtractionVisitor visitor = new ExtractionVisitor(declarations); - descriptor.accept(visitor, rootScope); - return declarations; + static public Declarations newInstance(@NotNull JsScope rootScope) { + return new Declarations(rootScope); + } + + public void extractDeclarations(@NotNull DeclarationDescriptor descriptor) { + DeclarationVisitor visitor = new DeclarationVisitor(this); + descriptor.accept(visitor, DeclarationContext.rootContext(rootScope, null)); + } + + //TODO: provide a mechanism to do intrinsics + public void extractStandardLibrary(@NotNull JetStandardLibrary standardLibrary) { + DeclarationVisitor visitor = new DeclarationVisitor(this); +// for (DeclarationDescriptor descriptor : +// standardLibrary.getLibraryScope().getAllDescriptors()) { +// descriptor.accept(visitor, rootScope); +// } + // standardLibrary.getArray().accept(visitor, rootScope); } @NotNull public JsScope getScope(@NotNull DeclarationDescriptor descriptor) { - JsScope scope = descriptorToScopeMap.get(descriptor); + JsScope scope = descriptorToScopeMap.get(descriptor.getOriginal()); assert scope != null : "Unknown declaration"; return scope; } @NotNull public JsName getName(@NotNull DeclarationDescriptor descriptor) { - JsName name = descriptorToNameMap.get(descriptor); + JsName name = descriptorToNameMap.get(descriptor.getOriginal()); assert name != null : "Unknown declaration"; return name; } public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) { - return descriptorToNameMap.containsKey(descriptor); + return descriptorToNameMap.containsKey(descriptor.getOriginal()); } /*package*/ void putScope(@NotNull DeclarationDescriptor descriptor, @NotNull JsScope scope) { + assert !descriptorToScopeMap.containsKey(descriptor) : "Already contains that key!"; descriptorToScopeMap.put(descriptor, scope); } /*package*/ void putName(@NotNull DeclarationDescriptor descriptor, @NotNull JsName name) { + assert !descriptorToNameMap.containsKey(descriptor) : "Already contains that key!"; descriptorToNameMap.put(descriptor, name); } + + /*package*/ void putQualifier(@NotNull DeclarationDescriptor descriptor, @Nullable JsNameRef qualifier) { + assert !descriptorToQualifierMap.containsKey(descriptor) : "Already contains that key!"; + descriptorToQualifierMap.put(descriptor, qualifier); + } } diff --git a/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java b/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java deleted file mode 100644 index 320c921aecc..00000000000 --- a/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.jetbrains.k2js.declarations; - -import com.google.dart.compiler.backend.js.ast.JsName; -import com.google.dart.compiler.backend.js.ast.JsScope; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.k2js.translate.utils.Namer; - -/** - * @author Talanov Pavel - */ -public final class ExtractionVisitor extends DeclarationDescriptorVisitor { - - @NotNull - private final Declarations declarations; - - /*package*/ ExtractionVisitor(@NotNull Declarations declarations) { - this.declarations = declarations; - } - - @Override - public Void visitClassDescriptor(@NotNull ClassDescriptor descriptor, @NotNull JsScope enclosingScope) { - JsScope classScope = extractClassDeclarations(descriptor, enclosingScope); - visitClassMembers(descriptor, classScope); - return null; - } - - @NotNull - private JsScope extractClassDeclarations(@NotNull ClassDescriptor descriptor, @NotNull JsScope enclosingScope) { - String className = descriptor.getName(); - declarations.putName(descriptor, enclosingScope.declareName(className)); - JsScope classScope = new JsScope(enclosingScope, "class " + className); - declarations.putScope(descriptor, classScope); - return classScope; - } - - private void visitClassMembers(@NotNull ClassDescriptor descriptor, @NotNull JsScope classScope) { - visitClassConstructor(descriptor, classScope); - for (DeclarationDescriptor memberDescriptor : - descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { - memberDescriptor.accept(this, classScope); - } - } - - private void visitClassConstructor(@NotNull ClassDescriptor descriptor, @NotNull JsScope classScope) { - for (ConstructorDescriptor constructorDescriptor : descriptor.getConstructors()) { - constructorDescriptor.accept(this, classScope); - } - } - - //TODO: think about the ways to make this less hacky - //For now constructor just references the name of the class. Initialize method scope is defined independently. - @Override - public Void visitConstructorDescriptor(@NotNull ConstructorDescriptor descriptor, @NotNull JsScope enclosingScope) { - String className = descriptor.getContainingDeclaration().getName(); - JsName alreadyDeclaredClassName = enclosingScope.findExistingName(className); - declarations.putName(descriptor, alreadyDeclaredClassName); - return null; - } - - @Override - public Void visitFunctionDescriptor(@NotNull FunctionDescriptor descriptor, @NotNull JsScope enclosingScope) { - String functionName = descriptor.getName(); - declarations.putName(descriptor, enclosingScope.declareName(functionName)); - JsScope functionScope = new JsScope(enclosingScope, "function " + functionName); - declarations.putScope(descriptor, functionScope); - return null; - } - - @Override - public Void visitPropertyDescriptor(@NotNull PropertyDescriptor descriptor, @NotNull JsScope enclosingScope) { - String propertyName = descriptor.getName(); - declarations.putName(descriptor, enclosingScope.declareName(Namer.getKotlinBackingFieldName(propertyName))); - extractAccessor(descriptor.getGetter(), true, propertyName, enclosingScope); - if (descriptor.isVar()) { - extractAccessor(descriptor.getSetter(), false, propertyName, enclosingScope); - } - return null; - } - - //Not using visitors here for convenience - public void extractAccessor(@Nullable PropertyAccessorDescriptor descriptor, boolean isGetter, String propertyName, - @NotNull JsScope enclosingScope) { - assert descriptor != null : "Accessor descriptor should not be null"; - String accessorName = Namer.getNameForAccessor(propertyName, isGetter); - JsName jsName = enclosingScope.declareName(accessorName); - JsScope accessorScope = new JsScope(enclosingScope, (isGetter ? "getter " : "setter ") + propertyName); - declarations.putScope(descriptor, accessorScope); - declarations.putName(descriptor, jsName); - } - - @Override - public Void visitNamespaceDescriptor(@NotNull NamespaceDescriptor descriptor, @NotNull JsScope enclosingScope) { - JsScope namespaceScope = extractNamespaceDeclaration(descriptor, enclosingScope); - visitMemberDeclarations(descriptor, namespaceScope); - return null; - } - - @NotNull - private JsScope extractNamespaceDeclaration(@NotNull NamespaceDescriptor descriptor, - @NotNull JsScope enclosingScope) { - JsName name; - String namespaceName = descriptor.getName(); - name = getNameForNamespace(enclosingScope, namespaceName); - declarations.putName(descriptor, name); - JsScope namespaceScope = new JsScope(enclosingScope, "namespace " + namespaceName); - declarations.putScope(descriptor, namespaceScope); - return namespaceScope; - } - - @NotNull - private JsName getNameForNamespace(@NotNull JsScope enclosingScope, @NotNull String namespaceName) { - JsName name; - if (namespaceName.equals("")) { - name = enclosingScope.declareName("Anonymous"); - } else { - name = enclosingScope.declareName(namespaceName); - } - return name; - } - - private void visitMemberDeclarations(@NotNull NamespaceDescriptor descriptor, @NotNull JsScope namespaceScope) { - for (DeclarationDescriptor memberDescriptor : - descriptor.getMemberScope().getAllDescriptors()) { - memberDescriptor.accept(this, namespaceScope); - } - } - -} diff --git a/translator/src/org/jetbrains/k2js/translate/general/Translation.java b/translator/src/org/jetbrains/k2js/translate/general/Translation.java index c9b36f82d3b..6b498adacc3 100644 --- a/translator/src/org/jetbrains/k2js/translate/general/Translation.java +++ b/translator/src/org/jetbrains/k2js/translate/general/Translation.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.k2js.declarations.Declarations; import org.jetbrains.k2js.translate.declaration.ClassTranslator; import org.jetbrains.k2js.translate.declaration.NamespaceTranslator; @@ -98,7 +99,9 @@ public final class Translation { //TODO hardcoded JsProgram result = new JsProgram("main"); NamespaceDescriptor descriptor = BindingUtils.getNamespaceDescriptor(bindingContext, namespace); - Declarations declarations = Declarations.extractDeclarations(descriptor, result.getRootScope()); + Declarations declarations = Declarations.newInstance(result.getRootScope()); + declarations.extractStandardLibrary(JetStandardLibrary.getJetStandardLibrary(project)); + declarations.extractDeclarations(descriptor); JsBlock block = result.getFragmentBlock(0); TranslationContext context = TranslationContext.rootContext(result, bindingContext, declarations, project); block.addStatement(Translation.translateNamespace(namespace, context)); diff --git a/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java index 5ac229be92e..d22810ed8b7 100644 --- a/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java @@ -77,6 +77,7 @@ public class ReferenceTranslator extends AbstractTranslator { if (referencedDescriptor == null) { return null; } + //TODO: think about the places where we should check for original descriptors if (!context().isDeclared(referencedDescriptor)) { return null; }