Add some validation for Experimental/UseExperimental usages
#KT-22759 In Progress
This commit is contained in:
@@ -229,6 +229,12 @@ public interface Errors {
|
|||||||
DiagnosticFactory2<PsiElement, FqName, Boolean> EXPERIMENTAL_API_USAGE = DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory2<PsiElement, FqName, Boolean> EXPERIMENTAL_API_USAGE = DiagnosticFactory2.create(WARNING);
|
||||||
DiagnosticFactory2<PsiElement, FqName, Boolean> EXPERIMENTAL_API_USAGE_ERROR = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<PsiElement, FqName, Boolean> EXPERIMENTAL_API_USAGE_ERROR = DiagnosticFactory2.create(ERROR);
|
||||||
|
|
||||||
|
DiagnosticFactory0<KtAnnotationEntry> USE_EXPERIMENTAL_WITHOUT_ARGUMENTS = DiagnosticFactory0.create(WARNING);
|
||||||
|
DiagnosticFactory1<KtAnnotationEntry, FqName> USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER = DiagnosticFactory1.create(WARNING);
|
||||||
|
DiagnosticFactory1<KtAnnotationEntry, FqName> USE_EXPERIMENTAL_ARGUMENT_HAS_NON_COMPILATION_IMPACT = DiagnosticFactory1.create(ERROR);
|
||||||
|
DiagnosticFactory0<KtAnnotationEntry> EXPERIMENTAL_ANNOTATION_WITH_NO_IMPACT = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory1<KtAnnotationEntry, String> EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET = DiagnosticFactory1.create(ERROR);
|
||||||
|
|
||||||
// Const
|
// Const
|
||||||
DiagnosticFactory0<PsiElement> CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> CONST_VAL_WITH_GETTER = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> CONST_VAL_WITH_GETTER = DiagnosticFactory0.create(ERROR);
|
||||||
|
|||||||
+7
@@ -151,6 +151,13 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(EXPERIMENTAL_API_USAGE, "This declaration is experimental and its usage should be marked with ''@{0}''{1}", TO_STRING, renderUseExperimental);
|
MAP.put(EXPERIMENTAL_API_USAGE, "This declaration is experimental and its usage should be marked with ''@{0}''{1}", TO_STRING, renderUseExperimental);
|
||||||
MAP.put(EXPERIMENTAL_API_USAGE_ERROR, "This declaration is experimental and its usage must be marked with ''@{0}''{1}", TO_STRING, renderUseExperimental);
|
MAP.put(EXPERIMENTAL_API_USAGE_ERROR, "This declaration is experimental and its usage must be marked with ''@{0}''{1}", TO_STRING, renderUseExperimental);
|
||||||
|
|
||||||
|
MAP.put(USE_EXPERIMENTAL_WITHOUT_ARGUMENTS, "@UseExperimental without any arguments has no effect");
|
||||||
|
MAP.put(USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER, "Annotation ''{0}'' is not an experimental API marker, therefore its usage in @UseExperimental is ignored", TO_STRING);
|
||||||
|
MAP.put(USE_EXPERIMENTAL_ARGUMENT_HAS_NON_COMPILATION_IMPACT,
|
||||||
|
"Experimental annotation ''{0}'' has impact other than COMPILATION, therefore its usage in @UseExperimental is forbidden", TO_STRING);
|
||||||
|
MAP.put(EXPERIMENTAL_ANNOTATION_WITH_NO_IMPACT, "Experimental annotation with changesMayBreak = [] is not allowed");
|
||||||
|
MAP.put(EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET, "Experimental annotation cannot be used on the following code elements: {0}. Please remove these targets", STRING);
|
||||||
|
|
||||||
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
|
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
|
||||||
MAP.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members");
|
MAP.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members");
|
||||||
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
|
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ 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.descriptors.annotations.KotlinTarget.*
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.*
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
|
import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
|
||||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||||
@@ -193,6 +194,8 @@ class AnnotationChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val TARGET_ALLOWED_TARGETS = Name.identifier("allowedTargets")
|
||||||
|
|
||||||
private fun applicableTargetSet(entry: KtAnnotationEntry, trace: BindingTrace): Set<KotlinTarget> {
|
private fun applicableTargetSet(entry: KtAnnotationEntry, trace: BindingTrace): Set<KotlinTarget> {
|
||||||
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET
|
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET
|
||||||
// For descriptor with error type, all targets are considered as possible
|
// For descriptor with error type, all targets are considered as possible
|
||||||
@@ -207,10 +210,12 @@ class AnnotationChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun applicableTargetSet(classDescriptor: ClassDescriptor): Set<KotlinTarget>? {
|
fun applicableTargetSet(classDescriptor: ClassDescriptor): Set<KotlinTarget>? {
|
||||||
val targetEntryDescriptor = classDescriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.target)
|
val targetEntryDescriptor = classDescriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.target) ?: return null
|
||||||
?: return null
|
return loadAnnotationTargets(targetEntryDescriptor)
|
||||||
val valueArguments = targetEntryDescriptor.allValueArguments
|
}
|
||||||
val valueArgument = valueArguments.entries.firstOrNull()?.value as? ArrayValue ?: return null
|
|
||||||
|
fun loadAnnotationTargets(targetEntryDescriptor: AnnotationDescriptor): Set<KotlinTarget>? {
|
||||||
|
val valueArgument = targetEntryDescriptor.allValueArguments[TARGET_ALLOWED_TARGETS] as? ArrayValue ?: return null
|
||||||
return valueArgument.value.filterIsInstance<EnumValue>().mapNotNull {
|
return valueArgument.value.filterIsInstance<EnumValue>().mapNotNull {
|
||||||
KotlinTarget.valueOrNull(it.enumEntryName.asString())
|
KotlinTarget.valueOrNull(it.enumEntryName.asString())
|
||||||
}.toSet()
|
}.toSet()
|
||||||
|
|||||||
@@ -98,7 +98,9 @@ private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(
|
|||||||
DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker, MissingDependencyClassChecker.ClassifierUsage,
|
DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker, MissingDependencyClassChecker.ClassifierUsage,
|
||||||
ExperimentalUsageChecker.ClassifierUsage
|
ExperimentalUsageChecker.ClassifierUsage
|
||||||
)
|
)
|
||||||
private val DEFAULT_ANNOTATION_CHECKERS = emptyList<AdditionalAnnotationChecker>()
|
private val DEFAULT_ANNOTATION_CHECKERS = listOf<AdditionalAnnotationChecker>(
|
||||||
|
ExperimentalMarkerDeclarationAnnotationChecker
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
abstract class PlatformConfigurator(
|
abstract class PlatformConfigurator(
|
||||||
|
|||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.checkers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
|
import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
|
||||||
|
object ExperimentalMarkerDeclarationAnnotationChecker : AdditionalAnnotationChecker {
|
||||||
|
private val WRONG_TARGETS_FOR_MARKER = setOf(KotlinTarget.EXPRESSION, KotlinTarget.FILE)
|
||||||
|
|
||||||
|
override fun checkEntries(entries: List<KtAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
|
||||||
|
var isAnnotatedWithExperimental = false
|
||||||
|
|
||||||
|
for (entry in entries) {
|
||||||
|
val annotation = trace.bindingContext.get(BindingContext.ANNOTATION, entry)
|
||||||
|
when (annotation?.fqName) {
|
||||||
|
ExperimentalUsageChecker.USE_EXPERIMENTAL_FQ_NAME -> {
|
||||||
|
val annotationClasses =
|
||||||
|
(annotation.allValueArguments[ExperimentalUsageChecker.USE_EXPERIMENTAL_ANNOTATION_CLASS] as? ArrayValue)?.value.orEmpty()
|
||||||
|
checkUseExperimentalUsage(annotationClasses, trace, entry)
|
||||||
|
}
|
||||||
|
ExperimentalUsageChecker.EXPERIMENTAL_FQ_NAME -> {
|
||||||
|
val impact = (annotation.allValueArguments[ExperimentalUsageChecker.IMPACT] as? ArrayValue)?.value
|
||||||
|
checkExperimentalUsage(impact, trace, entry)
|
||||||
|
isAnnotatedWithExperimental = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAnnotatedWithExperimental) {
|
||||||
|
checkMarkerTargets(entries, trace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkUseExperimentalUsage(annotationClasses: List<ConstantValue<*>>, trace: BindingTrace, entry: KtAnnotationEntry) {
|
||||||
|
if (annotationClasses.isEmpty()) {
|
||||||
|
trace.report(Errors.USE_EXPERIMENTAL_WITHOUT_ARGUMENTS.on(entry))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (annotationClass in annotationClasses) {
|
||||||
|
val classDescriptor =
|
||||||
|
(annotationClass as? KClassValue)?.value?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||||
|
?: continue
|
||||||
|
val experimentality = with(ExperimentalUsageChecker) {
|
||||||
|
classDescriptor.loadExperimentalityForMarkerAnnotation()
|
||||||
|
}
|
||||||
|
if (experimentality == null) {
|
||||||
|
trace.report(Errors.USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER.on(entry, classDescriptor.fqNameSafe))
|
||||||
|
} else if (!experimentality.isCompilationOnly) {
|
||||||
|
trace.report(Errors.USE_EXPERIMENTAL_ARGUMENT_HAS_NON_COMPILATION_IMPACT.on(entry, experimentality.annotationFqName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkExperimentalUsage(impact: List<ConstantValue<*>>?, trace: BindingTrace, entry: KtAnnotationEntry) {
|
||||||
|
if (impact != null && impact.isEmpty()) {
|
||||||
|
trace.report(Errors.EXPERIMENTAL_ANNOTATION_WITH_NO_IMPACT.on(entry))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkMarkerTargets(entries: List<KtAnnotationEntry>, trace: BindingTrace) {
|
||||||
|
val targetEntry =
|
||||||
|
entries.associate { entry -> entry to trace.bindingContext.get(BindingContext.ANNOTATION, entry) }
|
||||||
|
.entries
|
||||||
|
.firstOrNull { (_, descriptor) -> descriptor != null && descriptor.fqName == KotlinBuiltIns.FQ_NAMES.target }
|
||||||
|
?: return
|
||||||
|
val (entry, descriptor) = targetEntry
|
||||||
|
val allowedTargets = AnnotationChecker.loadAnnotationTargets(descriptor!!) ?: return
|
||||||
|
val wrongTargets = allowedTargets.intersect(WRONG_TARGETS_FOR_MARKER)
|
||||||
|
if (wrongTargets.isNotEmpty()) {
|
||||||
|
trace.report(
|
||||||
|
Errors.EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET.on(entry, wrongTargets.joinToString(transform = KotlinTarget::description))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-12
@@ -41,20 +41,20 @@ import org.jetbrains.kotlin.utils.SmartSet
|
|||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
object ExperimentalUsageChecker : CallChecker {
|
object ExperimentalUsageChecker : CallChecker {
|
||||||
private val EXPERIMENTAL_FQ_NAME = FqName("kotlin.Experimental")
|
internal val EXPERIMENTAL_FQ_NAME = FqName("kotlin.Experimental")
|
||||||
private val USE_EXPERIMENTAL_FQ_NAME = FqName("kotlin.UseExperimental")
|
internal val USE_EXPERIMENTAL_FQ_NAME = FqName("kotlin.UseExperimental")
|
||||||
private val USE_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass")
|
internal val USE_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass")
|
||||||
|
|
||||||
private val LEVEL = Name.identifier("level")
|
private val LEVEL = Name.identifier("level")
|
||||||
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 IMPACT = Name.identifier("changesMayBreak")
|
internal val IMPACT = Name.identifier("changesMayBreak")
|
||||||
private val COMPILATION_IMPACT = Name.identifier("COMPILATION")
|
private val COMPILATION_IMPACT = Name.identifier("COMPILATION")
|
||||||
private val LINKAGE_IMPACT = Name.identifier("LINKAGE")
|
private val LINKAGE_IMPACT = Name.identifier("LINKAGE")
|
||||||
private val RUNTIME_IMPACT = Name.identifier("RUNTIME")
|
private val RUNTIME_IMPACT = Name.identifier("RUNTIME")
|
||||||
|
|
||||||
private data class Experimentality(val annotationFqName: FqName, val severity: Severity, val impact: List<Impact>) {
|
internal data class Experimentality(val annotationFqName: FqName, val severity: Severity, private val impact: List<Impact>) {
|
||||||
val isCompilationOnly: Boolean get() = impact.all(Impact.COMPILATION::equals)
|
val isCompilationOnly: Boolean get() = impact.all(Impact.COMPILATION::equals)
|
||||||
|
|
||||||
enum class Severity { WARNING, ERROR }
|
enum class Severity { WARNING, ERROR }
|
||||||
@@ -72,7 +72,7 @@ object ExperimentalUsageChecker : CallChecker {
|
|||||||
|
|
||||||
private fun checkExperimental(descriptor: DeclarationDescriptor, element: PsiElement, trace: BindingTrace) {
|
private fun checkExperimental(descriptor: DeclarationDescriptor, element: PsiElement, trace: BindingTrace) {
|
||||||
for (experimentality in descriptor.loadExperimentalities()) {
|
for (experimentality in descriptor.loadExperimentalities()) {
|
||||||
val (annotationFqName, severity, impact) = experimentality
|
val (annotationFqName, severity) = experimentality
|
||||||
val isBodyUsageOfCompilationExperimentality =
|
val isBodyUsageOfCompilationExperimentality =
|
||||||
experimentality.isCompilationOnly && element.isBodyUsage()
|
experimentality.isCompilationOnly && element.isBodyUsage()
|
||||||
|
|
||||||
@@ -95,22 +95,21 @@ object ExperimentalUsageChecker : CallChecker {
|
|||||||
val result = SmartSet.create<Experimentality>()
|
val result = SmartSet.create<Experimentality>()
|
||||||
|
|
||||||
for (annotation in annotations) {
|
for (annotation in annotations) {
|
||||||
result.addIfNotNull(annotation.loadExperimentalityForMarkerAnnotation())
|
result.addIfNotNull(annotation.annotationClass?.loadExperimentalityForMarkerAnnotation())
|
||||||
}
|
}
|
||||||
|
|
||||||
val container = containingDeclaration
|
val container = containingDeclaration
|
||||||
if (container is ClassDescriptor && this !is ConstructorDescriptor) {
|
if (container is ClassDescriptor && this !is ConstructorDescriptor) {
|
||||||
for (annotation in container.annotations) {
|
for (annotation in container.annotations) {
|
||||||
result.addIfNotNull(annotation.loadExperimentalityForMarkerAnnotation())
|
result.addIfNotNull(annotation.annotationClass?.loadExperimentalityForMarkerAnnotation())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AnnotationDescriptor.loadExperimentalityForMarkerAnnotation(): Experimentality? {
|
internal fun ClassDescriptor.loadExperimentalityForMarkerAnnotation(): Experimentality? {
|
||||||
val experimental = annotationClass?.annotations?.findAnnotation(EXPERIMENTAL_FQ_NAME) ?: return null
|
val experimental = annotations.findAnnotation(EXPERIMENTAL_FQ_NAME) ?: return null
|
||||||
val annotationFqName = fqName ?: return null
|
|
||||||
|
|
||||||
val severity = when ((experimental.allValueArguments[LEVEL] as? EnumValue)?.enumEntryName) {
|
val severity = when ((experimental.allValueArguments[LEVEL] as? EnumValue)?.enumEntryName) {
|
||||||
WARNING_LEVEL -> Experimentality.Severity.WARNING
|
WARNING_LEVEL -> Experimentality.Severity.WARNING
|
||||||
@@ -126,7 +125,7 @@ object ExperimentalUsageChecker : CallChecker {
|
|||||||
}
|
}
|
||||||
} ?: Experimentality.DEFAULT_IMPACT
|
} ?: Experimentality.DEFAULT_IMPACT
|
||||||
|
|
||||||
return Experimentality(annotationFqName, severity, impact)
|
return Experimentality(fqNameSafe, severity, impact)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if this element appears in the body of some function and is not visible in any non-local declaration signature.
|
// Returns true if this element appears in the body of some function and is not visible in any non-local declaration signature.
|
||||||
@@ -189,4 +188,5 @@ object ExperimentalUsageChecker : CallChecker {
|
|||||||
checkExperimental(targetDescriptor, element, context.trace)
|
checkExperimental(targetDescriptor, element, context.trace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ package api
|
|||||||
|
|
||||||
@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
|
@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
|
||||||
@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.EXPRESSION)
|
AnnotationTarget.VALUE_PARAMETER)
|
||||||
annotation class ExperimentalAPI
|
annotation class ExperimentalAPI
|
||||||
|
|
||||||
@ExperimentalAPI
|
@ExperimentalAPI
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ package api {
|
|||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION}) public final annotation class ExperimentalAPI : kotlin.Annotation {
|
@kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, AnnotationTarget.VALUE_PARAMETER}) public final annotation class ExperimentalAPI : kotlin.Annotation {
|
||||||
public constructor ExperimentalAPI()
|
public constructor ExperimentalAPI()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
|||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// !API_VERSION: 1.3
|
||||||
|
|
||||||
|
<!EXPERIMENTAL_ANNOTATION_WITH_NO_IMPACT!>@Experimental(Experimental.Level.WARNING, [])<!>
|
||||||
|
annotation class ExperimentalAPI
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
@kotlin.Experimental(changesMayBreak = {}, level = Level.WARNING) public final annotation class ExperimentalAPI : kotlin.Annotation {
|
||||||
|
public constructor ExperimentalAPI()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
// !API_VERSION: 1.3
|
||||||
|
// FILE: api.kt
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import kotlin.annotation.AnnotationTarget.*
|
||||||
|
|
||||||
|
@Experimental(Experimental.Level.WARNING, [Experimental.Impact.RUNTIME])
|
||||||
|
@Target(CLASS, ANNOTATION_CLASS, TYPE_PARAMETER, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION,
|
||||||
|
PROPERTY_GETTER, PROPERTY_SETTER, TYPE, TYPEALIAS)
|
||||||
|
annotation class E1
|
||||||
|
|
||||||
|
@Experimental(Experimental.Level.WARNING, [Experimental.Impact.RUNTIME])
|
||||||
|
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(FILE)<!>
|
||||||
|
annotation class E2
|
||||||
|
|
||||||
|
@Experimental(Experimental.Level.WARNING, [Experimental.Impact.RUNTIME])
|
||||||
|
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(EXPRESSION)<!>
|
||||||
|
annotation class E3
|
||||||
|
|
||||||
|
@Experimental(Experimental.Level.WARNING, [Experimental.Impact.RUNTIME])
|
||||||
|
<!EXPERIMENTAL_ANNOTATION_WITH_WRONG_TARGET!>@Target(FILE, EXPRESSION)<!>
|
||||||
|
annotation class E4
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
package api {
|
||||||
|
|
||||||
|
@kotlin.Experimental(changesMayBreak = {Impact.RUNTIME}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY, AnnotationTarget.FIELD, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.TYPE, AnnotationTarget.TYPEALIAS}) public final annotation class E1 : kotlin.Annotation {
|
||||||
|
public constructor E1()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Experimental(changesMayBreak = {Impact.RUNTIME}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE}) public final annotation class E2 : kotlin.Annotation {
|
||||||
|
public constructor E2()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Experimental(changesMayBreak = {Impact.RUNTIME}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.EXPRESSION}) public final annotation class E3 : kotlin.Annotation {
|
||||||
|
public constructor E3()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Experimental(changesMayBreak = {Impact.RUNTIME}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE, AnnotationTarget.EXPRESSION}) public final annotation class E4 : kotlin.Annotation {
|
||||||
|
public constructor E4()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
// !API_VERSION: 1.3
|
||||||
|
// FILE: api.kt
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
@Experimental(Experimental.Level.WARNING, [Experimental.Impact.RUNTIME])
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
annotation class BinaryExperimental
|
||||||
|
|
||||||
|
@BinaryExperimental
|
||||||
|
val x = ""
|
||||||
|
|
||||||
|
// FILE: usage.kt
|
||||||
|
|
||||||
|
import api.*
|
||||||
|
|
||||||
|
<!USE_EXPERIMENTAL_WITHOUT_ARGUMENTS!>@UseExperimental<!>
|
||||||
|
fun use1(): String {
|
||||||
|
return <!EXPERIMENTAL_API_USAGE!>x<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!USE_EXPERIMENTAL_ARGUMENT_HAS_NON_COMPILATION_IMPACT!>@UseExperimental(BinaryExperimental::class)<!>
|
||||||
|
fun use2(): String {
|
||||||
|
return <!EXPERIMENTAL_API_USAGE!>x<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!USE_EXPERIMENTAL_ARGUMENT_IS_NOT_MARKER!>@UseExperimental(UseExperimental::class)<!>
|
||||||
|
fun use3(): String {
|
||||||
|
return <!EXPERIMENTAL_API_USAGE!>x<!>
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
@kotlin.UseExperimental(annotationClass = {}) public fun use1(): kotlin.String
|
||||||
|
@kotlin.UseExperimental(annotationClass = {api.BinaryExperimental::class}) public fun use2(): kotlin.String
|
||||||
|
@kotlin.UseExperimental(annotationClass = {kotlin.UseExperimental::class}) public fun use3(): kotlin.String
|
||||||
|
|
||||||
|
package api {
|
||||||
|
@api.BinaryExperimental public val x: kotlin.String = ""
|
||||||
|
|
||||||
|
@kotlin.Experimental(changesMayBreak = {Impact.RUNTIME}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY}) public final annotation class BinaryExperimental : kotlin.Annotation {
|
||||||
|
public constructor BinaryExperimental()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ package api
|
|||||||
|
|
||||||
@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
|
@Experimental(Experimental.Level.WARNING, [Experimental.Impact.COMPILATION])
|
||||||
@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.EXPRESSION)
|
AnnotationTarget.VALUE_PARAMETER)
|
||||||
annotation class ExperimentalAPI
|
annotation class ExperimentalAPI
|
||||||
|
|
||||||
@ExperimentalAPI
|
@ExperimentalAPI
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ package api {
|
|||||||
@api.ExperimentalAPI public val property: kotlin.String = ""
|
@api.ExperimentalAPI public val property: kotlin.String = ""
|
||||||
@api.ExperimentalAPI public fun function(): kotlin.String
|
@api.ExperimentalAPI public fun function(): kotlin.String
|
||||||
|
|
||||||
@kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION}) public final annotation class ExperimentalAPI : kotlin.Annotation {
|
@kotlin.Experimental(changesMayBreak = {Impact.COMPILATION}, level = Level.WARNING) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS, AnnotationTarget.VALUE_PARAMETER}) public final annotation class ExperimentalAPI : kotlin.Annotation {
|
||||||
public constructor ExperimentalAPI()
|
public constructor ExperimentalAPI()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
|||||||
+18
@@ -1833,6 +1833,24 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("experimentalWithNoImpact.kt")
|
||||||
|
public void testExperimentalWithNoImpact() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalWithNoImpact.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("incorrectTargetsForExperimentalAnnotation.kt")
|
||||||
|
public void testIncorrectTargetsForExperimentalAnnotation() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("incorrectUseExperimental.kt")
|
||||||
|
public void testIncorrectUseExperimental() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectUseExperimental.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("topLevel.kt")
|
@TestMetadata("topLevel.kt")
|
||||||
public void testTopLevel() throws Exception {
|
public void testTopLevel() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt");
|
||||||
|
|||||||
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
Generated
+18
@@ -1833,6 +1833,24 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("experimentalWithNoImpact.kt")
|
||||||
|
public void testExperimentalWithNoImpact() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/experimentalWithNoImpact.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("incorrectTargetsForExperimentalAnnotation.kt")
|
||||||
|
public void testIncorrectTargetsForExperimentalAnnotation() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectTargetsForExperimentalAnnotation.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("incorrectUseExperimental.kt")
|
||||||
|
public void testIncorrectUseExperimental() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/incorrectUseExperimental.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("topLevel.kt")
|
@TestMetadata("topLevel.kt")
|
||||||
public void testTopLevel() throws Exception {
|
public void testTopLevel() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/experimental/topLevel.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user