From a60777b9a73f68c7577e94f29769ca98f173c0e0 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Wed, 18 Oct 2023 15:01:59 +0200 Subject: [PATCH] [FIR] move annotation recheck logic to ANNOTATIONS_ARGUMENTS_MAPPING phase ARGUMENTS_OF_ANNOTATIONS will be dropped, so this check should be moved This commit also drops class annotations resolution from implicit type phase and provides the correct scope during argument mapping phase. This code was effectively unreachable before ^KT-62679 --- ...irAnnotationArgumentMappingLazyResolver.kt | 3 +- .../compilerRequiredAnnotationConflict.txt | 60 ++++------ .../compilerRequiredAnnotationConflict2.txt | 44 +++----- .../FirDeclarationsResolveTransformer.kt | 23 ++-- .../body/resolve/FirImplicitBodyResolve.kt | 12 ++ ...irAnnotationArgumentsMappingTransformer.kt | 103 +++++++++++++++++- ...irAnnotationArgumentsResolveTransformer.kt | 81 -------------- ...annotationTargetResolvedAmbiguously.fir.kt | 2 +- 8 files changed, 168 insertions(+), 160 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentMappingLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentMappingLazyResolver.kt index e010d29678a..172c804dcf8 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentMappingLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentMappingLazyResolver.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList +import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.isError import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession @@ -131,7 +132,7 @@ internal object AnnotationArgumentMappingStateKeepers { source = oldList.source for ((index, argument) in oldList.arguments.withIndex()) { val replacement = when { - argument is FirPropertyAccessExpression && argument.calleeReference.isError() -> argument + argument is FirPropertyAccessExpression && argument.calleeReference.let { it.isError() || it is FirResolvedNamedReference } -> argument else -> newArguments[index] } diff --git a/analysis/low-level-api-fir/testData/lazyResolve/classes/compilerRequiredAnnotationConflict.txt b/analysis/low-level-api-fir/testData/lazyResolve/classes/compilerRequiredAnnotationConflict.txt index 08899b0dfcd..ff95193fd59 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/classes/compilerRequiredAnnotationConflict.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/classes/compilerRequiredAnnotationConflict.txt @@ -269,31 +269,27 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationConflict.kt LAZY_super } - @R|kotlin/annotation/Target|[Types](Q|Some.AnnotationTarget|.< - Annotation symbol resolved differently on compiler annotation and symbols stages: - - compiler annotations: FirEnumEntrySymbol kotlin/annotation/AnnotationTarget.CLASS - - compiler arguments stage: FirEnumEntrySymbol /Some.AnnotationTarget.CLASS - >#) public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] annotation class Ann : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] annotation class Ann : R|kotlin/Annotation| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Ann] constructor(): R|Some.Ann| { LAZY_super } } - public final [ResolvedTo(STATUS)] enum class AnnotationTarget : R|kotlin/Enum| { - private [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] constructor(): R|Some.AnnotationTarget| { + public? final? [ResolvedTo(RAW_FIR)] enum class AnnotationTarget : R|kotlin/Enum| { + private [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] constructor(): R|Some.AnnotationTarget| { LAZY_super|> } - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] enum entry CLASS: R|Some.AnnotationTarget| - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] fun values(): R|kotlin/Array| { + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] enum entry CLASS: R|Some.AnnotationTarget| + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] fun values(): R|kotlin/Array| { } - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] fun valueOf([ResolvedTo(STATUS)] value: R|kotlin/String|): R|Some.AnnotationTarget| { + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] fun valueOf([ResolvedTo(RAW_FIR)] value: R|kotlin/String|): R|Some.AnnotationTarget| { } - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] val entries: R|kotlin/enums/EnumEntries| - public [ResolvedTo(STATUS)] get(): R|kotlin/enums/EnumEntries| + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] val entries: R|kotlin/enums/EnumEntries| + public [ResolvedTo(RAW_FIR)] get(): R|kotlin/enums/EnumEntries| } @@ -306,31 +302,27 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationConflict.kt LAZY_super } - @R|kotlin/annotation/Target|[Types](Q|Some.AnnotationTarget|.< - Annotation symbol resolved differently on compiler annotation and symbols stages: - - compiler annotations: FirEnumEntrySymbol kotlin/annotation/AnnotationTarget.CLASS - - compiler arguments stage: FirEnumEntrySymbol /Some.AnnotationTarget.CLASS - >#) public final [ResolvedTo(CONTRACTS)] annotation class Ann : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) public final [ResolvedTo(CONTRACTS)] annotation class Ann : R|kotlin/Annotation| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Ann] constructor(): R|Some.Ann| { LAZY_super } } - public final [ResolvedTo(STATUS)] enum class AnnotationTarget : R|kotlin/Enum| { - private [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] constructor(): R|Some.AnnotationTarget| { + public? final? [ResolvedTo(RAW_FIR)] enum class AnnotationTarget : R|kotlin/Enum| { + private [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] constructor(): R|Some.AnnotationTarget| { LAZY_super|> } - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] enum entry CLASS: R|Some.AnnotationTarget| - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] fun values(): R|kotlin/Array| { + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] enum entry CLASS: R|Some.AnnotationTarget| + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] fun values(): R|kotlin/Array| { } - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] fun valueOf([ResolvedTo(STATUS)] value: R|kotlin/String|): R|Some.AnnotationTarget| { + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] fun valueOf([ResolvedTo(RAW_FIR)] value: R|kotlin/String|): R|Some.AnnotationTarget| { } - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] val entries: R|kotlin/enums/EnumEntries| - public [ResolvedTo(STATUS)] get(): R|kotlin/enums/EnumEntries| + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] val entries: R|kotlin/enums/EnumEntries| + public [ResolvedTo(RAW_FIR)] get(): R|kotlin/enums/EnumEntries| } @@ -343,31 +335,27 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationConflict.kt LAZY_super } - @R|kotlin/annotation/Target|[Types](Q|Some.AnnotationTarget|.< - Annotation symbol resolved differently on compiler annotation and symbols stages: - - compiler annotations: FirEnumEntrySymbol kotlin/annotation/AnnotationTarget.CLASS - - compiler arguments stage: FirEnumEntrySymbol /Some.AnnotationTarget.CLASS - >#) public final [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] annotation class Ann : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) public final [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] annotation class Ann : R|kotlin/Annotation| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Ann] constructor(): R|Some.Ann| { LAZY_super } } - public final [ResolvedTo(STATUS)] enum class AnnotationTarget : R|kotlin/Enum| { - private [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] constructor(): R|Some.AnnotationTarget| { + public? final? [ResolvedTo(RAW_FIR)] enum class AnnotationTarget : R|kotlin/Enum| { + private [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] constructor(): R|Some.AnnotationTarget| { LAZY_super|> } - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] enum entry CLASS: R|Some.AnnotationTarget| - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] fun values(): R|kotlin/Array| { + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] enum entry CLASS: R|Some.AnnotationTarget| + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] fun values(): R|kotlin/Array| { } - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] fun valueOf([ResolvedTo(STATUS)] value: R|kotlin/String|): R|Some.AnnotationTarget| { + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] fun valueOf([ResolvedTo(RAW_FIR)] value: R|kotlin/String|): R|Some.AnnotationTarget| { } - public final static [ResolvedTo(STATUS)] [ContainingClassKey=AnnotationTarget] val entries: R|kotlin/enums/EnumEntries| - public [ResolvedTo(STATUS)] get(): R|kotlin/enums/EnumEntries| + public final static [ResolvedTo(RAW_FIR)] [ContainingClassKey=AnnotationTarget] val entries: R|kotlin/enums/EnumEntries| + public [ResolvedTo(RAW_FIR)] get(): R|kotlin/enums/EnumEntries| } diff --git a/analysis/low-level-api-fir/testData/lazyResolve/classes/compilerRequiredAnnotationConflict2.txt b/analysis/low-level-api-fir/testData/lazyResolve/classes/compilerRequiredAnnotationConflict2.txt index a07873ddb76..6f5c9c307cb 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/classes/compilerRequiredAnnotationConflict2.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/classes/compilerRequiredAnnotationConflict2.txt @@ -157,11 +157,7 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationConflict2.kt LAZY_super } - @R|kotlin/annotation/Target|[Types](< - Annotation symbol resolved differently on compiler annotation and symbols stages: - - compiler annotations: FirEnumEntrySymbol kotlin/annotation/AnnotationTarget.FIELD - - compiler arguments stage: null - >#) public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] annotation class Ann : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|[Types](R|kotlin/annotation/AnnotationTarget.FIELD|) public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] annotation class Ann : R|kotlin/Annotation| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Ann] constructor(): R|Some.Ann| { LAZY_super } @@ -180,11 +176,7 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationConflict2.kt LAZY_super } - @R|kotlin/annotation/Target|[Types](< - Annotation symbol resolved differently on compiler annotation and symbols stages: - - compiler annotations: FirEnumEntrySymbol kotlin/annotation/AnnotationTarget.FIELD - - compiler arguments stage: null - >#) public final [ResolvedTo(CONTRACTS)] annotation class Ann : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|[Types](R|kotlin/annotation/AnnotationTarget.FIELD|) public final [ResolvedTo(CONTRACTS)] annotation class Ann : R|kotlin/Annotation| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Ann] constructor(): R|Some.Ann| { LAZY_super } @@ -203,11 +195,7 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationConflict2.kt LAZY_super } - @R|kotlin/annotation/Target|[Types](< - Annotation symbol resolved differently on compiler annotation and symbols stages: - - compiler annotations: FirEnumEntrySymbol kotlin/annotation/AnnotationTarget.FIELD - - compiler arguments stage: null - >#) public final [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] annotation class Ann : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|[Types](R|kotlin/annotation/AnnotationTarget.FIELD|) public final [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] annotation class Ann : R|kotlin/Annotation| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Ann] constructor(): R|Some.Ann| { LAZY_super } @@ -226,19 +214,19 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationConflict2.kt LAZY_super } - @R|kotlin/annotation/Target|[Types](allowedTargets = vararg(< + @R|kotlin/annotation/Target|[Types](allowedTargets = this@R|/Some|.< Annotation symbol resolved differently on compiler annotation and symbols stages: - compiler annotations: FirEnumEntrySymbol kotlin/annotation/AnnotationTarget.FIELD - - compiler arguments stage: null - >#)) public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] annotation class Ann : R|kotlin/Annotation| { + - compiler arguments stage: FirPropertySymbol /Some.FIELD + >#) public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] annotation class Ann : R|kotlin/Annotation| { public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Ann] constructor(): R|Some.Ann| { LAZY_super } } - public final const [ResolvedTo(STATUS)] val FIELD: = LAZY_EXPRESSION - public [ResolvedTo(STATUS)] [ContainingClassKey=Some] get(): + public final const [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] val FIELD: R|kotlin/String| = String() + public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] [ContainingClassKey=Some] get(): R|kotlin/String| } @@ -249,19 +237,19 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationConflict2.kt LAZY_super } - @R|kotlin/annotation/Target|[Types](allowedTargets = vararg(< + @R|kotlin/annotation/Target|[Types](allowedTargets = this@R|/Some|.< Annotation symbol resolved differently on compiler annotation and symbols stages: - compiler annotations: FirEnumEntrySymbol kotlin/annotation/AnnotationTarget.FIELD - - compiler arguments stage: null - >#)) public final [ResolvedTo(BODY_RESOLVE)] annotation class Ann : R|kotlin/Annotation| { + - compiler arguments stage: FirPropertySymbol /Some.FIELD + >#) public final [ResolvedTo(BODY_RESOLVE)] annotation class Ann : R|kotlin/Annotation| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Ann] constructor(): R|Some.Ann| { super() } } - public final const [ResolvedTo(STATUS)] val FIELD: = LAZY_EXPRESSION - public [ResolvedTo(STATUS)] [ContainingClassKey=Some] get(): + public final const [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] val FIELD: R|kotlin/String| = String() + public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] [ContainingClassKey=Some] get(): R|kotlin/String| } @@ -272,11 +260,11 @@ FILE: [ResolvedTo(BODY_RESOLVE)] compilerRequiredAnnotationConflict2.kt super() } - @R|kotlin/annotation/Target|[Types](allowedTargets = vararg(< + @R|kotlin/annotation/Target|[Types](allowedTargets = this@R|/Some|.< Annotation symbol resolved differently on compiler annotation and symbols stages: - compiler annotations: FirEnumEntrySymbol kotlin/annotation/AnnotationTarget.FIELD - - compiler arguments stage: null - >#)) public final [ResolvedTo(BODY_RESOLVE)] annotation class Ann : R|kotlin/Annotation| { + - compiler arguments stage: FirPropertySymbol /Some.FIELD + >#) public final [ResolvedTo(BODY_RESOLVE)] annotation class Ann : R|kotlin/Annotation| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Ann] constructor(): R|Some.Ann| { super() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 600c1d68452..7e42b21df1b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -630,18 +630,21 @@ open class FirDeclarationsResolveTransformer( override fun transformRegularClass( regularClass: FirRegularClass, - data: ResolutionMode - ): FirRegularClass = - whileAnalysing(session, regularClass) { - return context.withContainingClass(regularClass) { - if (regularClass.isLocal && regularClass !in context.targetedLocalClasses) { - return regularClass.runAllPhasesForLocalClass(transformer, components, data, transformer.firResolveContextCollector) - } - - doTransformTypeParameters(regularClass) - doTransformRegularClass(regularClass, data) + data: ResolutionMode, + ): FirRegularClass = whileAnalysing(session, regularClass) { + context.withContainingClass(regularClass) { + val isLocal = regularClass.isLocal + if (isLocal && regularClass !in context.targetedLocalClasses) { + return regularClass.runAllPhasesForLocalClass(transformer, components, data, transformer.firResolveContextCollector) } + + if (isLocal || !implicitTypeOnly) { + doTransformTypeParameters(regularClass) + } + + doTransformRegularClass(regularClass, data) } + } fun withScript(script: FirScript, action: () -> FirScript): FirScript { dataFlowAnalyzer.enterScript(script) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt index c742f35214c..a101e30451d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt @@ -125,6 +125,18 @@ open class FirImplicitAwareBodyResolveTransformer( outerBodyResolveContext, firResolveContextCollector ) { + /** + * This is required to avoid transformations of class annotations + */ + override fun transformDeclarationContent( + declaration: FirDeclaration, + data: ResolutionMode, + ): FirDeclaration = if (implicitTypeOnly && declaration is FirRegularClass && !declaration.isLocal) { + declaration.transformDeclarations(this, data) + } else { + super.transformDeclarationContent(declaration, data) + } + override fun transformSimpleFunction( simpleFunction: FirSimpleFunction, data: ResolutionMode diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsMappingTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsMappingTransformer.kt index 876cf770e76..e9374423149 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsMappingTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsMappingTransformer.kt @@ -5,17 +5,32 @@ package org.jetbrains.kotlin.fir.resolve.transformers.plugin +import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.containingClassLookupTag import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall +import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.expressions.builder.buildPropertyAccessExpression +import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference +import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference +import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguouslyResolvedAnnotationArgument import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.* +import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol import org.jetbrains.kotlin.fir.visitors.transformSingle +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.util.PrivateForInline open class FirAnnotationArgumentsMappingTransformer( @@ -64,6 +79,11 @@ open class FirAnnotationArgumentsMappingTransformer( } } +/** + * Set of enum class IDs that are resolved in COMPILER_REQUIRED_ANNOTATIONS phase that need to be rechecked here. + */ +private val classIdsToCheck: Set = setOf(StandardClassIds.DeprecationLevel, StandardClassIds.AnnotationTarget) + private class FirExpressionTransformerForAnnotationArgumentsMapping( private val annotationArgumentsMappingTransformer: FirAnnotationArgumentsMappingTransformer, ) : FirExpressionsResolveTransformer(annotationArgumentsMappingTransformer) { @@ -80,6 +100,81 @@ private class FirExpressionTransformerForAnnotationArgumentsMapping( } } + override fun transformQualifiedAccessExpression( + qualifiedAccessExpression: FirQualifiedAccessExpression, + data: ResolutionMode + ): FirStatement { + if (qualifiedAccessExpression is FirPropertyAccessExpression) { + val calleeReference = qualifiedAccessExpression.calleeReference + if (calleeReference is FirResolvedNamedReference) { + val resolvedSymbol = calleeReference.resolvedSymbol + if (resolvedSymbol is FirEnumEntrySymbol && resolvedSymbol.containingClassLookupTag()?.classId in classIdsToCheck) { + return resolveSpecialPropertyAccess(qualifiedAccessExpression, calleeReference, resolvedSymbol, data) + } + } + } + + return super.transformQualifiedAccessExpression(qualifiedAccessExpression, data) + } + + private fun resolveSpecialPropertyAccess( + originalAccess: FirPropertyAccessExpression, + originalCalleeReference: FirResolvedNamedReference, + originalResolvedSymbol: FirEnumEntrySymbol, + data: ResolutionMode, + ): FirStatement { + val accessCopyForResolution = buildPropertyAccessExpression { + source = originalAccess.source + typeArguments.addAll(originalAccess.typeArguments) + + val originalResolvedQualifier = originalAccess.explicitReceiver + if (originalResolvedQualifier is FirResolvedQualifier) { + val fqName = originalResolvedQualifier.classId + ?.let { if (originalResolvedQualifier.isFullyQualified) it.asSingleFqName() else it.relativeClassName } + ?: originalResolvedQualifier.packageFqName + explicitReceiver = generatePropertyAccessExpression(fqName, originalResolvedQualifier.source) + } + + calleeReference = buildSimpleNamedReference { + source = originalCalleeReference.source + name = originalCalleeReference.name + } + } + + val resolved = super.transformQualifiedAccessExpression(accessCopyForResolution, data) + + if (resolved is FirQualifiedAccessExpression) { + // The initial resolution must have been to an enum entry. Report ambiguity if symbolFromArgumentsPhase is different to + // original symbol including null (meaning we would resolve to something other than an enum entry). + val symbolFromArgumentsPhase = resolved.calleeReference.toResolvedBaseSymbol() + if (originalResolvedSymbol != symbolFromArgumentsPhase) { + resolved.replaceCalleeReference(buildErrorNamedReference { + source = resolved.calleeReference.source + diagnostic = ConeAmbiguouslyResolvedAnnotationArgument(originalResolvedSymbol, symbolFromArgumentsPhase) + }) + } + } + + return resolved + } + + private fun generatePropertyAccessExpression(fqName: FqName, accessSource: KtSourceElement?): FirPropertyAccessExpression { + var result: FirPropertyAccessExpression? = null + + val pathSegments = fqName.pathSegments() + for ((index, pathSegment) in pathSegments.withIndex()) { + result = buildPropertyAccessExpression { + calleeReference = buildSimpleNamedReference { name = pathSegment } + explicitReceiver = result + + if (index == pathSegments.lastIndex) { + source = accessSource + } + } + } + + return result ?: error("Got an empty ClassId") + } } private class FirDeclarationsResolveTransformerForAnnotationArgumentsMapping( @@ -92,9 +187,11 @@ private class FirDeclarationsResolveTransformerForAnnotationArgumentsMapping( } override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirRegularClass { - regularClass.transformAnnotations(this, data) - doTransformTypeParameters(regularClass) - regularClass.transformSuperTypeRefs(this, data) + context.insideClassHeader { + regularClass.transformAnnotations(this, ResolutionMode.ContextIndependent) + regularClass.transformTypeParameters(this, ResolutionMode.ContextIndependent) + regularClass.transformSuperTypeRefs(this, ResolutionMode.ContextIndependent) + } doTransformRegularClass(regularClass, data) return regularClass diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt index 0d5803905df..509c508913d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt @@ -314,90 +314,9 @@ abstract class AbstractFirExpressionsResolveTransformerForAnnotations(transforme } } -/** - * Set of enum class IDs that are resolved in COMPILER_REQUIRED_ANNOTATIONS phase that need to be rechecked here. - */ -private val classIdsToCheck: Set = setOf(StandardClassIds.DeprecationLevel, StandardClassIds.AnnotationTarget) - private class FirExpressionsResolveTransformerForSpecificAnnotations(transformer: FirAbstractBodyResolveTransformerDispatcher) : AbstractFirExpressionsResolveTransformerForAnnotations(transformer) { - override fun transformQualifiedAccessExpression( - qualifiedAccessExpression: FirQualifiedAccessExpression, - data: ResolutionMode - ): FirStatement { - if (qualifiedAccessExpression is FirPropertyAccessExpression) { - val calleeReference = qualifiedAccessExpression.calleeReference - if (calleeReference is FirResolvedNamedReference) { - val resolvedSymbol = calleeReference.resolvedSymbol - if (resolvedSymbol is FirEnumEntrySymbol && resolvedSymbol.containingClassLookupTag()?.classId in classIdsToCheck) { - return resolveSpecialPropertyAccess(qualifiedAccessExpression, calleeReference, resolvedSymbol, data) - } - } - } - - return super.transformQualifiedAccessExpression(qualifiedAccessExpression, data) - } - - private fun resolveSpecialPropertyAccess( - originalAccess: FirPropertyAccessExpression, - originalCalleeReference: FirResolvedNamedReference, - originalResolvedSymbol: FirEnumEntrySymbol, - data: ResolutionMode, - ): FirStatement { - val accessCopyForResolution = buildPropertyAccessExpression { - source = originalAccess.source - typeArguments.addAll(originalAccess.typeArguments) - - val originalResolvedQualifier = originalAccess.explicitReceiver - if (originalResolvedQualifier is FirResolvedQualifier) { - val fqName = originalResolvedQualifier.classId - ?.let { if (originalResolvedQualifier.isFullyQualified) it.asSingleFqName() else it.relativeClassName } - ?: originalResolvedQualifier.packageFqName - explicitReceiver = generatePropertyAccessExpression(fqName, originalResolvedQualifier.source) - } - - calleeReference = buildSimpleNamedReference { - source = originalCalleeReference.source - name = originalCalleeReference.name - } - } - - val resolved = super.transformQualifiedAccessExpression(accessCopyForResolution, data) - - if (resolved is FirQualifiedAccessExpression) { - // The initial resolution must have been to an enum entry. Report ambiguity if symbolFromArgumentsPhase is different to - // original symbol including null (meaning we would resolve to something other than an enum entry). - val symbolFromArgumentsPhase = resolved.calleeReference.toResolvedBaseSymbol() - if (originalResolvedSymbol != symbolFromArgumentsPhase) { - resolved.replaceCalleeReference(buildErrorNamedReference { - source = resolved.calleeReference.source - diagnostic = ConeAmbiguouslyResolvedAnnotationArgument(originalResolvedSymbol, symbolFromArgumentsPhase) - }) - } - } - - return resolved - } - - private fun generatePropertyAccessExpression(fqName: FqName, accessSource: KtSourceElement?): FirPropertyAccessExpression { - var result: FirPropertyAccessExpression? = null - - val pathSegments = fqName.pathSegments() - for ((index, pathSegment) in pathSegments.withIndex()) { - result = buildPropertyAccessExpression { - calleeReference = buildSimpleNamedReference { name = pathSegment } - explicitReceiver = result - - if (index == pathSegments.lastIndex) { - source = accessSource - } - } - } - - return result ?: error("Got an empty ClassId") - } - override fun resolveQualifiedAccessAndSelectCandidate( qualifiedAccessExpression: FirQualifiedAccessExpression, isUsedAsReceiver: Boolean, diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationTargetResolvedAmbiguously.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationTargetResolvedAmbiguously.fir.kt index 42b6cd5a77f..c2bcf8da194 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationTargetResolvedAmbiguously.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationTargetResolvedAmbiguously.fir.kt @@ -8,7 +8,7 @@ object Some { CLASS } - @Target(FIELD) + @Target(FIELD) annotation class Ann2 const val FIELD = ""