diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/OperatorOverloadingTest.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/OperatorOverloadingTest.java index e21b88448c0..291b090ed3a 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/OperatorOverloadingTest.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/OperatorOverloadingTest.java @@ -120,4 +120,8 @@ public final class OperatorOverloadingTest extends SingleFileTranslationTest { public void testOverloadUnaryOperationsViaExtensionFunctions() throws Exception { fooBoxTest(); } + + public void testLambdaRhs() throws Exception { + checkFooBoxIsOk(); + } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/AssignmentTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/AssignmentTranslator.java index 77712a8d9bf..f063160c36a 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/AssignmentTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/AssignmentTranslator.java @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.js.translate.operation; -import com.google.dart.compiler.backend.js.ast.JsBlock; import com.google.dart.compiler.backend.js.ast.JsExpression; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +36,6 @@ import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.isVariableRea import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getSimpleName; import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment; import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.hasCorrespondingFunctionIntrinsic; -import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateRightExpression; public abstract class AssignmentTranslator extends AbstractTranslator { @@ -56,10 +54,7 @@ public abstract class AssignmentTranslator extends AbstractTranslator { @NotNull protected final KtBinaryExpression expression; - protected final AccessTranslator accessTranslator; protected final boolean isVariableReassignment; - @NotNull - protected final JsExpression right; protected AssignmentTranslator(@NotNull KtBinaryExpression expression, @NotNull TranslationContext context) { @@ -68,19 +63,16 @@ public abstract class AssignmentTranslator extends AbstractTranslator { this.isVariableReassignment = isVariableReassignment(context.bindingContext(), expression); KtExpression left = expression.getLeft(); assert left != null : "No left-hand side: " + expression.getText(); + } - JsBlock rightBlock = new JsBlock(); - this.right = translateRightExpression(context, expression, rightBlock); - - if (isReferenceToBackingFieldFromConstructor(left, context)) { + protected final AccessTranslator createAccessTranslator(KtExpression left, boolean forceOrderOfEvaluation) { + if (isReferenceToBackingFieldFromConstructor(left, context())) { KtSimpleNameExpression simpleName = getSimpleName(left); assert simpleName != null; - this.accessTranslator = BackingFieldAccessTranslator.newInstance(simpleName, context); + return BackingFieldAccessTranslator.newInstance(simpleName, context()); } else { - this.accessTranslator = AccessTranslationUtils.getAccessTranslator(left, context(), !rightBlock.isEmpty()); + return AccessTranslationUtils.getAccessTranslator(left, context(), forceOrderOfEvaluation); } - - context.addStatementsToCurrentBlockFrom(rightBlock); } private static boolean isReferenceToBackingFieldFromConstructor( diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/IntrinsicAssignmentTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/IntrinsicAssignmentTranslator.java index d08c2c61c1b..7de4fa56146 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/IntrinsicAssignmentTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/IntrinsicAssignmentTranslator.java @@ -18,9 +18,11 @@ package org.jetbrains.kotlin.js.translate.operation; import com.google.dart.compiler.backend.js.ast.JsBinaryOperation; import com.google.dart.compiler.backend.js.ast.JsBinaryOperator; +import com.google.dart.compiler.backend.js.ast.JsBlock; import com.google.dart.compiler.backend.js.ast.JsExpression; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.js.translate.context.TranslationContext; +import org.jetbrains.kotlin.js.translate.reference.AccessTranslator; import org.jetbrains.kotlin.js.translate.utils.TranslationUtils; import org.jetbrains.kotlin.lexer.KtToken; import org.jetbrains.kotlin.psi.KtBinaryExpression; @@ -29,9 +31,11 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions; import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken; import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment; import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleNameExpressionNotDelegatedLocalVar; +import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateRightExpression; public final class IntrinsicAssignmentTranslator extends AssignmentTranslator { - + private JsExpression right; + private AccessTranslator accessTranslator; @NotNull public static JsExpression doTranslate(@NotNull KtBinaryExpression expression, @@ -42,6 +46,11 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator { private IntrinsicAssignmentTranslator(@NotNull KtBinaryExpression expression, @NotNull TranslationContext context) { super(expression, context); + + JsBlock rightBlock = new JsBlock(); + right = translateRightExpression(context, expression, rightBlock); + accessTranslator = createAccessTranslator(expression.getLeft(), !rightBlock.isEmpty()); + context.addStatementsToCurrentBlockFrom(rightBlock); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/OverloadedAssignmentTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/OverloadedAssignmentTranslator.java index 1e88ed5414c..4125566767c 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/OverloadedAssignmentTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/OverloadedAssignmentTranslator.java @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.js.translate.operation; +import com.google.dart.compiler.backend.js.ast.JsBlock; import com.google.dart.compiler.backend.js.ast.JsExpression; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.FunctionDescriptor; @@ -26,6 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; public final class OverloadedAssignmentTranslator extends AssignmentTranslator { + private boolean forceOrderOfEvaluation; @NotNull public static JsExpression doTranslate(@NotNull KtBinaryExpression expression, @@ -52,11 +54,18 @@ public final class OverloadedAssignmentTranslator extends AssignmentTranslator { @NotNull private JsExpression reassignment() { - return accessTranslator.translateAsSet(overloadedMethodInvocation()); + JsExpression newValue = overloadedMethodInvocation(); + return createAccessTranslator(expression.getLeft(), forceOrderOfEvaluation).translateAsSet(newValue); } @NotNull private JsExpression overloadedMethodInvocation() { - return CallTranslator.translate(context(), resolvedCall, accessTranslator.translateAsGet()); + JsBlock innerBlock = new JsBlock(); + TranslationContext innerContext = context().innerBlock(innerBlock); + JsExpression oldValue = createAccessTranslator(expression.getLeft(), false).translateAsGet(); + JsExpression result = CallTranslator.translate(innerContext, resolvedCall, oldValue); + forceOrderOfEvaluation = !innerBlock.isEmpty(); + context().addStatementsToCurrentBlockFrom(innerBlock); + return result; } } diff --git a/js/js.translator/testData/operatorOverloading/cases/lambdaRhs.kt b/js/js.translator/testData/operatorOverloading/cases/lambdaRhs.kt new file mode 100644 index 00000000000..761f790f7c2 --- /dev/null +++ b/js/js.translator/testData/operatorOverloading/cases/lambdaRhs.kt @@ -0,0 +1,27 @@ +package foo + +var global = "" + +fun log(message: String) { + global += message +} + +fun test1(): String { + val list = mutableListOf<(Int) -> Unit>() + + var result = "" + list += { log("<$it>") } + list += { result += "($it)" } + list += { result += "[$it]"; result += "{$it}" } + + for(f in list) f(1) + + return result +} + +fun box(): String { + assertEquals("(1)[1]{1}", test1()) + assertEquals(global, "<1>") + + return "OK" +} \ No newline at end of file