diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StandardClassesTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StandardClassesTest.java index 50ab20490ff..a5a4bdd8ef3 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StandardClassesTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StandardClassesTest.java @@ -60,4 +60,8 @@ public final class StandardClassesTest extends SingleFileTranslationTest { public void testArraysIterator() throws Exception { fooBoxTest(failOnEcma5()); } + + public void testArrayFactoryMethods() throws Exception { + checkFooBoxIsOk(); + } } \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java index ff936ef94fe..7fe9001c75b 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java @@ -22,11 +22,15 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.plugin.JetLanguage; /** * Encapuslates different types of constants and naming conventions. */ public final class Namer { + public static final String KOTLIN_NAME = JetLanguage.NAME; + public static final String KOTLIN_LOWER_NAME = KOTLIN_NAME.toLowerCase(); + public static final String CALLEE_NAME = "$fun"; private static final String INITIALIZE_METHOD_NAME = "initialize"; @@ -37,7 +41,6 @@ public final class Namer { private static final String GETTER_PREFIX = "get_"; private static final String BACKING_FIELD_PREFIX = "$"; private static final String SUPER_METHOD_NAME = "super_init"; - private static final String KOTLIN_OBJECT_NAME = "Kotlin"; private static final String ROOT_NAMESPACE = "_"; private static final String RECEIVER_PARAMETER_NAME = "receiver"; private static final String CLASSES_OBJECT_NAME = "classes"; @@ -123,7 +126,7 @@ public final class Namer { private final JsName isTypeName; private Namer(@NotNull JsScope rootScope) { - kotlinName = rootScope.declareName(KOTLIN_OBJECT_NAME); + kotlinName = rootScope.declareName(KOTLIN_NAME); kotlinScope = new JsScope(rootScope, "Kotlin standard object"); traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/ArrayFIF.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/ArrayFIF.java index 600862be1d3..92161cd83bd 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/ArrayFIF.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/ArrayFIF.java @@ -22,23 +22,20 @@ import com.google.dart.compiler.backend.js.ast.JsExpression; 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.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.lang.PrimitiveType; +import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInPropertyIntrinsic; import org.jetbrains.k2js.translate.intrinsic.functions.basic.CallStandardMethodIntrinsic; import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic; import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredicate; import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate; -import org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder; import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.List; +import static com.intellij.openapi.util.text.StringUtil.decapitalize; import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern; public final class ArrayFIF extends CompositeFIF { @@ -58,12 +55,18 @@ public final class ArrayFIF extends CompositeFIF { @NotNull private static final NamePredicate ARRAYS; + @NotNull + private static final DescriptorPredicate ARRAY_FACTORY_METHODS; + static { List arrayTypeNames = Lists.newArrayList(); - for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) { - if (type != PrimitiveType.CHAR) { - arrayTypeNames.add(type.getArrayTypeName()); + List arrayFactoryMethodNames = Lists.newArrayList(Name.identifier("array")); + for (PrimitiveType type : PrimitiveType.values()) { + Name arrayTypeName = type.getArrayTypeName(); + if (type != PrimitiveType.CHAR && type != PrimitiveType.BOOLEAN) { + arrayTypeNames.add(arrayTypeName); } + arrayFactoryMethodNames.add(Name.identifier(decapitalize(arrayTypeName.asString()))); } Name arrayName = Name.identifier("Array"); @@ -79,6 +82,7 @@ public final class ArrayFIF extends CompositeFIF { arrayTypeNames.add(booleanArrayName); arrayTypeNames.add(arrayName); ARRAYS = new NamePredicate(arrayTypeNames); + ARRAY_FACTORY_METHODS = pattern(Namer.KOTLIN_LOWER_NAME, new NamePredicate(arrayFactoryMethodNames)); } private static final FunctionIntrinsic ARRAY_INTRINSIC = new FunctionIntrinsic() { @@ -140,22 +144,6 @@ public final class ArrayFIF extends CompositeFIF { add(pattern(NUMBER_ARRAY, ""), new CallStandardMethodIntrinsic(new JsNameRef("numberArrayOfSize", "Kotlin"), false, 1)); add(pattern(CHAR_ARRAY, ""), new CallStandardMethodIntrinsic(new JsNameRef("charArrayOfSize", "Kotlin"), false, 1)); add(pattern(BOOLEAN_ARRAY, ""), new CallStandardMethodIntrinsic(new JsNameRef("booleanArrayOfSize", "Kotlin"), false, 1)); - add(PatternBuilder.create("kotlin", "array"), ARRAY_INTRINSIC); - add(new DescriptorPredicate() { - @Override - public boolean apply(@Nullable FunctionDescriptor descriptor) { - if (descriptor == null) { - return false; - } - - for (PrimitiveType type : PrimitiveType.values()) { - if (type.getArrayTypeName().equals(descriptor.getName())) { - DeclarationDescriptor nsDeclaration = descriptor.getContainingDeclaration(); - return nsDeclaration instanceof NamespaceDescriptor && DescriptorUtils.isRootNamespace((NamespaceDescriptor) nsDeclaration) && nsDeclaration.getName().asString().equals("kotlin"); - } - } - return false; - } - }, ARRAY_INTRINSIC); + add(ARRAY_FACTORY_METHODS, ARRAY_INTRINSIC); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/patterns/PatternBuilder.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/patterns/PatternBuilder.java index 9485872d020..4eeb6bdf192 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/patterns/PatternBuilder.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/patterns/PatternBuilder.java @@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.k2js.translate.context.Namer; import java.util.Arrays; import java.util.List; @@ -33,6 +34,9 @@ public final class PatternBuilder { @NotNull private static final NamePredicate JET = new NamePredicate("jet"); + @NotNull + private static final Name KOTLIN_NAME = Name.identifier(Namer.KOTLIN_LOWER_NAME); + private PatternBuilder() { } @@ -69,8 +73,16 @@ public final class PatternBuilder { @NotNull private static DescriptorPredicate pattern(@NotNull List checkers) { - final List checkersWithPrefixChecker = Lists.newArrayList(JET); + assert !checkers.isEmpty(); + final List checkersWithPrefixChecker = Lists.newArrayList(); + if (!checkers.get(0).apply(KOTLIN_NAME)) { + checkersWithPrefixChecker.add(JET); + } + checkersWithPrefixChecker.addAll(checkers); + + assert checkersWithPrefixChecker.size() > 1; + return new DescriptorPredicate() { @Override public boolean apply(@Nullable FunctionDescriptor descriptor) { @@ -89,8 +101,7 @@ public final class PatternBuilder { if (nameParts.size() != checkersWithPrefixChecker.size()) { return false; } - if (!allNamePartsValid(nameParts)) return false; - return true; + return allNamePartsValid(nameParts); } private boolean allNamePartsValid(@NotNull List nameParts) { diff --git a/js/js.translator/testFiles/standardClasses/cases/arrayFactoryMethods.kt b/js/js.translator/testFiles/standardClasses/cases/arrayFactoryMethods.kt new file mode 100644 index 00000000000..08f2ceec385 Binary files /dev/null and b/js/js.translator/testFiles/standardClasses/cases/arrayFactoryMethods.kt differ