From 10ea2883f771d6513b986cb6fb4cb0c4b1d92a62 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Tue, 14 Mar 2017 13:06:40 +0300 Subject: [PATCH] Supported KProperty2 and KMutableProperty2 for delegated properties Consider this code: object Delegate { operator fun getValue(t: Any?, p: KProperty<*>): String { return "" } } class A { val String.ext by Delegate } then the type of

is KProperty2 (it has 2 receivers). Test fix + review fixes --- .../DoubleColonExpressionResolver.kt | 2 +- .../generators/DelegatedPropertyGenerator.kt | 7 +++-- .../provideDelegate/memberExtension.txt | 4 +-- .../kotlin/builtins/ReflectionTypes.kt | 26 ++++++++++--------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index 54a8e7059a6..20c4be37453 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -772,7 +772,7 @@ class DoubleColonExpressionResolver( val setter = descriptor.setter setter == null || Visibilities.isVisible(receiverType?.let(::TransientReceiver), setter, scopeOwnerDescriptor) } - reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.type, mutable) + reflectionTypes.getKPropertyType(Annotations.EMPTY, listOfNotNull(receiverType), descriptor.type, mutable) } is VariableDescriptor -> null else -> throw UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: $descriptor") diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt index 82b6804274a..841af1088e3 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt @@ -80,9 +80,8 @@ class DelegatedPropertyGenerator(override val context: GeneratorContext) : Gener } private fun getKPropertyTypeForDelegatedProperty(propertyDescriptor: PropertyDescriptor): KotlinType { - val propertyReceiverType = propertyDescriptor.extensionReceiverParameter?.type ?: - propertyDescriptor.dispatchReceiverParameter?.type - return context.reflectionTypes.getKPropertyType(Annotations.EMPTY, propertyReceiverType, propertyDescriptor.type, propertyDescriptor.isVar) + val receivers = listOfNotNull(propertyDescriptor.extensionReceiverParameter, propertyDescriptor.dispatchReceiverParameter) + return context.reflectionTypes.getKPropertyType(Annotations.EMPTY, receivers.map{ it.type }, propertyDescriptor.type, propertyDescriptor.isVar) } private fun generateDelegateFieldForProperty( @@ -195,7 +194,7 @@ class DelegatedPropertyGenerator(override val context: GeneratorContext) : Gener } private fun getKPropertyTypeForLocalDelegatedProperty(variableDescriptor: VariableDescriptorWithAccessors) = - context.reflectionTypes.getKPropertyType(Annotations.EMPTY, null, variableDescriptor.type, variableDescriptor.isVar) + context.reflectionTypes.getKPropertyType(Annotations.EMPTY, emptyList(), variableDescriptor.type, variableDescriptor.isVar) private fun createPropertyDelegateDescriptor( propertyDescriptor: PropertyDescriptor, diff --git a/compiler/testData/ir/irText/declarations/provideDelegate/memberExtension.txt b/compiler/testData/ir/irText/declarations/provideDelegate/memberExtension.txt index 77ff6298acb..51b20c2c02c 100644 --- a/compiler/testData/ir/irText/declarations/provideDelegate/memberExtension.txt +++ b/compiler/testData/ir/irText/declarations/provideDelegate/memberExtension.txt @@ -37,7 +37,7 @@ FILE /memberExtension.kt $this: GET_VAR '' type=Host origin=null $receiver: CONST String type=kotlin.String value='K' host: GET_VAR '' type=Host origin=null - p: CALLABLE_REFERENCE 'plusK: String on String' type=kotlin.reflect.KProperty1 origin=PROPERTY_REFERENCE_FOR_DELEGATE + p: CALLABLE_REFERENCE 'plusK: String on String' type=kotlin.reflect.KProperty2 origin=PROPERTY_REFERENCE_FOR_DELEGATE FUN DELEGATED_PROPERTY_ACCESSOR public final fun kotlin.String.(): kotlin.String BLOCK_BODY RETURN type=kotlin.Nothing from='() on String: String' @@ -45,7 +45,7 @@ FILE /memberExtension.kt $this: GET_FIELD '`plusK$delegate`: Host.StringDelegate' type=Host.StringDelegate origin=null receiver: GET_VAR '' type=Host origin=null receiver: GET_VAR '' type=kotlin.String origin=null - p: CALLABLE_REFERENCE 'plusK: String on String' type=kotlin.reflect.KProperty1 origin=PROPERTY_REFERENCE_FOR_DELEGATE + p: CALLABLE_REFERENCE 'plusK: String on String' type=kotlin.reflect.KProperty2 origin=PROPERTY_REFERENCE_FOR_DELEGATE PROPERTY public final val ok: kotlin.String FIELD PROPERTY_BACKING_FIELD public final val ok: kotlin.String EXPRESSION_BODY diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt index c0127e1b83e..e9a147a4bc3 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/ReflectionTypes.kt @@ -60,6 +60,7 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not val kProperty2: ClassDescriptor by ClassLookup(3) val kMutableProperty0: ClassDescriptor by ClassLookup(1) val kMutableProperty1: ClassDescriptor by ClassLookup(2) + val kMutableProperty2: ClassDescriptor by ClassLookup(3) fun getKClassType(annotations: Annotations, type: KotlinType, variance: Variance): KotlinType = KotlinTypeFactory.simpleNotNullType(annotations, kClass, listOf(TypeProjectionImpl(variance, type))) @@ -77,23 +78,24 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not return KotlinTypeFactory.simpleNotNullType(annotations, classDescriptor, arguments) } - fun getKPropertyType(annotations: Annotations, receiverType: KotlinType?, returnType: KotlinType, mutable: Boolean): KotlinType { - val classDescriptor = when { - receiverType != null -> when { - mutable -> kMutableProperty1 - else -> kProperty1 - } - else -> when { + fun getKPropertyType(annotations: Annotations, receiverTypes: List, returnType: KotlinType, mutable: Boolean): KotlinType { + val classDescriptor = when (receiverTypes.size) { + 0 -> when { mutable -> kMutableProperty0 else -> kProperty0 } + 1 -> when { + mutable -> kMutableProperty1 + else -> kProperty1 + } + 2 -> when { + mutable -> kMutableProperty2 + else -> kProperty2 + } + else -> throw AssertionError("More than 2 receivers is not allowed") } - val arguments = ArrayList(2) - if (receiverType != null) { - arguments.add(TypeProjectionImpl(receiverType)) - } - arguments.add(TypeProjectionImpl(returnType)) + val arguments = (receiverTypes + returnType).map(::TypeProjectionImpl) return KotlinTypeFactory.simpleNotNullType(annotations, classDescriptor, arguments) }