From 8baff4404dcf374383f4d9d57e2a0d8d74dc088d Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 31 May 2022 10:35:51 +0200 Subject: [PATCH] Partial rename of 'Experimentality' around K1 checkers --- .../messages/AnalyzerWithCompilerReport.kt | 4 +- .../FirOptInAnnotationClassChecker.kt | 4 +- .../jetbrains/kotlin/frontend/di/injection.kt | 8 +- .../resolve/PlatformConfiguratorBase.kt | 2 +- ...ptInMarkerDeclarationAnnotationChecker.kt} | 47 +----- ...alUsageChecker.kt => OptInUsageChecker.kt} | 158 +++++++++--------- .../evaluate/ConstantExpressionEvaluator.kt | 16 +- .../deprecation/DeprecationResolver.kt | 6 +- ...Experimentality.kt => OptInDescription.kt} | 2 +- 9 files changed, 108 insertions(+), 139 deletions(-) rename compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/{ExperimentalMarkerDeclarationAnnotationChecker.kt => OptInMarkerDeclarationAnnotationChecker.kt} (76%) rename compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/{ExperimentalUsageChecker.kt => OptInUsageChecker.kt} (76%) rename core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/{Experimentality.kt => OptInDescription.kt} (86%) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt index d997df6d62f..9eac07f9aec 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt @@ -33,7 +33,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.load.java.components.TraceBasedErrorReporter import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker +import org.jetbrains.kotlin.resolve.checkers.OptInUsageChecker import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices class AnalyzerWithCompilerReport( @@ -114,7 +114,7 @@ class AnalyzerWithCompilerReport( override fun analyzeAndReport(files: Collection, analyze: () -> AnalysisResult) { analysisResult = analyze() if (!analysisResult.isError()) { - ExperimentalUsageChecker.checkCompilerArguments( + OptInUsageChecker.checkCompilerArguments( analysisResult.moduleDescriptor, languageVersionSettings, reportError = { message -> messageCollector.report(ERROR, message) }, reportWarning = { message -> messageCollector.report(WARNING, message) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOptInAnnotationClassChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOptInAnnotationClassChecker.kt index 8add22bc5fb..26cf1773680 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOptInAnnotationClassChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOptInAnnotationClassChecker.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId -import org.jetbrains.kotlin.resolve.checkers.Experimentality +import org.jetbrains.kotlin.resolve.checkers.OptInDescription import org.jetbrains.kotlin.resolve.checkers.OptInNames object FirOptInAnnotationClassChecker : FirRegularClassChecker() { @@ -26,7 +26,7 @@ object FirOptInAnnotationClassChecker : FirRegularClassChecker() { reporter.reportOn(target?.source, FirErrors.OPT_IN_MARKER_WITH_WRONG_RETENTION, context) } - val wrongTargets = declaration.getAllowedAnnotationTargets().intersect(Experimentality.WRONG_TARGETS_FOR_MARKER) + val wrongTargets = declaration.getAllowedAnnotationTargets().intersect(OptInDescription.WRONG_TARGETS_FOR_MARKER) if (wrongTargets.isNotEmpty()) { val target = declaration.getTargetAnnotation() reporter.reportOn( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt index 350c4b1b956..d2247e14fe4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt @@ -39,7 +39,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.ClassicConstraint import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbacksImpl import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker -import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker +import org.jetbrains.kotlin.resolve.checkers.OptInUsageChecker import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled import org.jetbrains.kotlin.resolve.lazy.* import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory @@ -105,9 +105,9 @@ private fun StorageComponentContainer.configurePlatformIndependentComponents() { useImpl() useImpl() - useImpl() - useImpl() - useImpl() + useImpl() + useImpl() + useImpl() useImpl() useImpl() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt index bdd2bec9dca..659a8d0ff81 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt @@ -123,7 +123,7 @@ abstract class PlatformConfiguratorBase( } override fun configureModuleDependentCheckers(container: StorageComponentContainer) { - container.useImpl() + container.useImpl() } fun configureExtensionsAndCheckers(container: StorageComponentContainer) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInMarkerDeclarationAnnotationChecker.kt similarity index 76% rename from compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt rename to compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInMarkerDeclarationAnnotationChecker.kt index b71148112eb..18f2d17263e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalMarkerDeclarationAnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInMarkerDeclarationAnnotationChecker.kt @@ -6,9 +6,7 @@ package org.jetbrains.kotlin.resolve.checkers import org.jetbrains.kotlin.builtins.StandardNames -import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget @@ -16,12 +14,8 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.* import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtAnnotated import org.jetbrains.kotlin.psi.KtAnnotationEntry -import org.jetbrains.kotlin.psi.KtCallableDeclaration -import org.jetbrains.kotlin.psi.KtPropertyAccessor import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker import org.jetbrains.kotlin.resolve.AnnotationChecker import org.jetbrains.kotlin.resolve.BindingContext @@ -34,7 +28,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention import org.jetbrains.kotlin.utils.addToStdlib.safeAs -class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleDescriptor) : AdditionalAnnotationChecker { +class OptInMarkerDeclarationAnnotationChecker(private val module: ModuleDescriptor) : AdditionalAnnotationChecker { override fun checkEntries( entries: List, actualTargets: List, @@ -42,7 +36,7 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD annotated: KtAnnotated?, languageVersionSettings: LanguageVersionSettings ) { - var isAnnotatedWithExperimental = false + var hasOptIn = false for (entry in entries) { val annotation = trace.bindingContext.get(BindingContext.ANNOTATION, entry) ?: continue @@ -54,7 +48,7 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD checkOptInUsage(annotationClasses, trace, entry) } in OptInNames.REQUIRES_OPT_IN_FQ_NAMES -> { - isAnnotatedWithExperimental = true + hasOptIn = true } } val annotationClass = annotation.annotationClass ?: continue @@ -85,36 +79,11 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD } } - if (isAnnotatedWithExperimental) { + if (hasOptIn) { checkMarkerTargetsAndRetention(entries, trace) } } - private fun CallableMemberDescriptor.hasExperimentalOverriddenDescriptors( - experimentalFqName: FqName, - visited: MutableSet = mutableSetOf() - ): Boolean { - if (!visited.add(this)) return false - for (overridden in overriddenDescriptors) { - if (overridden.annotations.any { it.fqName == experimentalFqName }) { - return true - } - var containingDeclaration = overridden.containingDeclaration - while (containingDeclaration is ClassDescriptor) { - if (containingDeclaration.annotations.any { it.fqName == experimentalFqName }) { - return true - } - containingDeclaration = containingDeclaration.containingDeclaration - } - if (overridden.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE && - overridden.hasExperimentalOverriddenDescriptors(experimentalFqName) - ) { - return true - } - } - return false - } - private fun checkOptInUsage(annotationClasses: List>, trace: BindingTrace, entry: KtAnnotationEntry) { if (annotationClasses.isEmpty()) { trace.report(Errors.OPT_IN_WITHOUT_ARGUMENTS.on(entry)) @@ -125,10 +94,10 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD val classDescriptor = (annotationClass as? KClassValue)?.getArgumentType(module)?.constructor?.declarationDescriptor as? ClassDescriptor ?: continue - val experimentality = with(ExperimentalUsageChecker) { - classDescriptor.loadExperimentalityForMarkerAnnotation() + val optInDescription = with(OptInUsageChecker) { + classDescriptor.loadOptInForMarkerAnnotation() } - if (experimentality == null) { + if (optInDescription == null) { trace.report(Errors.OPT_IN_ARGUMENT_IS_NOT_MARKER.on(entry, classDescriptor.fqNameSafe)) } } @@ -145,7 +114,7 @@ class ExperimentalMarkerDeclarationAnnotationChecker(private val module: ModuleD if (targetEntry != null) { val (entry, descriptor) = targetEntry val allowedTargets = AnnotationChecker.loadAnnotationTargets(descriptor!!) ?: return - val wrongTargets = allowedTargets.intersect(Experimentality.WRONG_TARGETS_FOR_MARKER) + val wrongTargets = allowedTargets.intersect(OptInDescription.WRONG_TARGETS_FOR_MARKER) if (wrongTargets.isNotEmpty()) { trace.report( Errors.OPT_IN_MARKER_WITH_WRONG_TARGET.on( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInUsageChecker.kt similarity index 76% rename from compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt rename to compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInUsageChecker.kt index 1b389863c6e..2fbcc991aa3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExperimentalUsageChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/OptInUsageChecker.kt @@ -59,45 +59,45 @@ import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.addIfNotNull -class ExperimentalUsageChecker(project: Project) : CallChecker { +class OptInUsageChecker(project: Project) : CallChecker { private val moduleAnnotationsResolver = ModuleAnnotationsResolver.getInstance(project) - interface ExperimentalityDiagnostic { + interface OptInDiagnosticReporter { fun report(trace: BindingTrace, element: PsiElement, fqName: FqName, message: String?) } - class ExperimentalityDiagnostic2( + class OptInFactoryBasedReporter( val factory: DiagnosticFactory2, val defaultMessage: (FqName) -> String - ) : ExperimentalityDiagnostic { + ) : OptInDiagnosticReporter { override fun report(trace: BindingTrace, element: PsiElement, fqName: FqName, message: String?) { trace.reportDiagnosticOnce(factory.on(element, fqName, message?.takeIf { it.isNotBlank() } ?: defaultMessage(fqName))) } } - data class ExperimentalityDiagnostics( - val warning: ExperimentalityDiagnostic, - val error: ExperimentalityDiagnostic, - val futureError: ExperimentalityDiagnostic + data class OptInReporterMultiplexer( + val warning: OptInDiagnosticReporter, + val error: OptInDiagnosticReporter, + val futureError: OptInDiagnosticReporter ) override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val resultingDescriptor = resolvedCall.resultingDescriptor - val experimentalities = resultingDescriptor.loadExperimentalities(moduleAnnotationsResolver, context.languageVersionSettings) + val optIns = resultingDescriptor.loadOptIns(moduleAnnotationsResolver, context.languageVersionSettings) if (resultingDescriptor is FunctionDescriptor && resultingDescriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED ) { val propertyDescriptor = resultingDescriptor.findRelevantDataClassPropertyIfAny(context) if (propertyDescriptor != null) { - reportNotAcceptedExperimentalities( - experimentalities + propertyDescriptor.loadExperimentalities( + reportNotAllowedOptIns( + optIns + propertyDescriptor.loadOptIns( moduleAnnotationsResolver, context.languageVersionSettings ), reportOn, context ) return } } - reportNotAcceptedExperimentalities(experimentalities, reportOn, context) + reportNotAllowedOptIns(optIns, reportOn, context) } private fun FunctionDescriptor.findRelevantDataClassPropertyIfAny(context: CallCheckerContext): PropertyDescriptor? { @@ -122,61 +122,61 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { OptInNames.buildDefaultDiagnosticMessage(prefix, fqName.asString()) } - private val USAGE_DIAGNOSTICS = ExperimentalityDiagnostics( - warning = ExperimentalityDiagnostic2( + private val USAGE_DIAGNOSTICS = OptInReporterMultiplexer( + warning = OptInFactoryBasedReporter( Errors.OPT_IN_USAGE, getDefaultDiagnosticMessage(OptInNames.buildMessagePrefix("should")) ), - error = ExperimentalityDiagnostic2( + error = OptInFactoryBasedReporter( Errors.OPT_IN_USAGE_ERROR, getDefaultDiagnosticMessage(OptInNames.buildMessagePrefix("must")) ), - futureError = ExperimentalityDiagnostic2( + futureError = OptInFactoryBasedReporter( Errors.OPT_IN_USAGE_FUTURE_ERROR, getDefaultDiagnosticMessage("This declaration is experimental due to signature types and its usage must be marked (will become an error in 1.6)") ), ) - fun reportNotAcceptedExperimentalities( - experimentalities: Collection, element: PsiElement, context: CheckerContext + fun reportNotAllowedOptIns( + descriptions: Collection, element: PsiElement, context: CheckerContext ) { - reportNotAcceptedExperimentalities( - experimentalities, element, context.languageVersionSettings, context.trace, USAGE_DIAGNOSTICS + reportNotAllowedOptIns( + descriptions, element, context.languageVersionSettings, context.trace, USAGE_DIAGNOSTICS ) } - fun reportNotAcceptedExperimentalities( - experimentalities: Collection, + fun reportNotAllowedOptIns( + descriptions: Collection, element: PsiElement, languageVersionSettings: LanguageVersionSettings, trace: BindingTrace, - diagnostics: ExperimentalityDiagnostics + diagnostics: OptInReporterMultiplexer ) { - for ((annotationFqName, severity, message) in experimentalities) { - if (!element.isExperimentalityAccepted(annotationFqName, languageVersionSettings, trace.bindingContext)) { + for ((annotationFqName, severity, message) in descriptions) { + if (!element.isOptInAllowed(annotationFqName, languageVersionSettings, trace.bindingContext)) { val diagnostic = when (severity) { - Experimentality.Severity.WARNING -> diagnostics.warning - Experimentality.Severity.ERROR -> diagnostics.error - Experimentality.Severity.FUTURE_ERROR -> diagnostics.futureError + OptInDescription.Severity.WARNING -> diagnostics.warning + OptInDescription.Severity.ERROR -> diagnostics.error + OptInDescription.Severity.FUTURE_ERROR -> diagnostics.futureError } diagnostic.report(trace, element, annotationFqName, message) } } } - fun DeclarationDescriptor.loadExperimentalities( + fun DeclarationDescriptor.loadOptIns( moduleAnnotationsResolver: ModuleAnnotationsResolver, languageVersionSettings: LanguageVersionSettings, visited: MutableSet = mutableSetOf(), useFutureError: Boolean = false, useMarkersFromContainer: Boolean = true, - ): Set { + ): Set { if (!visited.add(this)) return emptySet() - val result = SmartSet.create() + val result = SmartSet.create() if (this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { for (overridden in overriddenDescriptors) { result.addAll( - overridden.loadExperimentalities( + overridden.loadOptIns( moduleAnnotationsResolver, languageVersionSettings, visited, @@ -187,7 +187,7 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { if (useMarkersFromContainer) { (containingDeclaration as? ClassDescriptor)?.let { result.addAll( - it.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visited, useFutureError) + it.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visited, useFutureError) ) } } @@ -196,22 +196,22 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { } for (annotation in annotations) { - result.addIfNotNull(annotation.annotationClass?.loadExperimentalityForMarkerAnnotation(useFutureError)) + result.addIfNotNull(annotation.annotationClass?.loadOptInForMarkerAnnotation(useFutureError)) } if (this is CallableDescriptor && this !is ClassConstructorDescriptor) { result.addAll( - returnType.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visited) + returnType.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visited) ) result.addAll( - extensionReceiverParameter?.type.loadExperimentalities( + extensionReceiverParameter?.type.loadOptIns( moduleAnnotationsResolver, languageVersionSettings, visited ) ) if (this is FunctionDescriptor) { valueParameters.forEach { result.addAll( - it.type.loadExperimentalities( + it.type.loadOptIns( moduleAnnotationsResolver, languageVersionSettings, visited ) ) @@ -220,76 +220,76 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { } if (this is TypeAliasDescriptor) { - result.addAll(expandedType.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visited)) + result.addAll(expandedType.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visited)) } if (annotations.any { it.fqName == WAS_EXPERIMENTAL_FQ_NAME }) { val accessibility = checkSinceKotlinVersionAccessibility(languageVersionSettings) if (accessibility is SinceKotlinAccessibility.NotAccessibleButWasExperimental) { - result.addAll(accessibility.markerClasses.mapNotNull { it.loadExperimentalityForMarkerAnnotation() }) + result.addAll(accessibility.markerClasses.mapNotNull { it.loadOptInForMarkerAnnotation() }) } } val container = containingDeclaration if (useMarkersFromContainer && container is ClassDescriptor && this !is ConstructorDescriptor) { - result.addAll(container.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visited, useFutureError)) + result.addAll(container.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visited, useFutureError)) } return result } - private fun KotlinType?.loadExperimentalities( + private fun KotlinType?.loadOptIns( moduleAnnotationsResolver: ModuleAnnotationsResolver, languageVersionSettings: LanguageVersionSettings, visitedClassifiers: MutableSet - ): Set = + ): Set = when { this?.isError != false -> emptySet() - this is AbbreviatedType -> abbreviation.constructor.declarationDescriptor?.loadExperimentalities( + this is AbbreviatedType -> abbreviation.constructor.declarationDescriptor?.loadOptIns( moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers, useFutureError = !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures) - ).orEmpty() + expandedType.loadExperimentalities( + ).orEmpty() + expandedType.loadOptIns( moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers ) - else -> constructor.declarationDescriptor?.loadExperimentalities( + else -> constructor.declarationDescriptor?.loadOptIns( moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers, useFutureError = !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures) ).orEmpty() + arguments.flatMap { if (it.isStarProjection) emptySet() - else it.type.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers) + else it.type.loadOptIns(moduleAnnotationsResolver, languageVersionSettings, visitedClassifiers) } } - internal fun ClassDescriptor.loadExperimentalityForMarkerAnnotation(useFutureError: Boolean = false): Experimentality? { - val experimental = + internal fun ClassDescriptor.loadOptInForMarkerAnnotation(useFutureError: Boolean = false): OptInDescription? { + val optInAnnotationDescriptor = annotations.findAnnotation(REQUIRES_OPT_IN_FQ_NAME) ?: annotations.findAnnotation(OLD_EXPERIMENTAL_FQ_NAME) ?: return null - val arguments = experimental.allValueArguments + val arguments = optInAnnotationDescriptor.allValueArguments val severity = when ((arguments[LEVEL] as? EnumValue)?.enumEntryName) { - WARNING_LEVEL -> Experimentality.Severity.WARNING - ERROR_LEVEL -> if (useFutureError) Experimentality.Severity.FUTURE_ERROR else Experimentality.Severity.ERROR - else -> if (Experimentality.DEFAULT_SEVERITY == Experimentality.Severity.ERROR && useFutureError) { - Experimentality.Severity.FUTURE_ERROR + WARNING_LEVEL -> OptInDescription.Severity.WARNING + ERROR_LEVEL -> if (useFutureError) OptInDescription.Severity.FUTURE_ERROR else OptInDescription.Severity.ERROR + else -> if (OptInDescription.DEFAULT_SEVERITY == OptInDescription.Severity.ERROR && useFutureError) { + OptInDescription.Severity.FUTURE_ERROR } else { - Experimentality.DEFAULT_SEVERITY + OptInDescription.DEFAULT_SEVERITY } } val message = (arguments[MESSAGE] as? StringValue)?.value - return Experimentality(fqNameSafe, severity, message) + return OptInDescription(fqNameSafe, severity, message) } - private fun PsiElement.isExperimentalityAccepted(annotationFqName: FqName, context: CheckerContext): Boolean = - isExperimentalityAccepted(annotationFqName, context.languageVersionSettings, context.trace.bindingContext) + private fun PsiElement.isOptInAllowed(annotationFqName: FqName, context: CheckerContext): Boolean = + isOptInAllowed(annotationFqName, context.languageVersionSettings, context.trace.bindingContext) /** * Checks whether there's an element lexically above in the tree, annotated with `@UseExperimental(X::class)`, or a declaration * annotated with `@X` where [annotationFqName] is the FQ name of X */ - fun PsiElement.isExperimentalityAccepted( + fun PsiElement.isOptInAllowed( annotationFqName: FqName, languageVersionSettings: LanguageVersionSettings, bindingContext: BindingContext @@ -340,7 +340,7 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { // "-opt-in" arguments. However, it's not easy to do this. This should be solved in the future with the support of // module annotations. For now, we only check deprecations because this is needed to correctly retire unneeded compiler arguments. val deprecationResolver = DeprecationResolver( - LockBasedStorageManager("ExperimentalUsageChecker"), + LockBasedStorageManager("OptInUsageChecker"), languageVersionSettings, DeprecationSettings.Default ) @@ -353,7 +353,7 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { return false } - if (descriptor.loadExperimentalityForMarkerAnnotation() == null) { + if (descriptor.loadOptInForMarkerAnnotation() == null) { reportWarning("Class $fqName is not an opt-in requirement marker") return false } @@ -396,7 +396,7 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { is TypeAliasDescriptor -> targetDescriptor.classDescriptor else -> null } - if (targetClass != null && targetClass.loadExperimentalityForMarkerAnnotation() != null) { + if (targetClass != null && targetClass.loadOptInForMarkerAnnotation() != null) { if (!element.isUsageAsAnnotationOrImport() && !element.isUsageAsOptInArgument(context.trace.bindingContext) ) { @@ -407,16 +407,16 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { } if (element.getParentOfType(false) == null) { - val experimentalities = mutableSetOf() - experimentalities += targetDescriptor.loadExperimentalities(moduleAnnotationsResolver, context.languageVersionSettings) + val descriptions = mutableSetOf() + descriptions += targetDescriptor.loadOptIns(moduleAnnotationsResolver, context.languageVersionSettings) if (targetDescriptor is TypeAliasDescriptor) { - experimentalities.addAll( - targetDescriptor.expandedType.loadExperimentalities( + descriptions.addAll( + targetDescriptor.expandedType.loadOptIns( moduleAnnotationsResolver, context.languageVersionSettings, mutableSetOf(targetDescriptor) ) ) } - reportNotAcceptedExperimentalities(experimentalities, element, context) + reportNotAllowedOptIns(descriptions, element, context) } } @@ -466,27 +466,27 @@ class ExperimentalUsageChecker(project: Project) : CallChecker { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { if (descriptor !is CallableMemberDescriptor) return - val experimentalOverridden = descriptor.overriddenDescriptors.flatMap { member -> - member.loadExperimentalities(moduleAnnotationsResolver, context.languageVersionSettings) - .map { experimentality -> experimentality to member } + val optInOverriddenDescriptorMap = descriptor.overriddenDescriptors.flatMap { overriddenMember -> + overriddenMember.loadOptIns(moduleAnnotationsResolver, context.languageVersionSettings) + .map { description -> description to overriddenMember } }.toMap() - for ((experimentality, member) in experimentalOverridden) { - if (!declaration.isExperimentalityAccepted(experimentality.annotationFqName, context)) { + for ((description, overriddenMember) in optInOverriddenDescriptorMap) { + if (!declaration.isOptInAllowed(description.annotationFqName, context)) { val reportOn = (declaration as? KtNamedDeclaration)?.nameIdentifier ?: declaration - val (diagnostic, defaultMessageVerb) = when (experimentality.severity) { - Experimentality.Severity.WARNING -> Errors.OPT_IN_OVERRIDE to "should" - Experimentality.Severity.ERROR -> Errors.OPT_IN_OVERRIDE_ERROR to "must" - Experimentality.Severity.FUTURE_ERROR -> Errors.OPT_IN_OVERRIDE_ERROR to "must" + val (diagnostic, defaultMessageVerb) = when (description.severity) { + OptInDescription.Severity.WARNING -> Errors.OPT_IN_OVERRIDE to "should" + OptInDescription.Severity.ERROR -> Errors.OPT_IN_OVERRIDE_ERROR to "must" + OptInDescription.Severity.FUTURE_ERROR -> Errors.OPT_IN_OVERRIDE_ERROR to "must" } val message = OptInNames.buildOverrideMessage( - supertypeName = member.containingDeclaration.name.asString(), - markerMessage = experimentality.message, + supertypeName = overriddenMember.containingDeclaration.name.asString(), + markerMessage = description.message, verb = defaultMessageVerb, - markerName = experimentality.annotationFqName.asString() + markerName = description.annotationFqName.asString() ) - context.trace.report(diagnostic.on(reportOn, experimentality.annotationFqName, message)) + context.trace.report(diagnostic.on(reportOn, description.annotationFqName, message)) } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index 4edaabdedad..3512fc040e6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt @@ -35,7 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.util.getEffectiveExpectedType import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall -import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker +import org.jetbrains.kotlin.resolve.checkers.OptInUsageChecker import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.resolve.constants.evaluate.CompileTimeType.* import org.jetbrains.kotlin.resolve.descriptorUtil.classId @@ -322,12 +322,12 @@ class ConstantExpressionEvaluator( if (!UnsignedTypes.isUnsignedType(constantType)) return - with(ExperimentalUsageChecker) { + with(OptInUsageChecker) { val descriptor = constantType.constructor.declarationDescriptor ?: return - val experimentalities = descriptor.loadExperimentalities(moduleAnnotationsResolver, languageVersionSettings) + val optInDescriptions = descriptor.loadOptIns(moduleAnnotationsResolver, languageVersionSettings) - reportNotAcceptedExperimentalities( - experimentalities, expression, languageVersionSettings, trace, EXPERIMENTAL_UNSIGNED_LITERALS_DIAGNOSTICS + reportNotAllowedOptIns( + optInDescriptions, expression, languageVersionSettings, trace, EXPERIMENTAL_UNSIGNED_LITERALS_DIAGNOSTICS ) } } @@ -336,16 +336,16 @@ class ConstantExpressionEvaluator( private class ExperimentalityDiagnostic1( val factory: DiagnosticFactory1, val verb: String - ) : ExperimentalUsageChecker.ExperimentalityDiagnostic { + ) : OptInUsageChecker.OptInDiagnosticReporter { override fun report(trace: BindingTrace, element: PsiElement, fqName: FqName, message: String?) { - val defaultMessage = ExperimentalUsageChecker.getDefaultDiagnosticMessage( + val defaultMessage = OptInUsageChecker.getDefaultDiagnosticMessage( "Unsigned literals are experimental and their usages $verb be marked" ) trace.reportDiagnosticOnce(factory.on(element, defaultMessage(fqName))) } } - private val EXPERIMENTAL_UNSIGNED_LITERALS_DIAGNOSTICS = ExperimentalUsageChecker.ExperimentalityDiagnostics( + private val EXPERIMENTAL_UNSIGNED_LITERALS_DIAGNOSTICS = OptInUsageChecker.OptInReporterMultiplexer( warning = ExperimentalityDiagnostic1(Errors.EXPERIMENTAL_UNSIGNED_LITERALS, "should"), error = ExperimentalityDiagnostic1(Errors.EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "must"), futureError = ExperimentalityDiagnostic1(Errors.EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "must"), diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt index 1f7c5c8a2aa..0f892808bd3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.resolve.SinceKotlinAccessibility import org.jetbrains.kotlin.resolve.calls.checkers.isOperatorMod import org.jetbrains.kotlin.resolve.calls.checkers.shouldWarnAboutDeprecatedModFromBuiltIns import org.jetbrains.kotlin.resolve.checkSinceKotlinVersionAccessibility -import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker +import org.jetbrains.kotlin.resolve.checkers.OptInUsageChecker import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor @@ -115,9 +115,9 @@ class DeprecationResolver( if (sinceKotlinAccessibility is SinceKotlinAccessibility.NotAccessibleButWasExperimental) { return if (callElement != null && bindingContext != null) { - with(ExperimentalUsageChecker) { + with(OptInUsageChecker) { sinceKotlinAccessibility.markerClasses.any { classDescriptor -> - !callElement.isExperimentalityAccepted(classDescriptor.fqNameSafe, languageVersionSettings, bindingContext) + !callElement.isOptInAllowed(classDescriptor.fqNameSafe, languageVersionSettings, bindingContext) } } } else { diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/Experimentality.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/OptInDescription.kt similarity index 86% rename from core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/Experimentality.kt rename to core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/OptInDescription.kt index b4da1798664..253d99d3484 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/Experimentality.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/OptInDescription.kt @@ -8,7 +8,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?) { +data class OptInDescription(val annotationFqName: FqName, val severity: Severity, val message: String?) { enum class Severity { WARNING, ERROR, FUTURE_ERROR } companion object {