From d6803fb5ff1e80d84aeb5a65627d963516b59a97 Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Fri, 25 Oct 2013 15:28:18 +0400 Subject: [PATCH] JS backend: fixed ability to declare custom name for native properties and function parameters. #KT-3643 fixed --- .../test/semantics/NativeInteropTest.java | 4 +++ .../test/semantics/PropertyAccessTest.java | 4 +++ .../k2js/translate/context/StaticContext.java | 22 ++++++------ .../translate/utils/AnnotationsUtils.java | 13 +++++++ .../cases/nativePropertyWithCustomName.kt | 35 +++++++++++++++++++ .../native/nativePropertyWithCustomName.js | 17 +++++++++ .../cases/nativePropertiesNameClashes.kt | 35 +++++++++++++++++++ 7 files changed, 119 insertions(+), 11 deletions(-) create mode 100644 js/js.translator/testFiles/native/cases/nativePropertyWithCustomName.kt create mode 100644 js/js.translator/testFiles/native/native/nativePropertyWithCustomName.js create mode 100644 js/js.translator/testFiles/propertyAccess/cases/nativePropertiesNameClashes.kt diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java index a9b664306cb..093c1f0fb02 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java @@ -88,4 +88,8 @@ public final class NativeInteropTest extends SingleFileTranslationTest { public void testKt2323() throws Exception { fooBoxTest(); } + + public void testNativePropertyWithCustomName() throws Exception { + checkFooBoxIsOk(); + } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java index 63b336fcc20..244ebc221b9 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java @@ -94,6 +94,10 @@ public final class PropertyAccessTest extends SingleFileTranslationTest { fooBoxTest(); } + public void testNativePropertiesNameClashes() throws Exception { + checkFooBoxIsOk(); + } + @Override @NotNull protected List additionalJSFiles(@NotNull EcmaVersion ecmaVersion) { 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 302ab018a9e..92dedd0fc59 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 @@ -35,14 +35,14 @@ import org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator; import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.utils.AnnotationsUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils; -import org.jetbrains.k2js.translate.utils.PredefinedAnnotation; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Map; -import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.*; +import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.getNameForAnnotatedObject; +import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.isLibraryObject; import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*; import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMangledName; @@ -298,7 +298,12 @@ public final class StaticContext { return null; } - String propertyName = propertyDescriptor.getName().asString(); + String nameFromAnnotation = getNameForAnnotatedObject(propertyDescriptor); + if (nameFromAnnotation != null) { + return declarePropertyOrPropertyAccessorName(descriptor, nameFromAnnotation, false); + } + + String propertyName = propertyDescriptor.getName().asString(); if (!isExtension(propertyDescriptor)) { if (propertyDescriptor.getVisibility() == Visibilities.PRIVATE) { @@ -321,17 +326,12 @@ public final class StaticContext { Rule predefinedObjectsHasUnobfuscatableNames = new Rule() { @Override public JsName apply(@NotNull DeclarationDescriptor descriptor) { - for (PredefinedAnnotation annotation : PredefinedAnnotation.values()) { - if (!hasAnnotationOrInsideAnnotatedClass(descriptor, annotation)) { - continue; - } - String name = getNameForAnnotatedObject(descriptor, annotation); - name = (name != null) ? name : descriptor.getName().asString(); - return getEnclosingScope(descriptor).declareName(name); - } + String name = getNameForAnnotatedObject(descriptor); + if (name != null) return getEnclosingScope(descriptor).declareName(name); return null; } }; + Rule overridingDescriptorsReferToOriginalName = new Rule() { @Override public JsName apply(@NotNull DeclarationDescriptor descriptor) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java index c199fabaf3b..de275385345 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java @@ -67,6 +67,19 @@ public final class AnnotationsUtils { return getAnnotationStringParameter(declarationDescriptor, annotation); } + @Nullable + public static String getNameForAnnotatedObject(@NotNull DeclarationDescriptor descriptor) { + for (PredefinedAnnotation annotation : PredefinedAnnotation.values()) { + if (!hasAnnotationOrInsideAnnotatedClass(descriptor, annotation)) { + continue; + } + String name = getNameForAnnotatedObject(descriptor, annotation); + return name != null ? name : descriptor.getName().asString(); + } + + return null; + } + @Nullable private static AnnotationDescriptor getAnnotationByName(@NotNull DeclarationDescriptor descriptor, @NotNull PredefinedAnnotation annotation) { diff --git a/js/js.translator/testFiles/native/cases/nativePropertyWithCustomName.kt b/js/js.translator/testFiles/native/cases/nativePropertyWithCustomName.kt new file mode 100644 index 00000000000..cc51a408fc4 --- /dev/null +++ b/js/js.translator/testFiles/native/cases/nativePropertyWithCustomName.kt @@ -0,0 +1,35 @@ +package foo + +val PACKAGE = "Kotlin.modules.JS_TESTS.foo" + +native fun eval(e: String): Any? = noImpl +fun funToString(name: String) = eval("$PACKAGE.$name.toString()") as String + +native("\"O\"") val foo: String = noImpl +native("boo") val bar: String = noImpl + +class A +native("__proto__") val Any.proto: String = noImpl +native("__proto__") val A.proto: String = noImpl + +fun actual(foo: String, native("boo") bar: String) = foo + bar +fun expected(foo: String, boo: String) = foo + boo + +fun box(): String { + val OK = "OK" + + if (foo + bar != OK) return "$foo + $bar != $OK" + + val actualAsString = funToString("actual") + val expectedAsString = funToString("expected") + if (actualAsString != expectedAsString) return "$actualAsString != $expectedAsString" + if (actual("asd", "12345") != "asd12345") return "${actual("asd", "12345")} != \"asd12345\"" + + val a = A() + val any: Any = a + val protoA = eval("$PACKAGE.A.prototype") + if (a.proto != any.proto || a.proto != protoA) + return "a.proto != any.proto /*${a.proto != any.proto}*/ || a.proto != $PACKAGE.A.prototype /*${a.proto != protoA}*/" + + return OK +} diff --git a/js/js.translator/testFiles/native/native/nativePropertyWithCustomName.js b/js/js.translator/testFiles/native/native/nativePropertyWithCustomName.js new file mode 100644 index 00000000000..8ec804d6a80 --- /dev/null +++ b/js/js.translator/testFiles/native/native/nativePropertyWithCustomName.js @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2013 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. + */ + +var boo = "K"; \ No newline at end of file diff --git a/js/js.translator/testFiles/propertyAccess/cases/nativePropertiesNameClashes.kt b/js/js.translator/testFiles/propertyAccess/cases/nativePropertiesNameClashes.kt new file mode 100644 index 00000000000..adba75a6a67 --- /dev/null +++ b/js/js.translator/testFiles/propertyAccess/cases/nativePropertiesNameClashes.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2013 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 foo + +val PACKAGE = "Kotlin.modules.JS_TESTS.foo" + +native fun eval(e: String): Any? = noImpl + +class A +native val Any.__proto__: String = noImpl +native val A.__proto__: String = noImpl + +fun box(): String { + val a = A() + val any: Any = a + val protoA = eval("$PACKAGE.A.prototype") + if (a.__proto__ != any.__proto__ || a.__proto__ != protoA) + return "a.__proto__ != any.__proto__ /*${a.__proto__ != any.__proto__}*/ || a.__proto__ != $PACKAGE.A.prototype /*${a.__proto__ != protoA}*/" + + return "OK" +}