diff --git a/compiler/testData/codegen/box/properties/augmentedAssignmentsAndIncrements.kt b/compiler/testData/codegen/box/properties/augmentedAssignmentsAndIncrements.kt new file mode 100644 index 00000000000..bde3c09d5c4 --- /dev/null +++ b/compiler/testData/codegen/box/properties/augmentedAssignmentsAndIncrements.kt @@ -0,0 +1,147 @@ +// Enable when KT-14833 is fixed. +// IGNORE_BACKEND: JVM +import kotlin.reflect.KProperty + +var a = 0 + +var b: Int + get() = a + set(v: Int) { + a = v + } + +class A { + var c: Int + get() = a + set(v: Int) { + a = v + } +} + +var A.d: Int + get() = a + set(v: Int) { + a = v + } + +var Int.e: Int + get() = a + set(v: Int) { + a = v + } + +object SimpleDelegate { + operator fun getValue(thisRef: Any?, desc: KProperty<*>): Int { + return a + } + + operator fun setValue(thisRef: Any?, desc: KProperty<*>, value: Int) { + a = value + } +} + +var f by SimpleDelegate + +fun box(): String { + if (b++ != 0) return "fail b++: $b" + if (++b != 2) return "fail ++b: $b" + if (--b != 1) return "fail --b: $b" + if (b-- != 1) return "fail b--: $b" + b += 10 + if (b != 10) return "fail b +=: $b" + b *= 10 + if (b != 100) return "fail b *=: $b" + b /= 5 + if (b != 20) return "fail b /=: $b" + b -= 10 + if (b != 10) return "fail b -=: $b" + b %= 7 + if (b != 3) return "fail b %=: $b" + + var q = A() + + a = 0 + if (q.c++ != 0) return "fail q.c++: ${q.c}" + if (++q.c != 2) return "fail ++q.c: ${q.c}" + if (--q.c != 1) return "fail --q.c: ${q.c}" + if (q.c-- != 1) return "fail q.c--: ${q.c}" + q.c += 10 + if (q.c != 10) return "fail q.c +=: ${q.c}" + q.c *= 10 + if (q.c != 100) return "fail q.c *=: ${q.c}" + q.c /= 5 + if (q.c != 20) return "fail q.c /=: ${q.c}" + q.c -= 10 + if (q.c != 10) return "fail q.c -=: ${q.c}" + q.c %= 7 + if (q.c != 3) return "fail q.c %=: ${q.c}" + + a = 0 + if (q.d++ != 0) return "fail q.d++: ${q.d}" + if (++q.d != 2) return "fail ++q.d: ${q.d}" + if (--q.d != 1) return "fail --q.d: ${q.d}" + if (q.d-- != 1) return "fail q.d--: ${q.d}" + q.d += 10 + if (q.d != 10) return "fail q.d +=: ${q.d}" + q.d *= 10 + if (q.d != 100) return "fail q.d *=: ${q.d}" + q.d /= 5 + if (q.d != 20) return "fail q.d /=: ${q.d}" + q.d -= 10 + if (q.d != 10) return "fail q.d -=: ${q.d}" + q.d %= 7 + if (q.d != 3) return "fail q.d %=: ${q.d}" + + a = 0 + if (0.e++ != 0) return "fail 0.e++: ${0.e}" + if (++0.e != 2) return "fail ++0.e: ${0.e}" + if (--0.e != 1) return "fail --0.e: ${0.e}" + if (0.e-- != 1) return "fail 0.e--: ${0.e}" + 0.e += 10 + if (0.e != 10) return "fail 0.e +=: ${0.e}" + 0.e *= 10 + if (0.e != 100) return "fail 0.e *=: ${0.e}" + 0.e /= 5 + if (0.e != 20) return "fail 0.e /=: ${0.e}" + 0.e -= 10 + if (0.e != 10) return "fail 0.e -=: ${0.e}" + 0.e %= 7 + if (0.e != 3) return "fail 0.e %=: ${0.e}" + + a = 0 + if (f++ != 0) return "fail f++: $f" + if (++f != 2) return "fail ++f: $f" + if (--f != 1) return "fail --f: $f" + if (f-- != 1) return "fail f--: $f" + f += 10 + if (f != 10) return "fail f +=: $f" + f *= 10 + if (f != 100) return "fail f *=: $f" + f /= 5 + if (f != 20) return "fail f /=: $f" + f -= 10 + if (f != 10) return "fail f -=: $f" + f %= 7 + if (f != 3) return "fail f %=: $f" + + + var g by SimpleDelegate + + a = 0 + if (g++ != 0) return "fail g++: $g" + if (++g != 2) return "fail ++g: $g" + if (--g != 1) return "fail --g: $g" + if (g-- != 1) return "fail g--: $g" + g += 10 + if (g != 10) return "fail g +=: $g" + g *= 10 + if (g != 100) return "fail g *=: $g" + g /= 5 + if (g != 20) return "fail g /=: $g" + g -= 10 + if (g != 10) return "fail g -=: $g" + g %= 7 + if (g != 3) return "fail g %=: $g" + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index d44091a5cab..26e52582789 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -10895,6 +10895,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/properties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("augmentedAssignmentsAndIncrements.kt") + public void testAugmentedAssignmentsAndIncrements() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/augmentedAssignmentsAndIncrements.kt"); + try { + doTest(fileName); + } + catch (Throwable ignore) { + return; + } + throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + } + @TestMetadata("classArtificialFieldInsideNested.kt") public void testClassArtificialFieldInsideNested() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/classArtificialFieldInsideNested.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 14614dcbda1..ebdcb61dfce 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -10895,6 +10895,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/properties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("augmentedAssignmentsAndIncrements.kt") + public void testAugmentedAssignmentsAndIncrements() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/augmentedAssignmentsAndIncrements.kt"); + try { + doTest(fileName); + } + catch (Throwable ignore) { + return; + } + throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + } + @TestMetadata("classArtificialFieldInsideNested.kt") public void testClassArtificialFieldInsideNested() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/classArtificialFieldInsideNested.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 9f7bb7a9313..6c57eab6a14 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -13223,6 +13223,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/properties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); } + @TestMetadata("augmentedAssignmentsAndIncrements.kt") + public void testAugmentedAssignmentsAndIncrements() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/augmentedAssignmentsAndIncrements.kt"); + doTest(fileName); + } + @TestMetadata("classArtificialFieldInsideNested.kt") public void testClassArtificialFieldInsideNested() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/classArtificialFieldInsideNested.kt"); 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 7de4fa56146..aeb775221a4 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 @@ -23,7 +23,6 @@ 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; import org.jetbrains.kotlin.types.expressions.OperatorConventions; 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 410c25e7144..a818018802c 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 @@ -275,7 +275,12 @@ public final class TranslationUtils { return false; } DeclarationDescriptor descriptor = context.bindingContext().get(BindingContext.REFERENCE_TARGET, ((KtSimpleNameExpression) expression)); - return !(descriptor instanceof LocalVariableDescriptor) || !((LocalVariableDescriptor) descriptor).isDelegated(); + return !((descriptor instanceof LocalVariableDescriptor) && ((LocalVariableDescriptor) descriptor).isDelegated()) && + !((descriptor instanceof PropertyDescriptor) && propertyAccessedByFunctionsInternally((PropertyDescriptor) descriptor, context)); + } + + private static boolean propertyAccessedByFunctionsInternally(@NotNull PropertyDescriptor p, @NotNull TranslationContext context) { + return !JsDescriptorUtils.isSimpleFinalProperty(p) && context.isFromCurrentModule(p) || shouldAccessViaFunctions(p); } public static boolean shouldAccessViaFunctions(@NotNull CallableDescriptor descriptor) {