Support custom message in RequiresOptIn

#KT-34648 Fixed
This commit is contained in:
Alexander Udalov
2019-12-18 19:22:38 +01:00
parent 9187a85aaf
commit f954a6c812
41 changed files with 124 additions and 82 deletions
@@ -255,11 +255,11 @@ public interface Errors {
DiagnosticFactory1<PsiElement, FqName> ILLEGAL_KOTLIN_VERSION_STRING_VALUE = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<PsiElement, FqName> ILLEGAL_KOTLIN_VERSION_STRING_VALUE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> NEWER_VERSION_IN_SINCE_KOTLIN = DiagnosticFactory1.create(WARNING); DiagnosticFactory1<PsiElement, String> NEWER_VERSION_IN_SINCE_KOTLIN = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_API_USAGE = DiagnosticFactory1.create(WARNING); DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_API_USAGE = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_API_USAGE_ERROR = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_API_USAGE_ERROR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory2<PsiElement, FqName, DeclarationDescriptor> EXPERIMENTAL_OVERRIDE = DiagnosticFactory2.create(WARNING); DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_OVERRIDE = DiagnosticFactory1.create(WARNING);
DiagnosticFactory2<PsiElement, FqName, DeclarationDescriptor> EXPERIMENTAL_OVERRIDE_ERROR = DiagnosticFactory2.create(ERROR); DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_OVERRIDE_ERROR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> EXPERIMENTAL_IS_NOT_ENABLED = DiagnosticFactory0.create(WARNING); DiagnosticFactory0<PsiElement> EXPERIMENTAL_IS_NOT_ENABLED = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<PsiElement> EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> EXPERIMENTAL_CAN_ONLY_BE_USED_AS_ANNOTATION = DiagnosticFactory0.create(ERROR);
@@ -270,8 +270,8 @@ public interface Errors {
DiagnosticFactory1<KtAnnotationEntry, FqName> USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER = DiagnosticFactory1.create(WARNING); DiagnosticFactory1<KtAnnotationEntry, FqName> USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<KtAnnotationEntry, String> EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<KtAnnotationEntry, String> EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_UNSIGNED_LITERALS = DiagnosticFactory1.create(WARNING); DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_UNSIGNED_LITERALS = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_UNSIGNED_LITERALS_ERROR = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_UNSIGNED_LITERALS_ERROR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES = DiagnosticFactory0.create(ERROR);
@@ -147,11 +147,11 @@ public class DefaultErrorMessages {
MAP.put(ILLEGAL_KOTLIN_VERSION_STRING_VALUE, "Invalid @{0} annotation value (should be ''major.minor'' or ''major.minor.patch'')", TO_STRING); MAP.put(ILLEGAL_KOTLIN_VERSION_STRING_VALUE, "Invalid @{0} annotation value (should be ''major.minor'' or ''major.minor.patch'')", TO_STRING);
MAP.put(NEWER_VERSION_IN_SINCE_KOTLIN, "The version is greater than the specified API version {0}", STRING); MAP.put(NEWER_VERSION_IN_SINCE_KOTLIN, "The version is greater than the specified API version {0}", STRING);
MAP.put(EXPERIMENTAL_API_USAGE, "This declaration is experimental and its usage should be marked with ''@{0}'' or ''@OptIn({0}::class)''", TO_STRING); MAP.put(EXPERIMENTAL_API_USAGE, "{0}", STRING);
MAP.put(EXPERIMENTAL_API_USAGE_ERROR, "This declaration is experimental and its usage must be marked with ''@{0}'' or ''@OptIn({0}::class)''", TO_STRING); MAP.put(EXPERIMENTAL_API_USAGE_ERROR, "{0}", STRING);
MAP.put(EXPERIMENTAL_OVERRIDE, "This declaration overrides experimental member of supertype ''{1}'' and should be annotated with ''@{0}''", TO_STRING, NAME); MAP.put(EXPERIMENTAL_OVERRIDE, "{0}", STRING);
MAP.put(EXPERIMENTAL_OVERRIDE_ERROR, "This declaration overrides experimental member of supertype ''{1}'' and must be annotated with ''@{0}''", TO_STRING, NAME); MAP.put(EXPERIMENTAL_OVERRIDE_ERROR, "{0}", STRING);
MAP.put(EXPERIMENTAL_IS_NOT_ENABLED, "This class can only be used with the compiler argument '-Xopt-in=kotlin.RequiresOptIn'"); 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_CAN_ONLY_BE_USED_AS_ANNOTATION, "This class can only be used as an annotation");
@@ -161,8 +161,8 @@ public class DefaultErrorMessages {
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(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_TARGET, "Opt-in requirement marker annotation cannot be used on the following code elements: {0}. Please remove these targets", STRING);
MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS, "Unsigned literals are experimental and their usages should be marked with ''@{0}'' or ''@OptIn({0}::class)''", TO_STRING); MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS, "{0}", STRING);
MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "Unsigned literals are experimental and their usages must be marked with ''@{0}'' or ''@OptIn({0}::class)''", TO_STRING); MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "{0}", STRING);
MAP.put(NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES, "Non-parenthesized annotations on function types without receiver aren't yet supported (see KT-31734 for details)"); MAP.put(NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES, "Non-parenthesized annotations on function types without receiver aren't yet supported (see KT-31734 for details)");
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.constants.ArrayValue import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.constants.KClassValue import org.jetbrains.kotlin.resolve.constants.KClassValue
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
@@ -51,7 +52,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull
class ExperimentalUsageChecker(project: Project) : CallChecker { class ExperimentalUsageChecker(project: Project) : CallChecker {
private val moduleAnnotationsResolver = ModuleAnnotationsResolver.getInstance(project) private val moduleAnnotationsResolver = ModuleAnnotationsResolver.getInstance(project)
data class Experimentality(val annotationFqName: FqName, val severity: Severity) { data class Experimentality(val annotationFqName: FqName, val severity: Severity, val message: String?) {
enum class Severity { WARNING, ERROR } enum class Severity { WARNING, ERROR }
companion object { companion object {
@@ -59,9 +60,14 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
} }
} }
class ExperimentalityDiagnostic(
val factory: DiagnosticFactory1<PsiElement, String>,
val defaultMessage: (FqName) -> String
)
data class ExperimentalityDiagnostics( data class ExperimentalityDiagnostics(
val warning: DiagnosticFactory1<PsiElement, FqName>, val warning: ExperimentalityDiagnostic,
val error: DiagnosticFactory1<PsiElement, FqName> val error: ExperimentalityDiagnostic
) )
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
@@ -84,18 +90,30 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
internal val WAS_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass") internal val WAS_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass")
private val LEVEL = Name.identifier("level") private val LEVEL = Name.identifier("level")
private val MESSAGE = Name.identifier("message")
private val WARNING_LEVEL = Name.identifier("WARNING") private val WARNING_LEVEL = Name.identifier("WARNING")
private val ERROR_LEVEL = Name.identifier("ERROR") private val ERROR_LEVEL = Name.identifier("ERROR")
private val EXPERIMENTAL_API_DIAGNOSTICS = ExperimentalityDiagnostics( internal fun getDefaultDiagnosticMessage(prefix: String) = fun(fqName: FqName): String {
Errors.EXPERIMENTAL_API_USAGE, Errors.EXPERIMENTAL_API_USAGE_ERROR return "$prefix with '@${fqName.asString()}' or '@OptIn(${fqName.asString()}::class)'"
}
private val USAGE_DIAGNOSTICS = ExperimentalityDiagnostics(
warning = ExperimentalityDiagnostic(
Errors.EXPERIMENTAL_API_USAGE,
getDefaultDiagnosticMessage("This declaration is experimental and its usage should be marked")
),
error = ExperimentalityDiagnostic(
Errors.EXPERIMENTAL_API_USAGE_ERROR,
getDefaultDiagnosticMessage("This declaration is experimental and its usage must be marked")
)
) )
fun reportNotAcceptedExperimentalities( fun reportNotAcceptedExperimentalities(
experimentalities: Collection<Experimentality>, element: PsiElement, context: CheckerContext experimentalities: Collection<Experimentality>, element: PsiElement, context: CheckerContext
) { ) {
reportNotAcceptedExperimentalities( reportNotAcceptedExperimentalities(
experimentalities, element, context.languageVersionSettings, context.trace, EXPERIMENTAL_API_DIAGNOSTICS experimentalities, element, context.languageVersionSettings, context.trace, USAGE_DIAGNOSTICS
) )
} }
@@ -106,13 +124,13 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
trace: BindingTrace, trace: BindingTrace,
diagnostics: ExperimentalityDiagnostics diagnostics: ExperimentalityDiagnostics
) { ) {
for ((annotationFqName, severity) in experimentalities) { for ((annotationFqName, severity, message) in experimentalities) {
if (!element.isExperimentalityAccepted(annotationFqName, languageVersionSettings, trace.bindingContext)) { if (!element.isExperimentalityAccepted(annotationFqName, languageVersionSettings, trace.bindingContext)) {
val diagnostic = when (severity) { val diagnostic = when (severity) {
Experimentality.Severity.WARNING -> diagnostics.warning Experimentality.Severity.WARNING -> diagnostics.warning
Experimentality.Severity.ERROR -> diagnostics.error Experimentality.Severity.ERROR -> diagnostics.error
} }
trace.reportDiagnosticOnce(diagnostic.on(element, annotationFqName)) trace.reportDiagnosticOnce(diagnostic.factory.on(element, message ?: diagnostic.defaultMessage(annotationFqName)))
} }
} }
} }
@@ -153,13 +171,16 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
?: annotations.findAnnotation(OLD_EXPERIMENTAL_FQ_NAME) ?: annotations.findAnnotation(OLD_EXPERIMENTAL_FQ_NAME)
?: return null ?: return null
val severity = when ((experimental.allValueArguments[LEVEL] as? EnumValue)?.enumEntryName) { val arguments = experimental.allValueArguments
val severity = when ((arguments[LEVEL] as? EnumValue)?.enumEntryName) {
WARNING_LEVEL -> Experimentality.Severity.WARNING WARNING_LEVEL -> Experimentality.Severity.WARNING
ERROR_LEVEL -> Experimentality.Severity.ERROR ERROR_LEVEL -> Experimentality.Severity.ERROR
else -> Experimentality.DEFAULT_SEVERITY else -> Experimentality.DEFAULT_SEVERITY
} }
return Experimentality(fqNameSafe, severity) val message = (arguments[MESSAGE] as? StringValue)?.value
return Experimentality(fqNameSafe, severity, message)
} }
private fun PsiElement.isExperimentalityAccepted(annotationFqName: FqName, context: CheckerContext): Boolean = private fun PsiElement.isExperimentalityAccepted(annotationFqName: FqName, context: CheckerContext): Boolean =
@@ -344,12 +365,17 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
for ((experimentality, member) in experimentalOverridden) { for ((experimentality, member) in experimentalOverridden) {
if (!declaration.isExperimentalityAccepted(experimentality.annotationFqName, context)) { if (!declaration.isExperimentalityAccepted(experimentality.annotationFqName, context)) {
val diagnostic = when (experimentality.severity) {
Experimentality.Severity.WARNING -> Errors.EXPERIMENTAL_OVERRIDE
Experimentality.Severity.ERROR -> Errors.EXPERIMENTAL_OVERRIDE_ERROR
}
val reportOn = (declaration as? KtNamedDeclaration)?.nameIdentifier ?: declaration val reportOn = (declaration as? KtNamedDeclaration)?.nameIdentifier ?: declaration
context.trace.report(diagnostic.on(reportOn, experimentality.annotationFqName, member.containingDeclaration))
val (diagnostic, defaultMessageVerb) = when (experimentality.severity) {
Experimentality.Severity.WARNING -> Errors.EXPERIMENTAL_OVERRIDE to "should"
Experimentality.Severity.ERROR -> Errors.EXPERIMENTAL_OVERRIDE_ERROR to "must"
}
val message = experimentality.message
?: "This declaration overrides experimental member of supertype " +
"'${member.containingDeclaration.name.asString()}' and $defaultMessageVerb be annotated " +
"with '@${experimentality.annotationFqName.asString()}'"
context.trace.report(diagnostic.on(reportOn, message))
} }
} }
} }
@@ -319,7 +319,14 @@ class ConstantExpressionEvaluator(
companion object { companion object {
private val EXPERIMENTAL_UNSIGNED_LITERALS_DIAGNOSTICS = ExperimentalUsageChecker.ExperimentalityDiagnostics( private val EXPERIMENTAL_UNSIGNED_LITERALS_DIAGNOSTICS = ExperimentalUsageChecker.ExperimentalityDiagnostics(
Errors.EXPERIMENTAL_UNSIGNED_LITERALS, Errors.EXPERIMENTAL_UNSIGNED_LITERALS_ERROR warning = ExperimentalUsageChecker.ExperimentalityDiagnostic(
Errors.EXPERIMENTAL_UNSIGNED_LITERALS,
ExperimentalUsageChecker.getDefaultDiagnosticMessage("Unsigned literals are experimental and their usages should be marked")
),
error = ExperimentalUsageChecker.ExperimentalityDiagnostic(
Errors.EXPERIMENTAL_UNSIGNED_LITERALS_ERROR,
ExperimentalUsageChecker.getDefaultDiagnosticMessage("Unsigned literals are experimental and their usages must be marked")
)
) )
@JvmStatic @JvmStatic
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, @Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER) AnnotationTarget.VALUE_PARAMETER)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, @Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER) AnnotationTarget.VALUE_PARAMETER)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI annotation class ExperimentalAPI
interface I interface I
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI annotation class ExperimentalAPI
interface I interface I
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class API annotation class API
@API @API
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class API annotation class API
@API @API
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) @Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) @Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -5,21 +5,21 @@ package api
import kotlin.annotation.AnnotationTarget.* import kotlin.annotation.AnnotationTarget.*
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(CLASS, ANNOTATION_CLASS, TYPE_PARAMETER, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION, @Target(CLASS, ANNOTATION_CLASS, TYPE_PARAMETER, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION,
PROPERTY_GETTER, PROPERTY_SETTER, TYPE, TYPEALIAS) PROPERTY_GETTER, PROPERTY_SETTER, TYPE, TYPEALIAS)
annotation class E1 annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(FILE) @Target(FILE)
annotation class E2 annotation class E2
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(EXPRESSION) @Target(EXPRESSION)
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)
annotation class E3 annotation class E3
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(FILE, EXPRESSION) @Target(FILE, EXPRESSION)
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)
annotation class E4 annotation class E4
@@ -5,21 +5,21 @@ package api
import kotlin.annotation.AnnotationTarget.* import kotlin.annotation.AnnotationTarget.*
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(CLASS, ANNOTATION_CLASS, TYPE_PARAMETER, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION, @Target(CLASS, ANNOTATION_CLASS, TYPE_PARAMETER, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION,
PROPERTY_GETTER, PROPERTY_SETTER, TYPE, TYPEALIAS) PROPERTY_GETTER, PROPERTY_SETTER, TYPE, TYPEALIAS)
annotation class E1 annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(FILE)<!> <!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(FILE)<!>
annotation class E2 annotation class E2
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(EXPRESSION)<!> <!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(EXPRESSION)<!>
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)
annotation class E3 annotation class E3
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(FILE, EXPRESSION)<!> <!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(FILE, EXPRESSION)<!>
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)
annotation class E4 annotation class E4
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E annotation class E
open class Base { open class Base {
@@ -3,7 +3,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E annotation class E
open class Base { open class Base {
@@ -1,8 +1,8 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn // !USE_EXPERIMENTAL: kotlin.RequiresOptIn
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E1 annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E3 annotation class E3
interface Base1 { interface Base1 {
@@ -1,8 +1,8 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn // !USE_EXPERIMENTAL: kotlin.RequiresOptIn
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E1 annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E3 annotation class E3
interface Base1 { interface Base1 {
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@ExperimentalAPI @ExperimentalAPI
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, @Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER) AnnotationTarget.VALUE_PARAMETER)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, @Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER) AnnotationTarget.VALUE_PARAMETER)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@@ -14,7 +14,7 @@ import kotlin.RequiresOptIn
// Usages with FQ names should be OK // Usages with FQ names should be OK
@kotlin.RequiresOptIn(kotlin.RequiresOptIn.Level.ERROR) @kotlin.RequiresOptIn(level = kotlin.RequiresOptIn.Level.ERROR)
annotation class M annotation class M
@@ -14,7 +14,7 @@ import kotlin.RequiresOptIn
// Usages with FQ names should be OK // Usages with FQ names should be OK
@kotlin.RequiresOptIn(kotlin.RequiresOptIn.Level.ERROR) @kotlin.RequiresOptIn(level = kotlin.RequiresOptIn.Level.ERROR)
annotation class M annotation class M
@@ -3,11 +3,11 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI1 annotation class ExperimentalAPI1
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI2 annotation class ExperimentalAPI2
@@ -3,11 +3,11 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI1 annotation class ExperimentalAPI1
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI2 annotation class ExperimentalAPI2
@@ -3,11 +3,11 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@ExperimentalAPI @ExperimentalAPI
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class VeryExperimentalAPI annotation class VeryExperimentalAPI
@ExperimentalAPI @ExperimentalAPI
@@ -3,11 +3,11 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@ExperimentalAPI @ExperimentalAPI
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class VeryExperimentalAPI annotation class VeryExperimentalAPI
@ExperimentalAPI @ExperimentalAPI
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.ERROR) @RequiresOptIn(level = RequiresOptIn.Level.ERROR)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@ExperimentalAPI @ExperimentalAPI
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.ERROR) @RequiresOptIn(level = RequiresOptIn.Level.ERROR)
annotation class ExperimentalAPI annotation class ExperimentalAPI
@ExperimentalAPI @ExperimentalAPI
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
annotation class E annotation class E
@@ -4,7 +4,7 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
annotation class E annotation class E
@@ -3,15 +3,15 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class E1 annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class E2 annotation class E2
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class E3 annotation class E3
@@ -3,15 +3,15 @@
package api package api
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class E1 annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class E2 annotation class E2
@RequiresOptIn(RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FUNCTION)
annotation class E3 annotation class E3
@@ -15,16 +15,24 @@ import kotlin.reflect.KClass
/** /**
* Signals that the annotated annotation class is a marker of an API that requires an explicit opt-in. * Signals that the annotated annotation class is a marker of an API that requires an explicit opt-in.
* *
* Call sites of any declaration annotated with that marker should opt-in to the API either by using [OptIn], * Call sites of any declaration annotated with that marker should opt in to the API either by using [OptIn],
* or by being annotated with that marker themselves, effectively causing further propagation of the opt-in requirement. * or by being annotated with that marker themselves, effectively causing further propagation of the opt-in requirement.
* *
* This class requires opt-in itself and can only be used with the compiler argument `-Xopt-in=kotlin.RequiresOptIn`. * This class requires opt-in itself and can only be used with the compiler argument `-Xopt-in=kotlin.RequiresOptIn`.
*
* @property message message to be reported on usages of API without an explicit opt-in, or empty string for the default message.
* The default message is: "This declaration is experimental and its usage should be marked with 'Marker'
* or '@OptIn(Marker::class)'", where `Marker` is the opt-in requirement marker.
* @property level specifies how usages of API without an explicit opt-in are reported in code.
*/ */
@Target(ANNOTATION_CLASS) @Target(ANNOTATION_CLASS)
@Retention(BINARY) @Retention(BINARY)
@SinceKotlin("1.3") @SinceKotlin("1.3")
@RequireKotlin("1.3.70", versionKind = RequireKotlinVersionKind.COMPILER_VERSION) @RequireKotlin("1.3.70", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
public annotation class RequiresOptIn(val level: Level = Level.ERROR) { public annotation class RequiresOptIn(
val message: String = "",
val level: Level = Level.ERROR
) {
/** /**
* Severity of the diagnostic that should be reported on usages which did not explicitly opted into * Severity of the diagnostic that should be reported on usages which did not explicitly opted into
* the API either by using [OptIn] or by being annotated with the corresponding marker annotation. * the API either by using [OptIn] or by being annotated with the corresponding marker annotation.
@@ -40,7 +48,7 @@ public annotation class RequiresOptIn(val level: Level = Level.ERROR) {
/** /**
* Allows to use the API denoted by the given markers in the annotated file, declaration, or expression. * Allows to use the API denoted by the given markers in the annotated file, declaration, or expression.
* If a declaration is annotated with [OptIn], its usages are **not** required to opt-in to that API. * If a declaration is annotated with [OptIn], its usages are **not** required to opt in to that API.
* *
* This class requires opt-in itself and can only be used with the compiler argument `-Xopt-in=kotlin.RequiresOptIn`. * This class requires opt-in itself and can only be used with the compiler argument `-Xopt-in=kotlin.RequiresOptIn`.
*/ */
@@ -160,6 +160,7 @@ public abstract interface annotation class kotlin/ReplaceWith : java/lang/annota
public abstract interface annotation class kotlin/RequiresOptIn : java/lang/annotation/Annotation { public abstract interface annotation class kotlin/RequiresOptIn : java/lang/annotation/Annotation {
public abstract fun level ()Lkotlin/RequiresOptIn$Level; public abstract fun level ()Lkotlin/RequiresOptIn$Level;
public abstract fun message ()Ljava/lang/String;
} }
public final class kotlin/RequiresOptIn$Level : java/lang/Enum { public final class kotlin/RequiresOptIn$Level : java/lang/Enum {