From f1096cf2be2793cc474a1bc3a575642bb775bece Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Fri, 25 Nov 2011 16:53:03 +0400 Subject: [PATCH] Added support for initialization of properties as constructor parameters. --- .idea/workspace.xml | 512 ++++++++++-------- .../k2js/translate/ExpressionVisitor.java | 1 + .../k2js/translate/FunctionTranslator.java | 21 +- .../k2js/translate/ReferenceTranslator.java | 3 +- .../k2js/translate/TranslationUtils.java | 16 +- .../declaration/PropertyTranslator.java | 7 +- .../ClassInitializerTranslator.java | 53 +- .../jetbrains/k2js/test/BasicClassTest.java | 5 + .../propertiesAsParametersInitialized.kt | 10 + 9 files changed, 362 insertions(+), 266 deletions(-) create mode 100644 translator/testFiles/class/cases/propertiesAsParametersInitialized.kt diff --git a/.idea/workspace.xml b/.idea/workspace.xml index c0b596e7774..7ef651cbe4e 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -8,9 +8,15 @@ + - - + + + + + + + @@ -42,19 +48,6 @@ - - + + @@ -121,7 +127,7 @@ - + @@ -142,10 +148,10 @@ - + - + @@ -160,100 +166,108 @@ + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -280,22 +294,22 @@ @@ -445,7 +459,33 @@ - - - - - - - - - - - - - @@ -780,6 +810,38 @@ + + + + + + + + + + + + + + - - - - - + + + + + localhost @@ -936,15 +998,15 @@ - + - + - + - + @@ -954,7 +1016,7 @@ - + @@ -998,7 +1060,7 @@ @@ -1045,92 +1107,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1138,36 +1117,117 @@ - - - - - - - - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java index 778c7e8edfc..d8ad67e3b39 100644 --- a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java @@ -112,6 +112,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { return AstUtil.newInvocation(callee, arguments); } + //TODO: move to util private boolean isConstructorInvocation(@NotNull JetCallExpression expression, @NotNull TranslationContext context) { JetExpression calleeExpression = expression.getCalleeExpression(); diff --git a/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java b/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java index edd1fd8964a..c622115d1ec 100644 --- a/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java @@ -3,14 +3,17 @@ package org.jetbrains.k2js.translate; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetFunction; +import org.jetbrains.jet.lang.psi.JetFunctionLiteral; +import org.jetbrains.jet.lang.psi.JetNamedFunction; -import java.util.ArrayList; import java.util.List; /** * @author Talanov Pavel */ +//TODO: think about adding state to translator public final class FunctionTranslator extends AbstractTranslator { @NotNull @@ -37,7 +40,8 @@ public final class FunctionTranslator extends AbstractTranslator { @NotNull private JsFunction generateFunctionObject(@NotNull JetFunction jetFunction) { JsFunction result = createFunctionObject(jetFunction); - result.setParameters(translateParameters(jetFunction.getValueParameters(), result.getScope())); + result.setParameters(TranslationUtils.translateParameters + (jetFunction.getValueParameters(), result.getScope())); result.setBody(translateBody(jetFunction, result.getScope())); return result; } @@ -97,15 +101,4 @@ public final class FunctionTranslator extends AbstractTranslator { } throw new AssertionError("Unsupported type of function."); } - - @NotNull - private List translateParameters(@NotNull List jetParameters, - @NotNull JsScope functionScope) { - List jsParameters = new ArrayList(); - for (JetParameter jetParameter : jetParameters) { - JsName parameterName = functionScope.declareName(jetParameter.getName()); - jsParameters.add(new JsParameter(parameterName)); - } - return jsParameters; - } } diff --git a/translator/src/org/jetbrains/k2js/translate/ReferenceTranslator.java b/translator/src/org/jetbrains/k2js/translate/ReferenceTranslator.java index b0c4a3b49ea..5c63123f01d 100644 --- a/translator/src/org/jetbrains/k2js/translate/ReferenceTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/ReferenceTranslator.java @@ -24,8 +24,7 @@ public class ReferenceTranslator extends AbstractTranslator { @NotNull JsExpression translateSimpleName(@NotNull JetSimpleNameExpression expression) { - JsExpression result; - result = resolveAsPropertyAccess(expression); + JsExpression result = resolveAsPropertyAccess(expression); if (result != null) { return result; } diff --git a/translator/src/org/jetbrains/k2js/translate/TranslationUtils.java b/translator/src/org/jetbrains/k2js/translate/TranslationUtils.java index 8faec01e465..8b1fe14a1b4 100644 --- a/translator/src/org/jetbrains/k2js/translate/TranslationUtils.java +++ b/translator/src/org/jetbrains/k2js/translate/TranslationUtils.java @@ -5,10 +5,7 @@ import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetProperty; -import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; -import org.jetbrains.jet.lang.psi.ValueArgument; +import org.jetbrains.jet.lang.psi.*; import java.util.ArrayList; import java.util.List; @@ -102,5 +99,16 @@ public final class TranslationUtils { return context.enclosingScope().findExistingName(backingFieldName); } + @NotNull + static public List translateParameters(@NotNull List jetParameters, + @NotNull JsScope scopeToDeclareParameters) { + List jsParameters = new ArrayList(); + for (JetParameter jetParameter : jetParameters) { + JsName parameterName = scopeToDeclareParameters.declareName(jetParameter.getName()); + jsParameters.add(new JsParameter(parameterName)); + } + return jsParameters; + } + } diff --git a/translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java b/translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java index 479cd0ef569..03465169d3a 100644 --- a/translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java @@ -124,7 +124,7 @@ public final class PropertyTranslator extends AbstractTranslator { context().getScopeForDescriptor(propertySetterDescriptor)); JsParameter defaultParameter = new JsParameter(propertyAccessContext(propertySetterDescriptor).enclosingScope().declareTemporary()); - JsBinaryOperation assignment = assignmentToBackingFieldFromDefaultParameter(defaultParameter); + JsBinaryOperation assignment = assignmentToBackingFieldFromParameter(defaultParameter); result.setParameters(Arrays.asList(defaultParameter)); result.setBody(AstUtil.convertToBlock(assignment)); return result; @@ -135,9 +135,10 @@ public final class PropertyTranslator extends AbstractTranslator { return context().newPropertyAccess(propertySetterDescriptor); } + //TODO: similar code assignment to backing field 1 @NotNull - private JsBinaryOperation assignmentToBackingFieldFromDefaultParameter(@NotNull JsParameter defaultParameter) { - return AstUtil.newAssignment(backingFieldReference(), defaultParameter.getName().makeRef()); + private JsBinaryOperation assignmentToBackingFieldFromParameter(@NotNull JsParameter parameter) { + return AstUtil.newAssignment(backingFieldReference(), parameter.getName().makeRef()); } @NotNull diff --git a/translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java b/translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java index 5aaafbcefad..310123b2779 100644 --- a/translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java @@ -3,6 +3,7 @@ package org.jetbrains.k2js.translate.initializer; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall; @@ -22,6 +23,8 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla @NotNull private final JetClass classDeclaration; + @NotNull + private final List initializerStatements = new ArrayList(); public ClassInitializerTranslator(@NotNull JetClass classDeclaration, @NotNull TranslationContext context) { super(new JsScope(context.getScopeForElement(classDeclaration), @@ -33,35 +36,27 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla @NotNull protected JsFunction generateInitializerFunction() { JsFunction result = JsFunction.getAnonymousFunctionWithScope(initializerMethodScope); + //NOTE: that while we translate constructor parameters we also add property initializer statements + // for properties declared as constructor parameters result.setParameters(translatePrimaryConstructorParameters()); + addCallToSuperMethod(); result.setBody(generateInitializerMethodBody()); return result; } @NotNull private JsBlock generateInitializerMethodBody() { - - List initializerStatements = generateCallToSuperMethod(); - // initializerStatements.addAll(initializersForParameterProperties()); initializerStatements.addAll(translatePropertyAndAnonymousInitializers(classDeclaration)); return AstUtil.newBlock(initializerStatements); } - @NotNull - private List initializersForParameterProperties() { - return null; - } - - @NotNull - private List generateCallToSuperMethod() { - List result = new ArrayList(); + private void addCallToSuperMethod() { if (BindingUtils.hasAncestorClass(context().bindingContext(), classDeclaration)) { JsName superMethodName = initializerMethodScope.declareName(Namer.SUPER_METHOD_NAME); List arguments = translateArguments(); - result.add(AstUtil.convertToStatement + initializerStatements.add(AstUtil.convertToStatement (AstUtil.newInvocation(AstUtil.thisQualifiedReference(superMethodName), arguments))); } - return result; } @NotNull @@ -85,11 +80,35 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla @NotNull List translatePrimaryConstructorParameters() { List result = new ArrayList(); - List parameters = classDeclaration.getPrimaryConstructorParameters(); - for (JetParameter parameter : parameters) { - JsName parameterName = initializerMethodScope.declareName(parameter.getName()); - result.add(new JsParameter(parameterName)); + for (JetParameter jetParameter : classDeclaration.getPrimaryConstructorParameters()) { + result.add(translateParameter(jetParameter)); } return result; } + + @NotNull + private JsParameter translateParameter(@NotNull JetParameter jetParameter) { + JsName parameterName = initializerMethodScope.declareName(jetParameter.getName()); + JsParameter jsParameter = new JsParameter(parameterName); + mayBeAddInitializerStatementForProperty(jsParameter, jetParameter); + return jsParameter; + } + + private void mayBeAddInitializerStatementForProperty(@NotNull JsParameter jsParameter, + @NotNull JetParameter jetParameter) { + PropertyDescriptor propertyDescriptor = + BindingUtils.getPropertyDescriptorForConstructorParameter(context().bindingContext(), jetParameter); + if (propertyDescriptor != null) { + initializerStatements.add(assignmentToBackingFieldFromParameter(propertyDescriptor, jsParameter)); + } + } + + //TODO: similar code assignment to backing field 2 + @NotNull + private JsStatement assignmentToBackingFieldFromParameter(@NotNull PropertyDescriptor descriptor, + @NotNull JsParameter parameter) { + JsNameRef backingFieldReference = TranslationUtils.backingFieldReference(context(), descriptor); + return AstUtil.newAssignmentStatement(backingFieldReference, parameter.getName().makeRef()); + } + } diff --git a/translator/test/org/jetbrains/k2js/test/BasicClassTest.java b/translator/test/org/jetbrains/k2js/test/BasicClassTest.java index cde35b8cefa..95aa0ea1baa 100644 --- a/translator/test/org/jetbrains/k2js/test/BasicClassTest.java +++ b/translator/test/org/jetbrains/k2js/test/BasicClassTest.java @@ -54,4 +54,9 @@ public class BasicClassTest extends TranslationTest { public void propertyAccess() throws Exception { testFooBoxIsTrue("propertyAccess.kt"); } + + @Test + public void propertiesAsParametersInitialized() throws Exception { + testFooBoxIsTrue("propertiesAsParametersInitialized.kt"); + } } diff --git a/translator/testFiles/class/cases/propertiesAsParametersInitialized.kt b/translator/testFiles/class/cases/propertiesAsParametersInitialized.kt new file mode 100644 index 00000000000..79ae2136db8 --- /dev/null +++ b/translator/testFiles/class/cases/propertiesAsParametersInitialized.kt @@ -0,0 +1,10 @@ +namespace foo + +class A(var b : Int, var a : String) { + +} + +fun box() : Boolean { + val c = A(2, "2") + return (c.b == 2 && c.a == "2") +} \ No newline at end of file