From 78f2515e95469921757806c385c1ab8a7e7c98e5 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 22 Dec 2016 18:30:38 +0300 Subject: [PATCH] Introduce KProperty{0,1,2}.getDelegate #KT-8384 In Progress --- .../getDelegateWithoutReflection.kt | 22 ++ .../booleanPropertyNameStartsWithIs.kt | 21 ++ .../getDelegate/boundExtensionProperty.kt | 26 +++ .../getDelegate/boundMemberProperty.kt | 26 +++ .../getDelegate/extensionProperty.kt | 25 +++ .../properties/getDelegate/fakeOverride.kt | 25 +++ .../kPropertyForDelegatedProperty.kt | 32 +++ .../getDelegate/memberExtensionProperty.kt | 29 +++ .../properties/getDelegate/memberProperty.kt | 25 +++ .../getDelegate/nameClashClassAndCompanion.kt | 26 +++ .../nameClashExtensionProperties.kt | 42 ++++ .../getDelegate/noSetAccessibleTrue.kt | 44 ++++ .../getDelegate/notDelegatedProperty.kt | 29 +++ .../overrideDelegatedByDelegated.kt | 37 ++++ .../getDelegate/topLevelProperty.kt | 23 +++ .../getDelegateWithoutReflection.txt | 14 ++ .../booleanPropertyNameStartsWithIs.txt | 19 ++ .../getDelegate/boundExtensionProperty.txt | 24 +++ .../getDelegate/boundMemberProperty.txt | 24 +++ .../getDelegate/extensionProperty.txt | 24 +++ .../properties/getDelegate/fakeOverride.txt | 24 +++ .../kPropertyForDelegatedProperty.txt | 22 ++ .../getDelegate/memberExtensionProperty.txt | 29 +++ .../properties/getDelegate/memberProperty.txt | 24 +++ .../nameClashClassAndCompanion.txt | 31 +++ .../nameClashExtensionProperties.txt | 36 ++++ .../getDelegate/noSetAccessibleTrue.txt | 27 +++ .../getDelegate/notDelegatedProperty.txt | 15 ++ .../overrideDelegatedByDelegated.txt | 29 +++ .../getDelegate/topLevelProperty.txt | 19 ++ .../ir/IrBlackBoxCodegenTestGenerated.java | 99 +++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 99 +++++++++ ...LightAnalysisModeCodegenTestGenerated.java | 99 +++++++++ core/builtins/src/kotlin/reflect/KProperty.kt | 37 ++++ .../src/kotlin/reflect/full/exceptions.kt | 16 ++ .../reflect/jvm/internal/KProperty0Impl.kt | 5 + .../reflect/jvm/internal/KProperty1Impl.kt | 5 + .../reflect/jvm/internal/KProperty2Impl.kt | 5 + .../reflect/jvm/internal/KPropertyImpl.kt | 12 ++ .../internal/MutablePropertyReference0.java | 5 + .../internal/MutablePropertyReference1.java | 5 + .../internal/MutablePropertyReference2.java | 5 + .../jvm/internal/PropertyReference0.java | 5 + .../jvm/internal/PropertyReference1.java | 5 + .../jvm/internal/PropertyReference2.java | 5 + .../semantics/JsCodegenBoxTestGenerated.java | 189 ++++++++++++++++++ .../reference-public-api/kotlin-runtime.txt | 9 + 47 files changed, 1398 insertions(+) create mode 100644 compiler/testData/codegen/box/delegatedProperty/getDelegateWithoutReflection.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/boundExtensionProperty.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/boundMemberProperty.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/extensionProperty.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/fakeOverride.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/kPropertyForDelegatedProperty.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/memberExtensionProperty.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/memberProperty.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashClassAndCompanion.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashExtensionProperties.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/noSetAccessibleTrue.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/notDelegatedProperty.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/overrideDelegatedByDelegated.kt create mode 100644 compiler/testData/codegen/box/reflection/properties/getDelegate/topLevelProperty.kt create mode 100644 compiler/testData/codegen/light-analysis/delegatedProperty/getDelegateWithoutReflection.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/boundExtensionProperty.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/boundMemberProperty.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/extensionProperty.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/fakeOverride.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/kPropertyForDelegatedProperty.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/memberExtensionProperty.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/memberProperty.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/nameClashClassAndCompanion.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/nameClashExtensionProperties.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/noSetAccessibleTrue.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/notDelegatedProperty.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/overrideDelegatedByDelegated.txt create mode 100644 compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/topLevelProperty.txt diff --git a/compiler/testData/codegen/box/delegatedProperty/getDelegateWithoutReflection.kt b/compiler/testData/codegen/box/delegatedProperty/getDelegateWithoutReflection.kt new file mode 100644 index 00000000000..5e8026a79a0 --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/getDelegateWithoutReflection.kt @@ -0,0 +1,22 @@ +// IGNORE_BACKEND: JS + +// No kotlin-reflect.jar in this test +// WITH_RUNTIME + +import kotlin.reflect.KProperty + +object Delegate { + operator fun getValue(instance: Any?, property: KProperty<*>) = "" +} + +val foo: String by Delegate + +fun box(): String { + try { + ::foo.getDelegate() + return "Fail: error should have been thrown" + } + catch (e: KotlinReflectionNotSupportedError) { + return "OK" + } +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.kt new file mode 100644 index 00000000000..d1b8e66cd7a --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.kt @@ -0,0 +1,21 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +object Delegate { + operator fun getValue(instance: Any?, property: KProperty<*>) = true +} + +class Foo { + val isOK: Boolean by Delegate +} + +fun box(): String { + val foo = Foo() + assertEquals(Delegate, Foo::isOK.apply { isAccessible = true }.getDelegate(foo)) + assertEquals(Delegate, foo::isOK.apply { isAccessible = true }.getDelegate()) + return if (foo.isOK) "OK" else "Fail" +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/boundExtensionProperty.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/boundExtensionProperty.kt new file mode 100644 index 00000000000..b01b13a6f08 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/boundExtensionProperty.kt @@ -0,0 +1,26 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +object Delegate { + var storage = "" + operator fun getValue(instance: Any?, property: KProperty<*>) = storage + operator fun setValue(instance: Any?, property: KProperty<*>, value: String) { storage = value } +} + +class Foo + +var Foo.result: String by Delegate + +fun box(): String { + val foo = Foo() + foo.result = "Fail" + val d = (foo::result).apply { isAccessible = true }.getDelegate() as Delegate + foo.result = "OK" + assertEquals(d, (foo::result).apply { isAccessible = true }.getDelegate()) + assertEquals(d, (Foo()::result).apply { isAccessible = true }.getDelegate()) + return d.getValue(foo, Foo::result) +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/boundMemberProperty.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/boundMemberProperty.kt new file mode 100644 index 00000000000..d548cbde902 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/boundMemberProperty.kt @@ -0,0 +1,26 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +object Delegate { + var storage = "" + operator fun getValue(instance: Any?, property: KProperty<*>) = storage + operator fun setValue(instance: Any?, property: KProperty<*>, value: String) { storage = value } +} + +class Foo { + var result: String by Delegate +} + +fun box(): String { + val foo = Foo() + foo.result = "Fail" + val d = (foo::result).apply { isAccessible = true }.getDelegate() as Delegate + foo.result = "OK" + assertEquals(d, (foo::result).apply { isAccessible = true }.getDelegate()) + assertEquals(d, (Foo()::result).apply { isAccessible = true }.getDelegate()) + return d.getValue(foo, Foo::result) +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/extensionProperty.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/extensionProperty.kt new file mode 100644 index 00000000000..c9547d81374 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/extensionProperty.kt @@ -0,0 +1,25 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +object Delegate { + var storage = "" + operator fun getValue(instance: Any?, property: KProperty<*>) = storage + operator fun setValue(instance: Any?, property: KProperty<*>, value: String) { storage = value } +} + +class Foo + +var Foo.result: String by Delegate + +fun box(): String { + val foo = Foo() + foo.result = "Fail" + val d = Foo::result.apply { isAccessible = true }.getDelegate(foo) as Delegate + foo.result = "OK" + assertEquals(d, Foo::result.apply { isAccessible = true }.getDelegate(foo)) + return d.getValue(foo, Foo::result) +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/fakeOverride.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/fakeOverride.kt new file mode 100644 index 00000000000..02709feba32 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/fakeOverride.kt @@ -0,0 +1,25 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +object Delegate { + operator fun getValue(instance: Any?, property: KProperty<*>) = "OK" +} + +open class Base { + val x: String by Delegate +} + +class Derived : Base() + +fun box(): String { + val d = Derived() + assertEquals( + (Base::x).apply { isAccessible = true }.getDelegate(d), + (Derived::x).apply { isAccessible = true }.getDelegate(d) + ) + return d.x +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/kPropertyForDelegatedProperty.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/kPropertyForDelegatedProperty.kt new file mode 100644 index 00000000000..b2b1aa38731 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/kPropertyForDelegatedProperty.kt @@ -0,0 +1,32 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.KProperty0 +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +var ref: KProperty<*>? = null + +class Delegate { + var storage = "" + operator fun provideDelegate(instance: Any?, property: KProperty<*>): Delegate { + ref = property + return this + } + operator fun getValue(instance: Any?, property: KProperty<*>): String = storage + operator fun setValue(instance: Any?, property: KProperty<*>, value: String) { storage = value } +} + +var result: String by Delegate() + +fun box(): String { + result + val prop = ref as KProperty0<*> + + result = "Fail" + val d = prop.apply { isAccessible = true }.getDelegate() as Delegate + result = "OK" + assertEquals(d, prop.apply { isAccessible = true }.getDelegate()) + return result +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/memberExtensionProperty.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/memberExtensionProperty.kt new file mode 100644 index 00000000000..c00a23e2ee2 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/memberExtensionProperty.kt @@ -0,0 +1,29 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.* +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +object Delegate { + var storage = "" + operator fun getValue(instance: Any?, property: KProperty<*>) = storage + operator fun setValue(instance: Any?, property: KProperty<*>, value: String) { storage = value } +} + +class Bar + +class Foo { + var Bar.result: String by Delegate +} + +fun box(): String { + val foo = Foo() + val bar = Bar() + with(foo) { bar.result = "Fail" } + val prop = Foo::class.members.single { it.name == "result" } as KMutableProperty2 + val d = prop.apply { isAccessible = true }.getDelegate(foo, bar) as Delegate + with(foo) { bar.result = "OK" } + assertEquals(d, prop.apply { isAccessible = true }.getDelegate(foo, bar)) + return d.getValue(foo, prop) +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/memberProperty.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/memberProperty.kt new file mode 100644 index 00000000000..54607d29131 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/memberProperty.kt @@ -0,0 +1,25 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +object Delegate { + var storage = "" + operator fun getValue(instance: Any?, property: KProperty<*>) = storage + operator fun setValue(instance: Any?, property: KProperty<*>, value: String) { storage = value } +} + +class Foo { + var result: String by Delegate +} + +fun box(): String { + val foo = Foo() + foo.result = "Fail" + val d = (Foo::result).apply { isAccessible = true }.getDelegate(foo) as Delegate + foo.result = "OK" + assertEquals(d, (Foo::result).apply { isAccessible = true }.getDelegate(foo)) + return d.getValue(foo, Foo::result) +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashClassAndCompanion.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashClassAndCompanion.kt new file mode 100644 index 00000000000..ea02dd4c023 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashClassAndCompanion.kt @@ -0,0 +1,26 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +class Delegate(val value: String) { + operator fun getValue(instance: Any?, property: KProperty<*>) = value +} + +class Foo { + val x: String by Delegate("class") + + companion object { + val x: String by Delegate("companion") + } +} + +fun box(): String { + val foo = Foo() + assertEquals("class", ((foo::x).apply { isAccessible = true }.getDelegate() as Delegate).value) + assertEquals("class", ((Foo::x).apply { isAccessible = true }.getDelegate(foo) as Delegate).value) + assertEquals("companion", ((Foo.Companion::x).apply { isAccessible = true }.getDelegate() as Delegate).value) + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashExtensionProperties.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashExtensionProperties.kt new file mode 100644 index 00000000000..967ede7e2fd --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashExtensionProperties.kt @@ -0,0 +1,42 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.* +import kotlin.reflect.full.extensionReceiverParameter +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +class Delegate(val value: String) { + operator fun getValue(instance: Any?, property: KProperty<*>) = value +} + +class Foo + +val Foo.bar: String by Delegate("Foo") +val String.bar: String by Delegate("String") +val Unit.bar: String by Delegate("Unit") + +class MemberExtensions { + val Foo?.bar: String by Delegate("Foo") + val String?.bar: String by Delegate("String") + val Unit?.bar: String by Delegate("Unit") +} + +fun box(): String { + val foo = Foo() + + assertEquals("Foo", ((foo::bar).apply { isAccessible = true }.getDelegate() as Delegate).value) + assertEquals("Foo", ((Foo::bar).apply { isAccessible = true }.getDelegate(foo) as Delegate).value) + assertEquals("String", ((""::bar).apply { isAccessible = true }.getDelegate() as Delegate).value) + assertEquals("String", ((String::bar).apply { isAccessible = true }.getDelegate("") as Delegate).value) + assertEquals("Unit", ((Unit::bar).apply { isAccessible = true }.getDelegate() as Delegate).value) + + val me = MemberExtensions::class.members.filter { it.name == "bar" } as List> + assertEquals(listOf("Foo", "String", "Unit"), me.sortedBy { + it.extensionReceiverParameter!!.type.toString() + }.map { + (it.apply { isAccessible = true }.getDelegate(MemberExtensions(), null) as Delegate).value + }) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/noSetAccessibleTrue.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/noSetAccessibleTrue.kt new file mode 100644 index 00000000000..94d01a2ba9f --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/noSetAccessibleTrue.kt @@ -0,0 +1,44 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.KProperty2 +import kotlin.reflect.full.IllegalPropertyDelegateAccessException +import kotlin.test.* + +object Delegate { + operator fun getValue(instance: Any?, property: KProperty<*>) = true +} + +val topLevel: Boolean by Delegate +val String.extension: Boolean by Delegate + +class Foo { + val member: Boolean by Delegate + val String.memberExtension: Boolean by Delegate +} + +inline fun check(block: () -> Unit) { + try { + block() + throw AssertionError("No IllegalPropertyDelegateAccessException has been thrown") + } catch (e: IllegalPropertyDelegateAccessException) { + // OK + } +} + +fun box(): String { + check { ::topLevel.getDelegate() } + + check { String::extension.getDelegate("") } + check { ""::extension.getDelegate() } + + val foo = Foo() + check { Foo::member.getDelegate(foo) } + check { foo::member.getDelegate() } + + val me = Foo::class.members.single { it.name == "memberExtension" } as KProperty2 + check { me.getDelegate(foo, "") } + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/notDelegatedProperty.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/notDelegatedProperty.kt new file mode 100644 index 00000000000..32030a62e2d --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/notDelegatedProperty.kt @@ -0,0 +1,29 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty2 +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +val topLevel: Boolean = true +val String.extension: Boolean get() = true + +class Foo { + val member: Boolean = true + val String.memberExtension: Boolean get() = true +} + +fun box(): String { + assertNull(::topLevel.apply { isAccessible = true }.getDelegate()) + + assertNull(String::extension.apply { isAccessible = true }.getDelegate("")) + assertNull(""::extension.apply { isAccessible = true }.getDelegate()) + + assertNull(Foo::member.apply { isAccessible = true }.getDelegate(Foo())) + assertNull(Foo()::member.apply { isAccessible = true }.getDelegate()) + + val me = Foo::class.members.single { it.name == "memberExtension" } as KProperty2 + assertNull(me.apply { isAccessible = true }.getDelegate(Foo(), "")) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/overrideDelegatedByDelegated.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/overrideDelegatedByDelegated.kt new file mode 100644 index 00000000000..e08edb1b42d --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/overrideDelegatedByDelegated.kt @@ -0,0 +1,37 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +class Delegate(val value: String) { + operator fun getValue(instance: Any?, property: KProperty<*>) = value +} + +open class Base { + open val x: String by Delegate("Base") +} + +class Derived : Base() { + override val x: String by Delegate("Derived") +} + +fun check(expected: String, delegate: Any?) { + if (delegate == null) throw AssertionError("getDelegate returned null") + assertEquals(expected, (delegate as Delegate).value) +} + +fun box(): String { + val base = Base() + val derived = Derived() + + check("Base", (Base::x).apply { isAccessible = true }.getDelegate(base)) + check("Base", (base::x).apply { isAccessible = true }.getDelegate()) + check("Derived", (Derived::x).apply { isAccessible = true }.getDelegate(derived)) + check("Derived", (derived::x).apply { isAccessible = true }.getDelegate()) + + check("Base", (Base::x).apply { isAccessible = true }.getDelegate(derived)) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/properties/getDelegate/topLevelProperty.kt b/compiler/testData/codegen/box/reflection/properties/getDelegate/topLevelProperty.kt new file mode 100644 index 00000000000..91ab0928058 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/getDelegate/topLevelProperty.kt @@ -0,0 +1,23 @@ +// IGNORE_BACKEND: JS +// WITH_REFLECT + +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible +import kotlin.test.* + +object Delegate { + var storage = "" + operator fun getValue(instance: Any?, property: KProperty<*>) = storage + operator fun setValue(instance: Any?, property: KProperty<*>, value: String) { storage = value } +} + +var result: String by Delegate + +fun box(): String { + result = "Fail" + val p = (::result).apply { isAccessible = true } + val d = p.getDelegate() as Delegate + result = "OK" + assertEquals(d, (::result).apply { isAccessible = true }.getDelegate()) + return d.getValue(null, p) +} diff --git a/compiler/testData/codegen/light-analysis/delegatedProperty/getDelegateWithoutReflection.txt b/compiler/testData/codegen/light-analysis/delegatedProperty/getDelegateWithoutReflection.txt new file mode 100644 index 00000000000..2a7a226f333 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/delegatedProperty/getDelegateWithoutReflection.txt @@ -0,0 +1,14 @@ +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private method (): void + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String +} + +@kotlin.Metadata +public final class GetDelegateWithoutReflectionKt { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final static @org.jetbrains.annotations.NotNull field foo$delegate: Delegate + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getFoo(): java.lang.String +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.txt new file mode 100644 index 00000000000..1637fc82e6e --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.txt @@ -0,0 +1,19 @@ +@kotlin.Metadata +public final class BooleanPropertyNameStartsWithIsKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} + +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private method (): void + public final method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): boolean +} + +@kotlin.Metadata +public final class Foo { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field isOK$delegate: Delegate + public method (): void + public final method isOK(): boolean +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/boundExtensionProperty.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/boundExtensionProperty.txt new file mode 100644 index 00000000000..cb05798ca8d --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/boundExtensionProperty.txt @@ -0,0 +1,24 @@ +@kotlin.Metadata +public final class BoundExtensionPropertyKt { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final static @org.jetbrains.annotations.NotNull field result$delegate: Delegate + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getResult(@org.jetbrains.annotations.NotNull p0: Foo): java.lang.String + public final static method setResult(@org.jetbrains.annotations.NotNull p0: Foo, @org.jetbrains.annotations.NotNull p1: java.lang.String): void +} + +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private static @org.jetbrains.annotations.NotNull field storage: java.lang.String + private method (): void + public final @org.jetbrains.annotations.NotNull method getStorage(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String + public final method setStorage(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final method setValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty, @org.jetbrains.annotations.NotNull p2: java.lang.String): void +} + +@kotlin.Metadata +public final class Foo { + public method (): void +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/boundMemberProperty.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/boundMemberProperty.txt new file mode 100644 index 00000000000..cb5476385e2 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/boundMemberProperty.txt @@ -0,0 +1,24 @@ +@kotlin.Metadata +public final class BoundMemberPropertyKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} + +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private static @org.jetbrains.annotations.NotNull field storage: java.lang.String + private method (): void + public final @org.jetbrains.annotations.NotNull method getStorage(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String + public final method setStorage(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final method setValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty, @org.jetbrains.annotations.NotNull p2: java.lang.String): void +} + +@kotlin.Metadata +public final class Foo { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field result$delegate: Delegate + public method (): void + public final @org.jetbrains.annotations.NotNull method getResult(): java.lang.String + public final method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/extensionProperty.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/extensionProperty.txt new file mode 100644 index 00000000000..54c8b4f5933 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/extensionProperty.txt @@ -0,0 +1,24 @@ +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private static @org.jetbrains.annotations.NotNull field storage: java.lang.String + private method (): void + public final @org.jetbrains.annotations.NotNull method getStorage(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String + public final method setStorage(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final method setValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty, @org.jetbrains.annotations.NotNull p2: java.lang.String): void +} + +@kotlin.Metadata +public final class ExtensionPropertyKt { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final static @org.jetbrains.annotations.NotNull field result$delegate: Delegate + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getResult(@org.jetbrains.annotations.NotNull p0: Foo): java.lang.String + public final static method setResult(@org.jetbrains.annotations.NotNull p0: Foo, @org.jetbrains.annotations.NotNull p1: java.lang.String): void +} + +@kotlin.Metadata +public final class Foo { + public method (): void +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/fakeOverride.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/fakeOverride.txt new file mode 100644 index 00000000000..4294e8d6283 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/fakeOverride.txt @@ -0,0 +1,24 @@ +@kotlin.Metadata +public class Base { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field x$delegate: Delegate + public method (): void + public final @org.jetbrains.annotations.NotNull method getX(): java.lang.String +} + +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private method (): void + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String +} + +@kotlin.Metadata +public final class Derived { + public method (): void +} + +@kotlin.Metadata +public final class FakeOverrideKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/kPropertyForDelegatedProperty.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/kPropertyForDelegatedProperty.txt new file mode 100644 index 00000000000..deb52c061a9 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/kPropertyForDelegatedProperty.txt @@ -0,0 +1,22 @@ +@kotlin.Metadata +public final class Delegate { + private @org.jetbrains.annotations.NotNull field storage: java.lang.String + public method (): void + public final @org.jetbrains.annotations.NotNull method getStorage(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String + public final @org.jetbrains.annotations.NotNull method provideDelegate(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): Delegate + public final method setStorage(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final method setValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty, @org.jetbrains.annotations.NotNull p2: java.lang.String): void +} + +@kotlin.Metadata +public final class KPropertyForDelegatedPropertyKt { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private static @org.jetbrains.annotations.Nullable field ref: kotlin.reflect.KProperty + private final static @org.jetbrains.annotations.NotNull field result$delegate: Delegate + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.Nullable method getRef(): kotlin.reflect.KProperty + public final static @org.jetbrains.annotations.NotNull method getResult(): java.lang.String + public final static method setRef(@org.jetbrains.annotations.Nullable p0: kotlin.reflect.KProperty): void + public final static method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/memberExtensionProperty.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/memberExtensionProperty.txt new file mode 100644 index 00000000000..13c55fed2a0 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/memberExtensionProperty.txt @@ -0,0 +1,29 @@ +@kotlin.Metadata +public final class Bar { + public method (): void +} + +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private static @org.jetbrains.annotations.NotNull field storage: java.lang.String + private method (): void + public final @org.jetbrains.annotations.NotNull method getStorage(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String + public final method setStorage(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final method setValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty, @org.jetbrains.annotations.NotNull p2: java.lang.String): void +} + +@kotlin.Metadata +public final class Foo { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field result$delegate: Delegate + public method (): void + public final @org.jetbrains.annotations.NotNull method getResult(@org.jetbrains.annotations.NotNull p0: Bar): java.lang.String + public final method setResult(@org.jetbrains.annotations.NotNull p0: Bar, @org.jetbrains.annotations.NotNull p1: java.lang.String): void +} + +@kotlin.Metadata +public final class MemberExtensionPropertyKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/memberProperty.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/memberProperty.txt new file mode 100644 index 00000000000..a3ac02194d4 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/memberProperty.txt @@ -0,0 +1,24 @@ +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private static @org.jetbrains.annotations.NotNull field storage: java.lang.String + private method (): void + public final @org.jetbrains.annotations.NotNull method getStorage(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String + public final method setStorage(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final method setValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty, @org.jetbrains.annotations.NotNull p2: java.lang.String): void +} + +@kotlin.Metadata +public final class Foo { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field result$delegate: Delegate + public method (): void + public final @org.jetbrains.annotations.NotNull method getResult(): java.lang.String + public final method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void +} + +@kotlin.Metadata +public final class MemberPropertyKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/nameClashClassAndCompanion.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/nameClashClassAndCompanion.txt new file mode 100644 index 00000000000..4567dc1b089 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/nameClashClassAndCompanion.txt @@ -0,0 +1,31 @@ +@kotlin.Metadata +public final class Delegate { + private final @org.jetbrains.annotations.NotNull field value: java.lang.String + public method (@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final @org.jetbrains.annotations.NotNull method getValue(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String +} + +@kotlin.Metadata +public final class Foo { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + public final static field Companion: Foo.Companion + private final @org.jetbrains.annotations.NotNull field x$delegate$1: Delegate + private final static @org.jetbrains.annotations.NotNull field x$delegate: Delegate + inner class Foo/Companion + public method (): void + public final @org.jetbrains.annotations.NotNull method getX(): java.lang.String +} + +@kotlin.Metadata +public final static class Foo/Companion { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + inner class Foo/Companion + private method (): void + public final @org.jetbrains.annotations.NotNull method getX(): java.lang.String +} + +@kotlin.Metadata +public final class NameClashClassAndCompanionKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/nameClashExtensionProperties.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/nameClashExtensionProperties.txt new file mode 100644 index 00000000000..79ec3d72b10 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/nameClashExtensionProperties.txt @@ -0,0 +1,36 @@ +@kotlin.Metadata +public final class Delegate { + private final @org.jetbrains.annotations.NotNull field value: java.lang.String + public method (@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final @org.jetbrains.annotations.NotNull method getValue(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String +} + +@kotlin.Metadata +public final class Foo { + public method (): void +} + +@kotlin.Metadata +public final class MemberExtensions { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field bar$delegate$1: Delegate + private final @org.jetbrains.annotations.NotNull field bar$delegate$2: Delegate + private final @org.jetbrains.annotations.NotNull field bar$delegate: Delegate + public method (): void + public final @org.jetbrains.annotations.NotNull method getBar(@org.jetbrains.annotations.Nullable p0: Foo): java.lang.String + public final @org.jetbrains.annotations.NotNull method getBar(@org.jetbrains.annotations.Nullable p0: java.lang.String): java.lang.String + public final @org.jetbrains.annotations.NotNull method getBar(@org.jetbrains.annotations.Nullable p0: kotlin.Unit): java.lang.String +} + +@kotlin.Metadata +public final class NameClashExtensionPropertiesKt { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final static @org.jetbrains.annotations.NotNull field bar$delegate$1: Delegate + private final static @org.jetbrains.annotations.NotNull field bar$delegate$2: Delegate + private final static @org.jetbrains.annotations.NotNull field bar$delegate: Delegate + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getBar(@org.jetbrains.annotations.NotNull p0: Foo): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getBar(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getBar(@org.jetbrains.annotations.NotNull p0: kotlin.Unit): java.lang.String +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/noSetAccessibleTrue.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/noSetAccessibleTrue.txt new file mode 100644 index 00000000000..ae2c1a828ca --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/noSetAccessibleTrue.txt @@ -0,0 +1,27 @@ +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private method (): void + public final method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): boolean +} + +@kotlin.Metadata +public final class Foo { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field member$delegate: Delegate + private final @org.jetbrains.annotations.NotNull field memberExtension$delegate: Delegate + public method (): void + public final method getMember(): boolean + public final method getMemberExtension(@org.jetbrains.annotations.NotNull p0: java.lang.String): boolean +} + +@kotlin.Metadata +public final class NoSetAccessibleTrueKt { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final static @org.jetbrains.annotations.NotNull field extension$delegate: Delegate + private final static @org.jetbrains.annotations.NotNull field topLevel$delegate: Delegate + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static method check(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): void + public final static method getExtension(@org.jetbrains.annotations.NotNull p0: java.lang.String): boolean + public final static method getTopLevel(): boolean +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/notDelegatedProperty.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/notDelegatedProperty.txt new file mode 100644 index 00000000000..c2ff28d3648 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/notDelegatedProperty.txt @@ -0,0 +1,15 @@ +@kotlin.Metadata +public final class Foo { + private final field member: boolean + public method (): void + public final method getMember(): boolean + public final method getMemberExtension(@org.jetbrains.annotations.NotNull p0: java.lang.String): boolean +} + +@kotlin.Metadata +public final class NotDelegatedPropertyKt { + private final static field topLevel: boolean + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static method getExtension(@org.jetbrains.annotations.NotNull p0: java.lang.String): boolean + public final static method getTopLevel(): boolean +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/overrideDelegatedByDelegated.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/overrideDelegatedByDelegated.txt new file mode 100644 index 00000000000..3681090cee5 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/overrideDelegatedByDelegated.txt @@ -0,0 +1,29 @@ +@kotlin.Metadata +public class Base { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field x$delegate: Delegate + public method (): void + public @org.jetbrains.annotations.NotNull method getX(): java.lang.String +} + +@kotlin.Metadata +public final class Delegate { + private final @org.jetbrains.annotations.NotNull field value: java.lang.String + public method (@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final @org.jetbrains.annotations.NotNull method getValue(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String +} + +@kotlin.Metadata +public final class Derived { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field x$delegate: Delegate + public method (): void + public @org.jetbrains.annotations.NotNull method getX(): java.lang.String +} + +@kotlin.Metadata +public final class OverrideDelegatedByDelegatedKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static method check(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.Nullable p1: java.lang.Object): void +} diff --git a/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/topLevelProperty.txt b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/topLevelProperty.txt new file mode 100644 index 00000000000..08f4897217c --- /dev/null +++ b/compiler/testData/codegen/light-analysis/reflection/properties/getDelegate/topLevelProperty.txt @@ -0,0 +1,19 @@ +@kotlin.Metadata +public final class Delegate { + public final static field INSTANCE: Delegate + private static @org.jetbrains.annotations.NotNull field storage: java.lang.String + private method (): void + public final @org.jetbrains.annotations.NotNull method getStorage(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String + public final method setStorage(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final method setValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty, @org.jetbrains.annotations.NotNull p2: java.lang.String): void +} + +@kotlin.Metadata +public final class TopLevelPropertyKt { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final static @org.jetbrains.annotations.NotNull field result$delegate: Delegate + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getResult(): java.lang.String + public final static method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void +} 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 68b12869cd7..6e9feaef8c5 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 @@ -6032,6 +6032,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("getDelegateWithoutReflection.kt") + public void testGetDelegateWithoutReflection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/getDelegateWithoutReflection.kt"); + doTest(fileName); + } + @TestMetadata("inClassVal.kt") public void testInClassVal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/inClassVal.kt"); @@ -14556,6 +14562,99 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class GetDelegate extends AbstractIrBlackBoxCodegenTest { + public void testAllFilesPresentInGetDelegate() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/properties/getDelegate"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("booleanPropertyNameStartsWithIs.kt") + public void testBooleanPropertyNameStartsWithIs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.kt"); + doTest(fileName); + } + + @TestMetadata("boundExtensionProperty.kt") + public void testBoundExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/boundExtensionProperty.kt"); + doTest(fileName); + } + + @TestMetadata("boundMemberProperty.kt") + public void testBoundMemberProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/boundMemberProperty.kt"); + doTest(fileName); + } + + @TestMetadata("extensionProperty.kt") + public void testExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/extensionProperty.kt"); + doTest(fileName); + } + + @TestMetadata("fakeOverride.kt") + public void testFakeOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/fakeOverride.kt"); + doTest(fileName); + } + + @TestMetadata("kPropertyForDelegatedProperty.kt") + public void testKPropertyForDelegatedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/kPropertyForDelegatedProperty.kt"); + doTest(fileName); + } + + @TestMetadata("memberExtensionProperty.kt") + public void testMemberExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/memberExtensionProperty.kt"); + doTest(fileName); + } + + @TestMetadata("memberProperty.kt") + public void testMemberProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/memberProperty.kt"); + doTest(fileName); + } + + @TestMetadata("nameClashClassAndCompanion.kt") + public void testNameClashClassAndCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashClassAndCompanion.kt"); + doTest(fileName); + } + + @TestMetadata("nameClashExtensionProperties.kt") + public void testNameClashExtensionProperties() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashExtensionProperties.kt"); + doTest(fileName); + } + + @TestMetadata("noSetAccessibleTrue.kt") + public void testNoSetAccessibleTrue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/noSetAccessibleTrue.kt"); + doTest(fileName); + } + + @TestMetadata("notDelegatedProperty.kt") + public void testNotDelegatedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/notDelegatedProperty.kt"); + doTest(fileName); + } + + @TestMetadata("overrideDelegatedByDelegated.kt") + public void testOverrideDelegatedByDelegated() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/overrideDelegatedByDelegated.kt"); + doTest(fileName); + } + + @TestMetadata("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/topLevelProperty.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/box/reflection/specialBuiltIns") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 28745b4890f..fd2c7ba8912 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -6032,6 +6032,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("getDelegateWithoutReflection.kt") + public void testGetDelegateWithoutReflection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/getDelegateWithoutReflection.kt"); + doTest(fileName); + } + @TestMetadata("inClassVal.kt") public void testInClassVal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/inClassVal.kt"); @@ -14556,6 +14562,99 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class GetDelegate extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInGetDelegate() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/properties/getDelegate"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("booleanPropertyNameStartsWithIs.kt") + public void testBooleanPropertyNameStartsWithIs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.kt"); + doTest(fileName); + } + + @TestMetadata("boundExtensionProperty.kt") + public void testBoundExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/boundExtensionProperty.kt"); + doTest(fileName); + } + + @TestMetadata("boundMemberProperty.kt") + public void testBoundMemberProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/boundMemberProperty.kt"); + doTest(fileName); + } + + @TestMetadata("extensionProperty.kt") + public void testExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/extensionProperty.kt"); + doTest(fileName); + } + + @TestMetadata("fakeOverride.kt") + public void testFakeOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/fakeOverride.kt"); + doTest(fileName); + } + + @TestMetadata("kPropertyForDelegatedProperty.kt") + public void testKPropertyForDelegatedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/kPropertyForDelegatedProperty.kt"); + doTest(fileName); + } + + @TestMetadata("memberExtensionProperty.kt") + public void testMemberExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/memberExtensionProperty.kt"); + doTest(fileName); + } + + @TestMetadata("memberProperty.kt") + public void testMemberProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/memberProperty.kt"); + doTest(fileName); + } + + @TestMetadata("nameClashClassAndCompanion.kt") + public void testNameClashClassAndCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashClassAndCompanion.kt"); + doTest(fileName); + } + + @TestMetadata("nameClashExtensionProperties.kt") + public void testNameClashExtensionProperties() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashExtensionProperties.kt"); + doTest(fileName); + } + + @TestMetadata("noSetAccessibleTrue.kt") + public void testNoSetAccessibleTrue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/noSetAccessibleTrue.kt"); + doTest(fileName); + } + + @TestMetadata("notDelegatedProperty.kt") + public void testNotDelegatedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/notDelegatedProperty.kt"); + doTest(fileName); + } + + @TestMetadata("overrideDelegatedByDelegated.kt") + public void testOverrideDelegatedByDelegated() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/overrideDelegatedByDelegated.kt"); + doTest(fileName); + } + + @TestMetadata("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/topLevelProperty.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/box/reflection/specialBuiltIns") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java index 63a1dd37306..38bc9db2f54 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java @@ -6032,6 +6032,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis doTest(fileName); } + @TestMetadata("getDelegateWithoutReflection.kt") + public void testGetDelegateWithoutReflection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/getDelegateWithoutReflection.kt"); + doTest(fileName); + } + @TestMetadata("inClassVal.kt") public void testInClassVal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/inClassVal.kt"); @@ -14556,6 +14562,99 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class GetDelegate extends AbstractLightAnalysisModeCodegenTest { + public void testAllFilesPresentInGetDelegate() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/properties/getDelegate"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("booleanPropertyNameStartsWithIs.kt") + public void testBooleanPropertyNameStartsWithIs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.kt"); + doTest(fileName); + } + + @TestMetadata("boundExtensionProperty.kt") + public void testBoundExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/boundExtensionProperty.kt"); + doTest(fileName); + } + + @TestMetadata("boundMemberProperty.kt") + public void testBoundMemberProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/boundMemberProperty.kt"); + doTest(fileName); + } + + @TestMetadata("extensionProperty.kt") + public void testExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/extensionProperty.kt"); + doTest(fileName); + } + + @TestMetadata("fakeOverride.kt") + public void testFakeOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/fakeOverride.kt"); + doTest(fileName); + } + + @TestMetadata("kPropertyForDelegatedProperty.kt") + public void testKPropertyForDelegatedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/kPropertyForDelegatedProperty.kt"); + doTest(fileName); + } + + @TestMetadata("memberExtensionProperty.kt") + public void testMemberExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/memberExtensionProperty.kt"); + doTest(fileName); + } + + @TestMetadata("memberProperty.kt") + public void testMemberProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/memberProperty.kt"); + doTest(fileName); + } + + @TestMetadata("nameClashClassAndCompanion.kt") + public void testNameClashClassAndCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashClassAndCompanion.kt"); + doTest(fileName); + } + + @TestMetadata("nameClashExtensionProperties.kt") + public void testNameClashExtensionProperties() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashExtensionProperties.kt"); + doTest(fileName); + } + + @TestMetadata("noSetAccessibleTrue.kt") + public void testNoSetAccessibleTrue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/noSetAccessibleTrue.kt"); + doTest(fileName); + } + + @TestMetadata("notDelegatedProperty.kt") + public void testNotDelegatedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/notDelegatedProperty.kt"); + doTest(fileName); + } + + @TestMetadata("overrideDelegatedByDelegated.kt") + public void testOverrideDelegatedByDelegated() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/overrideDelegatedByDelegated.kt"); + doTest(fileName); + } + + @TestMetadata("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/topLevelProperty.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/box/reflection/specialBuiltIns") diff --git a/core/builtins/src/kotlin/reflect/KProperty.kt b/core/builtins/src/kotlin/reflect/KProperty.kt index 0ba33ca9c62..351575728e3 100644 --- a/core/builtins/src/kotlin/reflect/KProperty.kt +++ b/core/builtins/src/kotlin/reflect/KProperty.kt @@ -88,6 +88,14 @@ public interface KProperty0 : KProperty, () -> R { */ public fun get(): R + /** + * Returns the value of the delegate if this is a delegated property, or `null` if this property is not delegated. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/delegated-properties.html) + * for more information. + */ + @SinceKotlin("1.1") + public fun getDelegate(): Any? + override val getter: Getter public interface Getter : KProperty.Getter, () -> R @@ -126,6 +134,21 @@ public interface KProperty1 : KProperty, (T) -> R { */ public fun get(receiver: T): R + /** + * Returns the value of the delegate if this is a delegated property, or `null` if this property is not delegated. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/delegated-properties.html) + * for more information. + * + * Note that for a top level **extension** property, the delegate is the same for all extension receivers, + * so the actual [receiver] instance passed in is not going to make any difference, it must only be a value of [T]. + * + * @param receiver the receiver which is used to obtain the value of the property delegate. + * For example, it should be a class instance if this is a member property of that class, + * or an extension receiver if this is a top level extension property. + */ + @SinceKotlin("1.1") + public fun getDelegate(receiver: T): Any? + override val getter: Getter public interface Getter : KProperty.Getter, (T) -> R @@ -171,6 +194,20 @@ public interface KProperty2 : KProperty, (D, E) -> R { */ public fun get(receiver1: D, receiver2: E): R + /** + * Returns the value of the delegate if this is a delegated property, or `null` if this property is not delegated. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/delegated-properties.html) + * for more information. + * + * In case of the extension property in a class, the instance of the class should be passed first + * and the instance of the extension receiver second. + * + * @param receiver1 the instance of the first receiver. + * @param receiver2 the instance of the second receiver. + */ + @SinceKotlin("1.1") + public fun getDelegate(receiver1: D, receiver2: E): Any? + override val getter: Getter public interface Getter : KProperty.Getter, (D, E) -> R diff --git a/core/reflection.jvm/src/kotlin/reflect/full/exceptions.kt b/core/reflection.jvm/src/kotlin/reflect/full/exceptions.kt index 9e55c6dc687..d3dbe66c79b 100644 --- a/core/reflection.jvm/src/kotlin/reflect/full/exceptions.kt +++ b/core/reflection.jvm/src/kotlin/reflect/full/exceptions.kt @@ -16,6 +16,8 @@ package kotlin.reflect.full +import kotlin.reflect.KProperty +import kotlin.reflect.jvm.isAccessible /** * An exception that is thrown when `call` is invoked on a callable or `get` or `set` is invoked on a property @@ -27,6 +29,20 @@ package kotlin.reflect.full */ class IllegalCallableAccessException(cause: IllegalAccessException) : kotlin.reflect.IllegalCallableAccessException(cause) +/** + * An exception that is thrown when `getDelegate` is invoked on a [KProperty] object that was not made accessible + * with [isAccessible]. + * + * @see [kotlin.reflect.KProperty0.getDelegate] + * @see [kotlin.reflect.KProperty1.getDelegate] + * @see [kotlin.reflect.KProperty2.getDelegate] + * @see [kotlin.reflect.jvm.isAccessible] + */ +class IllegalPropertyDelegateAccessException(cause: IllegalAccessException) : Exception( + "Cannot obtain the delegate of a non-accessible property. Use \"isAccessible = true\" to make the property accessible", + cause +) + /** * An exception that is thrown when the code tries to introspect a property of a class or a package * and that class or the package no longer has that property. diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty0Impl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty0Impl.kt index 9ba9c13b5d5..4b9bdd8b984 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty0Impl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty0Impl.kt @@ -17,6 +17,7 @@ package kotlin.reflect.jvm.internal import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KProperty0 @@ -31,6 +32,10 @@ internal open class KProperty0Impl : KProperty0, KPropertyImpl { override fun get(): R = getter.call() + private val delegateFieldValue = lazy(PUBLICATION) { getDelegate(computeDelegateField(), boundReceiver) } + + override fun getDelegate(): Any? = delegateFieldValue.value + override fun invoke(): R = get() class Getter(override val property: KProperty0Impl) : KPropertyImpl.Getter(), KProperty0.Getter { diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty1Impl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty1Impl.kt index 41b984741fe..dbe1345d11b 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty1Impl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty1Impl.kt @@ -17,6 +17,7 @@ package kotlin.reflect.jvm.internal import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.reflect.KMutableProperty1 import kotlin.reflect.KProperty1 @@ -31,6 +32,10 @@ internal open class KProperty1Impl : KProperty1, KPropertyImpl(override val property: KProperty1Impl) : KPropertyImpl.Getter(), KProperty1.Getter { diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty2Impl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty2Impl.kt index f47847a0042..e57e5f5477d 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty2Impl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty2Impl.kt @@ -17,6 +17,7 @@ package kotlin.reflect.jvm.internal import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.jvm.internal.CallableReference import kotlin.reflect.KMutableProperty2 import kotlin.reflect.KProperty2 @@ -32,6 +33,10 @@ internal open class KProperty2Impl : KProperty2, KProperty override fun get(receiver1: D, receiver2: E): R = getter.call(receiver1, receiver2) + private val delegateField = lazy(PUBLICATION) { computeDelegateField() } + + override fun getDelegate(receiver1: D, receiver2: E): Any? = getDelegate(delegateField.value, receiver1) + override fun invoke(receiver1: D, receiver2: E): R = get(receiver1, receiver2) class Getter(override val property: KProperty2Impl) : KPropertyImpl.Getter(), KProperty2.Getter { diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt index fa0ff981179..9b49ce937e5 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt @@ -29,6 +29,7 @@ import kotlin.jvm.internal.CallableReference import kotlin.reflect.KFunction import kotlin.reflect.KMutableProperty import kotlin.reflect.KProperty +import kotlin.reflect.full.IllegalPropertyDelegateAccessException import kotlin.reflect.jvm.internal.JvmPropertySignature.* internal abstract class KPropertyImpl private constructor( @@ -81,6 +82,17 @@ internal abstract class KPropertyImpl private constructor( val javaField: Field? get() = javaField_() + protected fun computeDelegateField(): Field? = + if (@Suppress("DEPRECATION") descriptor.isDelegated) javaField else null + + protected fun getDelegate(field: Field?, receiver: Any?): Any? = + try { + field?.get(receiver) + } + catch (e: IllegalAccessException) { + throw IllegalPropertyDelegateAccessException(e) + } + override abstract val getter: Getter private val descriptor_ = ReflectProperties.lazySoft(descriptorInitialValue) { diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference0.java b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference0.java index 00d09c2125c..22c454ee3b1 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference0.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference0.java @@ -47,4 +47,9 @@ public abstract class MutablePropertyReference0 extends MutablePropertyReference public KMutableProperty0.Setter getSetter() { return ((KMutableProperty0) getReflected()).getSetter(); } + + @Override + public Object getDelegate() { + return ((KMutableProperty0) getReflected()).getDelegate(); + } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference1.java b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference1.java index c9c9ba9dfc6..8ffdd9652aa 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference1.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference1.java @@ -47,4 +47,9 @@ public abstract class MutablePropertyReference1 extends MutablePropertyReference public KMutableProperty1.Setter getSetter() { return ((KMutableProperty1) getReflected()).getSetter(); } + + @Override + public Object getDelegate(Object receiver) { + return ((KMutableProperty1) getReflected()).getDelegate(receiver); + } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference2.java b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference2.java index 84fe9fe7a31..54b0b0715db 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference2.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/MutablePropertyReference2.java @@ -40,4 +40,9 @@ public abstract class MutablePropertyReference2 extends MutablePropertyReference public KMutableProperty2.Setter getSetter() { return ((KMutableProperty2) getReflected()).getSetter(); } + + @Override + public Object getDelegate(Object receiver1, Object receiver2) { + return ((KMutableProperty2) getReflected()).getDelegate(receiver1, receiver2); + } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference0.java b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference0.java index ed40c2d9a95..1ce7789a792 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference0.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference0.java @@ -42,4 +42,9 @@ public abstract class PropertyReference0 extends PropertyReference implements KP public KProperty0.Getter getGetter() { return ((KProperty0) getReflected()).getGetter(); } + + @Override + public Object getDelegate() { + return ((KProperty0) getReflected()).getDelegate(); + } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference1.java b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference1.java index 9846916c43b..6a30bb86552 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference1.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference1.java @@ -41,4 +41,9 @@ public abstract class PropertyReference1 extends PropertyReference implements KP public KProperty1.Getter getGetter() { return ((KProperty1) getReflected()).getGetter(); } + + @Override + public Object getDelegate(Object receiver) { + return ((KProperty1) getReflected()).getDelegate(receiver); + } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference2.java b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference2.java index a2845cc19b0..f9228daa468 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference2.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference2.java @@ -34,4 +34,9 @@ public abstract class PropertyReference2 extends PropertyReference implements KP public KProperty2.Getter getGetter() { return ((KProperty2) getReflected()).getGetter(); } + + @Override + public Object getDelegate(Object receiver1, Object receiver2) { + return ((KProperty2) getReflected()).getDelegate(receiver1, receiver2); + } } 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 cdcdf5d1614..a51a5d02109 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 @@ -6861,6 +6861,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("getDelegateWithoutReflection.kt") + public void testGetDelegateWithoutReflection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/getDelegateWithoutReflection.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("inClassVal.kt") public void testInClassVal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/inClassVal.kt"); @@ -18367,6 +18379,183 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); } } + + @TestMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class GetDelegate extends AbstractJsCodegenBoxTest { + public void testAllFilesPresentInGetDelegate() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/properties/getDelegate"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("booleanPropertyNameStartsWithIs.kt") + public void testBooleanPropertyNameStartsWithIs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/booleanPropertyNameStartsWithIs.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("boundExtensionProperty.kt") + public void testBoundExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/boundExtensionProperty.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("boundMemberProperty.kt") + public void testBoundMemberProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/boundMemberProperty.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("extensionProperty.kt") + public void testExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/extensionProperty.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("fakeOverride.kt") + public void testFakeOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/fakeOverride.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("kPropertyForDelegatedProperty.kt") + public void testKPropertyForDelegatedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/kPropertyForDelegatedProperty.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("memberExtensionProperty.kt") + public void testMemberExtensionProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/memberExtensionProperty.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("memberProperty.kt") + public void testMemberProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/memberProperty.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("nameClashClassAndCompanion.kt") + public void testNameClashClassAndCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashClassAndCompanion.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("nameClashExtensionProperties.kt") + public void testNameClashExtensionProperties() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/nameClashExtensionProperties.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("noSetAccessibleTrue.kt") + public void testNoSetAccessibleTrue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/noSetAccessibleTrue.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("notDelegatedProperty.kt") + public void testNotDelegatedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/notDelegatedProperty.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("overrideDelegatedByDelegated.kt") + public void testOverrideDelegatedByDelegated() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/overrideDelegatedByDelegated.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("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/properties/getDelegate/topLevelProperty.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("compiler/testData/codegen/box/reflection/specialBuiltIns") diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-runtime.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-runtime.txt index a2d8590344a..6aee7b5db30 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-runtime.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-runtime.txt @@ -661,6 +661,7 @@ public abstract class kotlin/jvm/internal/MutablePropertyReference0 : kotlin/jvm public fun ()V public fun (Ljava/lang/Object;)V protected fun computeReflected ()Lkotlin/reflect/KCallable; + public fun getDelegate ()Ljava/lang/Object; public synthetic fun getGetter ()Lkotlin/reflect/KProperty$Getter; public fun getGetter ()Lkotlin/reflect/KProperty0$Getter; public synthetic fun getSetter ()Lkotlin/reflect/KMutableProperty$Setter; @@ -681,6 +682,7 @@ public abstract class kotlin/jvm/internal/MutablePropertyReference1 : kotlin/jvm public fun ()V public fun (Ljava/lang/Object;)V protected fun computeReflected ()Lkotlin/reflect/KCallable; + public fun getDelegate (Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun getGetter ()Lkotlin/reflect/KProperty$Getter; public fun getGetter ()Lkotlin/reflect/KProperty1$Getter; public synthetic fun getSetter ()Lkotlin/reflect/KMutableProperty$Setter; @@ -700,6 +702,7 @@ public class kotlin/jvm/internal/MutablePropertyReference1Impl : kotlin/jvm/inte public abstract class kotlin/jvm/internal/MutablePropertyReference2 : kotlin/jvm/internal/MutablePropertyReference, kotlin/reflect/KMutableProperty2 { public fun ()V protected fun computeReflected ()Lkotlin/reflect/KCallable; + public fun getDelegate (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun getGetter ()Lkotlin/reflect/KProperty$Getter; public fun getGetter ()Lkotlin/reflect/KProperty2$Getter; public synthetic fun getSetter ()Lkotlin/reflect/KMutableProperty$Setter; @@ -742,6 +745,7 @@ public abstract class kotlin/jvm/internal/PropertyReference0 : kotlin/jvm/intern public fun ()V public fun (Ljava/lang/Object;)V protected fun computeReflected ()Lkotlin/reflect/KCallable; + public fun getDelegate ()Ljava/lang/Object; public synthetic fun getGetter ()Lkotlin/reflect/KProperty$Getter; public fun getGetter ()Lkotlin/reflect/KProperty0$Getter; public fun invoke ()Ljava/lang/Object; @@ -759,6 +763,7 @@ public abstract class kotlin/jvm/internal/PropertyReference1 : kotlin/jvm/intern public fun ()V public fun (Ljava/lang/Object;)V protected fun computeReflected ()Lkotlin/reflect/KCallable; + public fun getDelegate (Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun getGetter ()Lkotlin/reflect/KProperty$Getter; public fun getGetter ()Lkotlin/reflect/KProperty1$Getter; public fun invoke (Ljava/lang/Object;)Ljava/lang/Object; @@ -775,6 +780,7 @@ public class kotlin/jvm/internal/PropertyReference1Impl : kotlin/jvm/internal/Pr public abstract class kotlin/jvm/internal/PropertyReference2 : kotlin/jvm/internal/PropertyReference, kotlin/reflect/KProperty2 { public fun ()V protected fun computeReflected ()Lkotlin/reflect/KCallable; + public fun getDelegate (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun getGetter ()Lkotlin/reflect/KProperty$Getter; public fun getGetter ()Lkotlin/reflect/KProperty2$Getter; public fun invoke (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1212,6 +1218,7 @@ public abstract interface class kotlin/reflect/KProperty$Getter : kotlin/reflect public abstract interface class kotlin/reflect/KProperty0 : kotlin/jvm/functions/Function0, kotlin/reflect/KProperty { public abstract fun get ()Ljava/lang/Object; + public abstract fun getDelegate ()Ljava/lang/Object; public abstract fun getGetter ()Lkotlin/reflect/KProperty0$Getter; } @@ -1220,6 +1227,7 @@ public abstract interface class kotlin/reflect/KProperty0$Getter : kotlin/jvm/fu public abstract interface class kotlin/reflect/KProperty1 : kotlin/jvm/functions/Function1, kotlin/reflect/KProperty { public abstract fun get (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun getDelegate (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun getGetter ()Lkotlin/reflect/KProperty1$Getter; } @@ -1228,6 +1236,7 @@ public abstract interface class kotlin/reflect/KProperty1$Getter : kotlin/jvm/fu public abstract interface class kotlin/reflect/KProperty2 : kotlin/jvm/functions/Function2, kotlin/reflect/KProperty { public abstract fun get (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun getDelegate (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun getGetter ()Lkotlin/reflect/KProperty2$Getter; }