[FIR] Add NOT_A_CLASS diagnostics

This commit is contained in:
Ivan Kochurkin
2021-11-18 20:33:54 +03:00
committed by TeamCityServer
parent aff885bcd1
commit 4caf3c5e83
10 changed files with 58 additions and 21 deletions
@@ -914,6 +914,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.NOT_A_CLASS) { firDiagnostic ->
NotAClassImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.OPT_IN_USAGE) { firDiagnostic ->
OptInUsageImpl(
firDiagnostic.a,
@@ -659,6 +659,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = RepeatedAnnotationWarning::class
}
abstract class NotAClass : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = NotAClass::class
}
abstract class OptInUsage : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = OptInUsage::class
abstract val optInMarkerFqName: FqName
@@ -790,6 +790,11 @@ internal class RepeatedAnnotationWarningImpl(
override val token: ValidityToken,
) : KtFirDiagnostic.RepeatedAnnotationWarning(), KtAbstractFirDiagnostic<KtAnnotationEntry>
internal class NotAClassImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.NotAClass(), KtAbstractFirDiagnostic<PsiElement>
internal class OptInUsageImpl(
override val optInMarkerFqName: FqName,
override val message: String,
@@ -281,6 +281,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val INAPPLICABLE_FILE_TARGET by error<KtAnnotationEntry>(PositioningStrategy.ANNOTATION_USE_SITE)
val REPEATED_ANNOTATION by error<KtAnnotationEntry>()
val REPEATED_ANNOTATION_WARNING by warning<KtAnnotationEntry>()
val NOT_A_CLASS by error<PsiElement>()
}
val OPT_IN by object : DiagnosticGroup("OptIn") {
@@ -247,6 +247,7 @@ object FirErrors {
val INAPPLICABLE_FILE_TARGET by error0<KtAnnotationEntry>(SourceElementPositioningStrategies.ANNOTATION_USE_SITE)
val REPEATED_ANNOTATION by error0<KtAnnotationEntry>()
val REPEATED_ANNOTATION_WARNING by warning0<KtAnnotationEntry>()
val NOT_A_CLASS by error0<PsiElement>()
// OptIn
val OPT_IN_USAGE by warning2<PsiElement, FqName, String>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirUnderscoredTypeArgum
object CommonExpressionCheckers : ExpressionCheckers() {
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
get() = setOf(
FirAnnotationArgumentChecker,
FirAnnotationExpressionChecker,
FirOptInAnnotationCallChecker,
)
@@ -7,23 +7,27 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.ConstantArgumentKind
import org.jetbrains.kotlin.fir.analysis.checkers.checkConstantArguments
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.fqName
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.RequireKotlinConstants
object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
object FirAnnotationExpressionChecker : FirAnnotationCallChecker() {
private val versionArgumentName = Name.identifier("version")
private val deprecatedSinceKotlinFqName = FqName("kotlin.DeprecatedSinceKotlin")
private val sinceKotlinFqName = FqName("kotlin.SinceKotlin")
@@ -44,13 +48,8 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
checkAnnotationsWithVersion(fqName, expression, context, reporter)
checkDeprecatedSinceKotlin(expression.source, fqName, argumentMapping, context, reporter)
val args = expression.argumentList.arguments
for (arg in args) {
for (ann in arg.unwrapArgument().annotations) {
reporter.reportOn(ann.source, FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, context)
}
}
checkAnnotationUsedAsAnnotationArgument(expression, context, reporter)
checkNotAClass(expression, context, reporter)
}
private fun checkAnnotationArgumentWithSubElements(
@@ -194,4 +193,31 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
reporter.reportOn(source, FirErrors.DEPRECATED_SINCE_KOTLIN_WITH_UNORDERED_VERSIONS, context)
}
}
private fun checkAnnotationUsedAsAnnotationArgument(
expression: FirAnnotationCall,
context: CheckerContext,
reporter: DiagnosticReporter
) {
val args = expression.argumentList.arguments
for (arg in args) {
for (ann in arg.unwrapArgument().annotations) {
reporter.reportOn(ann.source, FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, context)
}
}
}
private fun checkNotAClass(
expression: FirAnnotationCall,
context: CheckerContext,
reporter: DiagnosticReporter
) {
val annotationTypeRef = expression.annotationTypeRef
if (expression.calleeReference is FirErrorNamedReference &&
annotationTypeRef !is FirErrorTypeRef &&
annotationTypeRef.coneType !is ConeClassLikeType
) {
reporter.reportOn(annotationTypeRef.source, FirErrors.NOT_A_CLASS, context)
}
}
}
@@ -306,6 +306,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_VARARG_SPREAD
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_INLINE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_FUNCTION_LABEL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE
@@ -779,6 +780,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
OPT_IN_MARKER_ON_OVERRIDE_WARNING,
"Opt-in requirement marker annotation on override makes no sense without the same marker on base declaration"
)
map.put(NOT_A_CLASS, "Not a class")
// Exposed visibility group // #
map.put(
@@ -1,9 +0,0 @@
class Foo<T> {
@T
fun foo() = 0
}
class Bar<T : Annotation> {
@T
fun foo() = 0
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
class Foo<T> {
@<!NOT_A_CLASS!>T<!>
fun foo() = 0