[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
This commit is contained in:
committed by
Space Team
parent
01905a5a06
commit
a60777b9a7
+13
-10
@@ -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)
|
||||
|
||||
+12
@@ -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
|
||||
|
||||
+100
-3
@@ -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<ClassId> = 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
|
||||
|
||||
-81
@@ -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<ClassId> = 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,
|
||||
|
||||
Reference in New Issue
Block a user