From d6c725bcd9b42dc35b8df703c42e115d7223726a Mon Sep 17 00:00:00 2001 From: develar Date: Thu, 28 Jun 2012 10:28:33 +0400 Subject: [PATCH] classes declaration: fix: class of the same unqualified name in package inside module (see MultiFileTest.testClassOfTheSameNameInAnotherPackage) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't ever try to use meaningful var name for temp class declaration — we remember about incremental compilation inline final class declaration don't generate scope function if we don't need it failed and fixed test: fast fix Kt817 (we must investigate, actually, it seems dart ast bug — we must have ability to declare name in our scope without check the same name in the parent scope) perfomance: delete ClassSortingUtils, we don't need it --- .../k2js/test/semantics/MiscTest.java | 2 + .../k2js/test/semantics/MultiFileTest.java | 4 + .../k2js/translate/context/StaticContext.java | 3 + .../declaration/ClassAliasingMap.java | 10 + .../ClassDeclarationTranslator.java | 239 +++++++++++------- .../declaration/ClassTranslator.java | 37 +-- .../declaration/DeclarationBodyVisitor.java | 3 +- .../NamespaceDeclarationTranslator.java | 26 +- .../k2js/translate/general/Translation.java | 6 +- .../translate/utils/ClassSortingUtils.java | 88 ------- .../translate/utils/JsDescriptorUtils.java | 12 - .../translate/utils/PartiallyOrderedSet.java | 121 --------- .../testFiles/kotlin_lib_ecma3.js | 5 +- .../testFiles/kotlin_lib_ecma5.js | 9 - .../classOfTheSameNameInAnotherPackage/A.kt | 7 + .../classOfTheSameNameInAnotherPackage/B.kt | 5 + 16 files changed, 213 insertions(+), 364 deletions(-) create mode 100644 js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassAliasingMap.java delete mode 100644 js/js.translator/src/org/jetbrains/k2js/translate/utils/ClassSortingUtils.java delete mode 100644 js/js.translator/src/org/jetbrains/k2js/translate/utils/PartiallyOrderedSet.java create mode 100644 js/js.translator/testFiles/multiFile/cases/classOfTheSameNameInAnotherPackage/A.kt create mode 100644 js/js.translator/testFiles/multiFile/cases/classOfTheSameNameInAnotherPackage/B.kt diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java index f98cf55b87e..b8319b0b365 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java @@ -20,6 +20,8 @@ import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.translate.context.Namer; import org.mozilla.javascript.JavaScriptException; +import java.util.EnumSet; + /** * @author Pavel Talanov *

diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiFileTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiFileTest.java index 5dc8927264a..a7e5d11246f 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiFileTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiFileTest.java @@ -34,4 +34,8 @@ public final class MultiFileTest extends MultipleFilesTranslationTest { public void testClassesInheritedFromOtherFile() throws Exception { checkFooBoxIsTrue("classesInheritedFromOtherFile"); } + + public void testClassOfTheSameNameInAnotherPackage() throws Exception { + checkFooBoxIsTrue("classOfTheSameNameInAnotherPackage"); + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java index 094942b172b..d933bbb2ba0 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java @@ -205,6 +205,9 @@ public final class StaticContext { @Nullable public JsName apply(@NotNull DeclarationDescriptor descriptor) { NamingScope namingScope = getEnclosingScope(descriptor); + if (descriptor instanceof ClassDescriptor) { + return namingScope.declareUnobfuscatableName(descriptor.getName().getName()); + } return namingScope.declareObfuscatableName(descriptor.getName().getName()); } }; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassAliasingMap.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassAliasingMap.java new file mode 100644 index 00000000000..c7312044a4b --- /dev/null +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassAliasingMap.java @@ -0,0 +1,10 @@ +package org.jetbrains.k2js.translate.declaration; + +import com.google.dart.compiler.backend.js.ast.JsNameRef; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetClass; + +public interface ClassAliasingMap { + @Nullable + JsNameRef get(JetClass declaration, JetClass referencedDeclaration); +} 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 f6013a3c30e..f00caac0bd9 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,26 +16,29 @@ package org.jetbrains.k2js.translate.declaration; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; +import gnu.trove.THashMap; +import gnu.trove.TLinkable; +import gnu.trove.TLinkableAdaptor; +import gnu.trove.TLinkedList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.Modality; import org.jetbrains.jet.lang.psi.JetClass; 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.ClassSortingUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.ArrayList; import java.util.List; -import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; +import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar; +import static org.jetbrains.k2js.translate.general.Translation.translateClassDeclaration; +import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor; +import static org.jetbrains.k2js.translate.utils.JsAstUtils.newBlock; /** * @author Pavel Talanov @@ -43,114 +46,170 @@ import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; * Generates a big block where are all the classes(objects representing them) are created. */ public final class ClassDeclarationTranslator extends AbstractTranslator { + private int localNameCounter; @NotNull - private final List descriptors; - @NotNull - private final BiMap localToGlobalClassName; + private final THashMap openClassToItem = new THashMap(); + + private final TLinkedList openList = new TLinkedList(); + private final List finalList = new ArrayList(); + @NotNull private final JsFunction dummyFunction; - @Nullable - private JsName declarationsObject = null; - @Nullable - private JsStatement declarationsStatement = null; - public ClassDeclarationTranslator(@NotNull List descriptors, - @NotNull TranslationContext context) { + private final JsName declarationsObject; + private final JsVar classesVar; + + public ClassDeclarationTranslator(@NotNull TranslationContext context) { super(context); - this.descriptors = descriptors; - this.localToGlobalClassName = HashBiMap.create(); - this.dummyFunction = new JsFunction(context.jsScope()); + + dummyFunction = new JsFunction(context.jsScope()); + declarationsObject = context().jsScope().declareName(Namer.nameForClassesVariable()); + classesVar = new JsVars.JsVar(declarationsObject); + } + + private final class OpenClassRefProvider implements ClassAliasingMap { + @Override + @Nullable + public JsNameRef get(JetClass declaration, JetClass referencedDeclaration) { + ListItem item = openClassToItem.get(declaration); + // class declared in library + if (item == null) { + return null; + } + + addAfter(item, openClassToItem.get(referencedDeclaration)); + return item.label; + } + + private void addAfter(@NotNull ListItem item, @NotNull ListItem referencedItem) { + for (TLinkable link = item.getNext(); link != null; link = link.getNext()) { + if (link == referencedItem) { + return; + } + } + + openList.remove(referencedItem); + openList.addBefore((ListItem) item.getNext(), referencedItem); + } + } + + private final class FinalClassRefProvider implements ClassAliasingMap { + @Override + public JsNameRef get(JetClass declaration, JetClass referencedDeclaration) { + ListItem item = openClassToItem.get(declaration); + return item == null ? null : item.label; + } + } + + private static class ListItem extends TLinkableAdaptor { + private final JetClass declaration; + private final JsNameRef label; + + private JsExpression translatedDeclaration; + + private ListItem(JetClass declaration, JsNameRef label) { + this.declaration = declaration; + this.label = label; + } + } + + @NotNull + public JsVars getDeclarationsStatement() { + JsVars vars = new JsVars(); + vars.add(classesVar); + return vars; } public void generateDeclarations() { - declarationsObject = context().jsScope().declareName(Namer.nameForClassesVariable()); - assert declarationsObject != null; - declarationsStatement = - newVar(declarationsObject, generateDummyFunctionInvocation()); - } + JsObjectLiteral valueLiteral = new JsObjectLiteral(); + JsVars vars = new JsVars(); + List propertyInitializers = valueLiteral.getPropertyInitializers(); - @NotNull - public JsName getDeclarationsObjectName() { - assert declarationsObject != null : "Should run generateDeclarations first"; - return declarationsObject; - } + generateOpenClassDeclarations(vars, propertyInitializers); + generateFinalClassDeclarations(vars, propertyInitializers); - @NotNull - public JsStatement getDeclarationsStatement() { - assert declarationsStatement != null : "Should run generateDeclarations first"; - return declarationsStatement; - } - - @NotNull - private JsInvocation generateDummyFunctionInvocation() { - List classDeclarations = generateClassDeclarationStatements(); - classDeclarations.add(new JsReturn(generateReturnedObjectLiteral())); - dummyFunction.setBody(newBlock(classDeclarations)); - return AstUtil.newInvocation(dummyFunction); - } - - @NotNull - private JsObjectLiteral generateReturnedObjectLiteral() { - JsObjectLiteral returnedValueLiteral = new JsObjectLiteral(); - for (JsName localName : localToGlobalClassName.keySet()) { - returnedValueLiteral.getPropertyInitializers().add(classEntry(localName)); + if (vars.isEmpty()) { + classesVar.setInitExpr(valueLiteral); + return; } - return returnedValueLiteral; + + List result = new ArrayList(); + result.add(vars); + result.add(new JsReturn(valueLiteral)); + dummyFunction.setBody(newBlock(result)); + classesVar.setInitExpr(AstUtil.newInvocation(dummyFunction)); } - @NotNull - private JsPropertyInitializer classEntry(@NotNull JsName localName) { - return new JsPropertyInitializer(localToGlobalClassName.get(localName).makeRef(), localName.makeRef()); - } - - @NotNull - private List generateClassDeclarationStatements() { - List classDeclarations = new ArrayList(); - for (JetClass jetClass : getClassDeclarations()) { - classDeclarations.add(generateDeclaration(jetClass)); + private void generateOpenClassDeclarations(@NotNull JsVars vars, @NotNull List propertyInitializers) { + ClassAliasingMap classAliasingMap = new OpenClassRefProvider(); + // first pass: set up list order + for (ListItem item : openList) { + item.translatedDeclaration = translateClassDeclaration(item.declaration, classAliasingMap, context()); } - return classDeclarations; - } - - - @NotNull - private List getClassDeclarations() { - List classes = new ArrayList(); - for (ClassDescriptor classDescriptor : descriptors) { - classes.add(BindingUtils.getClassForDescriptor(bindingContext(), classDescriptor)); + // second pass: generate + for (ListItem item : openList) { + generate(item, propertyInitializers, item.translatedDeclaration, vars); } - return ClassSortingUtils.sortUsingInheritanceOrder(classes, bindingContext()); } - @NotNull - private JsStatement generateDeclaration(@NotNull JetClass declaration) { - JsName localClassName = generateLocalAlias(declaration); - JsExpression classDeclarationExpression = - Translation.translateClassDeclaration(declaration, localToGlobalClassName.inverse(), context()); - return newVar(localClassName, classDeclarationExpression); + private void generateFinalClassDeclarations(@NotNull JsVars vars, @NotNull List propertyInitializers) { + ClassAliasingMap classAliasingMap = new FinalClassRefProvider(); + for (ListItem item : finalList) { + generate(item, propertyInitializers, translateClassDeclaration(item.declaration, classAliasingMap, context()), vars); + } } - @NotNull - private JsName generateLocalAlias(@NotNull JetClass declaration) { - JsName globalClassName = context().getNameForElement(declaration); - JsName localAlias = dummyFunction.getScope().declareTemporary(); - localToGlobalClassName.put(localAlias, globalClassName); - return localAlias; - } - - @NotNull - public JsPropertyInitializer getClassNameToClassObject(@NotNull ClassDescriptor classDescriptor) { - JsName className = context().getNameForDescriptor(classDescriptor); - JsNameRef alreadyDefinedClassReference = qualified(className, getDeclarationsObjectName().makeRef()); + private static void generate(@NotNull ListItem item, + @NotNull List propertyInitializers, + @NotNull JsExpression definition, + @NotNull JsVars vars) { JsExpression value; - if (context().isEcma5()) { - value = JsAstUtils.createDataDescriptor(alreadyDefinedClassReference, false, context()); + if (item.label.getName() == null) { + value = definition; } else { - value = alreadyDefinedClassReference; + assert item.label.getName() != null; + vars.add(new JsVar(item.label.getName(), definition)); + value = item.label; } - return new JsPropertyInitializer(className.makeRef(), value); + propertyInitializers.add(new JsPropertyInitializer(item.label, value)); + } + + @NotNull + public JsPropertyInitializer translateAndGetClassNameToClassObject(@NotNull JetClass declaration) { + ClassDescriptor descriptor = getClassDescriptor(context().bindingContext(), declaration); + + JsNameRef labelRef; + String label = 'c' + Integer.toString(localNameCounter++, 36); + boolean isFinal = descriptor.getModality() == Modality.FINAL; + if (isFinal) { + labelRef = new JsNameRef(label); + } + else { + labelRef = dummyFunction.getScope().declareName(label).makeRef(); + } + + ListItem item = new ListItem(declaration, labelRef); + if (isFinal) { + finalList.add(item); + } + else { + openList.add(item); + openClassToItem.put(declaration, item); + } + + JsNameRef qualifiedLabelRef = new JsNameRef(labelRef.getIdent()); + qualifiedLabelRef.setQualifier(declarationsObject.makeRef()); + JsExpression value; + if (context().isEcma5()) { + value = JsAstUtils.createDataDescriptor(qualifiedLabelRef, false, context()); + } + else { + value = qualifiedLabelRef; + } + + return new JsPropertyInitializer(context().program().getStringLiteral(descriptor.getName().getName()), value); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java index d0e513971c6..0b3167d85af 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetObjectLiteralExpression; import org.jetbrains.jet.lang.psi.JetParameter; @@ -31,12 +32,11 @@ 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.initializer.InitializerUtils; +import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Map; import static com.google.dart.compiler.util.AstUtil.newSequence; import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor; @@ -64,8 +64,8 @@ public final class ClassTranslator extends AbstractTranslator { @NotNull public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration, - @NotNull Map aliasingMap, - @NotNull TranslationContext context) { + @NotNull ClassAliasingMap aliasingMap, + @NotNull TranslationContext context) { return (new ClassTranslator(classDeclaration, aliasingMap, context)).translateClassOrObjectCreation(); } @@ -73,13 +73,13 @@ public final class ClassTranslator extends AbstractTranslator { public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { - return (new ClassTranslator(classDeclaration, Collections.emptyMap(), context)).translateClassOrObjectCreation(); + return (new ClassTranslator(classDeclaration, null, context)).translateClassOrObjectCreation(); } @NotNull public static JsExpression generateObjectLiteralExpression(@NotNull JetObjectLiteralExpression objectLiteralExpression, @NotNull TranslationContext context) { - return (new ClassTranslator(objectLiteralExpression.getObjectDeclaration(), Collections.emptyMap(), context)) + return (new ClassTranslator(objectLiteralExpression.getObjectDeclaration(), null, context)) .translateObjectLiteralExpression(); } @@ -95,12 +95,12 @@ public final class ClassTranslator extends AbstractTranslator { @NotNull private final ClassDescriptor descriptor; - @NotNull - private final Map aliasingMap; + @Nullable + private final ClassAliasingMap aliasingMap; private ClassTranslator(@NotNull JetClassOrObject classDeclaration, - @NotNull Map aliasingMap, - @NotNull TranslationContext context) { + @Nullable ClassAliasingMap aliasingMap, + @NotNull TranslationContext context) { super(context.newDeclaration(classDeclaration)); this.aliasingMap = aliasingMap; this.descriptor = getClassDescriptor(context.bindingContext(), classDeclaration); @@ -209,8 +209,7 @@ public final class ClassTranslator extends AbstractTranslator { private void addTraits(@NotNull List superclassReferences, @NotNull List superclassDescriptors) { - for (ClassDescriptor superClassDescriptor : - superclassDescriptors) { + for (ClassDescriptor superClassDescriptor : superclassDescriptors) { assert (superClassDescriptor.getKind() == ClassKind.TRAIT) : "Only traits are expected here"; superclassReferences.add(getClassReference(superClassDescriptor)); } @@ -227,12 +226,16 @@ public final class ClassTranslator extends AbstractTranslator { @NotNull private JsExpression getClassReference(@NotNull ClassDescriptor superClassDescriptor) { - //NOTE: aliasing here is needed for the declaration generation step - JsName name = context().getNameForDescriptor(superClassDescriptor); - JsName alias = aliasingMap.get(name); - if (alias != null) { - return alias.makeRef(); + // aliasing here is needed for the declaration generation step + if (aliasingMap != null) { + JsNameRef name = aliasingMap.get(BindingUtils.getClassForDescriptor(bindingContext(), superClassDescriptor), + (JetClass) classDeclaration); + if (name != null) { + return name; + } } + + // from library return getQualifiedReference(context(), superClassDescriptor); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java index 540d47e980b..4ce9277b622 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java @@ -79,8 +79,7 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor getAllClasses() { - List result = Lists.newArrayList(); - for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) { - result.addAll(getAllClassesDefinedInNamespace(namespaceDescriptor, context().bindingContext())); - } - return result; + classDeclarationTranslator = new ClassDeclarationTranslator(context); } @NotNull private List translate() { List result = new ArrayList(); - classesDeclarations(result); + result.add(classDeclarationTranslator.getDeclarationsStatement()); namespacesDeclarations(result); - return result; - } - - private void classesDeclarations(List statements) { classDeclarationTranslator.generateDeclarations(); - statements.add(classDeclarationTranslator.getDeclarationsStatement()); + return result; } private void namespacesDeclarations(List statements) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java index 8174b81588d..ea77ec00559 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java @@ -38,6 +38,7 @@ import org.jetbrains.k2js.facade.exceptions.TranslationInternalException; import org.jetbrains.k2js.facade.exceptions.UnsupportedFeatureException; import org.jetbrains.k2js.translate.context.StaticContext; import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.declaration.ClassAliasingMap; import org.jetbrains.k2js.translate.declaration.ClassTranslator; import org.jetbrains.k2js.translate.declaration.NamespaceDeclarationTranslator; import org.jetbrains.k2js.translate.expression.ExpressionVisitor; @@ -54,7 +55,6 @@ import org.jetbrains.k2js.translate.utils.dangerous.DangerousTranslator; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import static org.jetbrains.jet.plugin.JetMainDetector.getMainFunction; import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor; @@ -85,9 +85,9 @@ public final class Translation { @NotNull public static JsExpression translateClassDeclaration(@NotNull JetClass classDeclaration, - @NotNull Map aliasingMap, + @NotNull ClassAliasingMap classAliasingMap, @NotNull TranslationContext context) { - return ClassTranslator.generateClassCreationExpression(classDeclaration, aliasingMap, context); + return ClassTranslator.generateClassCreationExpression(classDeclaration, classAliasingMap, context); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/ClassSortingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/ClassSortingUtils.java deleted file mode 100644 index d522d241a33..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/ClassSortingUtils.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.k2js.translate.utils; - -import com.google.common.collect.Lists; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.psi.JetClass; -import org.jetbrains.jet.lang.resolve.BindingContext; - -import java.util.ArrayList; -import java.util.List; - -import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getSuperclassDescriptors; - - -//TODO: can optimise using less dumb implementation -//TODO: pass list of descriptors here, not the list of jet classes - -/** - * @author Pavel Talanov - */ -public final class ClassSortingUtils { - - private ClassSortingUtils() { - } - - @NotNull - public static List sortUsingInheritanceOrder(@NotNull List elements, - @NotNull BindingContext bindingContext) { - List descriptors = descriptorsFromClasses(elements, bindingContext); - PartiallyOrderedSet partiallyOrderedSet - = new PartiallyOrderedSet(descriptors, inheritanceOrder()); - List sortedClasses = descriptorsToClasses(partiallyOrderedSet.partiallySortedElements(), bindingContext); - assert elements.size() == sortedClasses.size(); - return sortedClasses; - } - - @NotNull - private static PartiallyOrderedSet.Order inheritanceOrder() { - return new PartiallyOrderedSet.Order() { - @Override - public boolean firstDependsOnSecond(@NotNull ClassDescriptor first, @NotNull ClassDescriptor second) { - return isDerivedClass(first, second); - } - }; - } - - private static boolean isDerivedClass(@NotNull ClassDescriptor ancestor, @NotNull ClassDescriptor derived) { - return (getSuperclassDescriptors(derived).contains(ancestor)); - } - - @NotNull - private static List descriptorsToClasses(@NotNull List descriptors, - @NotNull BindingContext bindingContext) { - List sortedClasses = Lists.newArrayList(); - for (ClassDescriptor descriptor : descriptors) { - sortedClasses.add(BindingUtils.getClassForDescriptor(bindingContext, descriptor)); - } - return sortedClasses; - } - - - @NotNull - private static List descriptorsFromClasses(@NotNull List classesToSort, - @NotNull BindingContext bindingContext) { - List descriptorList = new ArrayList(); - for (JetClass jetClass : classesToSort) { - descriptorList.add(BindingUtils.getClassDescriptor(bindingContext, jetClass)); - } - return descriptorList; - } - -} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java index bf7f76bb8f7..c6d5d40d412 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java @@ -186,18 +186,6 @@ public final class JsDescriptorUtils { return null; } - @NotNull - public static List getAllClassesDefinedInNamespace(@NotNull NamespaceDescriptor namespaceDescriptor, - @NotNull BindingContext context) { - List classDescriptors = Lists.newArrayList(); - for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor, context)) { - if (descriptor instanceof ClassDescriptor) { - classDescriptors.add((ClassDescriptor) descriptor); - } - } - return classDescriptors; - } - @NotNull public static List getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor, @NotNull BindingContext context) { 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 deleted file mode 100644 index 79be5ba4890..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/PartiallyOrderedSet.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.k2js.translate.utils; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - * @author Pavel Talanov - *

- * This is very inefficient but simple implementation of partially orderered set. - * Feel free to replace with library implementation. - */ -public final class PartiallyOrderedSet { - - private class Arc { - @NotNull - public final Element from; - @NotNull - public final Element to; - - private Arc(@NotNull Element from, @NotNull Element to) { - this.from = from; - this.to = to; - } - } - - public interface Order { - boolean firstDependsOnSecond(@NotNull Element first, @NotNull Element second); - } - - @NotNull - private final List arcs = Lists.newArrayList(); - @NotNull - private final Map incomingArcs = Maps.newHashMap(); - @NotNull - private final List elementsWithZeroIncoming = Lists.newArrayList(); - - public PartiallyOrderedSet(@NotNull Collection elements, @NotNull Order order) { - elementsWithZeroIncoming.addAll(elements); - for (@NotNull Element first : elements) { - for (@NotNull Element second : elements) { - if (order.firstDependsOnSecond(first, second)) { - arcs.add(new Arc(first, second)); - increaseIncomingCount(second); - } - } - } - } - - private void increaseIncomingCount(@NotNull Element element) { - if (!incomingArcs.containsKey(element)) { - incomingArcs.put(element, 1); - elementsWithZeroIncoming.remove(element); - } - else { - Integer count = incomingArcs.get(element); - incomingArcs.put(element, count + 1); - } - } - - private void decreaseIncomingCount(@NotNull Element element) { - assert incomingArcs.containsKey(element); - Integer count = incomingArcs.get(element); - if (count == 1) { - incomingArcs.remove(element); - elementsWithZeroIncoming.add(element); - } - else { - incomingArcs.put(element, count - 1); - } - } - - @NotNull - public List partiallySortedElements() { - List result = Lists.newArrayList(); - while (!elementsWithZeroIncoming.isEmpty()) { - result.add(getNextElement()); - } - return result; - } - - @NotNull - private Element getNextElement() { - Element elementWithZeroIncoming = getElementWithZeroIncoming(); - for (Arc arc : arcs) { - if (arc.from == elementWithZeroIncoming) { - decreaseIncomingCount(arc.to); - } - } - return elementWithZeroIncoming; - } - - @NotNull - private Element getElementWithZeroIncoming() { - int indexOfLast = elementsWithZeroIncoming.size() - 1; - Element element = elementsWithZeroIncoming.get(indexOfLast); - elementsWithZeroIncoming.remove(indexOfLast); - return element; - } - -} diff --git a/js/js.translator/testFiles/kotlin_lib_ecma3.js b/js/js.translator/testFiles/kotlin_lib_ecma3.js index 81a472c5312..2f247b9d790 100644 --- a/js/js.translator/testFiles/kotlin_lib_ecma3.js +++ b/js/js.translator/testFiles/kotlin_lib_ecma3.js @@ -129,12 +129,11 @@ var Kotlin = {}; var property = properties[i]; object[property] = source[property]; } - return this; } return function () { - var result = {}; - for (var i = 0, length = arguments.length; i < length; i++) { + var result = arguments[0]; + for (var i = 1, n = arguments.length; i < n; i++) { add(result, arguments[i]); } return result; diff --git a/js/js.translator/testFiles/kotlin_lib_ecma5.js b/js/js.translator/testFiles/kotlin_lib_ecma5.js index 2398cc00ae4..3a66796361f 100644 --- a/js/js.translator/testFiles/kotlin_lib_ecma5.js +++ b/js/js.translator/testFiles/kotlin_lib_ecma5.js @@ -112,16 +112,7 @@ var Kotlin = {}; Kotlin.definePackage = function (functionsAndClasses, nestedNamespaces) { - //var p = parent[localName]; - //if (!p) { - // p = Object.create(null, functionsAndClasses || undefined); - // Object.defineProperty(parent, localName, {value: p}); - //} - //else if (functionsAndClasses) { - // Object.defineProperties(p, functionsAndClasses); - //} var p = Object.create(null, functionsAndClasses || undefined); - if (nestedNamespaces) { var keys = Object.keys(nestedNamespaces); for (var i = 0, n = keys.length; i < n; i++) { diff --git a/js/js.translator/testFiles/multiFile/cases/classOfTheSameNameInAnotherPackage/A.kt b/js/js.translator/testFiles/multiFile/cases/classOfTheSameNameInAnotherPackage/A.kt new file mode 100644 index 00000000000..e046cb6ffe3 --- /dev/null +++ b/js/js.translator/testFiles/multiFile/cases/classOfTheSameNameInAnotherPackage/A.kt @@ -0,0 +1,7 @@ +package foo + +open class A() { + fun f() = 3 +} + +fun box() = (A().f() + bar.A().f()) == 9 \ No newline at end of file diff --git a/js/js.translator/testFiles/multiFile/cases/classOfTheSameNameInAnotherPackage/B.kt b/js/js.translator/testFiles/multiFile/cases/classOfTheSameNameInAnotherPackage/B.kt new file mode 100644 index 00000000000..b9d474d092e --- /dev/null +++ b/js/js.translator/testFiles/multiFile/cases/classOfTheSameNameInAnotherPackage/B.kt @@ -0,0 +1,5 @@ +package bar + +open class A() { + fun f() = 6 +} \ No newline at end of file