diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 1f7f5701953..94e2cb8ce95 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -1139,12 +1139,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); } - @Test - @TestMetadata("deprecatedRepeatable.kt") - public void testDeprecatedRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.kt"); - } - @Test @TestMetadata("dontReportWarningAboutChangingExecutionOrderForVararg.kt") public void testDontReportWarningAboutChangingExecutionOrderForVararg() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 9d0b6bd42c2..6ca015aa897 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -1139,12 +1139,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); } - @Test - @TestMetadata("deprecatedRepeatable.kt") - public void testDeprecatedRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.kt"); - } - @Test @TestMetadata("dontReportWarningAboutChangingExecutionOrderForVararg.kt") public void testDontReportWarningAboutChangingExecutionOrderForVararg() throws Exception { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmPlatformAnnotationFeaturesSupport.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmPlatformAnnotationFeaturesSupport.kt new file mode 100644 index 00000000000..a8f705d621e --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmPlatformAnnotationFeaturesSupport.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.jvm + +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention +import org.jetbrains.kotlin.load.java.JvmAnnotationNames.REPEATABLE_ANNOTATION +import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor +import org.jetbrains.kotlin.resolve.PlatformAnnotationFeaturesSupport +import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention + +class JvmPlatformAnnotationFeaturesSupport( + private val languageVersionSettings: LanguageVersionSettings, +) : PlatformAnnotationFeaturesSupport { + override fun isRepeatableAnnotationClass(descriptor: ClassDescriptor): Boolean { + check(descriptor.kind == ClassKind.ANNOTATION_CLASS) { descriptor } + + // This service only handles annotation classes annotated with java.lang.annotation.Repeatable. + if (!descriptor.annotations.hasAnnotation(REPEATABLE_ANNOTATION)) return false + + // Before 1.6, only Java annotations with SOURCE retention could be used as repeatable. + // (Note that _Kotlin_ annotations must have been annotated with kotlin.annotation.Repeatable, not j.l.a.Repeatable!) + return languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations) || + descriptor.getAnnotationRetention() == KotlinRetention.SOURCE && descriptor is JavaClassDescriptor + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index b76196535da..17f0ef5d500 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -115,6 +115,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase( container.useImpl() container.useImpl() container.useImpl() + container.useImpl() container.useInstance(FunctionWithBigAritySupport.LanguageVersionDependent) container.useInstance(GenericArrayClassLiteralSupport.Enabled) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt index 97785e7575a..deece389004 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt @@ -34,7 +34,8 @@ import org.jetbrains.kotlin.types.isError class AnnotationChecker( private val additionalCheckers: Iterable, - private val languageVersionSettings: LanguageVersionSettings + private val languageVersionSettings: LanguageVersionSettings, + private val platformAnnotationFeaturesSupport: PlatformAnnotationFeaturesSupport, ) { fun check(annotated: KtAnnotated, trace: BindingTrace, descriptor: DeclarationDescriptor? = null) { val actualTargets = getActualTargetList(annotated, descriptor, trace.bindingContext) @@ -132,7 +133,7 @@ class AnnotationChecker( val useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget() ?: property.getDefaultUseSiteTarget(descriptor) val existingAnnotations = propertyAnnotations[useSiteTarget] ?: continue - if (classDescriptor in existingAnnotations && !classDescriptor.isRepeatableAnnotation()) { + if (classDescriptor in existingAnnotations && !isRepeatableAnnotation(classDescriptor)) { if (reportError) { trace.reportDiagnosticOnce(Errors.REPEATED_ANNOTATION.on(entry)) } else { @@ -231,7 +232,7 @@ class AnnotationChecker( val duplicateAnnotation = useSiteTarget in existingTargetsForAnnotation || (existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) }) - if (duplicateAnnotation && !classDescriptor.isRepeatableAnnotation()) { + if (duplicateAnnotation && !isRepeatableAnnotation(classDescriptor)) { trace.report(Errors.REPEATED_ANNOTATION.on(entry)) } @@ -292,6 +293,9 @@ class AnnotationChecker( } } + private fun isRepeatableAnnotation(descriptor: ClassDescriptor): Boolean = + descriptor.isRepeatableAnnotation() || platformAnnotationFeaturesSupport.isRepeatableAnnotationClass(descriptor) + companion object { private val TARGET_ALLOWED_TARGETS = Name.identifier("allowedTargets") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformAnnotationFeaturesSupport.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformAnnotationFeaturesSupport.kt new file mode 100644 index 00000000000..fe7ce16bdcb --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformAnnotationFeaturesSupport.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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 + +import org.jetbrains.kotlin.container.DefaultImplementation +import org.jetbrains.kotlin.descriptors.ClassDescriptor + +@DefaultImplementation(PlatformAnnotationFeaturesSupport.Default::class) +interface PlatformAnnotationFeaturesSupport { + fun isRepeatableAnnotationClass(descriptor: ClassDescriptor): Boolean + + object Default : PlatformAnnotationFeaturesSupport { + override fun isRepeatableAnnotationClass(descriptor: ClassDescriptor): Boolean = false + } +} diff --git a/compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.fir.kt b/compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.fir.kt deleted file mode 100644 index df340589e70..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.fir.kt +++ /dev/null @@ -1,11 +0,0 @@ -// FULL_JDK - -import java.lang.annotation.Repeatable - -@java.lang.annotation.Repeatable(Annotations::class) annotation class RepAnn - -@Repeatable(OtherAnnotations::class) annotation class OtherAnn - -annotation class Annotations(vararg val value: RepAnn) - -annotation class OtherAnnotations(vararg val value: OtherAnn) diff --git a/compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.kt b/compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.kt deleted file mode 100644 index ad9220cdb6a..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.kt +++ /dev/null @@ -1,11 +0,0 @@ -// FULL_JDK - -import java.lang.annotation.Repeatable - -@java.lang.annotation.Repeatable(Annotations::class) annotation class RepAnn - -@Repeatable(OtherAnnotations::class) annotation class OtherAnn - -annotation class Annotations(vararg val value: RepAnn) - -annotation class OtherAnnotations(vararg val value: OtherAnn) diff --git a/compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.txt b/compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.txt deleted file mode 100644 index 62ada953559..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.txt +++ /dev/null @@ -1,31 +0,0 @@ -package - -public final annotation class Annotations : kotlin.Annotation { - public constructor Annotations(/*0*/ vararg value: RepAnn /*kotlin.Array*/) - public final val value: kotlin.Array - 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 = OtherAnnotations::class) public final annotation class OtherAnn : kotlin.Annotation { - public constructor OtherAnn() - 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 OtherAnnotations : kotlin.Annotation { - public constructor OtherAnnotations(/*0*/ vararg value: OtherAnn /*kotlin.Array*/) - public final val value: kotlin.Array - 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 = Annotations::class) public final annotation class RepAnn : kotlin.Annotation { - public constructor RepAnn() - 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 -} diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt index 65de39a55e2..018e8335c60 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt @@ -37,10 +37,10 @@ public @interface Source { // FILE: usage.kt -@Runtime @Runtime +@Runtime @Runtime class UseRuntime -@Clazz @Clazz +@Clazz @Clazz class UseClazz @Source @Source diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.txt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.txt index f03aa0ca86a..7c295b4f6cc 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.txt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.txt @@ -1,6 +1,6 @@ package -@kotlin.annotation.Repeatable @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class Clazz : kotlin.Annotation { +@java.lang.annotation.Repeatable(value = Clazz.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class Clazz : kotlin.Annotation { public constructor Clazz() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -15,7 +15,7 @@ package } } -@kotlin.annotation.Repeatable @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class Runtime : kotlin.Annotation { +@java.lang.annotation.Repeatable(value = Runtime.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class Runtime : kotlin.Annotation { public constructor Runtime() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -30,7 +30,7 @@ package } } -@kotlin.annotation.Repeatable @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final annotation class Source : kotlin.Annotation { +@java.lang.annotation.Repeatable(value = Source.Container::class) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final annotation class Source : kotlin.Annotation { public constructor Source() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 4f557af34d5..e5245d9100f 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -1145,12 +1145,6 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); } - @Test - @TestMetadata("deprecatedRepeatable.kt") - public void testDeprecatedRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.kt"); - } - @Test @TestMetadata("dontReportWarningAboutChangingExecutionOrderForVararg.kt") public void testDontReportWarningAboutChangingExecutionOrderForVararg() throws Exception { diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 0d5f41f085c..883ddbf916b 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -218,6 +218,7 @@ enum class LanguageFeature( InstantiationOfAnnotationClasses(KOTLIN_1_6), OptInOnOverrideForbidden(KOTLIN_1_6, kind = BUG_FIX), OptInContagiousSignatures(KOTLIN_1_6, kind = BUG_FIX), + RepeatableAnnotations(KOTLIN_1_6), // 1.7 diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt index 7e8322220a5..bed349c36de 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt @@ -39,7 +39,6 @@ import org.jetbrains.kotlin.types.SimpleType import java.util.* object JavaAnnotationMapper { - // Java8-specific thing internal val DEPRECATED_ANNOTATION_MESSAGE = Name.identifier("message") internal val TARGET_ANNOTATION_ALLOWED_TARGETS = Name.identifier("allowedTargets") internal val RETENTION_ANNOTATION_VALUE = Name.identifier("value") @@ -52,7 +51,6 @@ object JavaAnnotationMapper { when (annotation.classId) { ClassId.topLevel(TARGET_ANNOTATION) -> JavaTargetAnnotationDescriptor(annotation, c) ClassId.topLevel(RETENTION_ANNOTATION) -> JavaRetentionAnnotationDescriptor(annotation, c) - ClassId.topLevel(REPEATABLE_ANNOTATION) -> JavaAnnotationDescriptor(c, annotation, StandardNames.FqNames.repeatable) ClassId.topLevel(DOCUMENTED_ANNOTATION) -> JavaAnnotationDescriptor(c, annotation, StandardNames.FqNames.mustBeDocumented) ClassId.topLevel(DEPRECATED_ANNOTATION) -> null else -> LazyJavaAnnotationDescriptor(c, annotation, isFreshlySupportedAnnotation) @@ -76,12 +74,10 @@ object JavaAnnotationMapper { } } - // kotlin.annotation.annotation is treated separately private val kotlinToJavaNameMap: Map = mapOf( StandardNames.FqNames.target to TARGET_ANNOTATION, StandardNames.FqNames.retention to RETENTION_ANNOTATION, - StandardNames.FqNames.repeatable to REPEATABLE_ANNOTATION, StandardNames.FqNames.mustBeDocumented to DOCUMENTED_ANNOTATION ) @@ -90,7 +86,6 @@ object JavaAnnotationMapper { TARGET_ANNOTATION to StandardNames.FqNames.target, RETENTION_ANNOTATION to StandardNames.FqNames.retention, DEPRECATED_ANNOTATION to StandardNames.FqNames.deprecated, - REPEATABLE_ANNOTATION to StandardNames.FqNames.repeatable, DOCUMENTED_ANNOTATION to StandardNames.FqNames.mustBeDocumented ) } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 1079cd02f79..807643ae0ce 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -1139,12 +1139,6 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); } - @Test - @TestMetadata("deprecatedRepeatable.kt") - public void testDeprecatedRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/deprecatedRepeatable.kt"); - } - @Test @TestMetadata("dontReportWarningAboutChangingExecutionOrderForVararg.kt") public void testDontReportWarningAboutChangingExecutionOrderForVararg() throws Exception {