FIR: support EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION...

This commit is contained in:
Mikhail Glukhikh
2021-07-08 19:42:09 +03:00
parent 543ce06d85
commit d020948933
2 changed files with 16 additions and 10 deletions
@@ -9,13 +9,16 @@ import org.jetbrains.kotlin.fir.FirRealSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
@@ -24,16 +27,19 @@ import org.jetbrains.kotlin.resolve.checkers.OptInNames
object FirOptInUsageTypeRefChecker : FirTypeRefChecker() {
@OptIn(SymbolInternals::class)
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
if (typeRef.source?.kind !is FirRealSourceElementKind) return
val source = typeRef.source
if (source?.kind !is FirRealSourceElementKind) return
val coneType = typeRef.coneTypeSafe<ConeClassLikeType>() ?: return
val symbol = coneType.lookupTag.toSymbol(context.session) ?: return
symbol.ensureResolved(FirResolvePhase.STATUS)
val fqName = symbol.classId.asSingleFqName()
val lastAnnotationCall = context.qualifiedAccessOrAnnotationCalls.lastOrNull() as? FirAnnotationCall
if ((lastAnnotationCall == null || lastAnnotationCall.annotationTypeRef !== typeRef) &&
(fqName == OptInNames.REQUIRES_OPT_IN_FQ_NAME || fqName == OptInNames.OPT_IN_FQ_NAME)
) {
reporter.reportOn(typeRef.source, FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
if (lastAnnotationCall == null || lastAnnotationCall.annotationTypeRef !== typeRef) {
if (fqName == OptInNames.REQUIRES_OPT_IN_FQ_NAME || fqName == OptInNames.OPT_IN_FQ_NAME) {
reporter.reportOn(source, EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
} else if (symbol is FirRegularClassSymbol && symbol.fir.getAnnotationByFqName(OptInNames.REQUIRES_OPT_IN_FQ_NAME) != null) {
reporter.reportOn(source, EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL, context)
}
}
with(FirOptInUsageBaseChecker) {
@@ -54,11 +54,11 @@ annotation class Marker {
}
}
fun f6(m: Marker) {}
fun f7(): List<Marker>? = null
fun f8(): test.Marker? = null
fun f6(m: <!EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL!>Marker<!>) {}
fun f7(): List<<!EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL!>Marker<!>>? = null
fun f8(): <!EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL!>test.Marker?<!> = null
typealias Marker0 = Marker
typealias Marker0 = <!EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL!>Marker<!>
fun f9(m: Marker0) {}