[AA FIR] fix contract violation for Target annotation
^KT-57849
This commit is contained in:
committed by
Space Team
parent
d66b919c12
commit
0caaca45ae
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.api.fir
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationInfo
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationWithArgumentsInfo
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtNamedAnnotationValue
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.mapAnnotationParameters
|
||||
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
@@ -71,14 +72,15 @@ internal fun ConeDiagnostic.getCandidateSymbols(): Collection<FirBasedSymbol<*>>
|
||||
internal fun FirAnnotation.toKtAnnotationApplication(
|
||||
useSiteSession: FirSession,
|
||||
index: Int,
|
||||
arguments: List<KtNamedAnnotationValue> = FirAnnotationValueConverter.toNamedConstantValue(
|
||||
mapAnnotationParameters(this),
|
||||
useSiteSession,
|
||||
)
|
||||
): KtAnnotationApplicationWithArgumentsInfo = KtAnnotationApplicationWithArgumentsInfo(
|
||||
classId = toAnnotationClassId(useSiteSession),
|
||||
psi = psi as? KtCallElement,
|
||||
useSiteTarget = useSiteTarget,
|
||||
arguments = FirAnnotationValueConverter.toNamedConstantValue(
|
||||
mapAnnotationParameters(this),
|
||||
useSiteSession,
|
||||
),
|
||||
arguments = arguments,
|
||||
index = index,
|
||||
)
|
||||
|
||||
|
||||
+77
-6
@@ -8,13 +8,18 @@ package org.jetbrains.kotlin.analysis.api.fir.annotations
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.AnnotationUseSiteTargetFilter
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationInfo
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationWithArgumentsInfo
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtArrayAnnotationValue
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtEnumEntryAnnotationValue
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtNamedAnnotationValue
|
||||
import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationApplication
|
||||
import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationInfo
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.withClassEntry
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.resolved
|
||||
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
|
||||
@@ -31,6 +36,13 @@ import org.jetbrains.kotlin.fir.symbols.resolvedCompilerRequiredAnnotations
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.fir.declarations.resolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.unwrapAndFlattenArgument
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.ParameterNames
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
|
||||
internal fun mapAnnotationParameters(annotation: FirAnnotation): Map<Name, FirExpression> {
|
||||
if (annotation is FirAnnotationCall && annotation.arguments.isEmpty()) return emptyMap()
|
||||
@@ -50,13 +62,72 @@ internal fun annotationsByClassId(
|
||||
useSiteTargetFilter: AnnotationUseSiteTargetFilter,
|
||||
useSiteSession: FirSession,
|
||||
annotationContainer: FirAnnotationContainer = firSymbol.fir,
|
||||
): List<KtAnnotationApplicationWithArgumentsInfo> {
|
||||
return annotationContainer.resolvedAnnotationsWithArguments(firSymbol).mapIndexedNotNull { index, annotation ->
|
||||
if (!useSiteTargetFilter.isAllowed(annotation.useSiteTarget) || annotation.toAnnotationClassId(useSiteSession) != classId) {
|
||||
return@mapIndexedNotNull null
|
||||
}
|
||||
): List<KtAnnotationApplicationWithArgumentsInfo> =
|
||||
if (classId == StandardClassIds.Annotations.Target && firSymbol.fir.resolvePhase < FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING) {
|
||||
annotationContainer.resolvedAnnotationsWithClassIds(firSymbol)
|
||||
.mapIndexedToAnnotationApplication(useSiteTargetFilter, useSiteSession, classId) { index, annotation ->
|
||||
annotation.asKtAnnotationApplicationForTargetAnnotation(useSiteSession, index)
|
||||
}
|
||||
} else {
|
||||
annotationContainer.resolvedAnnotationsWithArguments(firSymbol)
|
||||
.mapIndexedToAnnotationApplication(useSiteTargetFilter, useSiteSession, classId) { index, annotation ->
|
||||
annotation.toKtAnnotationApplication(useSiteSession, index)
|
||||
}
|
||||
}
|
||||
|
||||
annotation.toKtAnnotationApplication(useSiteSession, index)
|
||||
private inline fun List<FirAnnotation>.mapIndexedToAnnotationApplication(
|
||||
useSiteTargetFilter: AnnotationUseSiteTargetFilter,
|
||||
useSiteSession: FirSession,
|
||||
classId: ClassId,
|
||||
transformer: (index: Int, annotation: FirAnnotation) -> KtAnnotationApplicationWithArgumentsInfo?,
|
||||
): List<KtAnnotationApplicationWithArgumentsInfo> = mapIndexedNotNull { index, annotation ->
|
||||
if (!useSiteTargetFilter.isAllowed(annotation.useSiteTarget) || annotation.toAnnotationClassId(useSiteSession) != classId) {
|
||||
return@mapIndexedNotNull null
|
||||
}
|
||||
|
||||
transformer(index, annotation)
|
||||
}
|
||||
|
||||
private fun FirAnnotation.asKtAnnotationApplicationForTargetAnnotation(
|
||||
useSiteSession: FirSession,
|
||||
index: Int,
|
||||
): KtAnnotationApplicationWithArgumentsInfo {
|
||||
val arguments = findAllowedTargets().ifNotEmpty {
|
||||
listOf(
|
||||
KtNamedAnnotationValue(
|
||||
name = StandardClassIds.Annotations.ParameterNames.targetAllowedTargets,
|
||||
expression = KtArrayAnnotationValue(
|
||||
values = map {
|
||||
KtEnumEntryAnnotationValue(
|
||||
callableId = CallableId(
|
||||
classId = StandardClassIds.AnnotationTarget,
|
||||
callableName = Name.identifier(it.name),
|
||||
),
|
||||
sourcePsi = null,
|
||||
)
|
||||
},
|
||||
sourcePsi = null,
|
||||
)
|
||||
)
|
||||
)
|
||||
}.orEmpty()
|
||||
|
||||
return toKtAnnotationApplication(useSiteSession, index, arguments)
|
||||
}
|
||||
|
||||
private fun FirAnnotation.findAllowedTargets(): Set<KotlinTarget> = buildSet {
|
||||
fun addIfMatching(arg: FirExpression) {
|
||||
if (arg !is FirQualifiedAccessExpression) return
|
||||
val callableSymbol = arg.calleeReference.toResolvedCallableSymbol() ?: return
|
||||
if (callableSymbol.containingClassLookupTag()?.classId != StandardClassIds.AnnotationTarget) return
|
||||
val identifier = callableSymbol.callableId.callableName.identifier
|
||||
KotlinTarget.values().firstOrNull { identifier == it.name }?.let(::add)
|
||||
}
|
||||
|
||||
if (this@findAllowedTargets is FirAnnotationCall) {
|
||||
for (arg in argumentList.arguments) {
|
||||
arg.unwrapAndFlattenArgument().forEach(::addIfMatching)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user