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))
if (packageOrClassDescriptor.kind == ClassKind.OBJECT) {
descriptors.addAll(packageOrClassDescriptor.unsubstitutedMemberScope.getContributedFunctions(lastName, location).map {
FunctionImportedFromObject(it)
})
val properties = packageOrClassDescriptor.unsubstitutedMemberScope.getContributedVariables(lastName, location)
.filterIsInstance<PropertyDescriptor>().map { PropertyImportedFromObject(it) }
descriptors.addAll(properties)
descriptors.addAll(
packageOrClassDescriptor.unsubstitutedMemberScope.getContributedFunctions(lastName, location)
.map { it.asImportedFromObject() }
)
descriptors.addAll(
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.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>(
val callableFromObject: TCallable
val callableFromObject: TCallable,
originalOrNull: TCallable?
) : CallableDescriptor {
val containingObject = callableFromObject.containingDeclaration as ClassDescriptor
protected val _original = originalOrNull ?: this
}
// members imported from object should be wrapped to not require dispatch receiver
class FunctionImportedFromObject(functionFromObject: FunctionDescriptor) :
FunctionDescriptor by functionFromObject,
ImportedFromObjectCallableDescriptor<FunctionDescriptor>(functionFromObject) {
class FunctionImportedFromObject(
functionFromObject: FunctionDescriptor,
originalOrNull: FunctionDescriptor? = null
) : ImportedFromObjectCallableDescriptor<FunctionDescriptor>(functionFromObject, originalOrNull),
FunctionDescriptor by functionFromObject {
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 {
functionFromObject.original.wrap()
}
override fun getOriginal() = _original
override fun getOriginal() = _original as FunctionDescriptor
override fun copy(
newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?,
kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean
): 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) :
PropertyDescriptor by propertyFromObject,
ImportedFromObjectCallableDescriptor<PropertyDescriptor>(propertyFromObject) {
class PropertyImportedFromObject(
propertyFromObject: PropertyDescriptor,
originalOrNull: PropertyDescriptor? = null
) : ImportedFromObjectCallableDescriptor<PropertyDescriptor>(propertyFromObject, originalOrNull),
PropertyDescriptor by propertyFromObject {
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 {
propertyFromObject.original.wrap()
}
override fun getOriginal() = _original
override fun getOriginal() = _original as PropertyDescriptor
override fun copy(
newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?,
kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean
): 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)