diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInAnnotationCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInAnnotationCallChecker.kt index f411ee2496b..f835776e181 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInAnnotationCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInAnnotationCallChecker.kt @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.resolve.checkers.OptInNames -import org.jetbrains.kotlin.resolve.checkers.OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS +import org.jetbrains.kotlin.resolve.checkers.OptInNames.OPT_IN_ANNOTATION_CLASS object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() { override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) { @@ -45,7 +45,7 @@ object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() { if (arguments.isEmpty()) { reporter.reportOn(expression.source, FirErrors.OPT_IN_WITHOUT_ARGUMENTS, context) } else { - val annotationClasses = expression.findArgumentByName(USE_EXPERIMENTAL_ANNOTATION_CLASS) + val annotationClasses = expression.findArgumentByName(OPT_IN_ANNOTATION_CLASS) for (classSymbol in annotationClasses?.extractClassesFromArgument().orEmpty()) { checkOptInArgumentIsMarker(classSymbol, expression.source, reporter, context) } @@ -73,7 +73,7 @@ object FirOptInAnnotationCallChecker : FirAnnotationCallChecker() { return } } - val classSymbol = expression.findArgumentByName(USE_EXPERIMENTAL_ANNOTATION_CLASS)?.extractClassFromArgument() ?: return + val classSymbol = expression.findArgumentByName(OPT_IN_ANNOTATION_CLASS)?.extractClassFromArgument() ?: return checkOptInArgumentIsMarker(classSymbol, expression.source, reporter, context) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt index aa47c9c5d2f..1f6177b996a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt @@ -97,7 +97,7 @@ object FirOptInUsageBaseChecker { ) if (fromSupertype) { if (annotationType.lookupTag.classId == OptInNames.SUBCLASS_OPT_IN_REQUIRED_CLASS_ID) { - val annotationClass = annotation.findArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS) ?: continue + val annotationClass = annotation.findArgumentByName(OptInNames.OPT_IN_ANNOTATION_CLASS) ?: continue result.addIfNotNull( annotationClass.extractClassFromArgument()?.loadExperimentalityForMarkerAnnotation()?.copy(fromSupertype = true) ) @@ -320,7 +320,7 @@ object FirOptInUsageBaseChecker { if (coneType?.lookupTag?.classId != OptInNames.OPT_IN_CLASS_ID) { continue } - val annotationClasses = annotation.findArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS) ?: continue + val annotationClasses = annotation.findArgumentByName(OptInNames.OPT_IN_ANNOTATION_CLASS) ?: continue if (annotationClasses.extractClassesFromArgument().any { it.classId == annotationClassId }) { return true } @@ -334,7 +334,7 @@ object FirOptInUsageBaseChecker { if (coneType?.lookupTag?.classId != OptInNames.SUBCLASS_OPT_IN_REQUIRED_CLASS_ID) { continue } - val annotationClass = annotation.findArgumentByName(OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS) ?: continue + val annotationClass = annotation.findArgumentByName(OptInNames.OPT_IN_ANNOTATION_CLASS) ?: continue if (annotationClass.extractClassFromArgument()?.classId == annotationClassId) { return true } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInMarkerDeclarationAnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInMarkerDeclarationAnnotationChecker.kt index 6c65c7c5483..4dd709dd146 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInMarkerDeclarationAnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInMarkerDeclarationAnnotationChecker.kt @@ -42,23 +42,23 @@ class OptInMarkerDeclarationAnnotationChecker(private val module: ModuleDescript for (entry in entries) { val annotation = trace.bindingContext.get(BindingContext.ANNOTATION, entry) ?: continue when (annotation.fqName) { - in OptInNames.OPT_IN_FQ_NAMES -> { + OptInNames.OPT_IN_FQ_NAME -> { val annotationClasses = - annotation.allValueArguments[OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS] + annotation.allValueArguments[OptInNames.OPT_IN_ANNOTATION_CLASS] .safeAs()?.value.orEmpty() checkOptInUsage(annotationClasses, trace, entry) } OptInNames.SUBCLASS_OPT_IN_REQUIRED_FQ_NAME -> { val annotationClass = - annotation.allValueArguments[OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS] + annotation.allValueArguments[OptInNames.OPT_IN_ANNOTATION_CLASS] checkSubclassOptInUsage(annotated, listOfNotNull(annotationClass), trace, entry) } - in OptInNames.REQUIRES_OPT_IN_FQ_NAMES -> { + OptInNames.REQUIRES_OPT_IN_FQ_NAME -> { hasOptIn = true } } val annotationClass = annotation.annotationClass ?: continue - if (annotationClass.annotations.any { it.fqName in OptInNames.REQUIRES_OPT_IN_FQ_NAMES }) { + if (annotationClass.annotations.any { it.fqName == OptInNames.REQUIRES_OPT_IN_FQ_NAME }) { val applicableTargets = AnnotationChecker.applicableTargetSet(annotationClass) val possibleTargets = applicableTargets.intersect(actualTargets) val annotationUseSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInUsageChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInUsageChecker.kt index fc8e9a1ef5e..318629c5462 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInUsageChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInUsageChecker.kt @@ -36,14 +36,10 @@ import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.checkers.OptInNames.OLD_EXPERIMENTAL_FQ_NAME -import org.jetbrains.kotlin.resolve.checkers.OptInNames.OLD_USE_EXPERIMENTAL_FQ_NAME import org.jetbrains.kotlin.resolve.checkers.OptInNames.OPT_IN_FQ_NAME -import org.jetbrains.kotlin.resolve.checkers.OptInNames.OPT_IN_FQ_NAMES import org.jetbrains.kotlin.resolve.checkers.OptInNames.REQUIRES_OPT_IN_FQ_NAME -import org.jetbrains.kotlin.resolve.checkers.OptInNames.REQUIRES_OPT_IN_FQ_NAMES import org.jetbrains.kotlin.resolve.checkers.OptInNames.SUBCLASS_OPT_IN_REQUIRED_FQ_NAME -import org.jetbrains.kotlin.resolve.checkers.OptInNames.USE_EXPERIMENTAL_ANNOTATION_CLASS +import org.jetbrains.kotlin.resolve.checkers.OptInNames.OPT_IN_ANNOTATION_CLASS import org.jetbrains.kotlin.resolve.checkers.OptInNames.WAS_EXPERIMENTAL_FQ_NAME import org.jetbrains.kotlin.resolve.constants.ArrayValue import org.jetbrains.kotlin.resolve.constants.EnumValue @@ -286,9 +282,7 @@ class OptInUsageChecker(project: Project) : CallChecker { subclassesOnly: Boolean = false ): OptInDescription? { val optInAnnotationDescriptor = - annotations.findAnnotation(REQUIRES_OPT_IN_FQ_NAME) - ?: annotations.findAnnotation(OLD_EXPERIMENTAL_FQ_NAME) - ?: return null + annotations.findAnnotation(REQUIRES_OPT_IN_FQ_NAME) ?: return null val arguments = optInAnnotationDescriptor.allValueArguments val severity = when ((arguments[LEVEL] as? EnumValue)?.enumEntryName) { @@ -308,7 +302,7 @@ class OptInUsageChecker(project: Project) : CallChecker { private fun AnnotationDescriptor.loadSubclassOptInRequired(context: BindingContext?): OptInDescription? { if (this.fqName != SUBCLASS_OPT_IN_REQUIRED_FQ_NAME) return null - val markerClass = allValueArguments[USE_EXPERIMENTAL_ANNOTATION_CLASS] + val markerClass = allValueArguments[OPT_IN_ANNOTATION_CLASS] if (markerClass !is KClassValue) return null val value = markerClass.value if (value !is KClassValue.Value.NormalClass) return null @@ -320,7 +314,7 @@ class OptInUsageChecker(project: Project) : CallChecker { isOptInAllowed(annotationFqName, context.languageVersionSettings, context.trace.bindingContext, subclassesOnly) /** - * Checks whether there's an element lexically above in the tree, annotated with `@UseExperimental(X::class)`, or a declaration + * Checks whether there's an element lexically above in the tree, annotated with `@OptIn(X::class)`, or a declaration * annotated with `@X` where [annotationFqName] is the FQ name of X */ fun PsiElement.isOptInAllowed( @@ -354,8 +348,8 @@ class OptInUsageChecker(project: Project) : CallChecker { private fun PsiElement.isElementAnnotatedWithOptIn(annotationFqName: FqName, bindingContext: BindingContext): Boolean { return this is KtAnnotated && annotationEntries.any { entry -> val descriptor = bindingContext.get(BindingContext.ANNOTATION, entry) - if (descriptor != null && descriptor.fqName in OPT_IN_FQ_NAMES) { - val annotationClasses = descriptor.allValueArguments[USE_EXPERIMENTAL_ANNOTATION_CLASS] + if (descriptor != null && descriptor.fqName == OPT_IN_FQ_NAME) { + val annotationClasses = descriptor.allValueArguments[OPT_IN_ANNOTATION_CLASS] annotationClasses is ArrayValue && annotationClasses.value.any { annotationClass -> annotationClass is KClassValue && annotationClass.value.let { value -> value is KClassValue.Value.NormalClass && @@ -373,7 +367,7 @@ class OptInUsageChecker(project: Project) : CallChecker { return this is KtAnnotated && annotationEntries.any { entry -> val descriptor = bindingContext.get(BindingContext.ANNOTATION, entry) if (descriptor != null && descriptor.fqName == SUBCLASS_OPT_IN_REQUIRED_FQ_NAME) { - val annotationClass = descriptor.allValueArguments[USE_EXPERIMENTAL_ANNOTATION_CLASS] + val annotationClass = descriptor.allValueArguments[OPT_IN_ANNOTATION_CLASS] annotationClass is KClassValue && annotationClass.value.let { value -> value is KClassValue.Value.NormalClass && value.classId.asSingleFqName() == annotationFqName && value.arrayDimensions == 0 @@ -429,7 +423,7 @@ class OptInUsageChecker(project: Project) : CallChecker { } languageVersionSettings.getFlag(AnalysisFlags.optIn).forEach { fqName -> - if (fqName != REQUIRES_OPT_IN_FQ_NAME.asString() && fqName != OLD_EXPERIMENTAL_FQ_NAME.asString()) { + if (fqName != REQUIRES_OPT_IN_FQ_NAME.asString()) { checkAnnotation(fqName) } } @@ -441,12 +435,10 @@ class OptInUsageChecker(project: Project) : CallChecker { override fun check(targetDescriptor: ClassifierDescriptor, element: PsiElement, context: ClassifierUsageCheckerContext) { val name = targetDescriptor.name - if (name == OLD_EXPERIMENTAL_FQ_NAME.shortName() || name == REQUIRES_OPT_IN_FQ_NAME.shortName() || - name == OLD_USE_EXPERIMENTAL_FQ_NAME.shortName() || name == OPT_IN_FQ_NAME.shortName() - ) { + if (name == REQUIRES_OPT_IN_FQ_NAME.shortName() || name == OPT_IN_FQ_NAME.shortName()) { val fqName = targetDescriptor.fqNameSafe - if (fqName in REQUIRES_OPT_IN_FQ_NAMES || fqName in OPT_IN_FQ_NAMES) { - checkUsageOfKotlinExperimentalOrOptIn(element, context) + if (fqName == REQUIRES_OPT_IN_FQ_NAME || fqName == OPT_IN_FQ_NAME) { + checkUsageOfKotlinRequiresOptInOrOptIn(element, context) return } } @@ -481,11 +473,10 @@ class OptInUsageChecker(project: Project) : CallChecker { } } - private fun checkUsageOfKotlinExperimentalOrOptIn(element: PsiElement, context: CheckerContext) { + private fun checkUsageOfKotlinRequiresOptInOrOptIn(element: PsiElement, context: CheckerContext) { val optInFqNames = context.languageVersionSettings.getFlag(AnalysisFlags.optIn) if (!context.languageVersionSettings.supportsFeature(LanguageFeature.OptInRelease) && - REQUIRES_OPT_IN_FQ_NAME.asString() !in optInFqNames && - OLD_EXPERIMENTAL_FQ_NAME.asString() !in optInFqNames + REQUIRES_OPT_IN_FQ_NAME.asString() !in optInFqNames ) { context.trace.report(Errors.OPT_IN_IS_NOT_ENABLED.on(element)) } @@ -515,7 +506,7 @@ class OptInUsageChecker(project: Project) : CallChecker { parent.parent.parent is KtValueArgumentList && parent.parent.parent.parent.let { entry -> entry is KtAnnotationEntry && bindingContext.get(BindingContext.ANNOTATION, entry)?.let { annotation -> - annotation.fqName in OPT_IN_FQ_NAMES || annotation.fqName == WAS_EXPERIMENTAL_FQ_NAME || + annotation.fqName == OPT_IN_FQ_NAME || annotation.fqName == WAS_EXPERIMENTAL_FQ_NAME || annotation.fqName == SUBCLASS_OPT_IN_REQUIRED_FQ_NAME } == true } diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/OptInNames.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/OptInNames.kt index ed021a2c2c8..d2662edd3be 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/OptInNames.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/OptInNames.kt @@ -10,8 +10,6 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name object OptInNames { - val OLD_EXPERIMENTAL_FQ_NAME = FqName("kotlin.Experimental") - val OLD_USE_EXPERIMENTAL_FQ_NAME = FqName("kotlin.UseExperimental") 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") @@ -21,26 +19,9 @@ object OptInNames { 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 OPT_IN_ANNOTATION_CLASS = Name.identifier("markerClass") val WAS_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass") - val REQUIRES_OPT_IN_FQ_NAMES = setOf(OLD_EXPERIMENTAL_FQ_NAME, REQUIRES_OPT_IN_FQ_NAME) - val OPT_IN_FQ_NAMES = setOf(OLD_USE_EXPERIMENTAL_FQ_NAME, OPT_IN_FQ_NAME) - - @Deprecated( - message = "EXPERIMENTAL_FQ_NAMES is deprecated, please use REQUIRES_OPT_IN_FQ_NAMES instead", - ReplaceWith("REQUIRES_OPT_IN_FQ_NAMES", imports = ["org.jetbrains.kotlin.resolve.checkers.OptInNames.REQUIRES_OPT_IN_FQ_NAMES"]) - ) - @Suppress("unused") - val EXPERIMENTAL_FQ_NAMES = REQUIRES_OPT_IN_FQ_NAMES - - @Deprecated( - message = "USE_EXPERIMENTAL_FQ_NAMES is deprecated, please use OPT_IN_FQ_NAMES instead", - ReplaceWith("OPT_IN_FQ_NAMES", imports = ["org.jetbrains.kotlin.resolve.checkers.OptInNames.OPT_IN_FQ_NAMES"]) - ) - @Suppress("unused") - val USE_EXPERIMENTAL_FQ_NAMES = OPT_IN_FQ_NAMES - fun buildDefaultDiagnosticMessage(prefix: String, markerName: String): String { return "$prefix with '@$markerName' or '@OptIn($markerName::class)'" }