From e207b560097274be40ab29cd6db7befc9fc94c5a Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Fri, 6 May 2016 16:16:44 +0300 Subject: [PATCH] Support increment and '+=' on local delegated properties in JS backend --- .../test/semantics/DelegatePropertyTest.java | 8 ++++++++ .../IntrinsicAssignmentTranslator.java | 5 +++-- .../IntrinsicIncrementTranslator.java | 8 ++------ .../js/translate/utils/TranslationUtils.java | 9 +++++++++ .../delegateProperty/cases/localVarInc.kt | 19 ++++++++++++++++++ .../cases/localVarPlusAssign.kt | 20 +++++++++++++++++++ 6 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 js/js.translator/testData/delegateProperty/cases/localVarInc.kt create mode 100644 js/js.translator/testData/delegateProperty/cases/localVarPlusAssign.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/DelegatePropertyTest.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/DelegatePropertyTest.java index cd70b6c3d30..0d20b8ab5d3 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/DelegatePropertyTest.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/DelegatePropertyTest.java @@ -35,6 +35,14 @@ public class DelegatePropertyTest extends SingleFileTranslationTest { checkFooBoxIsOk(); } + public void testLocalVarInc() throws Exception { + checkFooBoxIsOk(); + } + + public void testLocalVarPlusAssign() throws Exception { + checkFooBoxIsOk(); + } + public void testCapturedLocalVal() throws Exception { checkFooBoxIsOk(); } 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 f17c0255378..d08c2c61c1b 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 @@ -21,13 +21,14 @@ import com.google.dart.compiler.backend.js.ast.JsBinaryOperator; 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.utils.TranslationUtils; import org.jetbrains.kotlin.lexer.KtToken; import org.jetbrains.kotlin.psi.KtBinaryExpression; -import org.jetbrains.kotlin.psi.KtSimpleNameExpression; 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; public final class IntrinsicAssignmentTranslator extends AssignmentTranslator { @@ -53,7 +54,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator { @NotNull private JsExpression translateAsAssignmentOperation() { - if (expression.getLeft() instanceof KtSimpleNameExpression) { + if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getLeft(), context())) { return translateAsPlainAssignmentOperation(); } return translateAsAssignToCounterpart(); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/IntrinsicIncrementTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/IntrinsicIncrementTranslator.java index f8f20917c5c..b029eed3feb 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/IntrinsicIncrementTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/IntrinsicIncrementTranslator.java @@ -21,11 +21,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.lexer.KtToken; import org.jetbrains.kotlin.lexer.KtTokens; -import org.jetbrains.kotlin.psi.KtSimpleNameExpression; import org.jetbrains.kotlin.psi.KtUnaryExpression; import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken; import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isPrefix; +import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleNameExpressionNotDelegatedLocalVar; public final class IntrinsicIncrementTranslator extends IncrementTranslator { @@ -44,16 +44,12 @@ public final class IntrinsicIncrementTranslator extends IncrementTranslator { @NotNull private JsExpression translate() { - if (isPrimitiveExpressionIncrement()) { + if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getBaseExpression(), context())) { return primitiveExpressionIncrement(); } return translateIncrementExpression(); } - private boolean isPrimitiveExpressionIncrement() { - return expression.getBaseExpression() instanceof KtSimpleNameExpression; - } - @NotNull private JsExpression primitiveExpressionIncrement() { JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression)); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java index 3ed96ce9e3b..2051812abb1 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.general.Translation; import org.jetbrains.kotlin.psi.*; +import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.types.KotlinType; @@ -295,4 +296,12 @@ public final class TranslationUtils { } return suggestedName; } + + public static boolean isSimpleNameExpressionNotDelegatedLocalVar(@Nullable KtExpression expression, @NotNull TranslationContext context) { + if (!(expression instanceof KtSimpleNameExpression)) { + return false; + } + DeclarationDescriptor descriptor = context.bindingContext().get(BindingContext.REFERENCE_TARGET, ((KtSimpleNameExpression) expression)); + return !(descriptor instanceof LocalVariableDescriptor) || !((LocalVariableDescriptor) descriptor).isDelegated(); + } } diff --git a/js/js.translator/testData/delegateProperty/cases/localVarInc.kt b/js/js.translator/testData/delegateProperty/cases/localVarInc.kt new file mode 100644 index 00000000000..90d3e7f8b7a --- /dev/null +++ b/js/js.translator/testData/delegateProperty/cases/localVarInc.kt @@ -0,0 +1,19 @@ +package foo + +import kotlin.reflect.KProperty + +class Delegate { + var inner = 1 + operator fun getValue(t: Any?, p: KProperty<*>): Int = inner + operator fun setValue(t: Any?, p: KProperty<*>, i: Int) { + inner = i + } +} + +fun box(): String { + var prop: Int by Delegate() + var result = prop++ + if (result != 1) return "fail increment result: $prop" + if (prop != 2) return "fail increment: $prop" + return "OK" +} diff --git a/js/js.translator/testData/delegateProperty/cases/localVarPlusAssign.kt b/js/js.translator/testData/delegateProperty/cases/localVarPlusAssign.kt new file mode 100644 index 00000000000..762e9db3f4c --- /dev/null +++ b/js/js.translator/testData/delegateProperty/cases/localVarPlusAssign.kt @@ -0,0 +1,20 @@ +//TODO: reuse same tests from JVM backend +package foo + +import kotlin.reflect.KProperty + +class Delegate { + var inner = 1 + operator fun getValue(t: Any?, p: KProperty<*>): Int = inner + operator fun setValue(t: Any?, p: KProperty<*>, i: Int) { + inner = i + } +} + +fun box(): String { + var prop: Int by Delegate() + prop += 1 + if (prop != 2) return "fail : $prop" + return "OK" +} +