Fix TypeAliasConstructorDescriptor's to create only once when required

Some IDE features relates onto that same descriptors will remain same
between resolve calls
Fix it to be true for TypeAliasConstructorDescriptor's

 #KT-16265 fixed
This commit is contained in:
Simon Ogorodnik
2017-03-14 15:51:20 +03:00
parent 23cbb83c75
commit f56af41d1e
12 changed files with 113 additions and 46 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.descriptors
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeSubstitutor
@@ -33,4 +34,6 @@ interface TypeAliasDescriptor : ClassifierDescriptorWithTypeParameters {
override fun getOriginal(): TypeAliasDescriptor
override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor
val constructors: Collection<TypeAliasConstructorDescriptor>
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeConstructor
@@ -36,6 +37,8 @@ abstract class AbstractTypeAliasDescriptor(
) : DeclarationDescriptorNonRootImpl(containingDeclaration, annotations, name, sourceElement),
TypeAliasDescriptor {
protected abstract val storageManager: StorageManager
// TODO kotlinize some interfaces
private lateinit var declaredTypeParametersImpl: List<TypeParameterDescriptor>
@@ -58,6 +61,15 @@ abstract class AbstractTypeAliasDescriptor(
}
}
fun getTypeAliasConstructors(): Collection<TypeAliasConstructorDescriptor> {
val classDescriptor = this.classDescriptor ?: return emptyList()
return classDescriptor.constructors.mapNotNull {
TypeAliasConstructorDescriptorImpl.createIfAvailable(storageManager, this, it)
}
}
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> =
declaredTypeParametersImpl
@@ -20,6 +20,8 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.types.*
interface TypeAliasConstructorDescriptor : ConstructorDescriptor {
@@ -34,6 +36,8 @@ interface TypeAliasConstructorDescriptor : ConstructorDescriptor {
override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor
val withDispatchReceiver: TypeAliasConstructorDescriptor?
override fun copy(
newOwner: DeclarationDescriptor,
modality: Modality,
@@ -44,6 +48,7 @@ interface TypeAliasConstructorDescriptor : ConstructorDescriptor {
}
class TypeAliasConstructorDescriptorImpl private constructor(
val storageManager: StorageManager,
override val typeAliasDescriptor: TypeAliasDescriptor,
override val underlyingConstructorDescriptor: ClassConstructorDescriptor,
original: TypeAliasConstructorDescriptor?,
@@ -53,6 +58,32 @@ class TypeAliasConstructorDescriptorImpl private constructor(
) : TypeAliasConstructorDescriptor,
FunctionDescriptorImpl(typeAliasDescriptor, original, annotations, Name.special("<init>"), kind, source)
{
// When resolution is ran for common calls, type aliases constructors are resolved as extensions
// (i.e. after members, and with extension receiver)
// But when resolving super-calls (with known set of candidates) constructors of inner classes are expected to have
// a dispatch receiver
override val withDispatchReceiver: TypeAliasConstructorDescriptor? by storageManager.createNullableLazyValue {
val typeAliasConstructor = TypeAliasConstructorDescriptorImpl(storageManager,
typeAliasDescriptor,
underlyingConstructorDescriptor,
this,
underlyingConstructorDescriptor.annotations,
underlyingConstructorDescriptor.kind,
typeAliasDescriptor.source)
val substitutorForUnderlyingClass = typeAliasDescriptor.getTypeSubstitutorForUnderlyingClass() ?: return@createNullableLazyValue null
typeAliasConstructor.initialize(null,
underlyingConstructorDescriptor.dispatchReceiverParameter?.substitute(substitutorForUnderlyingClass),
typeAliasDescriptor.declaredTypeParameters,
valueParameters,
returnType,
Modality.FINAL,
typeAliasDescriptor.visibility)
return@createNullableLazyValue typeAliasConstructor
}
override fun isPrimary(): Boolean =
underlyingConstructorDescriptor.isPrimary
@@ -99,7 +130,9 @@ class TypeAliasConstructorDescriptorImpl private constructor(
}
assert(newName == null) { "Renaming type alias constructor: $this" }
return TypeAliasConstructorDescriptorImpl(
typeAliasDescriptor, underlyingConstructorDescriptor,
storageManager,
typeAliasDescriptor,
underlyingConstructorDescriptor,
this,
annotations,
Kind.DECLARATION, source)
@@ -112,25 +145,21 @@ class TypeAliasConstructorDescriptorImpl private constructor(
}
fun createIfAvailable(
storageManager: StorageManager,
typeAliasDescriptor: TypeAliasDescriptor,
constructor: ClassConstructorDescriptor,
// When resolution is ran for common calls, type aliases constructors are resolved as extensions
// (i.e. after members, and with extension receiver)
// But when resolving super-calls (with known set of candidates) constructors of inner classes are expected to have
// an dispatch receiver
withDispatchReceiver: Boolean
constructor: ClassConstructorDescriptor
): TypeAliasConstructorDescriptor? {
val substitutorForUnderlyingClass = typeAliasDescriptor.getTypeSubstitutorForUnderlyingClass() ?: return null
val typeAliasConstructor =
TypeAliasConstructorDescriptorImpl(typeAliasDescriptor, constructor, null, constructor.annotations,
constructor.kind, typeAliasDescriptor.source)
TypeAliasConstructorDescriptorImpl(
storageManager, typeAliasDescriptor, constructor, null, constructor.annotations,
constructor.kind, typeAliasDescriptor.source)
val valueParameters =
FunctionDescriptorImpl.getSubstitutedValueParameters(
typeAliasConstructor, constructor.valueParameters, substitutorForUnderlyingClass, false, false
)
?: return null
) ?: return null
val returnType = run {
val returnTypeNoAbbreviation = substitutorForUnderlyingClass.substitute(constructor.returnType, Variance.INVARIANT)
@@ -142,17 +171,11 @@ class TypeAliasConstructorDescriptorImpl private constructor(
returnTypeNoAbbreviation
}
val receiverParameterType =
if (withDispatchReceiver) null
else constructor.dispatchReceiverParameter?.let { substitutorForUnderlyingClass.safeSubstitute(it.type, Variance.INVARIANT) }
val dispatchReceiver =
if (withDispatchReceiver) constructor.dispatchReceiverParameter?.substitute(substitutorForUnderlyingClass)
else null
val receiverParameterType = constructor.dispatchReceiverParameter?.let { substitutorForUnderlyingClass.safeSubstitute(it.type, Variance.INVARIANT) }
typeAliasConstructor.initialize(
receiverParameterType,
dispatchReceiver,
null,
typeAliasDescriptor.declaredTypeParameters,
valueParameters,
returnType,
@@ -182,7 +182,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
val visibility = Deserialization.visibility(Flags.VISIBILITY.get(proto.flags))
val typeAlias = DeserializedTypeAliasDescriptor(
c.containingDeclaration, annotations, c.nameResolver.getName(proto.name),
c.storageManager, c.containingDeclaration, annotations, c.nameResolver.getName(proto.name),
visibility, proto, c.nameResolver, c.typeTable, c.sinceKotlinInfoTable, c.containerSource
)
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
@@ -173,6 +174,7 @@ class DeserializedClassConstructorDescriptor(
}
class DeserializedTypeAliasDescriptor(
override val storageManager: StorageManager,
containingDeclaration: DeclarationDescriptor,
annotations: Annotations,
name: Name,
@@ -184,6 +186,7 @@ class DeserializedTypeAliasDescriptor(
override val containerSource: DeserializedContainerSource?
) : AbstractTypeAliasDescriptor(containingDeclaration, annotations, name, SourceElement.NO_SOURCE, visibility),
DeserializedMemberDescriptor {
override lateinit var constructors: Collection<TypeAliasConstructorDescriptor> private set
override lateinit var underlyingType: SimpleType private set
override lateinit var expandedType: SimpleType private set
@@ -200,6 +203,7 @@ class DeserializedTypeAliasDescriptor(
this.expandedType = expandedType
typeConstructorParameters = computeConstructorTypeParameters()
defaultTypeImpl = computeDefaultType()
constructors = getTypeAliasConstructors()
}
override val classDescriptor: ClassDescriptor?
@@ -211,7 +215,16 @@ class DeserializedTypeAliasDescriptor(
override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor {
if (substitutor.isEmpty) return this
val substituted = DeserializedTypeAliasDescriptor(
containingDeclaration, annotations, name, visibility, proto, nameResolver, typeTable, sinceKotlinInfoTable, containerSource
storageManager,
containingDeclaration,
annotations,
name,
visibility,
proto,
nameResolver,
typeTable,
sinceKotlinInfoTable,
containerSource
)
substituted.initialize(declaredTypeParameters,
substitutor.safeSubstitute(underlyingType, Variance.INVARIANT).asSimpleType(),