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:
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors
|
||||
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import java.util.*
|
||||
|
||||
@@ -68,7 +68,7 @@ class OverloadResolver(
|
||||
for (typeAlias in c.typeAliases.values) {
|
||||
val containingDeclaration = typeAlias.containingDeclaration
|
||||
if (containingDeclaration is ClassDescriptor) {
|
||||
constructorsByOuterClass.putValues(containingDeclaration, typeAlias.getTypeAliasConstructors())
|
||||
constructorsByOuterClass.putValues(containingDeclaration, typeAlias.constructors)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ class OverloadResolver(
|
||||
else
|
||||
functions
|
||||
is TypeAliasDescriptor ->
|
||||
functions + classifier.getTypeAliasConstructors()
|
||||
functions + classifier.constructors
|
||||
else ->
|
||||
functions
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -33,7 +34,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
@@ -210,7 +210,7 @@ fun createResolutionCandidatesForConstructors(
|
||||
else
|
||||
null
|
||||
|
||||
val constructors = typeAliasDescriptor?.getTypeAliasConstructors(withDispatchReceiver = true) ?: classWithConstructors.constructors
|
||||
val constructors = typeAliasDescriptor?.constructors?.mapNotNull(TypeAliasConstructorDescriptor::withDispatchReceiver) ?: classWithConstructors.constructors
|
||||
|
||||
if (constructors.isEmpty()) return emptyList()
|
||||
|
||||
|
||||
+6
-1
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractTypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtTypeAlias
|
||||
@@ -27,13 +28,14 @@ import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.storage.NotNullLazyValue
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.asSimpleType
|
||||
|
||||
class LazyTypeAliasDescriptor(
|
||||
private val storageManager: StorageManager,
|
||||
override val storageManager: StorageManager,
|
||||
private val trace: BindingTrace,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
annotations: Annotations,
|
||||
@@ -42,6 +44,9 @@ class LazyTypeAliasDescriptor(
|
||||
visibility: Visibility
|
||||
) : AbstractTypeAliasDescriptor(containingDeclaration, annotations, name, sourceElement, visibility),
|
||||
TypeAliasDescriptor {
|
||||
override val constructors: Collection<TypeAliasConstructorDescriptor> by storageManager.createLazyValue {
|
||||
getTypeAliasConstructors()
|
||||
}
|
||||
|
||||
private lateinit var underlyingTypeImpl: NotNullLazyValue<SimpleType>
|
||||
private lateinit var expandedTypeImpl: NotNullLazyValue<SimpleType>
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
|
||||
@@ -280,13 +278,12 @@ private fun ResolutionScope.getContributedFunctionsAndConstructors(
|
||||
}
|
||||
|
||||
private fun ClassifierDescriptor.getCallableConstructors(): Collection<FunctionDescriptor> =
|
||||
when (this) {
|
||||
is TypeAliasDescriptor ->
|
||||
getTypeAliasConstructors()
|
||||
is ClassDescriptor ->
|
||||
if (canHaveCallableConstructors) constructors else emptyList()
|
||||
else -> emptyList()
|
||||
}
|
||||
when (this) {
|
||||
is TypeAliasDescriptor -> if (canHaveCallableConstructors) constructors else emptyList()
|
||||
is ClassDescriptor -> if (canHaveCallableConstructors) constructors else emptyList()
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
|
||||
private fun ResolutionScope.getContributedObjectVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||
val objectDescriptor = getFakeDescriptorForObject(getContributedClassifier(name, location))
|
||||
@@ -319,11 +316,5 @@ private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDe
|
||||
private val ClassDescriptor.canHaveCallableConstructors: Boolean
|
||||
get() = !ErrorUtils.isError(this) && !kind.isSingleton
|
||||
|
||||
fun TypeAliasDescriptor.getTypeAliasConstructors(withDispatchReceiver: Boolean = false): Collection<TypeAliasConstructorDescriptor> {
|
||||
val classDescriptor = this.classDescriptor ?: return emptyList()
|
||||
if (!classDescriptor.canHaveCallableConstructors) return emptyList()
|
||||
|
||||
return classDescriptor.constructors.mapNotNull {
|
||||
TypeAliasConstructorDescriptorImpl.createIfAvailable(this, it, withDispatchReceiver)
|
||||
}
|
||||
}
|
||||
private val TypeAliasDescriptor.canHaveCallableConstructors: Boolean
|
||||
get() = classDescriptor != null && !ErrorUtils.isError(classDescriptor) && classDescriptor!!.canHaveCallableConstructors
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
+12
@@ -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
|
||||
|
||||
|
||||
+42
-19
@@ -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,
|
||||
|
||||
+1
-1
@@ -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
|
||||
)
|
||||
|
||||
|
||||
+14
-1
@@ -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(),
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.util
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors
|
||||
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
@@ -81,7 +81,7 @@ fun TypeConstructor.supertypesWithAny(): Collection<KotlinType> {
|
||||
|
||||
val ClassifierDescriptorWithTypeParameters.constructors: Collection<ConstructorDescriptor>
|
||||
get() = when (this) {
|
||||
is TypeAliasDescriptor -> getTypeAliasConstructors()
|
||||
is TypeAliasDescriptor -> this.constructors
|
||||
is ClassDescriptor -> this.constructors
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
class A(val a: Int) {
|
||||
constructor(val b: String) : this(b.toInt())
|
||||
}
|
||||
|
||||
typealias TA = A
|
||||
|
||||
fun usage() {
|
||||
val x = TA(<caret>)
|
||||
}
|
||||
|
||||
/*
|
||||
Text: (<highlight>a: Int</highlight>), Disabled: false, Strikeout: false, Green: false
|
||||
Text: (<highlight>b: String</highlight>), Disabled: false, Strikeout: false, Green: false
|
||||
*/
|
||||
@@ -323,6 +323,12 @@ public class ParameterInfoTestGenerated extends AbstractParameterInfoTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TypeAliasConstructor.kt")
|
||||
public void testTypeAliasConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/parameterInfo/functionCall/TypeAliasConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("UpdateOnTyping.kt")
|
||||
public void testUpdateOnTyping() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/parameterInfo/functionCall/UpdateOnTyping.kt");
|
||||
|
||||
Reference in New Issue
Block a user