FIR: add OptIn checkers draft + some annotation / SinceKotlin utilities

This commit is contained in:
Mikhail Glukhikh
2021-06-11 19:05:39 +03:00
parent bd39e457a7
commit ceb527c5e4
30 changed files with 617 additions and 46 deletions
@@ -1,3 +1,4 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
import kotlin.contracts.*
@OptIn(ExperimentalContracts::class)
@@ -1,3 +1,4 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
import kotlin.contracts.*
@OptIn(ExperimentalContracts::class)
@@ -1,3 +1,4 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
import kotlin.contracts.*
@OptIn(ExperimentalContracts::class)
@@ -1,3 +1,4 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
import kotlin.contracts.*
@OptIn(ExperimentalContracts::class)
@@ -1,3 +1,4 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
import kotlin.contracts.*
@OptIn(ExperimentalContracts::class)
@@ -1,3 +1,4 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
import kotlin.contracts.*
@OptIn(ExperimentalContracts::class)
@@ -1,3 +1,4 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
import kotlin.contracts.*
@OptIn(ExperimentalContracts::class)
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
@@ -212,6 +213,36 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val INAPPLICABLE_FILE_TARGET by error<KtAnnotationEntry>(PositioningStrategy.ANNOTATION_USE_SITE)
}
val EXPERIMENTAL by object : DiagnosticGroup("OptIn-related") {
val EXPERIMENTAL_API_USAGE by warning<PsiElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<FqName>("optInMarkerFqName")
parameter<String>("message")
}
val EXPERIMENTAL_API_USAGE_ERROR by error<PsiElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<FqName>("optInMarkerFqName")
parameter<String>("message")
}
val EXPERIMENTAL_OVERRIDE by warning<PsiElement> {
parameter<FqName>("optInMarkerFqName")
parameter<String>("message")
}
val EXPERIMENTAL_OVERRIDE_ERROR by error<PsiElement> {
parameter<FqName>("optInMarkerFqName")
parameter<String>("message")
}
val EXPERIMENTAL_IS_NOT_ENABLED by warning<KtAnnotationEntry>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
val EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION by error<PsiElement>()
val EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL by error<PsiElement>()
val USE_EXPERIMENTAL_WITHOUT_ARGUMENTS by warning<KtAnnotationEntry>()
val USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER by warning<KtAnnotationEntry> {
parameter<FqName>("notMarkerFqName")
}
val EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET by error<KtAnnotationEntry> {
parameter<String>("target")
}
val EXPERIMENTAL_ANNOTATION_WITH_WRONG_RETENTION by error<KtAnnotationEntry>()
}
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by exposedVisibilityError<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME)
val EXPOSED_FUNCTION_RETURN_TYPE by exposedVisibilityError<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME)
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotation
import org.jetbrains.kotlin.psi.KtAnnotationEntry
@@ -200,6 +201,19 @@ object FirErrors {
val REDUNDANT_ANNOTATION_TARGET by warning1<KtAnnotationEntry, String>()
val INAPPLICABLE_FILE_TARGET by error0<KtAnnotationEntry>(SourceElementPositioningStrategies.ANNOTATION_USE_SITE)
// OptIn-related
val EXPERIMENTAL_API_USAGE by warning2<PsiElement, FqName, String>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val EXPERIMENTAL_API_USAGE_ERROR by error2<PsiElement, FqName, String>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val EXPERIMENTAL_OVERRIDE by warning2<PsiElement, FqName, String>()
val EXPERIMENTAL_OVERRIDE_ERROR by error2<PsiElement, FqName, String>()
val EXPERIMENTAL_IS_NOT_ENABLED by warning0<KtAnnotationEntry>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION by error0<PsiElement>()
val EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL by error0<PsiElement>()
val USE_EXPERIMENTAL_WITHOUT_ARGUMENTS by warning0<KtAnnotationEntry>()
val USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER by warning1<KtAnnotationEntry, FqName>()
val EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET by error1<KtAnnotationEntry, String>()
val EXPERIMENTAL_ANNOTATION_WITH_WRONG_RETENTION by error0<KtAnnotationEntry>()
// Exposed visibility
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<KtNamedDeclaration, EffectiveVisibility, FirMemberDeclaration, EffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
val EXPOSED_FUNCTION_RETURN_TYPE by error3<KtNamedDeclaration, EffectiveVisibility, FirMemberDeclaration, EffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
@@ -71,6 +71,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
override val regularClassCheckers: Set<FirRegularClassChecker>
get() = setOf(
FirAnnotationClassDeclarationChecker,
FirOptInAnnotationClassChecker,
FirCommonConstructorDelegationIssuesChecker,
FirConstructorInInterfaceChecker,
FirDelegationSuperCallInEnumConstructorChecker,
@@ -12,6 +12,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
get() = setOf(
FirAnnotationArgumentChecker,
FirOptInAnnotationCallChecker,
)
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
@@ -14,6 +15,7 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.coneType
@@ -49,11 +51,7 @@ fun FirAnnotationCall.getAllowedAnnotationTargets(session: FirSession): Set<Kotl
fun FirRegularClass.getAllowedAnnotationTargets(): Set<KotlinTarget> {
val targetAnnotation = getTargetAnnotation() ?: return defaultAnnotationTargets
if (targetAnnotation.argumentList.arguments.isEmpty()) return emptySet()
val arguments = when (val targetArgument = targetAnnotation.findSingleArgumentByName(TARGET_PARAMETER_NAME)) {
is FirVarargArgumentsExpression -> targetArgument.arguments
is FirArrayOfCall -> targetArgument.arguments
else -> return defaultAnnotationTargets
}
val arguments = targetAnnotation.findSingleArgumentByName(TARGET_PARAMETER_NAME)?.unfoldArrayOrVararg().orEmpty()
return arguments.mapNotNullTo(mutableSetOf()) { argument ->
val targetExpression = argument as? FirQualifiedAccessExpression
@@ -70,7 +68,7 @@ fun FirAnnotatedDeclaration.getTargetAnnotation(): FirAnnotationCall? {
return getAnnotationByFqName(StandardNames.FqNames.target)
}
fun FirAnnotatedDeclaration.getAnnotationByFqName(fqName: FqName): FirAnnotationCall? {
fun FirAnnotationContainer.getAnnotationByFqName(fqName: FqName): FirAnnotationCall? {
return annotations.find {
(it.annotationTypeRef.coneType as? ConeClassLikeType)?.lookupTag?.classId?.asSingleFqName() == fqName
}
@@ -79,7 +77,7 @@ fun FirAnnotatedDeclaration.getAnnotationByFqName(fqName: FqName): FirAnnotation
fun FirAnnotationCall.findSingleArgumentByName(name: Name): FirExpression? {
val argumentMapping = argumentMapping
if (argumentMapping != null) {
return argumentMapping.keys.firstOrNull()?.takeIf { argumentMapping[it]?.name == name }
return argumentMapping.keys.firstOrNull()?.takeIf { argumentMapping[it]?.name == name }?.unwrapArgument()
}
// NB: we have to consider both cases, because deserializer does not create argument mapping
val arguments = argumentList.arguments
@@ -87,3 +85,19 @@ fun FirAnnotationCall.findSingleArgumentByName(name: Name): FirExpression? {
return firstArgument.takeIf { it.name == name }?.expression
}
fun FirExpression.extractClassesFromArgument(): List<FirRegularClassSymbol> {
return unfoldArrayOrVararg().mapNotNull {
if (it !is FirGetClassCall) return@mapNotNull null
val qualifier = it.argument as? FirResolvedQualifier ?: return@mapNotNull null
qualifier.symbol as? FirRegularClassSymbol
}
}
private fun FirExpression.unfoldArrayOrVararg(): List<FirExpression> {
return when (this) {
is FirVarargArgumentsExpression -> arguments
is FirArrayOfCall -> arguments
else -> return emptyList()
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.arguments
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.resolve.SINCE_KOTLIN_FQ_NAME
import org.jetbrains.kotlin.resolve.checkers.OptInNames
sealed class FirSinceKotlinAccessibility {
object Accessible : FirSinceKotlinAccessibility()
data class NotAccessibleButWasExperimental(
val version: ApiVersion,
val markerClasses: List<FirRegularClassSymbol>
) : FirSinceKotlinAccessibility()
data class NotAccessible(
val version: ApiVersion
) : FirSinceKotlinAccessibility()
}
private data class FirSinceKotlinValue(
val apiVersion: ApiVersion,
val wasExperimentalMarkerClasses: List<FirRegularClassSymbol>
)
fun FirAnnotatedDeclaration.checkSinceKotlinVersionAccessibility(context: CheckerContext): FirSinceKotlinAccessibility {
val value = getOwnSinceKotlinVersion(context.session)
val version = value?.apiVersion
val languageVersionSettings = context.session.languageVersionSettings
// Allow access in the following cases:
// 1) There's no @SinceKotlin annotation for this descriptor
// 2) There's a @SinceKotlin annotation but its value is some unrecognizable nonsense
// 3) The value as a version is not greater than our API version
if (version == null || version <= languageVersionSettings.apiVersion) return FirSinceKotlinAccessibility.Accessible
val wasExperimentalFqNames = value.wasExperimentalMarkerClasses
if (wasExperimentalFqNames.isNotEmpty()) {
return FirSinceKotlinAccessibility.NotAccessibleButWasExperimental(version, wasExperimentalFqNames)
}
return FirSinceKotlinAccessibility.NotAccessible(version)
}
private fun FirAnnotatedDeclaration.getOwnSinceKotlinVersion(session: FirSession): FirSinceKotlinValue? {
var result: FirSinceKotlinValue? = null
// TODO: use-site targeted annotations
fun FirAnnotatedDeclaration.consider() {
val sinceKotlinSingleArgument = getAnnotationByFqName(SINCE_KOTLIN_FQ_NAME)?.arguments?.singleOrNull()
val apiVersion = ((sinceKotlinSingleArgument as? FirConstExpression<*>)?.value as? String)?.let(ApiVersion.Companion::parse)
if (apiVersion != null) {
// TODO: combine wasExperimentalMarkerClasses in case of several associated declarations with the same maximal API version
if (result == null || apiVersion > result!!.apiVersion) {
result = FirSinceKotlinValue(apiVersion, loadWasExperimentalMarkerClasses())
}
}
}
this.consider()
if (this is FirConstructor) {
val classId = symbol.callableId.classId
if (classId != null) {
val classSymbol = session.symbolProvider.getClassLikeSymbolByFqName(classId)
classSymbol?.fir?.consider()
}
}
if (this is FirTypeAlias) {
(this.expandedTypeRef.coneType as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir?.consider()
}
return result
}
private fun FirAnnotatedDeclaration.loadWasExperimentalMarkerClasses(): List<FirRegularClassSymbol> {
val wasExperimental = getAnnotationByFqName(OptInNames.WAS_EXPERIMENTAL_FQ_NAME) ?: return emptyList()
val annotationClasses = wasExperimental.findSingleArgumentByName(OptInNames.WAS_EXPERIMENTAL_ANNOTATION_CLASS) ?: return emptyList()
return annotationClasses.extractClassesFromArgument()
}
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.resolve.checkers.Experimentality
import org.jetbrains.kotlin.resolve.checkers.OptInNames
object FirOptInAnnotationClassChecker : FirRegularClassChecker() {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration.classKind != ClassKind.ANNOTATION_CLASS) return
if (declaration.getAnnotationByFqName(OptInNames.REQUIRES_OPT_IN_FQ_NAME) == null) return
if (declaration.getRetention() == AnnotationRetention.SOURCE) {
val target = declaration.getRetentionAnnotation()
reporter.reportOn(target?.source, FirErrors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_RETENTION, context)
}
val wrongTargets = declaration.getAllowedAnnotationTargets().intersect(Experimentality.WRONG_TARGETS_FOR_MARKER)
if (wrongTargets.isNotEmpty()) {
val target = declaration.getTargetAnnotation()
reporter.reportOn(
target?.source,
FirErrors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET,
wrongTargets.joinToString(transform = KotlinTarget::description),
context
)
}
}
}
@@ -20,11 +20,19 @@ import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtTokens.QUEST
import org.jetbrains.kotlin.resolve.checkers.OptInNames
object FirClassLiteralChecker : FirGetClassCallChecker() {
override fun check(expression: FirGetClassCall, context: CheckerContext, reporter: DiagnosticReporter) {
val source = expression.source ?: return
if (source.kind is FirFakeSourceElementKind) return
val argument = expression.argument
if (argument is FirResolvedQualifier) {
val fqName = argument.classId?.asSingleFqName()
if (fqName in OptInNames.EXPERIMENTAL_FQ_NAMES || fqName in OptInNames.USE_EXPERIMENTAL_FQ_NAMES) {
reporter.reportOn(argument.source, FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
}
}
// Note that raw FIR drops marked nullability "?" in, e.g., `A?::class`, `A<T?>::class`, or `A<T?>?::class`.
// That is, AST structures for those expressions have token type QUEST, whereas FIR element doesn't have any information about it.
@@ -36,7 +44,6 @@ object FirClassLiteralChecker : FirGetClassCallChecker() {
//
// Only the 2nd example is valid, and we want to check if token type QUEST doesn't exist at the same level as COLONCOLON.
val markedNullable = source.getChild(QUEST, depth = 1) != null
val argument = expression.argument
val isNullable = markedNullable ||
(argument as? FirResolvedQualifier)?.isNullableLHSForCallableReference == true ||
argument.typeRef.coneType.isMarkedNullable ||
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.extractClassesFromArgument
import org.jetbrains.kotlin.fir.analysis.checkers.findSingleArgumentByName
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.resolve.checkers.OptInNames
object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() {
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
val lookupTag = expression.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag ?: return
val fqName = lookupTag.classId.asSingleFqName()
val isMarker = fqName == OptInNames.REQUIRES_OPT_IN_FQ_NAME
val isOptIn = fqName == OptInNames.OPT_IN_FQ_NAME
if (isMarker || isOptIn) {
checkUsageOfKotlinExperimentalOrUseExperimental(expression.source, context, reporter)
if (isOptIn) {
val arguments = expression.arguments
if (arguments.isEmpty()) {
reporter.reportOn(expression.source, FirErrors.USE_EXPERIMENTAL_WITHOUT_ARGUMENTS, context)
} else {
val annotationClasses = expression.findSingleArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS)
for (classSymbol in annotationClasses?.extractClassesFromArgument().orEmpty()) {
with(FirOptInUsageBaseChecker) {
if (classSymbol.fir.loadExperimentalityForMarkerAnnotation() == null) {
reporter.reportOn(
expression.source,
FirErrors.USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER,
classSymbol.classId.asSingleFqName(),
context
)
}
}
}
}
}
}
}
private fun checkUsageOfKotlinExperimentalOrUseExperimental(
element: FirSourceElement?,
context: CheckerContext,
reporter: DiagnosticReporter
) {
val useExperimentalFqNames = context.session.languageVersionSettings.getFlag(AnalysisFlags.useExperimental)
if (OptInNames.REQUIRES_OPT_IN_FQ_NAME.asString() !in useExperimentalFqNames) {
reporter.reportOn(element, FirErrors.EXPERIMENTAL_IS_NOT_ENABLED, context)
}
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.analysis.checkers.findSingleArgumentByName
import org.jetbrains.kotlin.fir.analysis.checkers.getAnnotationByFqName
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.checkers.Experimentality
import org.jetbrains.kotlin.resolve.checkers.OptInNames
object FirOptInUsageBaseChecker {
internal fun FirRegularClass.loadExperimentalityForMarkerAnnotation(): Experimentality? {
val experimental = getAnnotationByFqName(OptInNames.REQUIRES_OPT_IN_FQ_NAME) ?: return null
val levelArgument = experimental.findSingleArgumentByName(LEVEL) as? FirQualifiedAccessExpression
val levelName = (levelArgument?.calleeReference as? FirResolvedNamedReference)?.name?.asString()
val level = OptInLevel.values().firstOrNull { it.name == levelName } ?: OptInLevel.DEFAULT
val message = (experimental.findSingleArgumentByName(MESSAGE) as? FirConstExpression<*>)?.value as? String
return Experimentality(symbol.classId.asSingleFqName(), level.severity, message)
}
private val LEVEL = Name.identifier("level")
private val MESSAGE = Name.identifier("message")
private enum class OptInLevel(val severity: Experimentality.Severity) {
WARNING(Experimentality.Severity.WARNING),
ERROR(Experimentality.Severity.ERROR),
DEFAULT(Experimentality.DEFAULT_SEVERITY)
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
import org.jetbrains.kotlin.diagnostics.rendering.*
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.RENDER_POSITION_VARIANCE
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.STRING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.AMBIGUOUS_CALLS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FIR
@@ -117,6 +118,15 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_DELEGATE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_LATEINIT_PROPERTY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_PRIVATE_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_PROPERTY_INITIALIZER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_RETENTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_API_USAGE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_API_USAGE_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_IS_NOT_ENABLED
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_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPERIMENTAL_OVERRIDE_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPLICIT_DELEGATION_CALL_REQUIRED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_FUNCTION_RETURN_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_PARAMETER_TYPE
@@ -336,6 +346,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS_RIGHT_IS_NULL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_IS_CHECK
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_VARARG_ON_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USE_EXPERIMENTAL_WITHOUT_ARGUMENTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_BE_CLONEABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_OR_VAR_ON_CATCH_PARAMETER
@@ -363,7 +375,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_MODIFIER_TA
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_PARAMETER_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_RETURN_TYPE
import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData
@Suppress("unused")
class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
@@ -399,10 +410,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(VARIABLE_EXPECTED, "Variable expected")
map.put(DELEGATION_IN_INTERFACE, "Interfaces cannot use delegation")
map.put(NESTED_CLASS_NOT_ALLOWED, "{0} is not allowed here", TO_STRING)
map.put(VAL_OR_VAR_ON_LOOP_PARAMETER, "''{0}'' on loop parameter is not allowed", TO_STRING);
map.put(VAL_OR_VAR_ON_FUN_PARAMETER, "''{0}'' on function parameter is not allowed", TO_STRING);
map.put(VAL_OR_VAR_ON_CATCH_PARAMETER, "''{0}'' on catch parameter is not allowed", TO_STRING);
map.put(VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER, "''{0}'' on secondary constructor parameter is not allowed", TO_STRING);
map.put(VAL_OR_VAR_ON_LOOP_PARAMETER, "''{0}'' on loop parameter is not allowed", TO_STRING)
map.put(VAL_OR_VAR_ON_FUN_PARAMETER, "''{0}'' on function parameter is not allowed", TO_STRING)
map.put(VAL_OR_VAR_ON_CATCH_PARAMETER, "''{0}'' on catch parameter is not allowed", TO_STRING)
map.put(VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER, "''{0}'' on secondary constructor parameter is not allowed", TO_STRING)
// Unresolved
map.put(INVISIBLE_REFERENCE, "Symbol {0} is invisible", SYMBOL)
@@ -528,6 +539,36 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
TO_STRING
)
// OptIn
map.put(EXPERIMENTAL_API_USAGE, "{1}", TO_STRING, STRING)
map.put(EXPERIMENTAL_API_USAGE_ERROR, "{1}", TO_STRING, STRING)
map.put(EXPERIMENTAL_OVERRIDE, "{1}", TO_STRING, STRING)
map.put(EXPERIMENTAL_OVERRIDE_ERROR, "{1}", TO_STRING, STRING)
map.put(EXPERIMENTAL_IS_NOT_ENABLED, "This class can only be used with the compiler argument '-Xopt-in=kotlin.RequiresOptIn'")
map.put(EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION, "This class can only be used as an annotation")
map.put(
EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL,
"This class can only be used as an annotation or as an argument to @OptIn"
)
map.put(USE_EXPERIMENTAL_WITHOUT_ARGUMENTS, "@OptIn without any arguments has no effect")
map.put(
USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER,
"Annotation ''{0}'' is not an opt-in requirement marker, therefore its usage in @OptIn is ignored",
TO_STRING
)
map.put(
EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET,
"Opt-in requirement marker annotation cannot be used on the following code elements: {0}. Please remove these targets",
STRING
)
map.put(
EXPERIMENTAL_ANNOTATION_WITH_WRONG_RETENTION,
"Opt-in requirement marker annotation cannot be used with SOURCE retention. Please replace retention with BINARY"
)
// Exposed visibility group // #
map.put(
EXPOSED_TYPEALIAS_EXPANDED_TYPE,
@@ -585,7 +626,13 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(TYPE_MISMATCH, "Type mismatch: inferred type is {1} but {0} was expected", TO_STRING, TO_STRING)
map.put(THROWABLE_TYPE_MISMATCH, "Throwable type mismatch: actual type is {0}", TO_STRING)
map.put(CONDITION_TYPE_MISMATCH, "Condition type mismatch: inferred type is {0} but Boolean was expected", TO_STRING)
map.put(ARGUMENT_TYPE_MISMATCH, "Argument type mismatch: actual type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE, NOT_RENDERED)
map.put(
ARGUMENT_TYPE_MISMATCH,
"Argument type mismatch: actual type is {1} but {0} was expected",
RENDER_TYPE,
RENDER_TYPE,
NOT_RENDERED
)
map.put(ASSIGNMENT_TYPE_MISMATCH, "Assignment type mismatch: actual type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE)
map.put(
RESULT_TYPE_MISMATCH,
@@ -33,15 +33,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleDescriptor) : AdditionalAnnotationChecker {
companion object {
private val WRONG_TARGETS_FOR_MARKER = setOf(
KotlinTarget.EXPRESSION,
KotlinTarget.FILE,
KotlinTarget.TYPE,
KotlinTarget.TYPE_PARAMETER
)
}
override fun checkEntries(
entries: List<KtAnnotationEntry>,
actualTargets: List<KotlinTarget>,
@@ -154,7 +145,7 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD
if (targetEntry != null) {
val (entry, descriptor) = targetEntry
val allowedTargets = AnnotationChecker.loadAnnotationTargets(descriptor!!) ?: return
val wrongTargets = allowedTargets.intersect(WRONG_TARGETS_FOR_MARKER)
val wrongTargets = allowedTargets.intersect(Experimentality.WRONG_TARGETS_FOR_MARKER)
if (wrongTargets.isNotEmpty()) {
trace.report(
Errors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET.on(
@@ -1,6 +1,6 @@
// FILE: api.kt
@RequiresOptIn
@<!EXPERIMENTAL_IS_NOT_ENABLED!>RequiresOptIn<!>
@Retention(AnnotationRetention.BINARY)
annotation class Marker
@@ -18,7 +18,7 @@ fun use2() {
f()
}
@OptIn(Marker::class)
@<!EXPERIMENTAL_IS_NOT_ENABLED!>OptIn<!>(Marker::class)
fun use3() {
f()
}
@@ -12,21 +12,21 @@ import kotlin.annotation.AnnotationTarget.*
annotation class E1
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(FILE)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(FILE)<!>
annotation class E2
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(EXPRESSION)<!>
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_RETENTION!>@Retention(AnnotationRetention.SOURCE)<!>
annotation class E3
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(TYPE_PARAMETER)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(TYPE_PARAMETER)<!>
@Retention(AnnotationRetention.BINARY)
annotation class E3A
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(TYPE)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(TYPE)<!>
@Retention(AnnotationRetention.BINARY)
annotation class E3B
@@ -1,9 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
annotation class NotAMarker
@OptIn
fun f1() {}
@OptIn(NotAMarker::class)
fun f2() {}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
annotation class NotAMarker
@@ -35,10 +35,10 @@ fun f4(u: OptIn0 /* TODO */) {}
annotation class VarargKClasses(vararg val k: KClass<*>)
@VarargKClasses(
RequiresOptIn::class,
OptIn::class,
kotlin.RequiresOptIn::class,
kotlin.OptIn::class
<!EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION!>RequiresOptIn<!>::class,
<!EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION!>OptIn<!>::class,
<!EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION!>kotlin.RequiresOptIn<!>::class,
<!EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION!>kotlin.OptIn<!>::class
)
fun f5() {}
@@ -15,5 +15,5 @@ class A {
}
}
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
@<!EXPERIMENTAL_IS_NOT_ENABLED!>RequiresOptIn<!>(level = RequiresOptIn.Level.ERROR)
annotation class ExperimentalTime
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.name.FqName
data class Experimentality(val annotationFqName: FqName, val severity: Severity, val message: String?) {
@@ -12,5 +13,12 @@ data class Experimentality(val annotationFqName: FqName, val severity: Severity,
companion object {
val DEFAULT_SEVERITY = Severity.ERROR
val WRONG_TARGETS_FOR_MARKER = setOf(
KotlinTarget.EXPRESSION,
KotlinTarget.FILE,
KotlinTarget.TYPE,
KotlinTarget.TYPE_PARAMETER
)
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
@@ -252,7 +253,8 @@ private object FirToKtConversionCreator {
ForbiddenNamedArgumentsTarget::class,
LanguageFeature::class,
LanguageVersionSettings::class,
Variance::class
Variance::class,
FqName::class,
)
private val KType.kClass: KClass<*>
@@ -717,6 +717,82 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.EXPERIMENTAL_API_USAGE) { firDiagnostic ->
ExperimentalApiUsageImpl(
firDiagnostic.a,
firDiagnostic.b,
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPERIMENTAL_API_USAGE_ERROR) { firDiagnostic ->
ExperimentalApiUsageErrorImpl(
firDiagnostic.a,
firDiagnostic.b,
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPERIMENTAL_OVERRIDE) { firDiagnostic ->
ExperimentalOverrideImpl(
firDiagnostic.a,
firDiagnostic.b,
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPERIMENTAL_OVERRIDE_ERROR) { firDiagnostic ->
ExperimentalOverrideErrorImpl(
firDiagnostic.a,
firDiagnostic.b,
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPERIMENTAL_IS_NOT_ENABLED) { firDiagnostic ->
ExperimentalIsNotEnabledImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION) { firDiagnostic ->
ExperimentalCanOnlyBeUsedAsAnnotationImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPERIMENTAL_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_USE_EXPERIMENTAL) { firDiagnostic ->
ExperimentalMarkerCanOnlyBeUsedAsAnnotationOrArgumentInUseExperimentalImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.USE_EXPERIMENTAL_WITHOUT_ARGUMENTS) { firDiagnostic ->
UseExperimentalWithoutArgumentsImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER) { firDiagnostic ->
UseExperimentalArgumentIsNotMarkerImpl(
firDiagnostic.a,
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET) { firDiagnostic ->
ExperimentalAnnotationWithWrongTargetImpl(
firDiagnostic.a,
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_RETENTION) { firDiagnostic ->
ExperimentalAnnotationWithWrongRetentionImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic ->
ExposedTypealiasExpandedTypeImpl(
firDiagnostic.a,
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotation
import org.jetbrains.kotlin.psi.KtAnnotationEntry
@@ -513,6 +514,60 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = InapplicableFileTarget::class
}
abstract class ExperimentalApiUsage : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = ExperimentalApiUsage::class
abstract val optInMarkerFqName: FqName
abstract val message: String
}
abstract class ExperimentalApiUsageError : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = ExperimentalApiUsageError::class
abstract val optInMarkerFqName: FqName
abstract val message: String
}
abstract class ExperimentalOverride : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = ExperimentalOverride::class
abstract val optInMarkerFqName: FqName
abstract val message: String
}
abstract class ExperimentalOverrideError : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = ExperimentalOverrideError::class
abstract val optInMarkerFqName: FqName
abstract val message: String
}
abstract class ExperimentalIsNotEnabled : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = ExperimentalIsNotEnabled::class
}
abstract class ExperimentalCanOnlyBeUsedAsAnnotation : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = ExperimentalCanOnlyBeUsedAsAnnotation::class
}
abstract class ExperimentalMarkerCanOnlyBeUsedAsAnnotationOrArgumentInUseExperimental : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = ExperimentalMarkerCanOnlyBeUsedAsAnnotationOrArgumentInUseExperimental::class
}
abstract class UseExperimentalWithoutArguments : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = UseExperimentalWithoutArguments::class
}
abstract class UseExperimentalArgumentIsNotMarker : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = UseExperimentalArgumentIsNotMarker::class
abstract val notMarkerFqName: FqName
}
abstract class ExperimentalAnnotationWithWrongTarget : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = ExperimentalAnnotationWithWrongTarget::class
abstract val target: String
}
abstract class ExperimentalAnnotationWithWrongRetention : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = ExperimentalAnnotationWithWrongRetention::class
}
abstract class ExposedTypealiasExpandedType : KtFirDiagnostic<KtNamedDeclaration>() {
override val diagnosticClass get() = ExposedTypealiasExpandedType::class
abstract val elementVisibility: EffectiveVisibility
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotation
import org.jetbrains.kotlin.psi.KtAnnotationEntry
@@ -832,6 +833,93 @@ internal class InapplicableFileTargetImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExperimentalApiUsageImpl(
override val optInMarkerFqName: FqName,
override val message: String,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExperimentalApiUsage(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExperimentalApiUsageErrorImpl(
override val optInMarkerFqName: FqName,
override val message: String,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExperimentalApiUsageError(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExperimentalOverrideImpl(
override val optInMarkerFqName: FqName,
override val message: String,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExperimentalOverride(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExperimentalOverrideErrorImpl(
override val optInMarkerFqName: FqName,
override val message: String,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExperimentalOverrideError(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExperimentalIsNotEnabledImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExperimentalIsNotEnabled(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExperimentalCanOnlyBeUsedAsAnnotationImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExperimentalCanOnlyBeUsedAsAnnotation(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExperimentalMarkerCanOnlyBeUsedAsAnnotationOrArgumentInUseExperimentalImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExperimentalMarkerCanOnlyBeUsedAsAnnotationOrArgumentInUseExperimental(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class UseExperimentalWithoutArgumentsImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.UseExperimentalWithoutArguments(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class UseExperimentalArgumentIsNotMarkerImpl(
override val notMarkerFqName: FqName,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.UseExperimentalArgumentIsNotMarker(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExperimentalAnnotationWithWrongTargetImpl(
override val target: String,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExperimentalAnnotationWithWrongTarget(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExperimentalAnnotationWithWrongRetentionImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExperimentalAnnotationWithWrongRetention(), KtAbstractFirDiagnostic<KtAnnotationEntry> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExposedTypealiasExpandedTypeImpl(
override val elementVisibility: EffectiveVisibility,
override val restrictingDeclaration: KtSymbol,