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, String> NEWER_VERSION_IN_SINCE_KOTLIN = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_API_USAGE = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_API_USAGE_ERROR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_API_USAGE = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_API_USAGE_ERROR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory2<PsiElement, FqName, DeclarationDescriptor> EXPERIMENTAL_OVERRIDE = DiagnosticFactory2.create(WARNING);
DiagnosticFactory2<PsiElement, FqName, DeclarationDescriptor> EXPERIMENTAL_OVERRIDE_ERROR = DiagnosticFactory2.create(ERROR);
DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_OVERRIDE = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_OVERRIDE_ERROR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> EXPERIMENTAL_IS_NOT_ENABLED = DiagnosticFactory0.create(WARNING);
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, String> EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_UNSIGNED_LITERALS = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_UNSIGNED_LITERALS_ERROR = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_UNSIGNED_LITERALS = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, String> EXPERIMENTAL_UNSIGNED_LITERALS_ERROR = DiagnosticFactory1.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(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_ERROR, "This declaration is experimental and its usage must be marked with ''@{0}'' or ''@OptIn({0}::class)''", TO_STRING);
MAP.put(EXPERIMENTAL_API_USAGE, "{0}", 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_ERROR, "This declaration overrides experimental member of supertype ''{1}'' and must be annotated with ''@{0}''", TO_STRING, NAME);
MAP.put(EXPERIMENTAL_OVERRIDE, "{0}", STRING);
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_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(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_ERROR, "Unsigned literals are experimental and their usages must be marked with ''@{0}'' or ''@OptIn({0}::class)''", TO_STRING);
MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS, "{0}", 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)");
@@ -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.EnumValue
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.DeprecationLevelValue
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
@@ -51,7 +52,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull
class ExperimentalUsageChecker(project: Project) : CallChecker {
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 }
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(
val warning: DiagnosticFactory1<PsiElement, FqName>,
val error: DiagnosticFactory1<PsiElement, FqName>
val warning: ExperimentalityDiagnostic,
val error: ExperimentalityDiagnostic
)
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")
private val LEVEL = Name.identifier("level")
private val MESSAGE = Name.identifier("message")
private val WARNING_LEVEL = Name.identifier("WARNING")
private val ERROR_LEVEL = Name.identifier("ERROR")
private val EXPERIMENTAL_API_DIAGNOSTICS = ExperimentalityDiagnostics(
Errors.EXPERIMENTAL_API_USAGE, Errors.EXPERIMENTAL_API_USAGE_ERROR
internal fun getDefaultDiagnosticMessage(prefix: String) = fun(fqName: FqName): String {
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(
experimentalities: Collection<Experimentality>, element: PsiElement, context: CheckerContext
) {
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,
diagnostics: ExperimentalityDiagnostics
) {
for ((annotationFqName, severity) in experimentalities) {
for ((annotationFqName, severity, message) in experimentalities) {
if (!element.isExperimentalityAccepted(annotationFqName, languageVersionSettings, trace.bindingContext)) {
val diagnostic = when (severity) {
Experimentality.Severity.WARNING -> diagnostics.warning
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)
?: 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
ERROR_LEVEL -> Experimentality.Severity.ERROR
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 =
@@ -344,12 +365,17 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
for ((experimentality, member) in experimentalOverridden) {
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
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 {
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
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER)
annotation class ExperimentalAPI
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER)
annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI
interface I
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI
interface I
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class API
@API
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class API
@API
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI
@@ -5,21 +5,21 @@ package api
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,
PROPERTY_GETTER, PROPERTY_SETTER, TYPE, TYPEALIAS)
annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(FILE)
annotation class E2
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
annotation class E3
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(FILE, EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
annotation class E4
@@ -5,21 +5,21 @@ package api
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,
PROPERTY_GETTER, PROPERTY_SETTER, TYPE, TYPEALIAS)
annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(FILE)<!>
annotation class E2
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(EXPRESSION)<!>
@Retention(AnnotationRetention.SOURCE)
annotation class E3
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(FILE, EXPRESSION)<!>
@Retention(AnnotationRetention.SOURCE)
annotation class E4
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E
open class Base {
@@ -3,7 +3,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E
open class Base {
@@ -1,8 +1,8 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E3
interface Base1 {
@@ -1,8 +1,8 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class E3
interface Base1 {
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI
@ExperimentalAPI
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER)
annotation class ExperimentalAPI
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS,
AnnotationTarget.VALUE_PARAMETER)
annotation class ExperimentalAPI
@@ -14,7 +14,7 @@ import kotlin.RequiresOptIn
// Usages with FQ names should be OK
@kotlin.RequiresOptIn(kotlin.RequiresOptIn.Level.ERROR)
@kotlin.RequiresOptIn(level = kotlin.RequiresOptIn.Level.ERROR)
annotation class M
@@ -14,7 +14,7 @@ import kotlin.RequiresOptIn
// Usages with FQ names should be OK
@kotlin.RequiresOptIn(kotlin.RequiresOptIn.Level.ERROR)
@kotlin.RequiresOptIn(level = kotlin.RequiresOptIn.Level.ERROR)
annotation class M
@@ -3,11 +3,11 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI1
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI2
@@ -3,11 +3,11 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI1
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
annotation class ExperimentalAPI2
@@ -3,11 +3,11 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI
@ExperimentalAPI
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class VeryExperimentalAPI
@ExperimentalAPI
@@ -3,11 +3,11 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalAPI
@ExperimentalAPI
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class VeryExperimentalAPI
@ExperimentalAPI
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.ERROR)
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
annotation class ExperimentalAPI
@ExperimentalAPI
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.ERROR)
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
annotation class ExperimentalAPI
@ExperimentalAPI
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS)
annotation class E
@@ -4,7 +4,7 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.CLASS)
annotation class E
@@ -3,15 +3,15 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
annotation class E2
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
annotation class E3
@@ -3,15 +3,15 @@
package api
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
annotation class E1
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
annotation class E2
@RequiresOptIn(RequiresOptIn.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Target(AnnotationTarget.FUNCTION)
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.
*
* 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.
*
* 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)
@Retention(BINARY)
@SinceKotlin("1.3")
@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
* 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.
* 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`.
*/
@@ -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 fun level ()Lkotlin/RequiresOptIn$Level;
public abstract fun message ()Ljava/lang/String;
}
public final class kotlin/RequiresOptIn$Level : java/lang/Enum {