From 12cb774f1ce919e89ccf942cfce8fb67e6cbe1f7 Mon Sep 17 00:00:00 2001 From: Erokhin Stanislav Date: Fri, 6 Sep 2013 15:22:21 +0400 Subject: [PATCH] JS backend: remake NameGenerator in case Property & PropertyAccessor. Fix overload extension property. --- .../semantics/RegressionMergeEcmaTest.java | 4 ++ .../k2js/translate/context/StaticContext.java | 72 +++++++++---------- .../translate/context/TranslationContext.java | 5 ++ .../translate/utils/TranslationUtils.java | 6 ++ .../testFiles/mergeEcma/cases/backendField.kt | 9 +++ 5 files changed, 59 insertions(+), 37 deletions(-) create mode 100644 js/js.translator/testFiles/mergeEcma/cases/backendField.kt diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/RegressionMergeEcmaTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/RegressionMergeEcmaTest.java index 92117428b32..847ac653f93 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/RegressionMergeEcmaTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/RegressionMergeEcmaTest.java @@ -84,6 +84,10 @@ public class RegressionMergeEcmaTest extends SingleFileTranslationTest { checkFooBoxIsOk(); } + public void testBackendField() throws Exception { + checkFooBoxIsOk(); + } + public void testExtensionClass() throws Exception { checkFooBoxIsOk(); } 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 7138d7e0a08..8ead4fb4efc 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,7 +35,6 @@ 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.JsDescriptorUtils; import org.jetbrains.k2js.translate.utils.PredefinedAnnotation; import java.util.Arrays; @@ -44,7 +43,6 @@ import java.util.Comparator; import java.util.Map; import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.*; -import static org.jetbrains.k2js.translate.utils.BindingUtils.isObjectDeclaration; import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*; /** @@ -199,13 +197,6 @@ public final class StaticContext { } private final class NameGenerator extends Generator { - private JsName declareName(DeclarationDescriptor descriptor, String name) { - JsScope scope = getEnclosingScope(descriptor); - // ecma 5 property name never declares as obfuscatable: - // 1) property cannot be overloaded, so, name collision is not possible - // 2) main reason: if property doesn't have any custom accessor, value holder will have the same name as accessor, so, the same name will be declared more than once - return isEcma5() ? scope.declareName(name) : scope.declareFreshName(name); - } public NameGenerator() { Rule namesForStandardClasses = new Rule() { @@ -286,23 +277,40 @@ public final class StaticContext { return getNameForDescriptor(containingClass); } }; - Rule accessorsHasNamesWithSpecialPrefixes = new Rule() { + + // ecma 5 property name never declares as obfuscatable: + // 1) property cannot be overloaded, so, name collision is not possible + // 2) main reason: if property doesn't have any custom accessor, value holder will have the same name as accessor, so, the same name will be declared more than once + // + // But extension property may obfuscatable, because transform into function. Example: String.foo = 1, Int.foo = 2 + Rule propertyOrPropertyAccessor = new Rule() { @Override public JsName apply(@NotNull DeclarationDescriptor descriptor) { - if (!(descriptor instanceof PropertyAccessorDescriptor)) { + PropertyDescriptor propertyDescriptor; + if (descriptor instanceof PropertyAccessorDescriptor) { + propertyDescriptor = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty(); + } + else if (descriptor instanceof PropertyDescriptor) { + propertyDescriptor = (PropertyDescriptor) descriptor; + } + else { return null; } - PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) descriptor; - String propertyName = accessorDescriptor.getCorrespondingProperty().getName().asString(); - if (isObjectDeclaration(accessorDescriptor.getCorrespondingProperty())) { - return declareName(descriptor, propertyName); - } + String propertyName = propertyDescriptor.getName().asString(); - boolean isGetter = descriptor instanceof PropertyGetterDescriptor; - String accessorName = Namer.getNameForAccessor(propertyName, isGetter, - accessorDescriptor.getReceiverParameter() == null && isEcma5()); - return declareName(descriptor, accessorName); + if (!isExtension(propertyDescriptor)) { + return declarePropertyOrPropertyAccessorName(descriptor, propertyName, false); + } else { + if (descriptor instanceof PropertyDescriptor) { + return declarePropertyOrPropertyAccessorName(descriptor, propertyName, true); + } else { + String propertyJsName = getNameForDescriptor(propertyDescriptor).getIdent(); + boolean isGetter = descriptor instanceof PropertyGetterDescriptor; + String accessorName = Namer.getNameForAccessor(propertyJsName, isGetter, false); + return declarePropertyOrPropertyAccessorName(descriptor, accessorName, false); + } + } } }; @@ -320,21 +328,6 @@ public final class StaticContext { return null; } }; - Rule propertiesCorrespondToSpeciallyTreatedBackingFieldNames = new Rule() { - @Override - public JsName apply(@NotNull DeclarationDescriptor descriptor) { - if (!(descriptor instanceof PropertyDescriptor)) { - return null; - } - - String name = descriptor.getName().asString(); - if (!isEcma5() || !JsDescriptorUtils.isSimpleProperty((PropertyDescriptor) descriptor)) { - name = Namer.getKotlinBackingFieldName(name); - } - - return declareName(descriptor, name); - } - }; Rule overridingDescriptorsReferToOriginalName = new Rule() { @Override public JsName apply(@NotNull DeclarationDescriptor descriptor) { @@ -355,15 +348,20 @@ public final class StaticContext { }; addRule(namesForStandardClasses); addRule(constructorHasTheSameNameAsTheClass); + addRule(propertyOrPropertyAccessor); addRule(predefinedObjectsHasUnobfuscatableNames); - addRule(propertiesCorrespondToSpeciallyTreatedBackingFieldNames); addRule(namespacesShouldBeDefinedInRootScope); addRule(overridingDescriptorsReferToOriginalName); - addRule(accessorsHasNamesWithSpecialPrefixes); addRule(memberDeclarationsInsideParentsScope); } } + @NotNull + public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name, boolean fresh) { + JsScope scope = getEnclosingScope(descriptor); + return fresh ? scope.declareFreshName(name) : scope.declareName(name); + } + @NotNull private JsScope getEnclosingScope(@NotNull DeclarationDescriptor descriptor) { DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java index e79d719535e..a1901801543 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java @@ -172,6 +172,11 @@ public class TranslationContext { return staticContext.getNameForDescriptor(descriptor); } + @NotNull + public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name, boolean fresh) { + return staticContext.declarePropertyOrPropertyAccessorName(descriptor, name, fresh); + } + @NotNull public JsStringLiteral nameToLiteral(@NotNull Named named) { return program().getStringLiteral(named.getName().asString()); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java index 23371f9ff52..fae687f5d34 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java @@ -34,6 +34,7 @@ import java.util.Collections; import java.util.List; import static com.google.dart.compiler.backend.js.ast.JsBinaryOperator.*; +import static org.jetbrains.k2js.translate.context.Namer.getKotlinBackingFieldName; import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression; import static org.jetbrains.k2js.translate.utils.JsAstUtils.assignment; import static org.jetbrains.k2js.translate.utils.JsAstUtils.createDataDescriptor; @@ -154,6 +155,11 @@ public final class TranslationUtils { public static JsNameRef backingFieldReference(@NotNull TranslationContext context, @NotNull PropertyDescriptor descriptor) { JsName backingFieldName = context.getNameForDescriptor(descriptor); + if(!JsDescriptorUtils.isSimpleProperty(descriptor)) { + backingFieldName = context.declarePropertyOrPropertyAccessorName(descriptor, + getKotlinBackingFieldName(backingFieldName.getIdent()), + false); + } return new JsNameRef(backingFieldName, JsLiteral.THIS); } diff --git a/js/js.translator/testFiles/mergeEcma/cases/backendField.kt b/js/js.translator/testFiles/mergeEcma/cases/backendField.kt new file mode 100644 index 00000000000..c4d774c8503 --- /dev/null +++ b/js/js.translator/testFiles/mergeEcma/cases/backendField.kt @@ -0,0 +1,9 @@ +package foo + +val a: Int = 1 + get() = $a + 1 + +fun box(): String { + if (a != 2) return "a != 2, it: $a" + return "OK" +} \ No newline at end of file