FIR: use getAnnotationByClassId instead of getAnnotationByFqName
This commit is contained in:
+8
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
|||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
private val RETENTION_PARAMETER_NAME = Name.identifier("value")
|
private val RETENTION_PARAMETER_NAME = Name.identifier("value")
|
||||||
@@ -79,6 +81,12 @@ fun FirAnnotatedDeclaration.getTargetAnnotation(): FirAnnotationCall? {
|
|||||||
return getAnnotationByFqName(StandardNames.FqNames.target)
|
return getAnnotationByFqName(StandardNames.FqNames.target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun FirAnnotationContainer.getAnnotationByClassId(classId: ClassId): FirAnnotationCall? {
|
||||||
|
return annotations.find {
|
||||||
|
(it.annotationTypeRef.coneType as? ConeClassLikeType)?.lookupTag?.classId == classId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun FirExpression.extractClassesFromArgument(): List<FirRegularClassSymbol> {
|
fun FirExpression.extractClassesFromArgument(): List<FirRegularClassSymbol> {
|
||||||
return unfoldArrayOrVararg().mapNotNull {
|
return unfoldArrayOrVararg().mapNotNull {
|
||||||
if (it !is FirGetClassCall) return@mapNotNull null
|
if (it !is FirGetClassCall) return@mapNotNull null
|
||||||
|
|||||||
+1
-1
@@ -98,7 +98,7 @@ private fun FirAnnotatedDeclaration.getOwnSinceKotlinVersion(session: FirSession
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FirAnnotatedDeclaration.loadWasExperimentalMarkerClasses(): List<FirRegularClassSymbol> {
|
private fun FirAnnotatedDeclaration.loadWasExperimentalMarkerClasses(): List<FirRegularClassSymbol> {
|
||||||
val wasExperimental = getAnnotationByFqName(OptInNames.WAS_EXPERIMENTAL_FQ_NAME) ?: return emptyList()
|
val wasExperimental = getAnnotationByClassId(OptInNames.WAS_EXPERIMENTAL_CLASS_ID) ?: return emptyList()
|
||||||
val annotationClasses = wasExperimental.findArgumentByName(OptInNames.WAS_EXPERIMENTAL_ANNOTATION_CLASS) ?: return emptyList()
|
val annotationClasses = wasExperimental.findArgumentByName(OptInNames.WAS_EXPERIMENTAL_ANNOTATION_CLASS) ?: return emptyList()
|
||||||
return annotationClasses.extractClassesFromArgument()
|
return annotationClasses.extractClassesFromArgument()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -13,14 +13,13 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName
|
|
||||||
import org.jetbrains.kotlin.resolve.checkers.Experimentality
|
import org.jetbrains.kotlin.resolve.checkers.Experimentality
|
||||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||||
|
|
||||||
object FirOptInAnnotationClassChecker : FirRegularClassChecker() {
|
object FirOptInAnnotationClassChecker : FirRegularClassChecker() {
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (declaration.classKind != ClassKind.ANNOTATION_CLASS) return
|
if (declaration.classKind != ClassKind.ANNOTATION_CLASS) return
|
||||||
if (declaration.getAnnotationByFqName(OptInNames.REQUIRES_OPT_IN_FQ_NAME) == null) return
|
if (declaration.getAnnotationByClassId(OptInNames.REQUIRES_OPT_IN_CLASS_ID) == null) return
|
||||||
if (declaration.getRetention() == AnnotationRetention.SOURCE) {
|
if (declaration.getRetention() == AnnotationRetention.SOURCE) {
|
||||||
val target = declaration.getRetentionAnnotation()
|
val target = declaration.getRetentionAnnotation()
|
||||||
reporter.reportOn(target?.source, FirErrors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_RETENTION, context)
|
reporter.reportOn(target?.source, FirErrors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_RETENTION, context)
|
||||||
|
|||||||
+2
-2
@@ -31,8 +31,8 @@ object FirClassLiteralChecker : FirGetClassCallChecker() {
|
|||||||
if (source.kind is FirFakeSourceElementKind) return
|
if (source.kind is FirFakeSourceElementKind) return
|
||||||
val argument = expression.argument
|
val argument = expression.argument
|
||||||
if (argument is FirResolvedQualifier) {
|
if (argument is FirResolvedQualifier) {
|
||||||
val fqName = argument.classId?.asSingleFqName()
|
val classId = argument.classId
|
||||||
if (fqName == OptInNames.REQUIRES_OPT_IN_FQ_NAME || fqName == OptInNames.OPT_IN_FQ_NAME) {
|
if (classId == OptInNames.REQUIRES_OPT_IN_CLASS_ID || classId == OptInNames.OPT_IN_CLASS_ID) {
|
||||||
reporter.reportOn(argument.source, FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
|
reporter.reportOn(argument.source, FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -23,9 +23,9 @@ import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
|||||||
object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() {
|
object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() {
|
||||||
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val lookupTag = expression.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag ?: return
|
val lookupTag = expression.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag ?: return
|
||||||
val fqName = lookupTag.classId.asSingleFqName()
|
val classId = lookupTag.classId
|
||||||
val isMarker = fqName == OptInNames.REQUIRES_OPT_IN_FQ_NAME
|
val isMarker = classId == OptInNames.REQUIRES_OPT_IN_CLASS_ID
|
||||||
val isOptIn = fqName == OptInNames.OPT_IN_FQ_NAME
|
val isOptIn = classId == OptInNames.OPT_IN_CLASS_ID
|
||||||
if (isMarker || isOptIn) {
|
if (isMarker || isOptIn) {
|
||||||
checkUsageOfKotlinExperimentalOrUseExperimental(expression.source, context, reporter)
|
checkUsageOfKotlinExperimentalOrUseExperimental(expression.source, context, reporter)
|
||||||
if (isOptIn) {
|
if (isOptIn) {
|
||||||
|
|||||||
+23
-21
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.declarations.*
|
|||||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
|
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
|
||||||
import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
@@ -29,17 +28,23 @@ import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
|||||||
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions
|
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions
|
||||||
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties
|
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.checkers.Experimentality
|
|
||||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
internal object FirOptInUsageBaseChecker {
|
object FirOptInUsageBaseChecker {
|
||||||
|
data class Experimentality(val annotationClassId: ClassId, val severity: Severity, val message: String?) {
|
||||||
|
enum class Severity { WARNING, ERROR }
|
||||||
|
companion object {
|
||||||
|
val DEFAULT_SEVERITY = Severity.ERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun FirRegularClassSymbol.loadExperimentalityForMarkerAnnotation(): Experimentality? {
|
fun FirRegularClassSymbol.loadExperimentalityForMarkerAnnotation(): Experimentality? {
|
||||||
ensureResolved(FirResolvePhase.BODY_RESOLVE)
|
ensureResolved(FirResolvePhase.BODY_RESOLVE)
|
||||||
@OptIn(SymbolInternals::class)
|
@OptIn(SymbolInternals::class)
|
||||||
@@ -132,7 +137,7 @@ internal object FirOptInUsageBaseChecker {
|
|||||||
expandedTypeRef.coneType.addExperimentalities(context, result, visited)
|
expandedTypeRef.coneType.addExperimentalities(context, result, visited)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getAnnotationByFqName(OptInNames.WAS_EXPERIMENTAL_FQ_NAME) != null) {
|
if (getAnnotationByClassId(OptInNames.WAS_EXPERIMENTAL_CLASS_ID) != null) {
|
||||||
val accessibility = checkSinceKotlinVersionAccessibility(context)
|
val accessibility = checkSinceKotlinVersionAccessibility(context)
|
||||||
if (accessibility is FirSinceKotlinAccessibility.NotAccessibleButWasExperimental) {
|
if (accessibility is FirSinceKotlinAccessibility.NotAccessibleButWasExperimental) {
|
||||||
accessibility.markerClasses.forEach {
|
accessibility.markerClasses.forEach {
|
||||||
@@ -178,14 +183,14 @@ internal object FirOptInUsageBaseChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FirRegularClass.loadExperimentalityForMarkerAnnotation(): Experimentality? {
|
private fun FirRegularClass.loadExperimentalityForMarkerAnnotation(): Experimentality? {
|
||||||
val experimental = getAnnotationByFqName(OptInNames.REQUIRES_OPT_IN_FQ_NAME)
|
val experimental = getAnnotationByClassId(OptInNames.REQUIRES_OPT_IN_CLASS_ID)
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
val levelArgument = experimental.findArgumentByName(LEVEL) as? FirQualifiedAccessExpression
|
val levelArgument = experimental.findArgumentByName(LEVEL) as? FirQualifiedAccessExpression
|
||||||
val levelName = (levelArgument?.calleeReference as? FirResolvedNamedReference)?.name?.asString()
|
val levelName = (levelArgument?.calleeReference as? FirResolvedNamedReference)?.name?.asString()
|
||||||
val level = OptInLevel.values().firstOrNull { it.name == levelName } ?: OptInLevel.DEFAULT
|
val level = OptInLevel.values().firstOrNull { it.name == levelName } ?: OptInLevel.DEFAULT
|
||||||
val message = (experimental.findArgumentByName(MESSAGE) as? FirConstExpression<*>)?.value as? String
|
val message = (experimental.findArgumentByName(MESSAGE) as? FirConstExpression<*>)?.value as? String
|
||||||
return Experimentality(symbol.classId.asSingleFqName(), level.severity, message)
|
return Experimentality(symbol.classId, level.severity, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reportNotAcceptedExperimentalities(
|
fun reportNotAcceptedExperimentalities(
|
||||||
@@ -194,8 +199,8 @@ internal object FirOptInUsageBaseChecker {
|
|||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
reporter: DiagnosticReporter
|
reporter: DiagnosticReporter
|
||||||
) {
|
) {
|
||||||
for ((annotationFqName, severity, message) in experimentalities) {
|
for ((annotationClassId, severity, message) in experimentalities) {
|
||||||
if (!isExperimentalityAcceptableInContext(annotationFqName, context)) {
|
if (!isExperimentalityAcceptableInContext(annotationClassId, context)) {
|
||||||
val diagnostic = when (severity) {
|
val diagnostic = when (severity) {
|
||||||
Experimentality.Severity.WARNING -> FirErrors.EXPERIMENTAL_API_USAGE
|
Experimentality.Severity.WARNING -> FirErrors.EXPERIMENTAL_API_USAGE
|
||||||
Experimentality.Severity.ERROR -> FirErrors.EXPERIMENTAL_API_USAGE_ERROR
|
Experimentality.Severity.ERROR -> FirErrors.EXPERIMENTAL_API_USAGE_ERROR
|
||||||
@@ -204,43 +209,40 @@ internal object FirOptInUsageBaseChecker {
|
|||||||
Experimentality.Severity.WARNING -> "This declaration is experimental and its usage should be marked"
|
Experimentality.Severity.WARNING -> "This declaration is experimental and its usage should be marked"
|
||||||
Experimentality.Severity.ERROR -> "This declaration is experimental and its usage must be marked"
|
Experimentality.Severity.ERROR -> "This declaration is experimental and its usage must be marked"
|
||||||
}
|
}
|
||||||
reporter.reportOn(element.source, diagnostic, annotationFqName, reportedMessage, context)
|
reporter.reportOn(element.source, diagnostic, annotationClassId.asSingleFqName(), reportedMessage, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isExperimentalityAcceptableInContext(
|
private fun isExperimentalityAcceptableInContext(
|
||||||
annotationFqName: FqName,
|
annotationClassId: ClassId,
|
||||||
context: CheckerContext
|
context: CheckerContext
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val languageVersionSettings = context.session.languageVersionSettings
|
val languageVersionSettings = context.session.languageVersionSettings
|
||||||
val fqNameAsString = annotationFqName.asString()
|
val fqNameAsString = annotationClassId.asFqNameString()
|
||||||
if (fqNameAsString in languageVersionSettings.getFlag(AnalysisFlags.useExperimental)) {
|
if (fqNameAsString in languageVersionSettings.getFlag(AnalysisFlags.useExperimental)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
for (annotationContainer in context.annotationContainers) {
|
for (annotationContainer in context.annotationContainers) {
|
||||||
if (annotationContainer.isExperimentalityAcceptable(annotationFqName)) {
|
if (annotationContainer.isExperimentalityAcceptable(annotationClassId)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirAnnotationContainer.isExperimentalityAcceptable(annotationFqName: FqName): Boolean {
|
private fun FirAnnotationContainer.isExperimentalityAcceptable(annotationClassId: ClassId): Boolean {
|
||||||
return getAnnotationByFqName(annotationFqName) != null || isAnnotatedWithUseExperimentalOf(annotationFqName)
|
return getAnnotationByClassId(annotationClassId) != null || isAnnotatedWithUseExperimentalOf(annotationClassId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirAnnotationContainer.isAnnotatedWithUseExperimentalOf(annotationFqName: FqName): Boolean {
|
private fun FirAnnotationContainer.isAnnotatedWithUseExperimentalOf(annotationClassId: ClassId): Boolean {
|
||||||
for (annotation in annotations) {
|
for (annotation in annotations) {
|
||||||
val coneType = annotation.annotationTypeRef.coneType as? ConeClassLikeType
|
val coneType = annotation.annotationTypeRef.coneType as? ConeClassLikeType
|
||||||
if (coneType?.lookupTag?.classId?.asSingleFqName() != OptInNames.OPT_IN_FQ_NAME) {
|
if (coneType?.lookupTag?.classId != OptInNames.OPT_IN_CLASS_ID) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val annotationClasses = annotation.findArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS) ?: continue
|
val annotationClasses = annotation.findArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS) ?: continue
|
||||||
if (annotationClasses.extractClassesFromArgument().any {
|
if (annotationClasses.extractClassesFromArgument().any { it.classId == annotationClassId }) {
|
||||||
it.classId.asSingleFqName() == annotationFqName
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -8,12 +8,12 @@ package org.jetbrains.kotlin.fir.analysis.checkers.type
|
|||||||
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.getAnnotationByClassId
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION
|
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.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.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
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.expressions.FirAnnotationCall
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
@@ -32,12 +32,12 @@ object FirOptInUsageTypeRefChecker : FirTypeRefChecker() {
|
|||||||
val coneType = typeRef.coneTypeSafe<ConeClassLikeType>() ?: return
|
val coneType = typeRef.coneTypeSafe<ConeClassLikeType>() ?: return
|
||||||
val symbol = coneType.lookupTag.toSymbol(context.session) ?: return
|
val symbol = coneType.lookupTag.toSymbol(context.session) ?: return
|
||||||
symbol.ensureResolved(FirResolvePhase.STATUS)
|
symbol.ensureResolved(FirResolvePhase.STATUS)
|
||||||
val fqName = symbol.classId.asSingleFqName()
|
val classId = symbol.classId
|
||||||
val lastAnnotationCall = context.qualifiedAccessOrAnnotationCalls.lastOrNull() as? FirAnnotationCall
|
val lastAnnotationCall = context.qualifiedAccessOrAnnotationCalls.lastOrNull() as? FirAnnotationCall
|
||||||
if (lastAnnotationCall == null || lastAnnotationCall.annotationTypeRef !== typeRef) {
|
if (lastAnnotationCall == null || lastAnnotationCall.annotationTypeRef !== typeRef) {
|
||||||
if (fqName == OptInNames.REQUIRES_OPT_IN_FQ_NAME || fqName == OptInNames.OPT_IN_FQ_NAME) {
|
if (classId == OptInNames.REQUIRES_OPT_IN_CLASS_ID || classId == OptInNames.OPT_IN_CLASS_ID) {
|
||||||
reporter.reportOn(source, EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
|
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) {
|
} else if (symbol is FirRegularClassSymbol && symbol.fir.getAnnotationByClassId(OptInNames.REQUIRES_OPT_IN_CLASS_ID) != null) {
|
||||||
reporter.reportOn(source, EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL, context)
|
reporter.reportOn(source, EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,6 +127,12 @@ public final class ClassId {
|
|||||||
return packageFqName.asString().replace('.', '/') + "/" + relativeClassName.asString();
|
return packageFqName.asString().replace('.', '/') + "/" + relativeClassName.asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String asFqNameString() {
|
||||||
|
if (packageFqName.isRoot()) return relativeClassName.asString();
|
||||||
|
return packageFqName.asString() + "." + relativeClassName.asString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.checkers
|
package org.jetbrains.kotlin.resolve.checkers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -12,9 +13,12 @@ object OptInNames {
|
|||||||
val OLD_EXPERIMENTAL_FQ_NAME = FqName("kotlin.Experimental")
|
val OLD_EXPERIMENTAL_FQ_NAME = FqName("kotlin.Experimental")
|
||||||
val OLD_USE_EXPERIMENTAL_FQ_NAME = FqName("kotlin.UseExperimental")
|
val OLD_USE_EXPERIMENTAL_FQ_NAME = FqName("kotlin.UseExperimental")
|
||||||
val REQUIRES_OPT_IN_FQ_NAME = FqName("kotlin.RequiresOptIn")
|
val REQUIRES_OPT_IN_FQ_NAME = FqName("kotlin.RequiresOptIn")
|
||||||
|
val REQUIRES_OPT_IN_CLASS_ID = ClassId.topLevel(REQUIRES_OPT_IN_FQ_NAME)
|
||||||
val OPT_IN_FQ_NAME = FqName("kotlin.OptIn")
|
val OPT_IN_FQ_NAME = FqName("kotlin.OptIn")
|
||||||
|
val OPT_IN_CLASS_ID = ClassId.topLevel(OPT_IN_FQ_NAME)
|
||||||
|
|
||||||
val WAS_EXPERIMENTAL_FQ_NAME = FqName("kotlin.WasExperimental")
|
val WAS_EXPERIMENTAL_FQ_NAME = FqName("kotlin.WasExperimental")
|
||||||
|
val WAS_EXPERIMENTAL_CLASS_ID = ClassId.topLevel(WAS_EXPERIMENTAL_FQ_NAME)
|
||||||
val USE_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass")
|
val USE_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass")
|
||||||
val WAS_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass")
|
val WAS_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user