From e3d62b7903bcb9136a1c24c9d051b9fd3045db78 Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Fri, 25 Nov 2011 21:00:18 +0400 Subject: [PATCH] Corrected class declaration logic. --- .idea/workspace.xml | 591 ++++++++++++------ .../ClassDeclarationTranslator.java | 19 +- .../declaration/ClassTranslator.java | 7 +- .../expression/ExpressionVisitor.java | 4 +- .../k2js/translate/general/Translation.java | 2 +- .../translate/general/TranslationContext.java | 45 +- .../reference/ReferenceTranslator.java | 46 +- .../k2js/translate/utils/BindingUtils.java | 10 + .../k2js/utils/PartiallyOrderedSet.java | 1 + 9 files changed, 490 insertions(+), 235 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index c217b072e67..651a1236dc1 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -8,11 +8,15 @@ - - - - + + + + + + + + @@ -43,6 +47,99 @@ + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - + - - + + - + + + + + + + + + + + + - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -211,7 +312,7 @@ - + @@ -299,15 +400,6 @@ @@ -494,6 +595,86 @@ - - - - - - - - - - - - - - - - - - - - + @@ -1048,6 +1190,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + localhost @@ -1266,7 +1463,7 @@ @@ -1313,116 +1510,120 @@ + + + + + + + + + + + + + + - + - + - + + + + + + + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + diff --git a/translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java b/translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java index 3abcc355143..3312083cfc9 100644 --- a/translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java @@ -89,9 +89,16 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { for (JetClass jetClass : getClassDeclarations()) { classDeclarations.add(generateDeclaration(jetClass)); } + removeAliases(); return classDeclarations; } + private void removeAliases() { + for (JetClass jetClass : getClassDeclarations()) { + context().aliases().remove(jetClass); + } + } + @NotNull private List getClassDeclarations() { List classes = new ArrayList(); @@ -105,11 +112,17 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { @NotNull private JsStatement generateDeclaration(@NotNull JetClass declaration) { - JsName globalClassName = context().getNameForElement(declaration); - JsName localClassName = dummyFunctionScope.declareName(globalClassName.getIdent()); - localToGlobalClassName.put(localClassName, globalClassName); + JsName localClassName = generateLocalAlias(declaration); JsInvocation classDeclarationExpression = Translation.translateClassDeclaration(declaration, context()); return AstUtil.newVar(localClassName, classDeclarationExpression); } + + private JsName generateLocalAlias(@NotNull JetClass declaration) { + JsName globalClassName = context().getNameForElement(declaration); + JsName localAlias = dummyFunctionScope.declareName(globalClassName.getIdent()); + localToGlobalClassName.put(localAlias, globalClassName); + context().aliases().put(declaration, localAlias); + return localAlias; + } } diff --git a/translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java b/translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java index 0d0537b02f7..c716ee81fa7 100644 --- a/translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java @@ -100,9 +100,10 @@ public final class ClassTranslator extends AbstractTranslator { @NotNull private JsNameRef getClassReference(@NotNull ClassDescriptor superClassDescriptor) { - //TODO should get a full class name here - return context().getNamespaceQualifiedReference - (context().getNameForDescriptor(superClassDescriptor)); + //TODO we actually know that in current implementation superclass must have an alias but + // if future it might change + return context().aliases().get + (BindingUtils.getClassForDescriptor(context().bindingContext(), superClassDescriptor)).makeRef(); } @Nullable diff --git a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index fb1249931cd..c6f7390909a 100644 --- a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -56,11 +56,11 @@ public final class ExpressionVisitor extends TranslatorVisitor { public JsNode visitBlockExpression(@NotNull JetBlockExpression jetBlock, @NotNull TranslationContext context) { List statements = jetBlock.getStatements(); JsBlock jsBlock = new JsBlock(); - TranslationContext newContext = context.newBlock(jsBlock); + ; for (JetElement statement : statements) { assert statement instanceof JetExpression : "Elements in JetBlockExpression " + "should be of type JetExpression"; - JsNode jsNode = statement.accept(this, newContext); + JsNode jsNode = statement.accept(this, context); jsBlock.addStatement(AstUtil.convertToStatement(jsNode)); } return jsBlock; diff --git a/translator/src/org/jetbrains/k2js/translate/general/Translation.java b/translator/src/org/jetbrains/k2js/translate/general/Translation.java index 7c3a4fd2fab..2b5459b8930 100644 --- a/translator/src/org/jetbrains/k2js/translate/general/Translation.java +++ b/translator/src/org/jetbrains/k2js/translate/general/Translation.java @@ -93,7 +93,7 @@ public final class Translation { public static void generateAst(@NotNull JsProgram result, @NotNull BindingContext bindingContext, @NotNull Declarations declarations, @NotNull JetNamespace namespace) { JsBlock block = result.getFragmentBlock(0); - TranslationContext context = TranslationContext.rootContext(result, bindingContext, declarations, block); + TranslationContext context = TranslationContext.rootContext(result, bindingContext, declarations); block.addStatement(Translation.translateNamespace(namespace, context)); } diff --git a/translator/src/org/jetbrains/k2js/translate/general/TranslationContext.java b/translator/src/org/jetbrains/k2js/translate/general/TranslationContext.java index a12e6a58c05..2778479daca 100644 --- a/translator/src/org/jetbrains/k2js/translate/general/TranslationContext.java +++ b/translator/src/org/jetbrains/k2js/translate/general/TranslationContext.java @@ -1,6 +1,9 @@ package org.jetbrains.k2js.translate.general; -import com.google.dart.compiler.backend.js.ast.*; +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.JsProgram; +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; @@ -10,6 +13,9 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.k2js.declarations.Declarations; import org.jetbrains.k2js.translate.utils.BindingUtils; +import java.util.HashMap; +import java.util.Map; + /** * @author Talanov Pavel */ @@ -33,10 +39,11 @@ public final class TranslationContext { @NotNull public static TranslationContext rootContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext, - @NotNull Declarations extractor, @NotNull JsBlock block) { + @NotNull Declarations extractor) { JsScope rootScope = program.getRootScope(); Scopes scopes = new Scopes(rootScope, rootScope, rootScope); - return new TranslationContext(null, program, bindingContext, scopes, extractor, block); + return new TranslationContext(null, program, bindingContext, + scopes, extractor, new HashMap()); } @NotNull @@ -50,18 +57,18 @@ public final class TranslationContext { @NotNull private final Declarations declarations; @NotNull - private final JsBlock block; + private final Map aliases; private TranslationContext(@Nullable JsName namespaceName, @NotNull JsProgram program, @NotNull BindingContext bindingContext, @NotNull Scopes scopes, - @NotNull Declarations declarations, @NotNull JsBlock block) { + @NotNull Declarations declarations, @NotNull Map aliases) { this.program = program; this.bindingContext = bindingContext; this.namespaceName = namespaceName; this.scopes = scopes; this.declarations = declarations; - this.block = block; + this.aliases = aliases; } @NotNull @@ -74,14 +81,7 @@ public final class TranslationContext { JsScope namespaceScope = declarations.getScope(descriptor); JsName namespaceName = scopes.enclosingScope.findExistingName(descriptor.getName()); Scopes newScopes = new Scopes(namespaceScope, namespaceScope, namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block); - } - - @NotNull - public TranslationContext newBlock(@NotNull JsBlock newBlock) { - Scopes newScopes = new Scopes(new JsScope - (scopes.enclosingScope, "Scope for a block"), scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, newBlock); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, aliases); } @NotNull @@ -93,7 +93,7 @@ public final class TranslationContext { public TranslationContext newClass(@NotNull ClassDescriptor descriptor) { JsScope classScope = declarations.getScope(descriptor); Scopes newScopes = new Scopes(classScope, classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, aliases); } @NotNull @@ -115,14 +115,20 @@ public final class TranslationContext { public TranslationContext newFunctionDeclaration(@NotNull FunctionDescriptor descriptor) { JsScope functionScope = declarations.getScope(descriptor); Scopes newScopes = new Scopes(functionScope, scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, aliases); } +// @NotNull TranslationContext newAliases(Map newAliases) { +// Map aliases = new HashMap(this.aliases); +// aliases.putAll(newAliases); +// return new TranslationContext(namespaceName, program, bindingContext, scopes, declarations, aliases); +// } + // Note: Should be used if and only if scope has no corresponding descriptor @NotNull public TranslationContext newEnclosingScope(@NotNull JsScope enclosingScope) { Scopes newScopes = new Scopes(enclosingScope, scopes.classScope, scopes.namespaceScope); - return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block); + return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, aliases); } @@ -159,6 +165,11 @@ public final class TranslationContext { return scopes.classScope; } + @NotNull + public Map aliases() { + return aliases; + } + @NotNull public JsName declareLocalName(@NotNull String name) { return scopes.enclosingScope.declareFreshName(name); diff --git a/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java index 9dd63d67532..28d318f8e7c 100644 --- a/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java @@ -3,9 +3,11 @@ package org.jetbrains.k2js.translate.reference; import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsInvocation; import com.google.dart.compiler.backend.js.ast.JsName; +import com.google.dart.compiler.backend.js.ast.JsNameRef; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.Translation; @@ -16,6 +18,7 @@ import org.jetbrains.k2js.translate.utils.TranslationUtils; /** * @author Talanov Pavel */ +//TODO: implement state public class ReferenceTranslator extends AbstractTranslator { @NotNull @@ -27,27 +30,42 @@ public class ReferenceTranslator extends AbstractTranslator { super(context); } + // TODO: refactor put the checks inside resolvers @NotNull public JsExpression translateSimpleName(@NotNull JetSimpleNameExpression expression) { - JsExpression result = resolveAsPropertyAccess(expression); - if (result != null) { - return result; - } - result = resolveAsGlobalReference(expression); - if (result != null) { - return result; - } - result = resolveAsLocalReference(expression); - if (result != null) { - return result; - } - throw new AssertionError("Undefined name in this scope: " + expression.getReferencedName()); + JsExpression result = resolveAsAliasReference(expression); + if (result != null) return result; + result = resolveAsPropertyAccess(expression); + if (result != null) return result; + + result = resolveAsGlobalReference(expression); + if (result != null) return result; + + result = resolveAsLocalReference(expression); + if (result != null) return result; + + throw new AssertionError("Undefined name in this scope: " + expression.getReferencedName()); + } + + @Nullable + private JsNameRef resolveAsAliasReference(@NotNull JetSimpleNameExpression expression) { + DeclarationDescriptor referencedDescriptor = + BindingUtils.getDescriptorForReferenceExpression(context().bindingContext(), expression); + if (referencedDescriptor == null) return null; + + JetDeclaration declaration = + BindingUtils.getDeclarationForDescriptor(context().bindingContext(), referencedDescriptor); + if (declaration == null) return null; + + JsName alias = context().aliases().get(declaration); + if (alias == null) return null; + + return alias.makeRef(); } @Nullable private JsInvocation resolveAsPropertyAccess(@NotNull JetSimpleNameExpression expression) { - PropertyAccessTranslator propertyAccessTranslator = Translation.propertyAccessTranslator(context()); if (propertyAccessTranslator.canBePropertyGetterCall(expression)) { return propertyAccessTranslator.translateAsPropertyGetterCall(expression); diff --git a/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index e5b03082618..fc6347ea74c 100644 --- a/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -88,6 +88,16 @@ public final class BindingUtils { return (JetClass) result; } + @Nullable + static public JetDeclaration getDeclarationForDescriptor(@NotNull BindingContext context, + @NotNull DeclarationDescriptor descriptor) { + PsiElement result = context.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); + if (!(result instanceof JetDeclaration)) { + return null; + } + return (JetDeclaration) result; + } + @NotNull static public List getSuperclassDescriptors(@NotNull BindingContext context, @NotNull JetClass classDeclaration) { diff --git a/translator/src/org/jetbrains/k2js/utils/PartiallyOrderedSet.java b/translator/src/org/jetbrains/k2js/utils/PartiallyOrderedSet.java index d1bc45a0c9d..d18b7b2cb34 100644 --- a/translator/src/org/jetbrains/k2js/utils/PartiallyOrderedSet.java +++ b/translator/src/org/jetbrains/k2js/utils/PartiallyOrderedSet.java @@ -1,5 +1,6 @@ package org.jetbrains.k2js.utils; +//TODO: find another implementation or steal it! /* * Copyright 2000 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.