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 8b7c4593348..7a4c916782a 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 @@ -1001,6 +1001,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.kt"); } + @Test + @TestMetadata("AnnotationForClassTypeParameter_typeUseFlag.kt") + public void testAnnotationForClassTypeParameter_typeUseFlag() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt"); + } + @Test @TestMetadata("AnnotationForFunctionTypeParameter.kt") public void testAnnotationForFunctionTypeParameter() 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 a5e3b03c05a..6b1253bc4c3 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 @@ -1001,6 +1001,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.kt"); } + @Test + @TestMetadata("AnnotationForClassTypeParameter_typeUseFlag.kt") + public void testAnnotationForClassTypeParameter_typeUseFlag() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt"); + } + @Test @TestMetadata("AnnotationForFunctionTypeParameter.kt") public void testAnnotationForFunctionTypeParameter() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt index bdfd21074c6..785d3ead555 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation import org.jetbrains.kotlin.resolve.inline.InlineUtil +import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils @@ -53,8 +54,16 @@ class AnnotationChecker( } if ( annotated is KtTypeParameterListOwner && - (annotated is KtCallableDeclaration || languageVersionSettings.supportsFeature(ProperCheckAnnotationsTargetInTypeUsePositions)) + (annotated is KtCallableDeclaration || languageVersionSettings.supportsFeature(ProperCheckAnnotationsTargetInTypeUsePositions) || + (annotated is KtClass && languageVersionSettings.supportsFeature(ClassTypeParameterAnnotations))) ) { + if (annotated is KtClass && languageVersionSettings.supportsFeature(ClassTypeParameterAnnotations)) { + (descriptor as? ClassDescriptor)?.declaredTypeParameters?.forEach { + //force annotation resolve to obtain targets + ForceResolveUtil.forceResolveAllContents(it.annotations) + } + } + annotated.typeParameters.forEach { check(it, trace) } for (typeParameter in annotated.typeParameters) { typeParameter.extendsBound?.let { diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.fir.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.fir.kt index 51db9183ab8..fd5a2fc1b9c 100644 --- a/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.fir.kt @@ -4,21 +4,22 @@ annotation class A2(val some: Int = 12) @Target(AnnotationTarget.TYPE) annotation class TA1 + @Target(AnnotationTarget.TYPE_PARAMETER) annotation class TA2(val some: Int = 12) -class TopLevelClass<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> { - class InnerClass<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> { +class TopLevelClass<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> { + class InnerClass<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> { fun test() { - class InFun<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> + class InFun<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> } } } -class TTopLevelClass<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> { - class TInnerClass<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> { +class TTopLevelClass<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> { + class TInnerClass<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> { fun test() { - class TInFun<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> + class TInFun<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> } } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.fir.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.fir.kt new file mode 100644 index 00000000000..82f7743c77b --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.fir.kt @@ -0,0 +1,26 @@ +// !LANGUAGE: +ProperCheckAnnotationsTargetInTypeUsePositions + +annotation class A1 +annotation class A2(val some: Int = 12) + +@Target(AnnotationTarget.TYPE) +annotation class TA1 + +@Target(AnnotationTarget.TYPE_PARAMETER) +annotation class TA2(val some: Int = 12) + +class TopLevelClass<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> { + class InnerClass<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> { + fun test() { + class InFun<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> + } + } +} + +class TTopLevelClass<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> { + class TInnerClass<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> { + fun test() { + class TInFun<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> + } + } +} diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt new file mode 100644 index 00000000000..24b3dab12f1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt @@ -0,0 +1,26 @@ +// !LANGUAGE: +ProperCheckAnnotationsTargetInTypeUsePositions + +annotation class A1 +annotation class A2(val some: Int = 12) + +@Target(AnnotationTarget.TYPE) +annotation class TA1 + +@Target(AnnotationTarget.TYPE_PARAMETER) +annotation class TA2(val some: Int = 12) + +class TopLevelClass<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> { + class InnerClass<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> { + fun test() { + class InFun<@A1 @A2(3) @A2 @A1(12) @A2("Test") T> + } + } +} + +class TTopLevelClass<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> { + class TInnerClass<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> { + fun test() { + class TInFun<@TA1 @TA2(3) @TA2 @TA1(12) @TA2("Test") T> + } + } +} diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.txt b/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.txt new file mode 100644 index 00000000000..815e36ef884 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.txt @@ -0,0 +1,61 @@ +package + +public final annotation class A1 : kotlin.Annotation { + public constructor A1() + 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 A2 : kotlin.Annotation { + public constructor A2(/*0*/ some: kotlin.Int = ...) + public final val some: 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.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class TA1 : kotlin.Annotation { + public constructor TA1() + 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.TYPE_PARAMETER}) public final annotation class TA2 : kotlin.Annotation { + public constructor TA2(/*0*/ some: kotlin.Int = ...) + public final val some: 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 +} + +public final class TTopLevelClass { + public constructor TTopLevelClass() + 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 class TInnerClass { + public constructor TInnerClass() + 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 final fun test(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public final class TopLevelClass { + public constructor TopLevelClass() + 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 class InnerClass { + public constructor InnerClass() + 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 final fun test(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.fir.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.fir.kt index ac4dd679e26..43c2ac054ec 100644 --- a/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.fir.kt @@ -10,3 +10,18 @@ class SomeClass { fun <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> innerFun() = 12 } } + +@Target(AnnotationTarget.TYPE) +annotation class TA +@Target(AnnotationTarget.TYPE_PARAMETER) +annotation class TPA(val some: Int = 12) + +fun <@TA @TPA(3) @TPA @TA(12) @TPA("Test") T> topFunTPA() = 12 + +class SomeClassTPA { + fun <@TA @TPA(3) @TPA @TA(12) @TPA("Test") T> method() = 12 + + fun foo() { + fun <@TA @TPA(3) @TPA @TA(12) @TPA("Test") T> innerFun() = 12 + } +} diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.kt index 3d99339006f..12e2f52bfc6 100644 --- a/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.kt +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.kt @@ -10,3 +10,18 @@ class SomeClass { fun <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> innerFun() = 12 } } + +@Target(AnnotationTarget.TYPE) +annotation class TA +@Target(AnnotationTarget.TYPE_PARAMETER) +annotation class TPA(val some: Int = 12) + +fun <@TA @TPA(3) @TPA @TA(12) @TPA("Test") T> topFunTPA() = 12 + +class SomeClassTPA { + fun <@TA @TPA(3) @TPA @TA(12) @TPA("Test") T> method() = 12 + + fun foo() { + fun <@TA @TPA(3) @TPA @TA(12) @TPA("Test") T> innerFun() = 12 + } +} diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.txt b/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.txt index d8974589996..7206c030c57 100644 --- a/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.txt +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.txt @@ -1,6 +1,7 @@ package public fun topFun(): kotlin.Int +public fun topFunTPA(): kotlin.Int public final annotation class A1 : kotlin.Annotation { public constructor A1() @@ -25,3 +26,28 @@ public final class SomeClass { public final fun method(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + +public final class SomeClassTPA { + public constructor SomeClassTPA() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun method(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class TA : kotlin.Annotation { + public constructor TA() + 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.TYPE_PARAMETER}) public final annotation class TPA : kotlin.Annotation { + public constructor TPA(/*0*/ some: kotlin.Int = ...) + public final val some: 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 +} + 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 c6f1c6b736b..cf2f301e7e9 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 @@ -1001,6 +1001,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.kt"); } + @Test + @TestMetadata("AnnotationForClassTypeParameter_typeUseFlag.kt") + public void testAnnotationForClassTypeParameter_typeUseFlag() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt"); + } + @Test @TestMetadata("AnnotationForFunctionTypeParameter.kt") public void testAnnotationForFunctionTypeParameter() throws Exception { diff --git a/core/builtins/src/kotlin/annotation/Annotations.kt b/core/builtins/src/kotlin/annotation/Annotations.kt index 119dbfa55d6..f03975300f5 100644 --- a/core/builtins/src/kotlin/annotation/Annotations.kt +++ b/core/builtins/src/kotlin/annotation/Annotations.kt @@ -26,7 +26,7 @@ public enum class AnnotationTarget { CLASS, /** Annotation class only */ ANNOTATION_CLASS, - /** Generic type parameter (unsupported yet) */ + /** Generic type parameter */ TYPE_PARAMETER, /** Property */ PROPERTY, 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 722d93c542d..f14e63b2f1f 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 @@ -848,6 +848,11 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.kt"); } + @TestMetadata("AnnotationForClassTypeParameter_typeUseFlag.kt") + public void testAnnotationForClassTypeParameter_typeUseFlag() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt"); + } + @TestMetadata("AnnotationForFunctionTypeParameter.kt") public void testAnnotationForFunctionTypeParameter() throws Exception { runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.kt");