FIR: use getAnnotationByClassId instead of getAnnotationByFqName

This commit is contained in:
Mikhail Glukhikh
2021-07-09 11:27:36 +03:00
parent 7cbea12c8a
commit cb847b945d
9 changed files with 52 additions and 33 deletions
@@ -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
@@ -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()
} }
@@ -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)
@@ -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)
} }
} }
@@ -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) {
@@ -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
} }
} }
@@ -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")