Remove Experimental and UseExperimental from compiler OptIn usage checkers
This commit is contained in:
committed by
Space
parent
bc684b8d36
commit
f2b0c30cba
+3
-3
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -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
|
||||
}
|
||||
|
||||
+5
-5
@@ -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<ArrayValue>()?.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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)'"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user