[FIR] Introduce NOT_AN_ANNOTATION_CLASS diagnostic
This commit is contained in:
+1
@@ -87,6 +87,7 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
|
||||
is ConeVariableExpectedError -> FirErrors.VARIABLE_EXPECTED.on(source)
|
||||
is ConeTypeMismatchError -> FirErrors.TYPE_MISMATCH.on(source, diagnostic.expectedType, diagnostic.actualType)
|
||||
is ConeUnexpectedTypeArgumentsError -> FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.on(diagnostic.source.safeAs() ?: source)
|
||||
is ConeIllegalAnnotationError -> FirErrors.NOT_AN_ANNOTATION_CLASS.on(source, diagnostic.name.asString())
|
||||
is ConeSimpleDiagnostic -> if (source.kind is FirFakeSourceElementKind) {
|
||||
null
|
||||
} else if (diagnostic.kind == SymbolNotFound) {
|
||||
|
||||
+4
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_PROPERTY_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_RECEIVER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HIDDEN
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_UNDERSCORE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_CANDIDATE
|
||||
@@ -74,6 +75,9 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
map.put(DEPRECATED_MODIFIER_PAIR, "Modifier ''{0}'' is deprecated in presence of ''{1}''", TO_STRING, TO_STRING)
|
||||
map.put(INCOMPATIBLE_MODIFIERS, "Modifier ''{0}'' is incompatible with ''{1}''", TO_STRING, TO_STRING)
|
||||
|
||||
// Annotations
|
||||
map.put(NOT_AN_ANNOTATION_CLASS, "Illegal annotation class: {0}", NULLABLE_STRING)
|
||||
|
||||
// Exposed visibility group
|
||||
map.put(EXPOSED_TYPEALIAS_EXPANDED_TYPE, "{0} typealias exposes {2} in expanded type{1}", TO_STRING, TO_STRING, TO_STRING)
|
||||
map.put(EXPOSED_PROPERTY_TYPE, "{0} property exposes its {2} type{1}", TO_STRING, TO_STRING, TO_STRING)
|
||||
|
||||
@@ -62,6 +62,7 @@ object FirErrors {
|
||||
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by existing<FirSourceElement, KtTypeReference>(Errors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER)
|
||||
val INVALID_TYPE_OF_ANNOTATION_MEMBER by existing<FirSourceElement, KtTypeReference>(Errors.INVALID_TYPE_OF_ANNOTATION_MEMBER)
|
||||
val VAR_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.VAR_ANNOTATION_PARAMETER)
|
||||
val NOT_AN_ANNOTATION_CLASS by error1<FirSourceElement, PsiElement, String>()
|
||||
|
||||
// Exposed visibility group
|
||||
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
|
||||
|
||||
@@ -20,10 +20,7 @@ import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.tower.FirTowerResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.tower.TowerResolveManager
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeHiddenCandidateError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.ResolvedCallableReferenceAtom
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.StoreNameReference
|
||||
@@ -333,24 +330,35 @@ class FirCallResolver(
|
||||
containingDeclarations
|
||||
)
|
||||
|
||||
val resolutionResult = createCandidateForAnnotationCall(annotationCall, callInfo)
|
||||
?: ResolutionResult(callInfo, CandidateApplicability.HIDDEN, emptyList())
|
||||
val resolvedReference = createResolvedNamedReference(
|
||||
reference,
|
||||
reference.name,
|
||||
callInfo,
|
||||
resolutionResult.candidates,
|
||||
resolutionResult.applicability,
|
||||
explicitReceiver = null
|
||||
)
|
||||
val annotationClassSymbol = annotationCall.getCorrespondingClassSymbolOrNull(session)
|
||||
val resolvedReference = if (annotationClassSymbol != null && annotationClassSymbol.fir.classKind == ClassKind.ANNOTATION_CLASS) {
|
||||
val resolutionResult = createCandidateForAnnotationCall(annotationClassSymbol, callInfo)
|
||||
?: ResolutionResult(callInfo, CandidateApplicability.HIDDEN, emptyList())
|
||||
createResolvedNamedReference(
|
||||
reference,
|
||||
reference.name,
|
||||
callInfo,
|
||||
resolutionResult.candidates,
|
||||
resolutionResult.applicability,
|
||||
explicitReceiver = null
|
||||
)
|
||||
} else {
|
||||
buildErrorReference(
|
||||
callInfo,
|
||||
if (annotationClassSymbol != null) ConeIllegalAnnotationError(reference.name)
|
||||
else ConeUnresolvedNameError(reference.name),
|
||||
reference.source,
|
||||
reference.name
|
||||
)
|
||||
}
|
||||
|
||||
return annotationCall.transformCalleeReference(StoreNameReference, resolvedReference)
|
||||
}
|
||||
|
||||
private fun createCandidateForAnnotationCall(annotationCall: FirAnnotationCall, callInfo: CallInfo): ResolutionResult? {
|
||||
val annotationClassSymbol = annotationCall.getCorrespondingClassSymbolOrNull(session)
|
||||
?.takeIf { it.fir.classKind == ClassKind.ANNOTATION_CLASS }
|
||||
?: return null
|
||||
private fun createCandidateForAnnotationCall(
|
||||
annotationClassSymbol: FirRegularClassSymbol,
|
||||
callInfo: CallInfo
|
||||
): ResolutionResult? {
|
||||
var constructorSymbol: FirConstructorSymbol? = null
|
||||
annotationClassSymbol.fir.buildUseSiteMemberScope(session, scopeSession)?.processDeclaredConstructors {
|
||||
if (it.fir.isPrimary && constructorSymbol == null) {
|
||||
|
||||
+4
@@ -67,6 +67,10 @@ class ConeTypeMismatchError(val expectedType: ConeKotlinType, val actualType: Co
|
||||
|
||||
class ConeContractDescriptionError(override val reason: String) : ConeDiagnostic()
|
||||
|
||||
class ConeIllegalAnnotationError(val name: Name) : ConeDiagnostic() {
|
||||
override val reason: String get() = "Not a legal annotation: $name"
|
||||
}
|
||||
|
||||
private fun describeSymbol(symbol: AbstractFirBasedSymbol<*>): String {
|
||||
return when (symbol) {
|
||||
is FirClassLikeSymbol<*> -> symbol.classId.asString()
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
import java.util.ArrayList
|
||||
|
||||
@ArrayList<Int>(1, 1) fun b() {}
|
||||
<!NOT_AN_ANNOTATION_CLASS!>@ArrayList<Int>(1, 1)<!> fun b() {}
|
||||
@<!UNRESOLVED_REFERENCE!>Xoo<!>(<!UNRESOLVED_REFERENCE!>x<!>) fun c() {}
|
||||
<!INAPPLICABLE_CANDIDATE!>@java.lang.Deprecated(<!UNRESOLVED_REFERENCE!>x<!>)<!> fun a() {}
|
||||
@@ -1,19 +0,0 @@
|
||||
// FILE: a.kt
|
||||
|
||||
annotation class annotation
|
||||
|
||||
// FILE: test/b.kt
|
||||
|
||||
package test
|
||||
|
||||
@test.annotation class annotation
|
||||
|
||||
// FILE: other/c.kt
|
||||
|
||||
package other
|
||||
|
||||
annotation class My
|
||||
|
||||
@test.annotation class Your
|
||||
|
||||
@My class Our
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: a.kt
|
||||
|
||||
annotation class annotation
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
class Foo
|
||||
|
||||
@Foo class Bar
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo
|
||||
|
||||
<!NOT_AN_ANNOTATION_CLASS!>@Foo<!> class Bar
|
||||
Vendored
+1
-1
@@ -1,2 +1,2 @@
|
||||
// Class constructor parameter CAN be recursively annotated
|
||||
class RecursivelyAnnotated(@RecursivelyAnnotated(1) val x: Int)
|
||||
class RecursivelyAnnotated(<!NOT_AN_ANNOTATION_CLASS, NOT_AN_ANNOTATION_CLASS!>@RecursivelyAnnotated(1)<!> val x: Int)
|
||||
|
||||
Reference in New Issue
Block a user