From debd58d3774b72554bb32a3818a7b0e837c26c15 Mon Sep 17 00:00:00 2001 From: pyos Date: Wed, 30 Jun 2021 19:58:03 +0200 Subject: [PATCH] JVM: use `$delegate` methods in KProperty[0-2].getDelegate #KT-39055 Fixed --- .../reflect/jvm/internal/KProperty0Impl.kt | 4 +-- .../reflect/jvm/internal/KProperty1Impl.kt | 4 +-- .../reflect/jvm/internal/KProperty2Impl.kt | 4 +-- .../reflect/jvm/internal/KPropertyImpl.kt | 35 ++++++++++++++++--- 4 files changed, 36 insertions(+), 11 deletions(-) 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 517a667035b..80bbad3acd8 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty0Impl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty0Impl.kt @@ -34,9 +34,9 @@ internal open class KProperty0Impl : KProperty0, KPropertyImpl { override fun get(): V = getter.call() - private val delegateFieldValue = lazy(PUBLICATION) { getDelegate(computeDelegateField(), boundReceiver) } + private val delegateValue = lazy(PUBLICATION) { getDelegateImpl(computeDelegateSource(), null, null) } - override fun getDelegate(): Any? = delegateFieldValue.value + override fun getDelegate(): Any? = delegateValue.value override fun invoke(): V = get() 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 921417fa8cd..93fdb08cd5a 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty1Impl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty1Impl.kt @@ -34,9 +34,9 @@ internal open class KProperty1Impl : KProperty1, KPropertyImpl : KProperty2, KProperty override fun get(receiver1: D, receiver2: E): V = getter.call(receiver1, receiver2) - private val delegateField = lazy(PUBLICATION) { computeDelegateField() } + private val delegateSource = lazy(PUBLICATION) { computeDelegateSource() } - override fun getDelegate(receiver1: D, receiver2: E): Any? = getDelegate(delegateField.value, receiver1) + override fun getDelegate(receiver1: D, receiver2: E): Any? = getDelegateImpl(delegateSource.value, receiver1, receiver2) override fun invoke(receiver1: D, receiver2: E): V = get(receiver1, receiver2) 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 bff42cc44f8..88bd9704e98 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt @@ -15,6 +15,8 @@ import org.jetbrains.kotlin.resolve.isUnderlyingPropertyOfInlineClass import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor import org.jetbrains.kotlin.types.TypeUtils import java.lang.reflect.Field +import java.lang.reflect.Member +import java.lang.reflect.Method import java.lang.reflect.Modifier import kotlin.jvm.internal.CallableReference import kotlin.reflect.KFunction @@ -77,12 +79,22 @@ internal abstract class KPropertyImpl private constructor( val javaField: Field? get() = _javaField() - protected fun computeDelegateField(): Field? = - if (descriptor.isDelegated) javaField else null + protected fun computeDelegateSource(): Member? { + if (!descriptor.isDelegated) return null + val jvmSignature = RuntimeTypeMapper.mapPropertySignature(descriptor) + if (jvmSignature is KotlinProperty && jvmSignature.signature.hasDelegateMethod()) { + val method = jvmSignature.signature.delegateMethod + if (!method.hasName() || !method.hasDesc()) return null + val name = jvmSignature.nameResolver.getString(method.name) + val desc = jvmSignature.nameResolver.getString(method.desc) + return container.findMethodBySignature(name, desc) + } + return javaField + } - protected fun getDelegate(field: Field?, receiver: Any?): Any? = + protected fun getDelegateImpl(fieldOrMethod: Member?, receiver1: Any?, receiver2: Any?): Any? = try { - if (receiver === EXTENSION_PROPERTY_DELEGATE) { + if (receiver1 === EXTENSION_PROPERTY_DELEGATE || receiver2 === EXTENSION_PROPERTY_DELEGATE) { if (descriptor.extensionReceiverParameter == null) { throw RuntimeException( "'$this' is not an extension property and thus getExtensionDelegate() " + @@ -90,7 +102,20 @@ internal abstract class KPropertyImpl private constructor( ) } } - field?.get(receiver) + + val realReceiver1 = (if (isBound) boundReceiver else receiver1).takeIf { it !== EXTENSION_PROPERTY_DELEGATE } + val realReceiver2 = (if (isBound) receiver1 else receiver2).takeIf { it !== EXTENSION_PROPERTY_DELEGATE } + when (fieldOrMethod) { + null -> null + is Field -> fieldOrMethod.get(realReceiver1) + is Method -> when (fieldOrMethod.parameterTypes.size) { + 0 -> fieldOrMethod.invoke(null) + 1 -> fieldOrMethod.invoke(null, realReceiver1 ?: defaultPrimitiveValue(fieldOrMethod.parameterTypes[0])) + 2 -> fieldOrMethod.invoke(null, realReceiver1, realReceiver2 ?: defaultPrimitiveValue(fieldOrMethod.parameterTypes[1])) + else -> throw AssertionError("delegate method $fieldOrMethod should take 0, 1, or 2 parameters") + } + else -> throw AssertionError("delegate field/method $fieldOrMethod neither field nor method") + } } catch (e: IllegalAccessException) { throw IllegalPropertyDelegateAccessException(e) }