[FIR] Lazy resolve annotation calls before accessing customAnnotations
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt
index edca47c..b72018d 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt
@@ -12,8 +12,13 @@
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClassId
+import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
+import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList
+import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.ConeKotlinType
+import org.jetbrains.kotlin.fir.types.custom
import org.jetbrains.kotlin.fir.types.customAnnotations
import org.jetbrains.kotlin.name.ClassId
@@ -46,11 +51,21 @@
useSiteSession: FirSession,
token: KtLifetimeToken,
): KtAnnotationsList {
- return if (coneType.customAnnotations.isEmpty()) {
- KtEmptyAnnotationsList(token)
- } else {
- KtFirAnnotationListForType(coneType, useSiteSession, token)
+ if (coneType.customAnnotations.isEmpty()) {
+ return KtEmptyAnnotationsList(token)
}
+
+ if (coneType.attributes.custom?.owningSymbol == null) {
+ val hasAnnotationsWithUnresolvedArguments = coneType.customAnnotations.filterIsInstance<FirAnnotationCall>()
+ .any { it.argumentList !is FirResolvedArgumentList }
+
+ if (hasAnnotationsWithUnresolvedArguments) {
+ error("$coneType has annotations with unresolved arguments mapping, but no symbol responsible for their resolution")
+ }
+ }
+
+ coneType.attributes.custom?.owningSymbol?.lazyResolveToPhase(FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING)
+ return KtFirAnnotationListForType(coneType, useSiteSession, token)
}
}
}
diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt
index f2b524a..f1a2c682 100644
--- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt
+++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt
@@ -124,7 +124,7 @@
val classDeserializer = context.memberDeserializer
val superTypesDeserialized = classProto.supertypes(context.typeTable).map { supertypeProto ->
- typeDeserializer.simpleType(supertypeProto, ConeAttributes.Empty)
+ typeDeserializer.simpleType(supertypeProto, ConeAttributes.Empty, symbol)
}
superTypesDeserialized.mapNotNullTo(superTypeRefs) {
@@ -209,7 +209,7 @@
})
companionObjectSymbol = (declarations.firstOrNull { it is FirRegularClass && it.isCompanion } as FirRegularClass?)?.symbol
- contextReceivers.addAll(classDeserializer.createContextReceiversForClass(classProto))
+ contextReceivers.addAll(classDeserializer.createContextReceiversForClass(classProto, symbol))
}.also {
if (isSealed) {
val inheritors = classProto.sealedSubclassFqNameList.map { nameIndex ->
diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirContractDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirContractDeserializer.kt
index ad65d9f..a0dc84f 100644
--- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirContractDeserializer.kt
+++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirContractDeserializer.kt
@@ -15,6 +15,9 @@
import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.expressions.LogicOperationKind
+import org.jetbrains.kotlin.fir.resolve.dfa.DfaInternals
+import org.jetbrains.kotlin.fir.resolve.dfa.symbol
+import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeAttributes
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.isBoolean
@@ -93,6 +96,7 @@
}
}
+ @OptIn(DfaInternals::class)
private fun extractPrimitiveExpression(proto: ProtoBuf.Expression, primitiveType: PrimitiveExpressionType?, owner: FirContractDescriptionOwner): ConeBooleanExpression? {
val isInverted = Flags.IS_NEGATED.get(proto.flags)
@@ -106,7 +110,7 @@
PrimitiveExpressionType.INSTANCE_CHECK -> {
val variable = extractVariable(proto, owner) ?: return null
- val type = extractType(proto) ?: return null
+ val type = extractType(proto, owner.symbol) ?: return null
ConeIsInstancePredicate(variable, type, isInverted)
}
@@ -151,8 +155,8 @@
ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE -> EventOccurrencesRange.AT_LEAST_ONCE
}
- private fun extractType(proto: ProtoBuf.Expression): ConeKotlinType? {
- return c.typeDeserializer.type(proto.isInstanceType(c.typeTable) ?: return null)
+ private fun extractType(proto: ProtoBuf.Expression, owningSymbol: FirBasedSymbol<*>?): ConeKotlinType? {
+ return c.typeDeserializer.type(proto.isInstanceType(c.typeTable) ?: return null, owningSymbol)
}
private fun loadConstant(value: ProtoBuf.Expression.ConstantValue): ConeConstantReference? = when (value) {
diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt
index 6c55e5c..1a6fce2 100644
--- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt
+++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt
@@ -213,7 +213,7 @@
annotations += c.annotationDeserializer.loadTypeAliasAnnotations(proto, local.nameResolver)
this.symbol = symbol
- expandedTypeRef = proto.underlyingType(c.typeTable).toTypeRef(local)
+ expandedTypeRef = proto.underlyingType(c.typeTable).toTypeRef(local, symbol)
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
}.apply {
@@ -349,7 +349,7 @@
false, false, false
)
- val returnTypeRef = proto.returnType(c.typeTable).toTypeRef(local)
+ val returnTypeRef = proto.returnType(c.typeTable).toTypeRef(local, symbol)
val hasGetter = Flags.HAS_GETTER.get(flags)
val receiverAnnotations = if (hasGetter && proto.hasReceiver()) {
@@ -367,7 +367,7 @@
moduleData = c.moduleData
origin = FirDeclarationOrigin.Library
this.returnTypeRef = returnTypeRef
- receiverTypeRef = proto.receiverType(c.typeTable)?.toTypeRef(local).apply {
+ receiverTypeRef = proto.receiverType(c.typeTable)?.toTypeRef(local, symbol).apply {
annotations += receiverAnnotations
}
name = callableName
@@ -424,14 +424,14 @@
this.initializer = c.constDeserializer.loadConstant(proto, symbol.callableId, c.nameResolver)
deprecationsProvider = annotations.getDeprecationsProviderFromAnnotations(fromJava = false, c.session.firCachesFactory)
- proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers, ::loadContextReceiver)
+ proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers) { loadContextReceiver(it, symbol) }
}.apply {
versionRequirementsTable = c.versionRequirementTable
}
}
- private fun loadContextReceiver(proto: ProtoBuf.Type): FirContextReceiver {
- val typeRef = proto.toTypeRef(c)
+ private fun loadContextReceiver(proto: ProtoBuf.Type, owningSymbol: FirBasedSymbol<*>): FirContextReceiver {
+ val typeRef = proto.toTypeRef(c, owningSymbol)
return buildContextReceiver {
val type = typeRef.coneType
this.labelNameFromTypeRef = (type as? ConeLookupTagBasedType)?.lookupTag?.name
@@ -439,8 +439,8 @@
}
}
- internal fun createContextReceiversForClass(classProto: ProtoBuf.Class): List<FirContextReceiver> =
- classProto.contextReceiverTypes(c.typeTable).map(::loadContextReceiver)
+ internal fun createContextReceiversForClass(classProto: ProtoBuf.Class, owningSymbol: FirBasedSymbol<*>): List<FirContextReceiver> =
+ classProto.contextReceiverTypes(c.typeTable).map { loadContextReceiver(it, owningSymbol) }
fun loadFunction(
proto: ProtoBuf.Function,
@@ -467,8 +467,8 @@
val simpleFunction = buildSimpleFunction {
moduleData = c.moduleData
origin = deserializationOrigin
- returnTypeRef = proto.returnType(local.typeTable).toTypeRef(local)
- receiverTypeRef = proto.receiverType(local.typeTable)?.toTypeRef(local).apply {
+ returnTypeRef = proto.returnType(local.typeTable).toTypeRef(local, symbol)
+ receiverTypeRef = proto.receiverType(local.typeTable)?.toTypeRef(local, symbol).apply {
annotations += receiverAnnotations
}
name = callableName
@@ -503,7 +503,7 @@
deprecationsProvider = annotations.getDeprecationsProviderFromAnnotations(fromJava = false, c.session.firCachesFactory)
this.containerSource = c.containerSource
- proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers, ::loadContextReceiver)
+ proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers) { loadContextReceiver(it, symbol) }
}.apply {
versionRequirementsTable = c.versionRequirementTable
}
@@ -581,7 +581,7 @@
containerSource = c.containerSource
deprecationsProvider = annotations.getDeprecationsProviderFromAnnotations(fromJava = false, c.session.firCachesFactory)
- contextReceivers.addAll(createContextReceiversForClass(classProto))
+ contextReceivers.addAll(createContextReceiversForClass(classProto, symbol))
}.build().apply {
containingClassForStaticMemberAttr = c.dispatchReceiver!!.lookupTag
versionRequirementsTable = c.versionRequirementTable
@@ -608,9 +608,9 @@
buildValueParameter {
moduleData = c.moduleData
origin = FirDeclarationOrigin.Library
- returnTypeRef = proto.type(c.typeTable).toTypeRef(c)
this.name = name
symbol = FirValueParameterSymbol(name)
+ returnTypeRef = proto.type(c.typeTable).toTypeRef(c, symbol)
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
defaultValue = defaultValue(flags)
if (addDefaultValue) {
@@ -635,11 +635,11 @@
}.toList()
}
- private fun ProtoBuf.Type.toTypeRef(context: FirDeserializationContext): FirTypeRef {
+ private fun ProtoBuf.Type.toTypeRef(context: FirDeserializationContext, owningSymbol: FirBasedSymbol<*>): FirTypeRef {
return buildResolvedTypeRef {
annotations += context.annotationDeserializer.loadTypeAnnotations(this@toTypeRef, context.nameResolver)
- val attributes = annotations.computeTypeAttributes(context.session)
- type = context.typeDeserializer.type(this@toTypeRef, attributes)
+ val attributes = annotations.computeTypeAttributes(context.session, owningSymbol = owningSymbol)
+ type = context.typeDeserializer.type(this@toTypeRef, attributes, owningSymbol)
}
}
}
diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt
index c9050e9..29654fe 100644
--- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt
+++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt
@@ -84,7 +84,7 @@
val builder = builders[index]
builder.apply {
proto.upperBounds(typeTable).mapTo(bounds) {
- buildResolvedTypeRef { type = type(it) }
+ buildResolvedTypeRef { type = type(it, builder.containingDeclarationSymbol) }
}
addDefaultBoundIfNecessary()
}.build()
@@ -105,16 +105,16 @@
}
}
- fun type(proto: ProtoBuf.Type): ConeKotlinType {
+ fun type(proto: ProtoBuf.Type, owningSymbol: FirBasedSymbol<*>?): ConeKotlinType {
val annotations = annotationDeserializer.loadTypeAnnotations(proto, nameResolver)
- val attributes = annotations.computeTypeAttributes(moduleData.session)
- return type(proto, attributes)
+ val attributes = annotations.computeTypeAttributes(moduleData.session, owningSymbol = owningSymbol)
+ return type(proto, attributes, owningSymbol)
}
- fun type(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeKotlinType {
+ fun type(proto: ProtoBuf.Type, attributes: ConeAttributes, owningSymbol: FirBasedSymbol<*>?): ConeKotlinType {
if (proto.hasFlexibleTypeCapabilitiesId()) {
- val lowerBound = simpleType(proto, attributes)
- val upperBound = simpleType(proto.flexibleUpperBound(typeTable)!!, attributes)
+ val lowerBound = simpleType(proto, attributes, owningSymbol)
+ val upperBound = simpleType(proto.flexibleUpperBound(typeTable)!!, attributes, owningSymbol)
val isDynamic = lowerBound == moduleData.session.builtinTypes.nothingType.coneType &&
upperBound == moduleData.session.builtinTypes.nullableAnyType.coneType
@@ -126,7 +126,8 @@
}
}
- return simpleType(proto, attributes) ?: ConeErrorType(ConeSimpleDiagnostic("?!id:0", DiagnosticKind.DeserializationError))
+ return simpleType(proto, attributes, owningSymbol)
+ ?: ConeErrorType(ConeSimpleDiagnostic("?!id:0", DiagnosticKind.DeserializationError))
}
private fun typeParameterSymbol(typeParameterId: Int): ConeTypeParameterLookupTag? =
@@ -144,7 +145,7 @@
fun FirClassLikeSymbol<*>.typeParameters(): List<FirTypeParameterSymbol> =
(fir as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol }.orEmpty()
- fun simpleType(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeSimpleKotlinType? {
+ fun simpleType(proto: ProtoBuf.Type, attributes: ConeAttributes, owningSymbol: FirBasedSymbol<*>?): ConeSimpleKotlinType? {
val constructor = typeSymbol(proto) ?: return null
if (constructor is ConeTypeParameterLookupTag) {
return ConeTypeParameterTypeImpl(constructor, isNullable = proto.nullable).let {
@@ -159,14 +160,14 @@
fun ProtoBuf.Type.collectAllArguments(): List<ProtoBuf.Type.Argument> =
argumentList + outerType(typeTable)?.collectAllArguments().orEmpty()
- val arguments = proto.collectAllArguments().map(this::typeArgument).toTypedArray()
+ val arguments = proto.collectAllArguments().map { typeArgument(it, owningSymbol) }.toTypedArray()
val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) {
createSuspendFunctionType(constructor, arguments, isNullable = proto.nullable, attributes)
} else {
ConeClassLikeTypeImpl(constructor, arguments, isNullable = proto.nullable, attributes)
}
val abbreviatedTypeProto = proto.abbreviatedType(typeTable) ?: return simpleType
- return simpleType(abbreviatedTypeProto, attributes)
+ return simpleType(abbreviatedTypeProto, attributes, owningSymbol)
}
private fun createSuspendFunctionTypeForBasicCase(
@@ -241,7 +242,7 @@
}
- private fun typeArgument(typeArgumentProto: ProtoBuf.Type.Argument): ConeTypeProjection {
+ private fun typeArgument(typeArgumentProto: ProtoBuf.Type.Argument, owningSymbol: FirBasedSymbol<*>?): ConeTypeProjection {
if (typeArgumentProto.projection == ProtoBuf.Type.Argument.Projection.STAR) {
return ConeStarProjection
}
@@ -249,7 +250,7 @@
val variance = ProtoEnumFlags.variance(typeArgumentProto.projection)
val type = typeArgumentProto.type(typeTable)
?: return ConeErrorType(ConeSimpleDiagnostic("No type recorded", DiagnosticKind.DeserializationError))
- val coneType = type(type)
+ val coneType = type(type, owningSymbol)
return coneType.toTypeProjection(variance)
}
}
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt
index 6287684..2a323f5 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt
@@ -99,7 +99,7 @@
}
}
- ConeAttributes.create(listOf(CustomAnnotationTypeAttribute(convertedAnnotations)))
+ ConeAttributes.create(listOf(CustomAnnotationTypeAttribute(convertedAnnotations, owningSymbol = null)))
} else {
ConeAttributes.Empty
}
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt
index bc47b5b..d3e7640 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt
@@ -98,8 +98,8 @@
buildConstExpression(fakeSource, ConstantValueKind.String, valueParameter.name.asString(), setType = true)
}
}
- val attributesWithParameterNameAnnotation =
- ConeAttributes.create(listOf(CustomAnnotationTypeAttribute(listOf(parameterNameAnnotationCall))))
+ val attribute = CustomAnnotationTypeAttribute(listOf(parameterNameAnnotationCall), owningSymbol = valueParameter.symbol)
+ val attributesWithParameterNameAnnotation = ConeAttributes.create(listOf(attribute))
return withCombinedAttributesFrom(attributesWithParameterNameAnnotation)
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt
index bfde838..ffe7687 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt
@@ -223,7 +223,8 @@
result: TypeResolutionResult,
areBareTypesAllowed: Boolean,
topContainer: FirDeclaration?,
- isOperandOfIsOperator: Boolean
+ isOperandOfIsOperator: Boolean,
+ owningSymbol: FirBasedSymbol<*>?,
): ConeKotlinType {
val (symbol, substitutor) = when (result) {
@@ -250,7 +251,7 @@
ConeUnresolvedQualifierError(typeRef.render())
}
}
- return ConeErrorType(diagnostic, attributes = typeRef.annotations.computeTypeAttributes(session))
+ return ConeErrorType(diagnostic, attributes = typeRef.annotations.computeTypeAttributes(session, owningSymbol = owningSymbol))
}
if (symbol is FirTypeParameterSymbol) {
for (part in typeRef.qualifier) {
@@ -353,7 +354,7 @@
return symbol.constructType(
allTypeArguments.toTypedArray(),
typeRef.isMarkedNullable,
- typeRef.annotations.computeTypeAttributes(session)
+ typeRef.annotations.computeTypeAttributes(session, owningSymbol = owningSymbol)
).also {
val lookupTag = it.lookupTag
if (lookupTag is ConeClassLikeLookupTagImpl && symbol is FirClassLikeSymbol<*>) {
@@ -462,7 +463,7 @@
}
}
- private fun createFunctionalType(typeRef: FirFunctionTypeRef): ConeClassLikeType {
+ private fun createFunctionalType(typeRef: FirFunctionTypeRef, owningSymbol: FirBasedSymbol<*>?): ConeClassLikeType {
val parameters =
typeRef.contextReceiverTypeRefs.map { it.coneType } +
listOfNotNull(typeRef.receiverTypeRef?.coneType) +
@@ -484,7 +485,8 @@
if (typeRef.contextReceiverTypeRefs.isNotEmpty()) {
add(CompilerConeAttributes.ContextFunctionTypeParams(typeRef.contextReceiverTypeRefs.size))
}
- }
+ },
+ owningSymbol = owningSymbol,
)
val symbol = resolveBuiltInQualified(classId, session)
return ConeClassLikeTypeImpl(
@@ -516,10 +518,11 @@
result,
areBareTypesAllowed,
scopeClassDeclaration.topContainer ?: scopeClassDeclaration.containingDeclarations.lastOrNull(),
- isOperandOfIsOperator
+ isOperandOfIsOperator,
+ scopeClassDeclaration.owningSymbol,
) to (result as? TypeResolutionResult.Resolved)?.typeCandidate?.diagnostic
}
- is FirFunctionTypeRef -> createFunctionalType(typeRef) to null
+ is FirFunctionTypeRef -> createFunctionalType(typeRef, scopeClassDeclaration.owningSymbol) to null
is FirDynamicTypeRef -> ConeDynamicType.create(session) to null
is FirIntersectionTypeRef -> {
val leftType = typeRef.leftType.coneType
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt
index 4335281..29b7f5d 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt
@@ -366,7 +366,7 @@
val resolvedTypesRefs = transformer.withFile(useSiteFile) {
resolveSuperTypeRefs(
transformer,
- ScopeClassDeclaration(scopes, classDeclarationsStack)
+ ScopeClassDeclaration(scopes, classDeclarationsStack, classLikeDeclaration.symbol)
)
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt
index ee96cb9..037755e 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt
@@ -10,6 +10,7 @@
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isFromVararg
import org.jetbrains.kotlin.fir.expressions.*
+import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeCyclicTypeBound
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
@@ -19,6 +20,7 @@
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType
+import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
@@ -61,6 +63,18 @@
scopes.addAll(initialScopes.asReversed())
}
+ private var owningSymbol: FirBasedSymbol<*>? = classDeclarationsStack.lastOrNull()?.symbol ?: initialCurrentFile?.symbol
+
+ private inline fun <R> withOwningSymbol(symbol: FirBasedSymbol<*>, block: () -> R): R {
+ val oldOwningSymbol = owningSymbol
+ return try {
+ owningSymbol = symbol
+ block()
+ } finally {
+ owningSymbol = oldOwningSymbol
+ }
+ }
+
private val typeResolverTransformer: FirSpecificTypeResolverTransformer = FirSpecificTypeResolverTransformer(session)
private var currentFile: FirFile? = initialCurrentFile
@@ -68,28 +82,34 @@
checkSessionConsistency(file)
currentFile = file
return withScopeCleanup {
- scopes.addAll(createImportingScopes(file, session, scopeSession))
- super.transformFile(file, data)
+ withOwningSymbol(file.symbol) {
+ scopes.addAll(createImportingScopes(file, session, scopeSession))
+ super.transformFile(file, data)
+ }
}
}
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): FirStatement {
withClassDeclarationCleanup(classDeclarationsStack, regularClass) {
- withScopeCleanup {
- regularClass.addTypeParametersScope()
- regularClass.typeParameters.forEach {
- it.accept(this, data)
+ withOwningSymbol(regularClass.symbol) {
+ withScopeCleanup {
+ regularClass.addTypeParametersScope()
+ regularClass.typeParameters.forEach {
+ it.accept(this, data)
+ }
+ unboundCyclesInTypeParametersSupertypes(regularClass)
}
- unboundCyclesInTypeParametersSupertypes(regularClass)
- }
- return resolveClassContent(regularClass, data)
+ return resolveClassContent(regularClass, data)
+ }
}
}
override fun transformAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): FirStatement {
withClassDeclarationCleanup(classDeclarationsStack, anonymousObject) {
- return resolveClassContent(anonymousObject, data)
+ withOwningSymbol(anonymousObject.symbol) {
+ return resolveClassContent(anonymousObject, data)
+ }
}
}
@@ -108,36 +128,40 @@
}
override fun transformEnumEntry(enumEntry: FirEnumEntry, data: Any?): FirEnumEntry {
- enumEntry.transformReturnTypeRef(this, data)
- enumEntry.transformTypeParameters(this, data)
- enumEntry.transformAnnotations(this, data)
- return enumEntry
+ withOwningSymbol(enumEntry.symbol) {
+ enumEntry.transformReturnTypeRef(this, data)
+ enumEntry.transformTypeParameters(this, data)
+ enumEntry.transformAnnotations(this, data)
+ return enumEntry
+ }
}
override fun transformProperty(property: FirProperty, data: Any?): FirProperty {
- return withScopeCleanup {
- property.addTypeParametersScope()
- property.transformTypeParameters(this, data)
- .transformReturnTypeRef(this, data)
- .transformReceiverTypeRef(this, data)
- .transformContextReceivers(this, data)
- .transformGetter(this, data)
- .transformSetter(this, data)
- .transformBackingField(this, data)
- .transformAnnotations(this, data)
- if (property.isFromVararg == true) {
- property.transformTypeToArrayType()
- property.backingField?.transformTypeToArrayType()
- setAccessorTypesByPropertyType(property)
+ return withOwningSymbol(property.symbol) {
+ withScopeCleanup {
+ property.addTypeParametersScope()
+ property.transformTypeParameters(this, data)
+ .transformReturnTypeRef(this, data)
+ .transformReceiverTypeRef(this, data)
+ .transformContextReceivers(this, data)
+ .transformGetter(this, data)
+ .transformSetter(this, data)
+ .transformBackingField(this, data)
+ .transformAnnotations(this, data)
+ if (property.isFromVararg == true) {
+ property.transformTypeToArrayType()
+ property.backingField?.transformTypeToArrayType()
+ setAccessorTypesByPropertyType(property)
+ }
+
+ if (property.returnTypeRef is FirResolvedTypeRef && property.delegate != null) {
+ setAccessorTypesByPropertyType(property)
+ }
+
+ unboundCyclesInTypeParametersSupertypes(property)
+
+ property
}
-
- if (property.returnTypeRef is FirResolvedTypeRef && property.delegate != null) {
- setAccessorTypesByPropertyType(property)
- }
-
- unboundCyclesInTypeParametersSupertypes(property)
-
- property
}
}
@@ -147,9 +171,11 @@
}
override fun transformField(field: FirField, data: Any?): FirField {
- return withScopeCleanup {
- field.transformReturnTypeRef(this, data).transformAnnotations(this, data)
- field
+ return withOwningSymbol(field.symbol) {
+ withScopeCleanup {
+ field.transformReturnTypeRef(this, data).transformAnnotations(this, data)
+ field
+ }
}
}
@@ -162,6 +188,12 @@
} as FirSimpleFunction
}
+ override fun transformDeclaration(declaration: FirDeclaration, data: Any?): FirDeclaration {
+ return withOwningSymbol(declaration.symbol) {
+ super.transformDeclaration(declaration, data)
+ }
+ }
+
private fun unboundCyclesInTypeParametersSupertypes(typeParametersOwner: FirTypeParameterRefsOwner) {
for (typeParameter in typeParametersOwner.typeParameters) {
if (typeParameter !is FirTypeParameter) continue
@@ -197,18 +229,29 @@
override fun transformTypeRef(typeRef: FirTypeRef, data: Any?): FirResolvedTypeRef {
return typeResolverTransformer.withFile(currentFile) {
+ if (owningSymbol == null) {
+ val hasAnnotationsWithUnresolvedArguments = typeRef.annotations.filterIsInstance<FirAnnotationCall>()
+ .any { it.argumentList !is FirResolvedArgumentList }
+
+ if (hasAnnotationsWithUnresolvedArguments) {
+ error("$typeRef has annotations with unresolved arguments mapping, but no symbol responsible for their resolution")
+ }
+ }
+
typeRef.transform(
typeResolverTransformer,
- ScopeClassDeclaration(towerScope, classDeclarationsStack)
+ ScopeClassDeclaration(towerScope, classDeclarationsStack, owningSymbol)
)
}
}
override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): FirStatement {
- valueParameter.transformReturnTypeRef(this, data)
- valueParameter.transformAnnotations(this, data)
- valueParameter.transformVarargTypeToArrayType()
- return valueParameter
+ withOwningSymbol(valueParameter.symbol) {
+ valueParameter.transformReturnTypeRef(this, data)
+ valueParameter.transformAnnotations(this, data)
+ valueParameter.transformVarargTypeToArrayType()
+ return valueParameter
+ }
}
override fun transformBlock(block: FirBlock, data: Any?): FirStatement {
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ScopeClassDeclaration.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ScopeClassDeclaration.kt
index e1e557d..6d76c7c 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ScopeClassDeclaration.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ScopeClassDeclaration.kt
@@ -7,9 +7,11 @@
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.scopes.FirScope
+import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
data class ScopeClassDeclaration(
val scopes: List<FirScope>,
val containingDeclarations: List<FirDeclaration>,
- val topContainer: FirDeclaration? = null
+ val owningSymbol: FirBasedSymbol<*>?,
+ val topContainer: FirDeclaration? = null,
)
\ No newline at end of file
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt
index fd6b096..cea1eb9 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt
@@ -70,6 +70,7 @@
ScopeClassDeclaration(
components.createCurrentScopeList(),
context.containingClassDeclarations,
+ (context.containers.lastOrNull() ?: context.file).symbol,
context.containers.lastOrNull { it is FirTypeParameterRefsOwner && it !is FirAnonymousFunction }
)
)
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt
index 67fbcd9..4c531eb 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt
@@ -200,9 +200,10 @@
val name = annotationTypeRef.qualifier.last().name
if (name !in REQUIRED_ANNOTATION_NAMES && acceptableFqNames.none { it.shortName() == name }) return annotation
+ val owner = classDeclarationsStack.lastOrNull() ?: argumentsTransformer.context.file
val transformedAnnotation = annotation.transformAnnotationTypeRef(
typeResolverTransformer,
- ScopeClassDeclaration(scopes.asReversed(), classDeclarationsStack)
+ ScopeClassDeclaration(scopes.asReversed(), classDeclarationsStack, owner.symbol)
)
// TODO: what if we have type alias here?
if (transformedAnnotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId == Deprecated) {
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/CustomAnnotationTypeAttribute.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/CustomAnnotationTypeAttribute.kt
index 36f79c8..7b665e4 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/CustomAnnotationTypeAttribute.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/CustomAnnotationTypeAttribute.kt
@@ -7,16 +7,20 @@
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.render
+import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import kotlin.reflect.KClass
-class CustomAnnotationTypeAttribute(val annotations: List<FirAnnotation>) : ConeAttribute<CustomAnnotationTypeAttribute>() {
+class CustomAnnotationTypeAttribute(
+ val annotations: List<FirAnnotation>,
+ val owningSymbol: FirBasedSymbol<*>?,
+) : ConeAttribute<CustomAnnotationTypeAttribute>() {
override fun union(other: CustomAnnotationTypeAttribute?): CustomAnnotationTypeAttribute? = null
override fun intersect(other: CustomAnnotationTypeAttribute?): CustomAnnotationTypeAttribute? = null
override fun add(other: CustomAnnotationTypeAttribute?): CustomAnnotationTypeAttribute {
if (other == null || other === this) return this
- return CustomAnnotationTypeAttribute(annotations + other.annotations)
+ return CustomAnnotationTypeAttribute(annotations + other.annotations, owningSymbol)
}
override fun isSubtypeOf(other: CustomAnnotationTypeAttribute?): Boolean = true
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt
index fdb235d..ca648e0 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt
@@ -11,6 +11,7 @@
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.typeAttributeExtensions
import org.jetbrains.kotlin.fir.render
+import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.StandardClassIds
@@ -112,7 +113,11 @@
else -> null
}
-fun List<FirAnnotation>.computeTypeAttributes(session: FirSession, predefined: List<ConeAttribute<*>> = emptyList()): ConeAttributes {
+fun List<FirAnnotation>.computeTypeAttributes(
+ session: FirSession,
+ predefined: List<ConeAttribute<*>> = emptyList(),
+ owningSymbol: FirBasedSymbol<*>?,
+): ConeAttributes {
if (this.isEmpty()) {
if (predefined.isEmpty()) return ConeAttributes.Empty
return ConeAttributes.create(predefined)
@@ -145,7 +150,7 @@
}
}
if (customAnnotations.isNotEmpty()) {
- attributes += CustomAnnotationTypeAttribute(customAnnotations)
+ attributes += CustomAnnotationTypeAttribute(customAnnotations, owningSymbol)
}
return ConeAttributes.create(attributes)
}