From 82af5427472e128d8111e57df0cf23b63571d769 Mon Sep 17 00:00:00 2001 From: Michael Nedzelsky Date: Wed, 6 Aug 2014 11:00:42 +0400 Subject: [PATCH] JS backend: convert PropertyTranslator to Kotlin --- .../declaration/ClassTranslator.java | 3 +- .../declaration/DeclarationBodyVisitor.java | 3 +- .../declaration/PropertyTranslator.java | 193 ------------------ .../declaration/PropertyTranslator.kt | 146 +++++++++++++ 4 files changed, 150 insertions(+), 195 deletions(-) delete mode 100644 js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java create mode 100644 js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.kt 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 1264a906422..b131baf59dd 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 @@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.k2js.translate.context.DefinitionPlace; import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.declaration.propertyTranslator.PropertyTranslatorPackage; import org.jetbrains.k2js.translate.expression.ExpressionPackage; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator; @@ -241,7 +242,7 @@ public final class ClassTranslator extends AbstractTranslator { for (JetParameter parameter : getPrimaryConstructorParameters(classDeclaration)) { PropertyDescriptor descriptor = getPropertyDescriptorForConstructorParameter(bindingContext(), parameter); if (descriptor != null) { - PropertyTranslator.translateAccessors(descriptor, result, classDeclarationContext); + PropertyTranslatorPackage.translateAccessors(descriptor, result, classDeclarationContext); } } } 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 bf1cf5a6003..6ebc2a6ff82 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 @@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.declaration.propertyTranslator.PropertyTranslatorPackage; import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.TranslatorVisitor; import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator; @@ -114,7 +115,7 @@ public class DeclarationBodyVisitor extends TranslatorVisitor { @Override public Void visitProperty(@NotNull JetProperty expression, TranslationContext context) { PropertyDescriptor propertyDescriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), expression); - PropertyTranslator.translateAccessors(propertyDescriptor, expression, result, context); + PropertyTranslatorPackage.translateAccessors(propertyDescriptor, expression, result, context); return null; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java deleted file mode 100644 index d66b8d6a0c1..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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 org.jetbrains.k2js.translate.declaration; - -import com.google.dart.compiler.backend.js.ast.*; -import com.intellij.util.SmartList; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.psi.JetProperty; -import org.jetbrains.jet.lang.psi.JetPropertyAccessor; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; -import org.jetbrains.k2js.translate.callTranslator.CallTranslator; -import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.expression.FunctionTranslator; -import org.jetbrains.k2js.translate.general.AbstractTranslator; -import org.jetbrains.k2js.translate.general.Translation; -import org.jetbrains.k2js.translate.utils.JsDescriptorUtils; -import org.jetbrains.k2js.translate.utils.TranslationUtils; - -import java.util.List; - -import static org.jetbrains.k2js.translate.context.Namer.getDelegateNameRef; -import static org.jetbrains.k2js.translate.utils.TranslationUtils.*; - -/** - * Translates single property /w accessors. - */ -public final class PropertyTranslator extends AbstractTranslator { - @NotNull - private final PropertyDescriptor descriptor; - @Nullable - private final JetProperty declaration; - - public static void translateAccessors(@NotNull PropertyDescriptor descriptor, @NotNull List result, @NotNull TranslationContext context) { - translateAccessors(descriptor, null, result, context); - } - - public static void translateAccessors(@NotNull PropertyDescriptor descriptor, - @Nullable JetProperty declaration, - @NotNull List result, - @NotNull TranslationContext context) { - if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor)) { - new PropertyTranslator(descriptor, declaration, context).translate(result); - } - } - - private PropertyTranslator(@NotNull PropertyDescriptor descriptor, @Nullable JetProperty declaration, @NotNull TranslationContext context) { - super(context); - - this.descriptor = descriptor; - this.declaration = declaration; - } - - private void translate(@NotNull List result) { - List to; - if (!JsDescriptorUtils.isExtension(descriptor)) { - to = new SmartList(); - result.add(new JsPropertyInitializer(context().getNameForDescriptor(descriptor).makeRef(), new JsObjectLiteral(to, true))); - } - else { - to = result; - } - - to.add(generateGetter()); - if (descriptor.isVar()) { - to.add(generateSetter()); - } - } - - private JsPropertyInitializer generateGetter() { - if (hasCustomGetter()) { - return translateCustomAccessor(getCustomGetterDeclaration()); - } - else { - return generateDefaultGetter(); - } - } - - private JsPropertyInitializer generateSetter() { - if (hasCustomSetter()) { - return translateCustomAccessor(getCustomSetterDeclaration()); - } - else { - return generateDefaultSetter(); - } - } - - private boolean hasCustomGetter() { - return declaration != null && declaration.getGetter() != null && getCustomGetterDeclaration().hasBody(); - } - - private boolean hasCustomSetter() { - return declaration != null && declaration.getSetter() != null && getCustomSetterDeclaration().hasBody(); - } - - @NotNull - private JetPropertyAccessor getCustomGetterDeclaration() { - assert declaration != null; - JetPropertyAccessor getterDeclaration = declaration.getGetter(); - assert getterDeclaration != null; - return getterDeclaration; - } - - @NotNull - private JetPropertyAccessor getCustomSetterDeclaration() { - assert declaration != null; - JetPropertyAccessor setter = declaration.getSetter(); - assert setter != null; - return setter; - } - - @NotNull - private JsPropertyInitializer generateDefaultGetter() { - PropertyGetterDescriptor getterDescriptor = descriptor.getGetter(); - assert getterDescriptor != null : "Getter descriptor should not be null"; - return generateDefaultAccessor(getterDescriptor, generateDefaultGetterFunction(getterDescriptor)); - } - - private String getPropertyName() { - return descriptor.getName().asString(); - } - - @NotNull - private JsFunction generateDefaultGetterFunction(@NotNull PropertyGetterDescriptor getterDescriptor) { - JsExpression value; - ResolvedCall delegatedCall = bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor); - if (delegatedCall != null) { - value = CallTranslator.INSTANCE$.translate(context(), delegatedCall, getDelegateNameRef(getPropertyName())); - } else { - value = backingFieldReference(context(), this.descriptor); - } - return simpleReturnFunction(context().getScopeForDescriptor(getterDescriptor.getContainingDeclaration()), value); - } - - @NotNull - private JsPropertyInitializer generateDefaultSetter() { - PropertySetterDescriptor setterDescriptor = descriptor.getSetter(); - assert setterDescriptor != null : "Setter descriptor should not be null"; - return generateDefaultAccessor(setterDescriptor, generateDefaultSetterFunction(setterDescriptor)); - } - - @NotNull - private JsFunction generateDefaultSetterFunction(@NotNull PropertySetterDescriptor setterDescriptor) { - JsFunction fun = new JsFunction(context().getScopeForDescriptor(setterDescriptor.getContainingDeclaration())); - - assert setterDescriptor.getValueParameters().size() == 1 : "Setter must have 1 parameter"; - ValueParameterDescriptor valueParameterDescriptor = setterDescriptor.getValueParameters().get(0); - JsParameter defaultParameter = new JsParameter(fun.getScope().declareTemporary()); - JsNameRef defaultParameterRef = defaultParameter.getName().makeRef(); - - fun.getParameters().add(defaultParameter); - TranslationContext contextWithAliased = context().innerContextWithAliased(valueParameterDescriptor, defaultParameterRef); - - JsExpression setExpression; - ResolvedCall delegatedCall = bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, - setterDescriptor); - if (delegatedCall != null) { - setExpression = CallTranslator.INSTANCE$.translate(contextWithAliased, delegatedCall, getDelegateNameRef(getPropertyName())); - } else { - setExpression = assignmentToBackingField(contextWithAliased, descriptor, defaultParameterRef); - } - fun.setBody(new JsBlock(setExpression.makeStmt())); - return fun; - } - - @NotNull - private JsPropertyInitializer generateDefaultAccessor(@NotNull PropertyAccessorDescriptor accessorDescriptor, - @NotNull JsFunction function) { - return TranslationUtils.translateFunctionAsEcma5PropertyDescriptor(function, accessorDescriptor, context()); - } - - @NotNull - private JsPropertyInitializer translateCustomAccessor(@NotNull JetPropertyAccessor expression) { - FunctionTranslator translator = Translation.functionTranslator(expression, context()); - return translator.translateAsEcma5PropertyDescriptor(); - } -} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.kt b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.kt new file mode 100644 index 00000000000..48d9472d3a5 --- /dev/null +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.kt @@ -0,0 +1,146 @@ +/* + * Copyright 2010-2014 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.declaration.propertyTranslator + +import com.google.dart.compiler.backend.js.ast.* +import com.intellij.util.SmartList +import org.jetbrains.jet.lang.descriptors.* +import org.jetbrains.jet.lang.psi.JetProperty +import org.jetbrains.jet.lang.psi.JetPropertyAccessor +import org.jetbrains.jet.lang.resolve.BindingContext +import org.jetbrains.k2js.translate.callTranslator.CallTranslator +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.JsDescriptorUtils + +import org.jetbrains.k2js.translate.context.Namer.getDelegateNameRef +import org.jetbrains.k2js.translate.utils.TranslationUtils.* + +/** + * Translates single property /w accessors. + */ + +public fun translateAccessors( + descriptor: PropertyDescriptor, + declaration: JetProperty?, + result: MutableList, + context: TranslationContext +) { + if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor)) { + PropertyTranslator(descriptor, declaration, context).translate(result) + } +} + +public fun translateAccessors( + descriptor: PropertyDescriptor, + result: MutableList, + context: TranslationContext +) { + translateAccessors(descriptor, null, result, context) +} + +private class PropertyTranslator( + val descriptor: PropertyDescriptor, + val declaration: JetProperty?, + context: TranslationContext +) : AbstractTranslator(context) { + + private val propertyName: String = descriptor.getName().asString() + + fun translate(result: MutableList) { + val to: MutableList + if (!JsDescriptorUtils.isExtension(descriptor)) { + to = SmartList() + result.add(JsPropertyInitializer(context().getNameForDescriptor(descriptor).makeRef(), JsObjectLiteral(to, true))) + } + else { + to = result + } + + to.add(generateGetter()) + if (descriptor.isVar()) { + to.add(generateSetter()) + } + } + + private fun generateGetter(): JsPropertyInitializer = + if (hasCustomGetter()) translateCustomAccessor(getCustomGetterDeclaration()) else generateDefaultGetter() + + private fun generateSetter(): JsPropertyInitializer = + if (hasCustomSetter()) translateCustomAccessor(getCustomSetterDeclaration()) else generateDefaultSetter() + + private fun hasCustomGetter() = declaration != null && declaration.getGetter() != null && getCustomGetterDeclaration().hasBody() + + private fun hasCustomSetter() = declaration != null && declaration.getSetter() != null && getCustomSetterDeclaration().hasBody() + + private fun getCustomGetterDeclaration(): JetPropertyAccessor = + declaration?.getGetter() ?: + throw IllegalStateException("declaration and getter should not be null descriptor=${descriptor} declaration=${declaration}") + + private fun getCustomSetterDeclaration(): JetPropertyAccessor = + declaration?.getSetter() ?: + throw IllegalStateException("declaration and setter should not be null descriptor=${descriptor} declaration=${declaration}") + + private fun generateDefaultGetter(): JsPropertyInitializer { + val getterDescriptor = descriptor.getGetter() ?: throw IllegalStateException("Getter descriptor should not be null") + return generateDefaultAccessor(getterDescriptor, generateDefaultGetterFunction(getterDescriptor)) + } + + private fun generateDefaultGetterFunction(getterDescriptor: PropertyGetterDescriptor): JsFunction { + val delegatedCall = bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor) + + val value = if (delegatedCall != null) + CallTranslator.translate(context(), delegatedCall, getDelegateNameRef(propertyName)) + else + backingFieldReference(context(), this.descriptor) + + return simpleReturnFunction(context().getScopeForDescriptor(getterDescriptor.getContainingDeclaration()), value) + } + + private fun generateDefaultSetter(): JsPropertyInitializer { + val setterDescriptor = descriptor.getSetter() ?: throw IllegalStateException("Setter descriptor should not be null") + return generateDefaultAccessor(setterDescriptor, generateDefaultSetterFunction(setterDescriptor)) + } + + private fun generateDefaultSetterFunction(setterDescriptor: PropertySetterDescriptor): JsFunction { + val jsFunction = JsFunction(context().getScopeForDescriptor(setterDescriptor.getContainingDeclaration())) + + assert(setterDescriptor.getValueParameters().size() == 1, "Setter must have 1 parameter") + val valueParameterDescriptor = setterDescriptor.getValueParameters().get(0) + val defaultParameter = JsParameter(jsFunction.getScope().declareTemporary()) + val defaultParameterRef = defaultParameter.getName().makeRef() + val contextWithAliased = context().innerContextWithAliased(valueParameterDescriptor, defaultParameterRef) + + val delegatedCall = bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor) + + val setExpression = if (delegatedCall != null) + CallTranslator.translate(contextWithAliased, delegatedCall, getDelegateNameRef(propertyName)) + else + assignmentToBackingField(contextWithAliased, descriptor, defaultParameterRef) + + jsFunction.getParameters().add(defaultParameter) + jsFunction.setBody(JsBlock(setExpression.makeStmt())) + return jsFunction + } + + private fun generateDefaultAccessor(accessorDescriptor: PropertyAccessorDescriptor, function: JsFunction): JsPropertyInitializer = + translateFunctionAsEcma5PropertyDescriptor(function, accessorDescriptor, context()) + + private fun translateCustomAccessor(expression: JetPropertyAccessor): JsPropertyInitializer = + Translation.functionTranslator(expression, context()).translateAsEcma5PropertyDescriptor() +}