From 87130edfa2c9d09000effda0c6350717139f9b24 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 20 Jul 2021 16:30:04 +0200 Subject: [PATCH] Support using Java-repeatable annotations in Kotlin #KT-12794 --- ...irOldFrontendDiagnosticsTestGenerated.java | 36 ++++-- ...DiagnosticsWithLightTreeTestGenerated.java | 36 ++++-- .../FirBlackBoxCodegenTestGenerated.java | 22 ++++ .../checkers/RepeatableAnnotationChecker.kt | 11 +- .../diagnostics/DefaultErrorMessagesJvm.java | 2 +- .../jvm/platform/JvmPlatformConfigurator.kt | 2 +- .../jetbrains/kotlin/backend/jvm/JvmLower.kt | 1 + .../backend/jvm/codegen/AnnotationCodegen.kt | 2 +- .../jvm/lower/RepeatedAnnotationLowering.kt | 110 ++++++++++++++++++ .../annotations/repeatable/javaAnnotation.kt | 56 +++++++++ .../jvmRepeatableKotlinAnnotation.kt | 32 +++++ .../annotations/repeatable/javaAnnotation.kt | 69 +++++++++++ .../annotations/repeatable/javaAnnotation.txt | 31 +++++ .../nonRepeatedAnnotationWithItsContainer.kt | 20 ++++ .../nonRepeatedAnnotationWithItsContainer.txt | 30 +++++ ...table.fir.kt => javaRepeatable_1_5.fir.kt} | 1 + ...avaRepeatable.kt => javaRepeatable_1_5.kt} | 1 + ...aRepeatable.txt => javaRepeatable_1_5.txt} | 0 .../repeatable/javaRepeatable_1_6.kt | 49 ++++++++ .../repeatable/javaRepeatable_1_6.txt | 68 +++++++++++ ...ble.fir.kt => javaUnrepeatable_1_5.fir.kt} | 1 + ...nrepeatable.kt => javaUnrepeatable_1_5.kt} | 1 + ...epeatable.txt => javaUnrepeatable_1_5.txt} | 0 .../repeatable/javaUnrepeatable_1_6.fir.kt | 33 ++++++ .../repeatable/javaUnrepeatable_1_6.kt | 33 ++++++ .../repeatable/javaUnrepeatable_1_6.txt | 44 +++++++ ...ble.fir.kt => kotlinRepeatable_1_5.fir.kt} | 2 + ...nRepeatable.kt => kotlinRepeatable_1_5.kt} | 4 +- ...epeatable.txt => kotlinRepeatable_1_5.txt} | 0 .../repeatable/kotlinRepeatable_1_6.kt | 34 ++++++ .../repeatable/kotlinRepeatable_1_6.txt | 68 +++++++++++ .../test/runners/DiagnosticTestGenerated.java | 36 ++++-- .../codegen/BlackBoxCodegenTestGenerated.java | 10 ++ .../codegen/BytecodeListingTestGenerated.java | 10 ++ .../IrBlackBoxCodegenTestGenerated.java | 22 ++++ .../IrBytecodeListingTestGenerated.java | 22 ++++ .../LightAnalysisModeTestGenerated.java | 13 +++ ...CompilerTestFE10TestdataTestGenerated.java | 36 ++++-- .../IrJsCodegenBoxES6TestGenerated.java | 13 +++ .../IrJsCodegenBoxTestGenerated.java | 13 +++ .../semantics/JsCodegenBoxTestGenerated.java | 13 +++ .../IrCodegenBoxWasmTestGenerated.java | 13 +++ 42 files changed, 958 insertions(+), 42 deletions(-) create mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/RepeatedAnnotationLowering.kt create mode 100644 compiler/testData/codegen/box/annotations/repeatable/javaAnnotation.kt create mode 100644 compiler/testData/codegen/box/annotations/repeatable/jvmRepeatableKotlinAnnotation.kt create mode 100644 compiler/testData/codegen/bytecodeListing/annotations/repeatable/javaAnnotation.kt create mode 100644 compiler/testData/codegen/bytecodeListing/annotations/repeatable/javaAnnotation.txt create mode 100644 compiler/testData/codegen/bytecodeListing/annotations/repeatable/nonRepeatedAnnotationWithItsContainer.kt create mode 100644 compiler/testData/codegen/bytecodeListing/annotations/repeatable/nonRepeatedAnnotationWithItsContainer.txt rename compiler/testData/diagnostics/tests/annotations/repeatable/{javaRepeatable.fir.kt => javaRepeatable_1_5.fir.kt} (95%) rename compiler/testData/diagnostics/tests/annotations/repeatable/{javaRepeatable.kt => javaRepeatable_1_5.kt} (95%) rename compiler/testData/diagnostics/tests/annotations/repeatable/{javaRepeatable.txt => javaRepeatable_1_5.txt} (100%) create mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.txt rename compiler/testData/diagnostics/tests/annotations/repeatable/{javaUnrepeatable.fir.kt => javaUnrepeatable_1_5.fir.kt} (92%) rename compiler/testData/diagnostics/tests/annotations/repeatable/{javaUnrepeatable.kt => javaUnrepeatable_1_5.kt} (93%) rename compiler/testData/diagnostics/tests/annotations/repeatable/{javaUnrepeatable.txt => javaUnrepeatable_1_5.txt} (100%) create mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.fir.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.txt rename compiler/testData/diagnostics/tests/annotations/repeatable/{kotlinRepeatable.fir.kt => kotlinRepeatable_1_5.fir.kt} (95%) rename compiler/testData/diagnostics/tests/annotations/repeatable/{kotlinRepeatable.kt => kotlinRepeatable_1_5.kt} (95%) rename compiler/testData/diagnostics/tests/annotations/repeatable/{kotlinRepeatable.txt => kotlinRepeatable_1_5.txt} (100%) create mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.txt 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 94e2cb8ce95..d81d3a6a162 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 @@ -2095,21 +2095,39 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti } @Test - @TestMetadata("javaRepeatable.kt") - public void testJavaRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt"); + @TestMetadata("javaRepeatable_1_5.kt") + public void testJavaRepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.kt"); } @Test - @TestMetadata("javaUnrepeatable.kt") - public void testJavaUnrepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.kt"); + @TestMetadata("javaRepeatable_1_6.kt") + public void testJavaRepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt"); } @Test - @TestMetadata("kotlinRepeatable.kt") - public void testKotlinRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.kt"); + @TestMetadata("javaUnrepeatable_1_5.kt") + public void testJavaUnrepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.kt"); + } + + @Test + @TestMetadata("javaUnrepeatable_1_6.kt") + public void testJavaUnrepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt"); + } + + @Test + @TestMetadata("kotlinRepeatable_1_5.kt") + public void testKotlinRepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.kt"); + } + + @Test + @TestMetadata("kotlinRepeatable_1_6.kt") + public void testKotlinRepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt"); } } 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 6ca015aa897..b3e8ae30734 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 @@ -2095,21 +2095,39 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac } @Test - @TestMetadata("javaRepeatable.kt") - public void testJavaRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt"); + @TestMetadata("javaRepeatable_1_5.kt") + public void testJavaRepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.kt"); } @Test - @TestMetadata("javaUnrepeatable.kt") - public void testJavaUnrepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.kt"); + @TestMetadata("javaRepeatable_1_6.kt") + public void testJavaRepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt"); } @Test - @TestMetadata("kotlinRepeatable.kt") - public void testKotlinRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.kt"); + @TestMetadata("javaUnrepeatable_1_5.kt") + public void testJavaUnrepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.kt"); + } + + @Test + @TestMetadata("javaUnrepeatable_1_6.kt") + public void testJavaUnrepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt"); + } + + @Test + @TestMetadata("kotlinRepeatable_1_5.kt") + public void testKotlinRepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.kt"); + } + + @Test + @TestMetadata("kotlinRepeatable_1_6.kt") + public void testKotlinRepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt"); } } diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 23eba7964b2..416cecc4c97 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -496,6 +496,28 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT } } + @Nested + @TestMetadata("compiler/testData/codegen/box/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + public class Repeatable { + @Test + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("javaAnnotation.kt") + public void testJavaAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/repeatable/javaAnnotation.kt"); + } + + @Test + @TestMetadata("jvmRepeatableKotlinAnnotation.kt") + public void testJvmRepeatableKotlinAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/repeatable/jvmRepeatableKotlinAnnotation.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/box/annotations/typeAnnotations") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt index aab2f1f384a..c53cf8ffd72 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.resolve.jvm.checkers +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention @@ -19,13 +20,17 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm -object RepeatableAnnotationChecker : AdditionalAnnotationChecker { +class RepeatableAnnotationChecker(languageVersionSettings: LanguageVersionSettings) : AdditionalAnnotationChecker { + private val nonSourceDisallowed = !languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations) + override fun checkEntries( entries: List, actualTargets: List, trace: BindingTrace, languageVersionSettings: LanguageVersionSettings ) { + if (entries.isEmpty()) return + val entryTypesWithAnnotations = hashMapOf>() for (entry in entries) { @@ -42,7 +47,9 @@ object RepeatableAnnotationChecker : AdditionalAnnotationChecker { && classDescriptor.isRepeatableAnnotation() && classDescriptor.getAnnotationRetention() != KotlinRetention.SOURCE ) { - trace.report(ErrorsJvm.NON_SOURCE_REPEATED_ANNOTATION.on(entry)) + if (nonSourceDisallowed) { + trace.report(ErrorsJvm.NON_SOURCE_REPEATED_ANNOTATION.on(entry)) + } } existingTargetsForAnnotation.add(useSiteTarget) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 27a526602fc..784f48f2fdd 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -71,7 +71,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION, "Only named arguments are available for Java annotations"); 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 not yet supported"); + MAP.put(NON_SOURCE_REPEATED_ANNOTATION, "Repeatable annotations with non-SOURCE retention are only supported starting from Kotlin 1.6"); 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"); 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 17f0ef5d500..ae9f9346d8d 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 @@ -73,7 +73,6 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase( ), additionalAnnotationCheckers = listOf( - RepeatableAnnotationChecker, FileClassAnnotationsChecker, ExplicitMetadataChecker ), @@ -125,5 +124,6 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase( override fun configureModuleDependentCheckers(container: StorageComponentContainer) { super.configureModuleDependentCheckers(container) container.useImpl() + container.useImpl() } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 9fc336a0c47..bea47560a42 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -323,6 +323,7 @@ private val jvmFilePhases = listOf( inventNamesForLocalClassesPhase, kCallableNamePropertyPhase, + repeatedAnnotationPhase, annotationPhase, annotationImplementationPhase, polymorphicSignaturePhase, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt index 07f605c1d1c..952d821d1ae 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt @@ -450,7 +450,7 @@ private fun isBareTypeParameterWithNullableUpperBound(type: IrType): Boolean { private val RETENTION_PARAMETER_NAME = Name.identifier("value") -private fun IrClass.getAnnotationRetention(): KotlinRetention? { +internal fun IrClass.getAnnotationRetention(): KotlinRetention? { val retentionArgument = getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(RETENTION_PARAMETER_NAME) as? IrGetEnumValue ?: return null diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/RepeatedAnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/RepeatedAnnotationLowering.kt new file mode 100644 index 00000000000..cacc2cf6a53 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/RepeatedAnnotationLowering.kt @@ -0,0 +1,110 @@ +/* + * 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.backend.jvm.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.codegen.AnnotationCodegen.Companion.annotationClass +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.IrClassReference +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.isAnnotation +import org.jetbrains.kotlin.ir.util.primaryConstructor +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.load.java.JvmAnnotationNames + +internal val repeatedAnnotationPhase = makeIrFilePhase( + ::RepeatedAnnotationLowering, + name = "RepeatedAnnotation", + description = "Enclose repeated annotations in a container annotation, generating a container class if needed" +) + +class RepeatedAnnotationLowering(private val context: JvmBackendContext) : FileLoweringPass, IrElementVisitorVoid { + override fun lower(irFile: IrFile) { + irFile.acceptVoid(this) + } + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFile(declaration: IrFile) { + declaration.annotations = transformAnnotations(declaration.annotations) + super.visitFile(declaration) + } + + override fun visitDeclaration(declaration: IrDeclarationBase) { + declaration.annotations = transformAnnotations(declaration.annotations) + super.visitDeclaration(declaration) + } + + private fun transformAnnotations(annotations: List): List { + if (annotations.size < 2) return annotations + + val annotationsByClass = annotations.groupByTo(mutableMapOf()) { it.annotationClass } + if (annotationsByClass.values.none { it.size > 1 }) return annotations + + val result = mutableListOf() + for (annotation in annotations) { + val annotationClass = annotation.annotationClass + val grouped = annotationsByClass.remove(annotationClass) ?: continue + if (grouped.size < 2) { + result.add(grouped.single()) + continue + } + + val containerClass = getOrCreateContainerClass(annotationClass) + result.add(wrapAnnotationEntriesInContainer(annotationClass, containerClass, grouped)) + } + return result + } + + private fun getOrCreateContainerClass(annotationClass: IrClass): IrClass { + val metaAnnotations = annotationClass.annotations + val jvmRepeatable = metaAnnotations.find { it.isAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION) } + return if (jvmRepeatable != null) { + val containerClassReference = jvmRepeatable.getValueArgument(0) + require(containerClassReference is IrClassReference) { + "Repeatable annotation container value must be a class reference: $annotationClass" + } + (containerClassReference.symbol as? IrClassSymbol)?.owner + ?: error("Repeatable annotation container must be a class: $annotationClass") + } else { + TODO("Kotlin repeatable annotations") + } + } + + private fun wrapAnnotationEntriesInContainer( + annotationClass: IrClass, + containerClass: IrClass, + entries: List, + ): IrConstructorCall { + val annotationType = annotationClass.typeWith() + return IrConstructorCallImpl.fromSymbolOwner(containerClass.defaultType, containerClass.primaryConstructor!!.symbol).apply { + putValueArgument( + 0, + IrVarargImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + context.irBuiltIns.arrayClass.typeWith(annotationType), + annotationType, + entries + ) + ) + } + } +} diff --git a/compiler/testData/codegen/box/annotations/repeatable/javaAnnotation.kt b/compiler/testData/codegen/box/annotations/repeatable/javaAnnotation.kt new file mode 100644 index 00000000000..358b895cbfa --- /dev/null +++ b/compiler/testData/codegen/box/annotations/repeatable/javaAnnotation.kt @@ -0,0 +1,56 @@ +// !LANGUAGE: +RepeatableAnnotations +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_RUNTIME +// FULL_JDK +// JVM_TARGET: 1.8 + +// java.lang.NoSuchMethodError: java.lang.Class.getAnnotationsByType +// IGNORE_BACKEND: ANDROID + +// FILE: box.kt + +import test.A +import test.As + +@A("O") +@A("") +@A("K") +class Z + +fun box(): String { + val annotations = Z::class.java.annotations.filter { it.annotationClass != Metadata::class } + val aa = annotations.singleOrNull() ?: return "Fail 1: $annotations" + if (aa !is As) return "Fail 2: $aa" + + val a = aa.value.asList() + if (a.size != 3) return "Fail 3: $a" + + val bytype = Z::class.java.getAnnotationsByType(A::class.java) + if (a.toList() != bytype.toList()) return "Fail 4: ${a.toList()} != ${bytype.toList()}" + + return a.fold("") { acc, it -> acc + it.value } +} + +// FILE: test/A.java + +package test; + +import java.lang.annotation.*; + +@Repeatable(As.class) +@Retention(RetentionPolicy.RUNTIME) +public @interface A { + String value(); +} + +// FILE: test/As.java + +package test; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +public @interface As { + A[] value(); +} diff --git a/compiler/testData/codegen/box/annotations/repeatable/jvmRepeatableKotlinAnnotation.kt b/compiler/testData/codegen/box/annotations/repeatable/jvmRepeatableKotlinAnnotation.kt new file mode 100644 index 00000000000..03f3d3e7a2b --- /dev/null +++ b/compiler/testData/codegen/box/annotations/repeatable/jvmRepeatableKotlinAnnotation.kt @@ -0,0 +1,32 @@ +// !LANGUAGE: +RepeatableAnnotations +// TARGET_BACKEND: JVM_IR +// WITH_RUNTIME +// FULL_JDK +// JVM_TARGET: 1.8 + +// java.lang.NoSuchMethodError: java.lang.Class.getAnnotationsByType +// IGNORE_BACKEND: ANDROID + +@java.lang.annotation.Repeatable(As::class) +annotation class A(val value: String) + +annotation class As(val value: Array) + +@A("O") +@A("") +@A("K") +class Z + +fun box(): String { + val annotations = Z::class.java.annotations.filter { it.annotationClass != Metadata::class } + val aa = annotations.singleOrNull() ?: return "Fail 1: $annotations" + if (aa !is As) return "Fail 2: $aa" + + val a = aa.value.asList() + if (a.size != 3) return "Fail 3: $a" + + val bytype = Z::class.java.getAnnotationsByType(A::class.java) + if (a.toList() != bytype.toList()) return "Fail 4: ${a.toList()} != ${bytype.toList()}" + + return a.fold("") { acc, it -> acc + it.value } +} diff --git a/compiler/testData/codegen/bytecodeListing/annotations/repeatable/javaAnnotation.kt b/compiler/testData/codegen/bytecodeListing/annotations/repeatable/javaAnnotation.kt new file mode 100644 index 00000000000..dd77294bbf5 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/repeatable/javaAnnotation.kt @@ -0,0 +1,69 @@ +// !LANGUAGE: +RepeatableAnnotations +// TARGET_BACKEND: JVM_IR +// WITH_RUNTIME +// FULL_JDK +// JVM_TARGET: 1.8 +// FILE: box.kt + +package test + +import test.A +import test.As + +@A("class1") @A("class2") +class Z @A("constructor1") @A("constructor2") constructor() { + @A("nestedClass1") @A("nestedClass2") + annotation class Nested + + @A("memberFunction1") @A("memberFunction2") + fun memberFunction() {} + + @A("memberProperty1") @A("memberProperty2") + var memberProperty: Int + @A("propertyGetter1") @A("propertyGetter2") + get() = 0 + @A("propertySetter1") @A("propertySetter2") + set(value) {} +} + +@A("topLevelFunction1") @A("topLevelFunction2") +fun topLevelFunction2( + @A("parameter1") @A("parameter2") + parameter: String +) {} + +@A("topLevelProperty1") @A("topLevelProperty2") +var String.z: Z + @A("propertyGetter1") @A("propertyGetter2") + get() = Z() + @A("propertySetter1") @A("propertySetter2") + set(value) {} + +@get:A("useSitePropertyGetter1") +@get:A("useSitePropertyGetter2") +@field:A("field1") +@field:A("field2") +val o: String = "" + +// FILE: test/A.java + +package test; + +import java.lang.annotation.*; + +@Repeatable(As.class) +@Retention(RetentionPolicy.RUNTIME) +public @interface A { + String value(); +} + +// FILE: test/As.java + +package test; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +public @interface As { + A[] value(); +} diff --git a/compiler/testData/codegen/bytecodeListing/annotations/repeatable/javaAnnotation.txt b/compiler/testData/codegen/bytecodeListing/annotations/repeatable/javaAnnotation.txt new file mode 100644 index 00000000000..35056346cd9 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/repeatable/javaAnnotation.txt @@ -0,0 +1,31 @@ +@kotlin.Metadata +public final class test/BoxKt { + // source: 'box.kt' + private final static @test.As(value=[test.A(value="field1"), test.A(value="field2")]) @org.jetbrains.annotations.NotNull field o: java.lang.String + static method (): void + public final static @test.As(value=[test.A(value="useSitePropertyGetter1"), test.A(value="useSitePropertyGetter2")]) @org.jetbrains.annotations.NotNull method getO(): java.lang.String + public synthetic deprecated static @test.As(value=[test.A(value="topLevelProperty1"), test.A(value="topLevelProperty2")]) method getZ$annotations(p0: java.lang.String): void + public final static @test.As(value=[test.A(value="propertyGetter1"), test.A(value="propertyGetter2")]) @org.jetbrains.annotations.NotNull method getZ(@org.jetbrains.annotations.NotNull p0: java.lang.String): test.Z + public final static @test.As(value=[test.A(value="propertySetter1"), test.A(value="propertySetter2")]) method setZ(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: test.Z): void + public final static @test.As(value=[test.A(value="topLevelFunction1"), test.A(value="topLevelFunction2")]) method topLevelFunction2(@test.As(value=[test.A(value="parameter1"), test.A(value="parameter2")]) @org.jetbrains.annotations.NotNull p0: java.lang.String): void +} + +@test.As(value=[test.A(value="nestedClass1"), test.A(value="nestedClass2")]) +@java.lang.annotation.Retention(value=RUNTIME) +@kotlin.Metadata +public annotation class test/Z$Nested { + // source: 'box.kt' + public inner class test/Z$Nested +} + +@test.As(value=[test.A(value="class1"), test.A(value="class2")]) +@kotlin.Metadata +public final class test/Z { + // source: 'box.kt' + public @test.As(value=[test.A(value="constructor1"), test.A(value="constructor2")]) method (): void + public synthetic deprecated static @test.As(value=[test.A(value="memberProperty1"), test.A(value="memberProperty2")]) method getMemberProperty$annotations(): void + public final @test.As(value=[test.A(value="propertyGetter1"), test.A(value="propertyGetter2")]) method getMemberProperty(): int + public final @test.As(value=[test.A(value="memberFunction1"), test.A(value="memberFunction2")]) method memberFunction(): void + public final @test.As(value=[test.A(value="propertySetter1"), test.A(value="propertySetter2")]) method setMemberProperty(p0: int): void + public inner class test/Z$Nested +} diff --git a/compiler/testData/codegen/bytecodeListing/annotations/repeatable/nonRepeatedAnnotationWithItsContainer.kt b/compiler/testData/codegen/bytecodeListing/annotations/repeatable/nonRepeatedAnnotationWithItsContainer.kt new file mode 100644 index 00000000000..6bd45970fb3 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/repeatable/nonRepeatedAnnotationWithItsContainer.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +RepeatableAnnotations +// TARGET_BACKEND: JVM_IR +// WITH_RUNTIME +// FULL_JDK +// JVM_TARGET: 1.8 + +package test + +@java.lang.annotation.Repeatable(As::class) +annotation class A(val value: String) + +annotation class As(val value: Array) + +@A("1") +@As([A("2"), A("3")]) +class Z + +@As([A("1"), A("2")]) +@A("3") +class ZZ diff --git a/compiler/testData/codegen/bytecodeListing/annotations/repeatable/nonRepeatedAnnotationWithItsContainer.txt b/compiler/testData/codegen/bytecodeListing/annotations/repeatable/nonRepeatedAnnotationWithItsContainer.txt new file mode 100644 index 00000000000..0effe69b954 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/repeatable/nonRepeatedAnnotationWithItsContainer.txt @@ -0,0 +1,30 @@ +@java.lang.annotation.Repeatable(value=test.As::class) +@java.lang.annotation.Retention(value=RUNTIME) +@kotlin.Metadata +public annotation class test/A { + // source: 'nonRepeatedAnnotationWithItsContainer.kt' + public abstract method value(): java.lang.String +} + +@java.lang.annotation.Retention(value=RUNTIME) +@kotlin.Metadata +public annotation class test/As { + // source: 'nonRepeatedAnnotationWithItsContainer.kt' + public abstract method value(): test.A[] +} + +@test.A(value="1") +@test.As(value=[test.A(value="2"), test.A(value="3")]) +@kotlin.Metadata +public final class test/Z { + // source: 'nonRepeatedAnnotationWithItsContainer.kt' + public method (): void +} + +@test.As(value=[test.A(value="1"), test.A(value="2")]) +@test.A(value="3") +@kotlin.Metadata +public final class test/ZZ { + // source: 'nonRepeatedAnnotationWithItsContainer.kt' + public method (): void +} diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.fir.kt similarity index 95% rename from compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.fir.kt rename to compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.fir.kt index a0086f35abd..ca1795663b3 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.fir.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: -RepeatableAnnotations // FULL_JDK // FILE: Runtime.java diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.kt similarity index 95% rename from compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt rename to compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.kt index 018e8335c60..377fcb361ee 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: -RepeatableAnnotations // FULL_JDK // FILE: Runtime.java diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.txt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.txt similarity index 100% rename from compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.txt rename to compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.txt diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt new file mode 100644 index 00000000000..a1f031934a0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt @@ -0,0 +1,49 @@ +// FIR_IDENTICAL +// !LANGUAGE: +RepeatableAnnotations +// FULL_JDK +// FILE: Runtime.java + +import java.lang.annotation.*; + +@Repeatable(Runtime.Container.class) +@Retention(RetentionPolicy.RUNTIME) +public @interface Runtime { + public @interface Container { + Runtime[] value(); + } +} + +// FILE: Clazz.java + +import java.lang.annotation.*; + +@Repeatable(Clazz.Container.class) +@Retention(RetentionPolicy.CLASS) +public @interface Clazz { + public @interface Container { + Clazz[] value(); + } +} + +// FILE: Source.java + +import java.lang.annotation.*; + +@Repeatable(Source.Container.class) +@Retention(RetentionPolicy.SOURCE) +public @interface Source { + public @interface Container { + Source[] value(); + } +} + +// FILE: usage.kt + +@Runtime @Runtime +class UseRuntime + +@Clazz @Clazz +class UseClazz + +@Source @Source +class UseSource diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.txt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.txt new file mode 100644 index 00000000000..7c295b4f6cc --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.txt @@ -0,0 +1,68 @@ +package + +@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 + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final annotation class Container : kotlin.Annotation { + public constructor Container(/*0*/ vararg value: Clazz /*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 = 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 + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final annotation class Container : kotlin.Annotation { + public constructor Container(/*0*/ vararg value: Runtime /*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 = 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 + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final annotation class Container : kotlin.Annotation { + public constructor Container(/*0*/ vararg value: Source /*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 + } +} + +@Clazz @Clazz public final class UseClazz { + public constructor UseClazz() + 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 +} + +@Runtime @Runtime public final class UseRuntime { + public constructor UseRuntime() + 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 +} + +@Source @Source public final class UseSource { + public constructor UseSource() + 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/javaUnrepeatable.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.fir.kt similarity index 92% rename from compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.fir.kt rename to compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.fir.kt index a2e6a6adb27..82eddbec07e 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.fir.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: -RepeatableAnnotations // FULL_JDK // FILE: Runtime.java diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.kt similarity index 93% rename from compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.kt rename to compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.kt index 47bc855196a..ac0da08e23c 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: -RepeatableAnnotations // FULL_JDK // FILE: Runtime.java diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.txt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.txt similarity index 100% rename from compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.txt rename to compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.txt diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.fir.kt new file mode 100644 index 00000000000..8f966fbcb9c --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.fir.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +RepeatableAnnotations +// FULL_JDK +// FILE: Runtime.java + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Runtime {} + +// FILE: Clazz.java + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +public @interface Clazz {} + +// FILE: Source.java + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.SOURCE) +public @interface Source {} + +// FILE: usage.kt + +@Runtime @Runtime +class UseRuntime + +@Clazz @Clazz +class UseClazz + +@Source @Source +class UseSource diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt new file mode 100644 index 00000000000..cb8a98ca5cd --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +RepeatableAnnotations +// FULL_JDK +// FILE: Runtime.java + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Runtime {} + +// FILE: Clazz.java + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +public @interface Clazz {} + +// FILE: Source.java + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.SOURCE) +public @interface Source {} + +// FILE: usage.kt + +@Runtime @Runtime +class UseRuntime + +@Clazz @Clazz +class UseClazz + +@Source @Source +class UseSource diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.txt b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.txt new file mode 100644 index 00000000000..3ad7ad8f163 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.txt @@ -0,0 +1,44 @@ +package + +@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 + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@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 + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@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 + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@Clazz @Clazz public final class UseClazz { + public constructor UseClazz() + 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 +} + +@Runtime @Runtime public final class UseRuntime { + public constructor UseRuntime() + 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 +} + +@Source @Source public final class UseSource { + public constructor UseSource() + 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/kotlinRepeatable.fir.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.fir.kt similarity index 95% rename from compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.fir.kt rename to compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.fir.kt index 1b3c23a9272..b5179ac8654 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.fir.kt @@ -1,3 +1,5 @@ +// !LANGUAGE: -RepeatableAnnotations + @Repeatable annotation class repann diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.kt similarity index 95% rename from compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.kt rename to compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.kt index cc393f60a39..68de8188765 100644 --- a/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.kt +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.kt @@ -1,3 +1,5 @@ +// !LANGUAGE: -RepeatableAnnotations + @Repeatable annotation class repann @@ -28,4 +30,4 @@ annotation class repexpr @repann @repann fun foo(@repann @repann x: Int): Int { @repexpr @repexpr return x -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.txt b/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.txt similarity index 100% rename from compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.txt rename to compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.txt diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt new file mode 100644 index 00000000000..ca511fc7965 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt @@ -0,0 +1,34 @@ +// FIR_IDENTICAL +// !LANGUAGE: +RepeatableAnnotations + +@Repeatable +annotation class repann + +@Retention(AnnotationRetention.SOURCE) +@Repeatable +annotation class repann1(val x: Int) + +@Retention(AnnotationRetention.SOURCE) +@Repeatable +annotation class repann2(val f: Boolean) + +@Retention(AnnotationRetention.BINARY) +@Repeatable +annotation class binrepann + +@Target(AnnotationTarget.EXPRESSION) +@Retention(AnnotationRetention.SOURCE) +@Repeatable +annotation class repexpr + +@repann @repann class DoubleAnnotated + +@repann1(1) @repann1(2) @repann1(3) class TripleAnnotated + +@repann2(true) @repann2(false) @repann2(false) @repann2(true) class FourTimesAnnotated + +@binrepann @binrepann class BinaryAnnotated + +@repann @repann fun foo(@repann @repann x: Int): Int { + @repexpr @repexpr return x +} diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.txt b/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.txt new file mode 100644 index 00000000000..225e401362a --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.txt @@ -0,0 +1,68 @@ +package + +@repann @repann public fun foo(/*0*/ @repann @repann x: kotlin.Int): kotlin.Int + +@binrepann @binrepann public final class BinaryAnnotated { + public constructor BinaryAnnotated() + 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 +} + +@repann @repann public final class DoubleAnnotated { + public constructor DoubleAnnotated() + 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 +} + +@repann2(f = true) @repann2(f = false) @repann2(f = false) @repann2(f = true) public final class FourTimesAnnotated { + public constructor FourTimesAnnotated() + 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 +} + +@repann1(x = 1) @repann1(x = 2) @repann1(x = 3) public final class TripleAnnotated { + public constructor TripleAnnotated() + 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.annotation.Retention(value = AnnotationRetention.BINARY) @kotlin.annotation.Repeatable public final annotation class binrepann : kotlin.Annotation { + public constructor binrepann() + 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.annotation.Repeatable 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 +} + +@kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.Repeatable public final annotation class repann1 : kotlin.Annotation { + public constructor repann1(/*0*/ x: kotlin.Int) + public final val x: kotlin.Int + 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.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.Repeatable public final annotation class repann2 : kotlin.Annotation { + public constructor repann2(/*0*/ f: kotlin.Boolean) + public final val f: 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 toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.EXPRESSION}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.Repeatable public final annotation class repexpr : kotlin.Annotation { + public constructor repexpr() + 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/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 e5245d9100f..f384eaa1ba3 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 @@ -2101,21 +2101,39 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { } @Test - @TestMetadata("javaRepeatable.kt") - public void testJavaRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt"); + @TestMetadata("javaRepeatable_1_5.kt") + public void testJavaRepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.kt"); } @Test - @TestMetadata("javaUnrepeatable.kt") - public void testJavaUnrepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.kt"); + @TestMetadata("javaRepeatable_1_6.kt") + public void testJavaRepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt"); } @Test - @TestMetadata("kotlinRepeatable.kt") - public void testKotlinRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.kt"); + @TestMetadata("javaUnrepeatable_1_5.kt") + public void testJavaUnrepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.kt"); + } + + @Test + @TestMetadata("javaUnrepeatable_1_6.kt") + public void testJavaUnrepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt"); + } + + @Test + @TestMetadata("kotlinRepeatable_1_5.kt") + public void testKotlinRepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.kt"); + } + + @Test + @TestMetadata("kotlinRepeatable_1_6.kt") + public void testKotlinRepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt"); } } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index f9e89f1ce52..c33321c6f8c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -436,6 +436,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @Nested + @TestMetadata("compiler/testData/codegen/box/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + public class Repeatable { + @Test + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + } + @Nested @TestMetadata("compiler/testData/codegen/box/annotations/typeAnnotations") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java index c18d059f8cf..357ba2165f3 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeListingTestGenerated.java @@ -423,6 +423,16 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { public void testUnsignedTypes() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/annotations/unsignedTypes.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/bytecodeListing/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + public class Repeatable { + @Test + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + } } @Nested diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index ce48292e426..3a36d5d046f 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -496,6 +496,28 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } } + @Nested + @TestMetadata("compiler/testData/codegen/box/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + public class Repeatable { + @Test + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("javaAnnotation.kt") + public void testJavaAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/repeatable/javaAnnotation.kt"); + } + + @Test + @TestMetadata("jvmRepeatableKotlinAnnotation.kt") + public void testJvmRepeatableKotlinAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/repeatable/jvmRepeatableKotlinAnnotation.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/box/annotations/typeAnnotations") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java index 345ec1b4319..ce6a98d118d 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeListingTestGenerated.java @@ -423,6 +423,28 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes public void testUnsignedTypes() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/annotations/unsignedTypes.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/bytecodeListing/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + public class Repeatable { + @Test + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("javaAnnotation.kt") + public void testJavaAnnotation() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/annotations/repeatable/javaAnnotation.kt"); + } + + @Test + @TestMetadata("nonRepeatedAnnotationWithItsContainer.kt") + public void testNonRepeatedAnnotationWithItsContainer() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/annotations/repeatable/nonRepeatedAnnotationWithItsContainer.kt"); + } + } } @Nested diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index fa32b67ef30..c3b279cc274 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -391,6 +391,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes } } + @TestMetadata("compiler/testData/codegen/box/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Repeatable extends AbstractLightAnalysisModeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/typeAnnotations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) 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 807643ae0ce..a88f26e1438 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 @@ -2095,21 +2095,39 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag } @Test - @TestMetadata("javaRepeatable.kt") - public void testJavaRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable.kt"); + @TestMetadata("javaRepeatable_1_5.kt") + public void testJavaRepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_5.kt"); } @Test - @TestMetadata("javaUnrepeatable.kt") - public void testJavaUnrepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable.kt"); + @TestMetadata("javaRepeatable_1_6.kt") + public void testJavaRepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaRepeatable_1_6.kt"); } @Test - @TestMetadata("kotlinRepeatable.kt") - public void testKotlinRepeatable() throws Exception { - runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable.kt"); + @TestMetadata("javaUnrepeatable_1_5.kt") + public void testJavaUnrepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_5.kt"); + } + + @Test + @TestMetadata("javaUnrepeatable_1_6.kt") + public void testJavaUnrepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/javaUnrepeatable_1_6.kt"); + } + + @Test + @TestMetadata("kotlinRepeatable_1_5.kt") + public void testKotlinRepeatable_1_5() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_5.kt"); + } + + @Test + @TestMetadata("kotlinRepeatable_1_6.kt") + public void testKotlinRepeatable_1_6() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/repeatable/kotlinRepeatable_1_6.kt"); } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 0733926f180..6c993065d70 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -106,6 +106,19 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes } } + @TestMetadata("compiler/testData/codegen/box/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Repeatable extends AbstractIrJsCodegenBoxES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/typeAnnotations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 76c1bd6e39e..c05c5d18bab 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -106,6 +106,19 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Repeatable extends AbstractIrJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/typeAnnotations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 5aebd79dc1b..29a30a5ab00 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -106,6 +106,19 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Repeatable extends AbstractJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/repeatable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/typeAnnotations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 09c8f512eb7..ea971240182 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -101,6 +101,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest } } + @TestMetadata("compiler/testData/codegen/box/annotations/repeatable") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Repeatable extends AbstractIrCodegenBoxWasmTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath); + } + + public void testAllFilesPresentInRepeatable() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/repeatable"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); + } + } + @TestMetadata("compiler/testData/codegen/box/annotations/typeAnnotations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)