[Analysis API] Do not expose error ClassIds in `KaFirAnnotationListForDeclaration`
Previously, `KaAnnotation` was adjusted to return `null` `ClassId`
instead of `ClassId("<error>")` for unresolved annotations.
This was done by rejecting annotations with `ConeClassLikeErrorLookupTag`
in the main annotation mapping utility - `FirAnnotation.toKaAnnotation`.
However, `KaFirAnnotationListForDeclaration` directly works with
FIR annotations to be able to answer various `ClassId` queries:
`get` / `contains` / `classIds`, etc.
As this logic uses generic FIR utilities for retrieving `ClassId`s,
it didn't reject `ConeClassLikeErrorLookupTag`. So in case of unresolved
annotations, all user queries for `ClassId("<error>")` returned some
actual results.
Rewrite the logic to reuse the new `toAnnotationNonErrorClassId` utility
for retrieving non-error `ClassId`s. Now all unresolved annotations
in the annotation list have `null` `ClassId` and it's impossible to
intentionally query the annotation list with an error `ClassId`.
^KT-84186
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt
index 9dc9b55..4c4a4e5 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt
@@ -18,7 +18,6 @@
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.*
-import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -60,7 +59,7 @@
// - `transformAnnotations` theoretically may modify annotations, but it is not allowed due
// to the compiler contract to change already published annotations – only their content can be changed
return annotationContainer.resolvedCompilerRequiredAnnotations(firSymbol).mapNotNull { annotation ->
- if (annotation.toAnnotationClassIdSafe(session) != classId) {
+ if (annotation.toAnnotationNonErrorClassId(session) != classId) {
return@mapNotNull null
}
@@ -69,7 +68,7 @@
}
return annotationContainer.resolvedAnnotationsWithClassIds(firSymbol).mapNotNull { annotation ->
- if (annotation.toAnnotationClassId(session) != classId) {
+ if (annotation.toAnnotationNonErrorClassId(session) != classId) {
return@mapNotNull null
}
@@ -175,7 +174,7 @@
useSiteSession: FirSession,
annotationContainer: FirAnnotationContainer = firSymbol.fir,
): Collection<ClassId> = annotationContainer.resolvedAnnotationsWithClassIds(firSymbol).mapNotNull {
- it.toAnnotationClassId(useSiteSession)
+ it.toAnnotationNonErrorClassId(useSiteSession)
}
internal fun hasAnnotation(
@@ -190,11 +189,11 @@
// - `transformAnnotations` theoretically may modify annotations, but it is not allowed due
// to the compiler contract to change already published annotations – only their content can be changed
annotationContainer.resolvedCompilerRequiredAnnotations(firSymbol).any {
- it.toAnnotationClassIdSafe(useSiteSession) == classId
+ it.toAnnotationNonErrorClassId(useSiteSession) == classId
}
} else {
annotationContainer.resolvedAnnotationsWithClassIds(firSymbol).any {
- it.toAnnotationClassId(useSiteSession) == classId
+ it.toAnnotationNonErrorClassId(useSiteSession) == classId
}
}
diff --git a/analysis/low-level-api-fir/testData/lazyAnnotations/annotations/unresolvedAnnotations.out.txt b/analysis/low-level-api-fir/testData/lazyAnnotations/annotations/unresolvedAnnotations.out.txt
index 36ea1c8..aaa574c 100644
--- a/analysis/low-level-api-fir/testData/lazyAnnotations/annotations/unresolvedAnnotations.out.txt
+++ b/analysis/low-level-api-fir/testData/lazyAnnotations/annotations/unresolvedAnnotations.out.txt
@@ -1,7 +1,7 @@
null()
psi: KtAnnotationEntry
-<error>()
+null()
psi: KtAnnotationEntry
kotlin/Int()
diff --git a/analysis/low-level-api-fir/testData/lazyAnnotations/classIds/unresolvedAnnotations.out.txt b/analysis/low-level-api-fir/testData/lazyAnnotations/classIds/unresolvedAnnotations.out.txt
index e190098..77f566e 100644
--- a/analysis/low-level-api-fir/testData/lazyAnnotations/classIds/unresolvedAnnotations.out.txt
+++ b/analysis/low-level-api-fir/testData/lazyAnnotations/classIds/unresolvedAnnotations.out.txt
@@ -1,3 +1 @@
-/<error>
-
kotlin/Int
diff --git a/analysis/low-level-api-fir/testData/lazyAnnotations/contains/unresolvedAnnotation.out.txt b/analysis/low-level-api-fir/testData/lazyAnnotations/contains/unresolvedAnnotation.out.txt
index 27ba77d..c508d53 100644
--- a/analysis/low-level-api-fir/testData/lazyAnnotations/contains/unresolvedAnnotation.out.txt
+++ b/analysis/low-level-api-fir/testData/lazyAnnotations/contains/unresolvedAnnotation.out.txt
@@ -1 +1 @@
-true
+false
diff --git a/analysis/low-level-api-fir/testData/lazyAnnotations/get/unresolvedAnnotation.out.txt b/analysis/low-level-api-fir/testData/lazyAnnotations/get/unresolvedAnnotation.out.txt
index 938e7ec..fe51488c 100644
--- a/analysis/low-level-api-fir/testData/lazyAnnotations/get/unresolvedAnnotation.out.txt
+++ b/analysis/low-level-api-fir/testData/lazyAnnotations/get/unresolvedAnnotation.out.txt
@@ -1,2 +1 @@
-<error>()
- psi: KtAnnotationEntry
+[]