Report error if both repeatable annotation and its container are used
#KT-12794
This commit is contained in:
+12
@@ -2094,6 +2094,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_5.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_6.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatableJvmTarget6.kt")
|
||||
public void testJavaRepeatableJvmTarget6() throws Exception {
|
||||
|
||||
+12
@@ -2094,6 +2094,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_5.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_6.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatableJvmTarget6.kt")
|
||||
public void testJavaRepeatableJvmTarget6() throws Exception {
|
||||
|
||||
+49
-12
@@ -9,14 +9,18 @@ import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotatedWithKotlinRepeatable
|
||||
@@ -28,8 +32,6 @@ class RepeatableAnnotationChecker(
|
||||
private val jvmTarget: JvmTarget,
|
||||
private val platformAnnotationFeaturesSupport: JvmPlatformAnnotationFeaturesSupport,
|
||||
) : AdditionalAnnotationChecker {
|
||||
private val nonSourceDisallowed = !languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations)
|
||||
|
||||
override fun checkEntries(
|
||||
entries: List<KtAnnotationEntry>,
|
||||
actualTargets: List<KotlinTarget>,
|
||||
@@ -38,14 +40,24 @@ class RepeatableAnnotationChecker(
|
||||
) {
|
||||
if (entries.isEmpty()) return
|
||||
|
||||
val annotations = entries.mapNotNull { entry ->
|
||||
val descriptor = trace.get(BindingContext.ANNOTATION, entry)
|
||||
val useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget()
|
||||
if (descriptor != null) {
|
||||
ResolvedAnnotation(entry, descriptor, useSiteTarget)
|
||||
} else null
|
||||
}
|
||||
|
||||
checkRepeatedEntries(annotations, trace)
|
||||
}
|
||||
|
||||
private fun checkRepeatedEntries(annotations: List<ResolvedAnnotation>, trace: BindingTrace) {
|
||||
val entryTypesWithAnnotations = hashMapOf<FqName, MutableList<AnnotationUseSiteTarget?>>()
|
||||
|
||||
for (entry in entries) {
|
||||
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
|
||||
for ((entry, descriptor, useSiteTarget) in annotations) {
|
||||
val fqName = descriptor.fqName ?: continue
|
||||
val classDescriptor = descriptor.annotationClass ?: continue
|
||||
|
||||
val useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget()
|
||||
val existingTargetsForAnnotation = entryTypesWithAnnotations.getOrPut(fqName) { arrayListOf() }
|
||||
val duplicateAnnotation = useSiteTarget in existingTargetsForAnnotation
|
||||
|| (existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) })
|
||||
@@ -54,13 +66,21 @@ class RepeatableAnnotationChecker(
|
||||
&& isRepeatableAnnotation(classDescriptor)
|
||||
&& classDescriptor.getAnnotationRetention() != KotlinRetention.SOURCE
|
||||
) {
|
||||
val error = when {
|
||||
jvmTarget == JvmTarget.JVM_1_6 -> ErrorsJvm.REPEATED_ANNOTATION_TARGET6
|
||||
nonSourceDisallowed -> ErrorsJvm.NON_SOURCE_REPEATED_ANNOTATION
|
||||
else -> null
|
||||
}
|
||||
if (error != null) {
|
||||
trace.report(error.on(entry))
|
||||
when {
|
||||
jvmTarget == JvmTarget.JVM_1_6 -> {
|
||||
trace.report(ErrorsJvm.REPEATED_ANNOTATION_TARGET6.on(entry))
|
||||
}
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations) -> {
|
||||
// It's not allowed to have both a repeated annotation (applied more than once) and its container
|
||||
// on the same element. See https://docs.oracle.com/javase/specs/jls/se16/html/jls-9.html#jls-9.7.5.
|
||||
val explicitContainer = resolveContainerAnnotation(classDescriptor)
|
||||
if (explicitContainer != null && annotations.any { it.descriptor.fqName == explicitContainer }) {
|
||||
trace.report(ErrorsJvm.REPEATED_ANNOTATION_WITH_CONTAINER.on(entry, fqName, explicitContainer))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
trace.report(ErrorsJvm.NON_SOURCE_REPEATED_ANNOTATION.on(entry))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,4 +90,21 @@ class RepeatableAnnotationChecker(
|
||||
|
||||
private fun isRepeatableAnnotation(classDescriptor: ClassDescriptor): Boolean =
|
||||
classDescriptor.isAnnotatedWithKotlinRepeatable() || platformAnnotationFeaturesSupport.isRepeatableAnnotationClass(classDescriptor)
|
||||
|
||||
private data class ResolvedAnnotation(
|
||||
val entry: KtAnnotationEntry,
|
||||
val descriptor: AnnotationDescriptor,
|
||||
val useSiteTarget: AnnotationUseSiteTarget?,
|
||||
)
|
||||
|
||||
// For a repeatable annotation class, returns FQ name of the container annotation if it can be resolved in Kotlin.
|
||||
// This only exists when the annotation class (whether declared in Java or Kotlin) is annotated with java.lang.annotation.Repeatable,
|
||||
// in which case the container annotation is @j.l.a.Repeatable's only argument.
|
||||
private fun resolveContainerAnnotation(annotationClass: ClassDescriptor): FqName? {
|
||||
val javaRepeatable = annotationClass.annotations.findAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION) ?: return null
|
||||
val value = javaRepeatable.allValueArguments[Name.identifier("value")] as? KClassValue ?: return null
|
||||
// Local annotations are supported neither in Java nor in Kotlin.
|
||||
val normalClass = value.value as? KClassValue.Value.NormalClass ?: return null
|
||||
return normalClass.classId.asSingleFqName()
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -73,6 +73,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(DEPRECATED_JAVA_ANNOTATION, "This annotation is deprecated in Kotlin. Use ''@{0}'' instead", TO_STRING);
|
||||
MAP.put(NON_SOURCE_REPEATED_ANNOTATION, "Repeatable annotations with non-SOURCE retention are only supported starting from Kotlin 1.6");
|
||||
MAP.put(REPEATED_ANNOTATION_TARGET6, "Repeatable annotations with non-SOURCE retention are not supported with JVM target 1.6. Use -jvm-target 1.8");
|
||||
MAP.put(REPEATED_ANNOTATION_WITH_CONTAINER, "Repeated annotation ''@{0}'' cannot be used on a declaration which is annotated with its container annotation ''@{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES, "Annotation ''@{0}'' is not applicable to the multi-file classes", TO_STRING);
|
||||
|
||||
MAP.put(JVM_PACKAGE_NAME_CANNOT_BE_EMPTY, "''@JvmPackageName'' annotation value cannot be empty");
|
||||
|
||||
@@ -71,6 +71,7 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory1<KtAnnotationEntry, FqName> DEPRECATED_JAVA_ANNOTATION = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory0<KtAnnotationEntry> NON_SOURCE_REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> REPEATED_ANNOTATION_TARGET6 = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory2<KtAnnotationEntry, FqName, FqName> REPEATED_ANNOTATION_WITH_CONTAINER = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<KtAnnotationEntry, FqName> ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtAnnotationEntry> JVM_PACKAGE_NAME_CANNOT_BE_EMPTY = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
// !LANGUAGE: -RepeatableAnnotations
|
||||
// FULL_JDK
|
||||
// FILE: JR.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Repeatable(JR.Container.class)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JR {
|
||||
public @interface Container {
|
||||
JR[] value();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: JS.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Repeatable(JS.Container.class)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface JS {
|
||||
public @interface Container {
|
||||
JS[] value();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: KR.kt
|
||||
|
||||
@java.lang.annotation.Repeatable(KR.Container::class)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class KR {
|
||||
annotation class Container(val value: Array<KR>)
|
||||
}
|
||||
|
||||
// FILE: KS.kt
|
||||
|
||||
@java.lang.annotation.Repeatable(KS.Container::class)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class KS {
|
||||
annotation class Container(val value: Array<KS>)
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
// Java runtime-retained annotation
|
||||
|
||||
@JR
|
||||
@JR.Container()
|
||||
fun jr1() {}
|
||||
|
||||
@JR
|
||||
@JR.Container()
|
||||
@JR
|
||||
fun jr2() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR())
|
||||
@JR
|
||||
fun jr3() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR())
|
||||
fun jr4() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR(), JR())
|
||||
fun jr5() {}
|
||||
|
||||
|
||||
// Java source-retained annotation
|
||||
|
||||
@JS
|
||||
@JS.Container()
|
||||
fun js1() {}
|
||||
|
||||
@JS
|
||||
@JS.Container()
|
||||
@JS
|
||||
fun js2() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS())
|
||||
@JS
|
||||
fun js3() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS())
|
||||
fun js4() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS(), JS())
|
||||
fun js5() {}
|
||||
|
||||
|
||||
// Kotlin runtime-retained annotation
|
||||
|
||||
@KR.Container([])
|
||||
@KR
|
||||
fun kr1() {}
|
||||
|
||||
@KR.Container([])
|
||||
@KR
|
||||
@KR
|
||||
fun kr2() {}
|
||||
|
||||
@KR
|
||||
@KR
|
||||
@KR.Container([KR()])
|
||||
fun kr3() {}
|
||||
|
||||
@KR.Container([KR()])
|
||||
@KR
|
||||
fun kr4() {}
|
||||
|
||||
@KR
|
||||
@KR.Container([KR(), KR()])
|
||||
fun kr5() {}
|
||||
|
||||
|
||||
// Kotlin source-retained annotation
|
||||
|
||||
@KS.Container([])
|
||||
@KS
|
||||
fun ks1() {}
|
||||
|
||||
@KS.Container([])
|
||||
@KS
|
||||
@KS
|
||||
fun ks2() {}
|
||||
|
||||
@KS
|
||||
@KS
|
||||
@KS.Container([KS()])
|
||||
fun ks3() {}
|
||||
|
||||
@KS.Container([KS()])
|
||||
@KS
|
||||
fun ks4() {}
|
||||
|
||||
@KS
|
||||
@KS.Container([KS(), KS()])
|
||||
fun ks5() {}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
// !LANGUAGE: -RepeatableAnnotations
|
||||
// FULL_JDK
|
||||
// FILE: JR.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Repeatable(JR.Container.class)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JR {
|
||||
public @interface Container {
|
||||
JR[] value();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: JS.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Repeatable(JS.Container.class)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface JS {
|
||||
public @interface Container {
|
||||
JS[] value();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: KR.kt
|
||||
|
||||
@java.lang.annotation.Repeatable(KR.Container::class)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class KR {
|
||||
annotation class Container(val value: Array<KR>)
|
||||
}
|
||||
|
||||
// FILE: KS.kt
|
||||
|
||||
@java.lang.annotation.Repeatable(KS.Container::class)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class KS {
|
||||
annotation class Container(val value: Array<KS>)
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
// Java runtime-retained annotation
|
||||
|
||||
@JR
|
||||
@JR.Container()
|
||||
fun jr1() {}
|
||||
|
||||
@JR
|
||||
@JR.Container()
|
||||
<!REPEATED_ANNOTATION!>@JR<!>
|
||||
fun jr2() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR())
|
||||
<!REPEATED_ANNOTATION!>@JR<!>
|
||||
fun jr3() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR())
|
||||
fun jr4() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR(), JR())
|
||||
fun jr5() {}
|
||||
|
||||
|
||||
// Java source-retained annotation
|
||||
|
||||
@JS
|
||||
@JS.Container()
|
||||
fun js1() {}
|
||||
|
||||
@JS
|
||||
@JS.Container()
|
||||
@JS
|
||||
fun js2() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS())
|
||||
@JS
|
||||
fun js3() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS())
|
||||
fun js4() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS(), JS())
|
||||
fun js5() {}
|
||||
|
||||
|
||||
// Kotlin runtime-retained annotation
|
||||
|
||||
@KR.Container([])
|
||||
@KR
|
||||
fun kr1() {}
|
||||
|
||||
@KR.Container([])
|
||||
@KR
|
||||
<!REPEATED_ANNOTATION!>@KR<!>
|
||||
fun kr2() {}
|
||||
|
||||
@KR
|
||||
<!REPEATED_ANNOTATION!>@KR<!>
|
||||
@KR.Container([KR()])
|
||||
fun kr3() {}
|
||||
|
||||
@KR.Container([KR()])
|
||||
@KR
|
||||
fun kr4() {}
|
||||
|
||||
@KR
|
||||
@KR.Container([KR(), KR()])
|
||||
fun kr5() {}
|
||||
|
||||
|
||||
// Kotlin source-retained annotation
|
||||
|
||||
@KS.Container([])
|
||||
@KS
|
||||
fun ks1() {}
|
||||
|
||||
@KS.Container([])
|
||||
@KS
|
||||
<!REPEATED_ANNOTATION!>@KS<!>
|
||||
fun ks2() {}
|
||||
|
||||
@KS
|
||||
<!REPEATED_ANNOTATION!>@KS<!>
|
||||
@KS.Container([KS()])
|
||||
fun ks3() {}
|
||||
|
||||
@KS.Container([KS()])
|
||||
@KS
|
||||
fun ks4() {}
|
||||
|
||||
@KS
|
||||
@KS.Container([KS(), KS()])
|
||||
fun ks5() {}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package
|
||||
|
||||
@JR @JR.Container(value = {}) public fun jr1(): kotlin.Unit
|
||||
@JR @JR.Container(value = {}) @JR public fun jr2(): kotlin.Unit
|
||||
@JR @JR.Container(value = {JR}) @JR public fun jr3(): kotlin.Unit
|
||||
@JR @JR.Container(value = {JR}) public fun jr4(): kotlin.Unit
|
||||
@JR @JR.Container(value = {JR, JR}) public fun jr5(): kotlin.Unit
|
||||
@JS @JS.Container(value = {}) public fun js1(): kotlin.Unit
|
||||
@JS @JS.Container(value = {}) @JS public fun js2(): kotlin.Unit
|
||||
@JS @JS.Container(value = {JS}) @JS public fun js3(): kotlin.Unit
|
||||
@JS @JS.Container(value = {JS}) public fun js4(): kotlin.Unit
|
||||
@JS @JS.Container(value = {JS, JS}) public fun js5(): kotlin.Unit
|
||||
@KR.Container(value = {}) @KR public fun kr1(): kotlin.Unit
|
||||
@KR.Container(value = {}) @KR @KR public fun kr2(): kotlin.Unit
|
||||
@KR @KR @KR.Container(value = {KR}) public fun kr3(): kotlin.Unit
|
||||
@KR.Container(value = {KR}) @KR public fun kr4(): kotlin.Unit
|
||||
@KR @KR.Container(value = {KR, KR}) public fun kr5(): kotlin.Unit
|
||||
@KS.Container(value = {}) @KS public fun ks1(): kotlin.Unit
|
||||
@KS.Container(value = {}) @KS @KS public fun ks2(): kotlin.Unit
|
||||
@KS @KS @KS.Container(value = {KS}) public fun ks3(): kotlin.Unit
|
||||
@KS.Container(value = {KS}) @KS public fun ks4(): kotlin.Unit
|
||||
@KS @KS.Container(value = {KS, KS}) public fun ks5(): kotlin.Unit
|
||||
|
||||
@java.lang.annotation.Repeatable(value = JR.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class JR : kotlin.Annotation {
|
||||
public constructor JR()
|
||||
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
|
||||
|
||||
public final annotation class Container : kotlin.Annotation {
|
||||
public constructor Container(/*0*/ vararg value: JR /*kotlin.Array<out JR>*/)
|
||||
public final val value: kotlin.Array<JR>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.annotation.Repeatable(value = JS.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final annotation class JS : kotlin.Annotation {
|
||||
public constructor JS()
|
||||
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
|
||||
|
||||
public final annotation class Container : kotlin.Annotation {
|
||||
public constructor Container(/*0*/ vararg value: JS /*kotlin.Array<out JS>*/)
|
||||
public final val value: kotlin.Array<JS>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.annotation.Repeatable(value = KR.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class KR : kotlin.Annotation {
|
||||
public constructor KR()
|
||||
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
|
||||
|
||||
public final annotation class Container : kotlin.Annotation {
|
||||
public constructor Container(/*0*/ value: kotlin.Array<KR>)
|
||||
public final val value: kotlin.Array<KR>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.annotation.Repeatable(value = KS.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final annotation class KS : kotlin.Annotation {
|
||||
public constructor KS()
|
||||
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
|
||||
|
||||
public final annotation class Container : kotlin.Annotation {
|
||||
public constructor Container(/*0*/ value: kotlin.Array<KS>)
|
||||
public final val value: kotlin.Array<KS>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
// !LANGUAGE: +RepeatableAnnotations
|
||||
// FULL_JDK
|
||||
// FILE: JR.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Repeatable(JR.Container.class)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JR {
|
||||
public @interface Container {
|
||||
JR[] value();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: JS.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Repeatable(JS.Container.class)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface JS {
|
||||
public @interface Container {
|
||||
JS[] value();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: KR.kt
|
||||
|
||||
@java.lang.annotation.Repeatable(KR.Container::class)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class KR {
|
||||
annotation class Container(val value: Array<KR>)
|
||||
}
|
||||
|
||||
// FILE: KS.kt
|
||||
|
||||
@java.lang.annotation.Repeatable(KS.Container::class)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class KS {
|
||||
annotation class Container(val value: Array<KS>)
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
// Java runtime-retained annotation
|
||||
|
||||
@JR
|
||||
@JR.Container()
|
||||
fun jr1() {}
|
||||
|
||||
@JR
|
||||
@JR.Container()
|
||||
@JR
|
||||
fun jr2() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR())
|
||||
@JR
|
||||
fun jr3() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR())
|
||||
fun jr4() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR(), JR())
|
||||
fun jr5() {}
|
||||
|
||||
|
||||
// Java source-retained annotation
|
||||
|
||||
@JS
|
||||
@JS.Container()
|
||||
fun js1() {}
|
||||
|
||||
@JS
|
||||
@JS.Container()
|
||||
@JS
|
||||
fun js2() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS())
|
||||
@JS
|
||||
fun js3() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS())
|
||||
fun js4() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS(), JS())
|
||||
fun js5() {}
|
||||
|
||||
|
||||
// Kotlin runtime-retained annotation
|
||||
|
||||
@KR.Container([])
|
||||
@KR
|
||||
fun kr1() {}
|
||||
|
||||
@KR.Container([])
|
||||
@KR
|
||||
@KR
|
||||
fun kr2() {}
|
||||
|
||||
@KR
|
||||
@KR
|
||||
@KR.Container([KR()])
|
||||
fun kr3() {}
|
||||
|
||||
@KR.Container([KR()])
|
||||
@KR
|
||||
fun kr4() {}
|
||||
|
||||
@KR
|
||||
@KR.Container([KR(), KR()])
|
||||
fun kr5() {}
|
||||
|
||||
|
||||
// Kotlin source-retained annotation
|
||||
|
||||
@KS.Container([])
|
||||
@KS
|
||||
fun ks1() {}
|
||||
|
||||
@KS.Container([])
|
||||
@KS
|
||||
@KS
|
||||
fun ks2() {}
|
||||
|
||||
@KS
|
||||
@KS
|
||||
@KS.Container([KS()])
|
||||
fun ks3() {}
|
||||
|
||||
@KS.Container([KS()])
|
||||
@KS
|
||||
fun ks4() {}
|
||||
|
||||
@KS
|
||||
@KS.Container([KS(), KS()])
|
||||
fun ks5() {}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
// !LANGUAGE: +RepeatableAnnotations
|
||||
// FULL_JDK
|
||||
// FILE: JR.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Repeatable(JR.Container.class)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JR {
|
||||
public @interface Container {
|
||||
JR[] value();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: JS.java
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Repeatable(JS.Container.class)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface JS {
|
||||
public @interface Container {
|
||||
JS[] value();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: KR.kt
|
||||
|
||||
@java.lang.annotation.Repeatable(KR.Container::class)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class KR {
|
||||
annotation class Container(val value: Array<KR>)
|
||||
}
|
||||
|
||||
// FILE: KS.kt
|
||||
|
||||
@java.lang.annotation.Repeatable(KS.Container::class)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class KS {
|
||||
annotation class Container(val value: Array<KS>)
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
// Java runtime-retained annotation
|
||||
|
||||
@JR
|
||||
@JR.Container()
|
||||
fun jr1() {}
|
||||
|
||||
@JR
|
||||
@JR.Container()
|
||||
<!REPEATED_ANNOTATION_WITH_CONTAINER!>@JR<!>
|
||||
fun jr2() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR())
|
||||
<!REPEATED_ANNOTATION_WITH_CONTAINER!>@JR<!>
|
||||
fun jr3() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR())
|
||||
fun jr4() {}
|
||||
|
||||
@JR
|
||||
@JR.Container(JR(), JR())
|
||||
fun jr5() {}
|
||||
|
||||
|
||||
// Java source-retained annotation
|
||||
|
||||
@JS
|
||||
@JS.Container()
|
||||
fun js1() {}
|
||||
|
||||
@JS
|
||||
@JS.Container()
|
||||
@JS
|
||||
fun js2() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS())
|
||||
@JS
|
||||
fun js3() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS())
|
||||
fun js4() {}
|
||||
|
||||
@JS
|
||||
@JS.Container(JS(), JS())
|
||||
fun js5() {}
|
||||
|
||||
|
||||
// Kotlin runtime-retained annotation
|
||||
|
||||
@KR.Container([])
|
||||
@KR
|
||||
fun kr1() {}
|
||||
|
||||
@KR.Container([])
|
||||
@KR
|
||||
<!REPEATED_ANNOTATION_WITH_CONTAINER!>@KR<!>
|
||||
fun kr2() {}
|
||||
|
||||
@KR
|
||||
<!REPEATED_ANNOTATION_WITH_CONTAINER!>@KR<!>
|
||||
@KR.Container([KR()])
|
||||
fun kr3() {}
|
||||
|
||||
@KR.Container([KR()])
|
||||
@KR
|
||||
fun kr4() {}
|
||||
|
||||
@KR
|
||||
@KR.Container([KR(), KR()])
|
||||
fun kr5() {}
|
||||
|
||||
|
||||
// Kotlin source-retained annotation
|
||||
|
||||
@KS.Container([])
|
||||
@KS
|
||||
fun ks1() {}
|
||||
|
||||
@KS.Container([])
|
||||
@KS
|
||||
@KS
|
||||
fun ks2() {}
|
||||
|
||||
@KS
|
||||
@KS
|
||||
@KS.Container([KS()])
|
||||
fun ks3() {}
|
||||
|
||||
@KS.Container([KS()])
|
||||
@KS
|
||||
fun ks4() {}
|
||||
|
||||
@KS
|
||||
@KS.Container([KS(), KS()])
|
||||
fun ks5() {}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package
|
||||
|
||||
@JR @JR.Container(value = {}) public fun jr1(): kotlin.Unit
|
||||
@JR @JR.Container(value = {}) @JR public fun jr2(): kotlin.Unit
|
||||
@JR @JR.Container(value = {JR}) @JR public fun jr3(): kotlin.Unit
|
||||
@JR @JR.Container(value = {JR}) public fun jr4(): kotlin.Unit
|
||||
@JR @JR.Container(value = {JR, JR}) public fun jr5(): kotlin.Unit
|
||||
@JS @JS.Container(value = {}) public fun js1(): kotlin.Unit
|
||||
@JS @JS.Container(value = {}) @JS public fun js2(): kotlin.Unit
|
||||
@JS @JS.Container(value = {JS}) @JS public fun js3(): kotlin.Unit
|
||||
@JS @JS.Container(value = {JS}) public fun js4(): kotlin.Unit
|
||||
@JS @JS.Container(value = {JS, JS}) public fun js5(): kotlin.Unit
|
||||
@KR.Container(value = {}) @KR public fun kr1(): kotlin.Unit
|
||||
@KR.Container(value = {}) @KR @KR public fun kr2(): kotlin.Unit
|
||||
@KR @KR @KR.Container(value = {KR}) public fun kr3(): kotlin.Unit
|
||||
@KR.Container(value = {KR}) @KR public fun kr4(): kotlin.Unit
|
||||
@KR @KR.Container(value = {KR, KR}) public fun kr5(): kotlin.Unit
|
||||
@KS.Container(value = {}) @KS public fun ks1(): kotlin.Unit
|
||||
@KS.Container(value = {}) @KS @KS public fun ks2(): kotlin.Unit
|
||||
@KS @KS @KS.Container(value = {KS}) public fun ks3(): kotlin.Unit
|
||||
@KS.Container(value = {KS}) @KS public fun ks4(): kotlin.Unit
|
||||
@KS @KS.Container(value = {KS, KS}) public fun ks5(): kotlin.Unit
|
||||
|
||||
@java.lang.annotation.Repeatable(value = JR.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class JR : kotlin.Annotation {
|
||||
public constructor JR()
|
||||
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
|
||||
|
||||
public final annotation class Container : kotlin.Annotation {
|
||||
public constructor Container(/*0*/ vararg value: JR /*kotlin.Array<out JR>*/)
|
||||
public final val value: kotlin.Array<JR>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.annotation.Repeatable(value = JS.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final annotation class JS : kotlin.Annotation {
|
||||
public constructor JS()
|
||||
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
|
||||
|
||||
public final annotation class Container : kotlin.Annotation {
|
||||
public constructor Container(/*0*/ vararg value: JS /*kotlin.Array<out JS>*/)
|
||||
public final val value: kotlin.Array<JS>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.annotation.Repeatable(value = KR.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class KR : kotlin.Annotation {
|
||||
public constructor KR()
|
||||
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
|
||||
|
||||
public final annotation class Container : kotlin.Annotation {
|
||||
public constructor Container(/*0*/ value: kotlin.Array<KR>)
|
||||
public final val value: kotlin.Array<KR>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.annotation.Repeatable(value = KS.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final annotation class KS : kotlin.Annotation {
|
||||
public constructor KS()
|
||||
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
|
||||
|
||||
public final annotation class Container : kotlin.Annotation {
|
||||
public constructor Container(/*0*/ value: kotlin.Array<KS>)
|
||||
public final val value: kotlin.Array<KS>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+12
@@ -2100,6 +2100,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/repeatable"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_5.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_6.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatableJvmTarget6.kt")
|
||||
public void testJavaRepeatableJvmTarget6() throws Exception {
|
||||
|
||||
+12
@@ -2094,6 +2094,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_5.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_5() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("containerAndAnnotationAreBothApplied_1_6.kt")
|
||||
public void testContainerAndAnnotationAreBothApplied_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/repeatable/containerAndAnnotationAreBothApplied_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaRepeatableJvmTarget6.kt")
|
||||
public void testJavaRepeatableJvmTarget6() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user