Function and property descriptors imported from object should keep track of the original imported descriptor,

otherwise they break an assumption that 'getOriginal()' chain would eventually converge on some callable descriptor.
This commit is contained in:
Dmitry Petrov
2017-01-25 15:35:00 +03:00
parent b1b295f00f
commit 500667ff45
2 changed files with 38 additions and 29 deletions
@@ -257,12 +257,15 @@ class QualifiedExpressionResolver {
descriptors.addAll(staticClassScope.getContributedVariables(lastName, location)) descriptors.addAll(staticClassScope.getContributedVariables(lastName, location))
if (packageOrClassDescriptor.kind == ClassKind.OBJECT) { if (packageOrClassDescriptor.kind == ClassKind.OBJECT) {
descriptors.addAll(packageOrClassDescriptor.unsubstitutedMemberScope.getContributedFunctions(lastName, location).map { descriptors.addAll(
FunctionImportedFromObject(it) packageOrClassDescriptor.unsubstitutedMemberScope.getContributedFunctions(lastName, location)
}) .map { it.asImportedFromObject() }
val properties = packageOrClassDescriptor.unsubstitutedMemberScope.getContributedVariables(lastName, location) )
.filterIsInstance<PropertyDescriptor>().map { PropertyImportedFromObject(it) } descriptors.addAll(
descriptors.addAll(properties) packageOrClassDescriptor.unsubstitutedMemberScope.getContributedVariables(lastName, location)
.filterIsInstance<PropertyDescriptor>()
.map { it.asImportedFromObject() }
)
} }
} }
@@ -19,55 +19,61 @@ package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
fun FunctionDescriptor.asImportedFromObject(original: FunctionImportedFromObject? = null) =
FunctionImportedFromObject(this, original)
fun PropertyDescriptor.asImportedFromObject(original: PropertyImportedFromObject? = null) =
PropertyImportedFromObject(this, original)
abstract class ImportedFromObjectCallableDescriptor<out TCallable : CallableMemberDescriptor>( abstract class ImportedFromObjectCallableDescriptor<out TCallable : CallableMemberDescriptor>(
val callableFromObject: TCallable val callableFromObject: TCallable,
originalOrNull: TCallable?
) : CallableDescriptor { ) : CallableDescriptor {
val containingObject = callableFromObject.containingDeclaration as ClassDescriptor val containingObject = callableFromObject.containingDeclaration as ClassDescriptor
protected val _original = originalOrNull ?: this
} }
// members imported from object should be wrapped to not require dispatch receiver // members imported from object should be wrapped to not require dispatch receiver
class FunctionImportedFromObject(functionFromObject: FunctionDescriptor) : class FunctionImportedFromObject(
FunctionDescriptor by functionFromObject, functionFromObject: FunctionDescriptor,
ImportedFromObjectCallableDescriptor<FunctionDescriptor>(functionFromObject) { originalOrNull: FunctionDescriptor? = null
) : ImportedFromObjectCallableDescriptor<FunctionDescriptor>(functionFromObject, originalOrNull),
FunctionDescriptor by functionFromObject {
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null
override fun substitute(substitutor: TypeSubstitutor) = callableFromObject.substitute(substitutor)?.wrap() override fun substitute(substitutor: TypeSubstitutor) =
callableFromObject.substitute(substitutor)?.asImportedFromObject(this)
private val _original by lazy { override fun getOriginal() = _original as FunctionDescriptor
functionFromObject.original.wrap()
}
override fun getOriginal() = _original
override fun copy( override fun copy(
newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?, newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?,
kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean
): FunctionDescriptor { ): FunctionDescriptor {
throw IllegalStateException("copy() should not be called on ${this.javaClass.simpleName}, was called for $this") throw UnsupportedOperationException("copy() should not be called on ${this.javaClass.simpleName}, was called for $this")
} }
} }
class PropertyImportedFromObject(propertyFromObject: PropertyDescriptor) : class PropertyImportedFromObject(
PropertyDescriptor by propertyFromObject, propertyFromObject: PropertyDescriptor,
ImportedFromObjectCallableDescriptor<PropertyDescriptor>(propertyFromObject) { originalOrNull: PropertyDescriptor? = null
) : ImportedFromObjectCallableDescriptor<PropertyDescriptor>(propertyFromObject, originalOrNull),
PropertyDescriptor by propertyFromObject {
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? = null
override fun substitute(substitutor: TypeSubstitutor) = callableFromObject.substitute(substitutor)?.wrap() override fun substitute(substitutor: TypeSubstitutor) = callableFromObject.substitute(substitutor)?.asImportedFromObject(this)
private val _original by lazy { override fun getOriginal() = _original as PropertyDescriptor
propertyFromObject.original.wrap()
}
override fun getOriginal() = _original
override fun copy( override fun copy(
newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?, newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?,
kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean
): FunctionDescriptor { ): FunctionDescriptor {
throw IllegalStateException("copy() should not be called on ${this.javaClass.simpleName}, was called for $this") throw UnsupportedOperationException("copy() should not be called on ${this.javaClass.simpleName}, was called for $this")
} }
} }
private fun FunctionDescriptor.wrap() = FunctionImportedFromObject(this)
private fun PropertyDescriptor.wrap() = PropertyImportedFromObject(this)