diff --git a/compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.fir.txt b/compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.fir.txt index d94e4fc3f3d..62029809d55 100644 --- a/compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.fir.txt @@ -1,17 +1,17 @@ FILE: annotationUsedAsAnnotationArgument.kt - public final annotation class Ann : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|(vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|)) @R|kotlin/annotation/Retention|(Q|kotlin/annotation/AnnotationRetention|.R|kotlin/annotation/AnnotationRetention.SOURCE|) public final annotation class Ann : R|kotlin/Annotation| { public constructor(): R|Ann| { super() } } - public final annotation class Ann2 : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|(vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|)) @R|kotlin/annotation/Retention|(Q|kotlin/annotation/AnnotationRetention|.R|kotlin/annotation/AnnotationRetention.SOURCE|) public final annotation class Ann2 : R|kotlin/Annotation| { public constructor(): R|Ann2| { super() } } - public final annotation class Ann3 : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|(vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|)) @R|kotlin/annotation/Retention|(Q|kotlin/annotation/AnnotationRetention|.R|kotlin/annotation/AnnotationRetention.SOURCE|) public final annotation class Ann3 : R|kotlin/Annotation| { public constructor(arg: R|kotlin/Int|, s: R|kotlin/String|): R|Ann3| { super() } diff --git a/compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.kt b/compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.kt index 6bb87e3d5cd..710d7d92063 100644 --- a/compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.kt +++ b/compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.kt @@ -1,7 +1,15 @@ +// WITH_RUNTIME + +@Target(AnnotationTarget.EXPRESSION) +@Retention(AnnotationRetention.SOURCE) annotation class Ann +@Target(AnnotationTarget.EXPRESSION) +@Retention(AnnotationRetention.SOURCE) annotation class Ann2 +@Target(AnnotationTarget.EXPRESSION) +@Retention(AnnotationRetention.SOURCE) annotation class Ann3(val arg: Int, val s: String) @Ann3( diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/annotations.fir.txt b/compiler/fir/analysis-tests/testData/resolve/expresssions/annotations.fir.txt index e476ef9184f..67412742ae4 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/annotations.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/annotations.fir.txt @@ -1,5 +1,5 @@ FILE: annotations.kt - public final annotation class MyAnn : R|kotlin/Annotation| { + @R|kotlin/annotation/Retention|(Q|kotlin/annotation/AnnotationRetention|.R|kotlin/annotation/AnnotationRetention.SOURCE|) @R|kotlin/annotation/Target|(vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|)) public final annotation class MyAnn : R|kotlin/Annotation| { public constructor(): R|MyAnn| { super() } diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/annotations.kt b/compiler/fir/analysis-tests/testData/resolve/expresssions/annotations.kt index d0e10bef1e9..bdf08d2430a 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/annotations.kt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/annotations.kt @@ -1,3 +1,7 @@ +// WITH_RUNTIME + +@Retention(AnnotationRetention.SOURCE) +@Target(AnnotationTarget.EXPRESSION) annotation class MyAnn fun bar(x: Int) {} diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 4dab107f228..09777cb79e0 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -173,6 +173,9 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val ANNOTATION_ON_SUPERCLASS by error() val RESTRICTED_RETENTION_FOR_EXPRESSION_ANNOTATION by error() + val WRONG_ANNOTATION_TARGET by error { + parameter("actualTarget") + } } val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index bda4ef2de9d..d6e05365252 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -179,6 +179,7 @@ object FirErrors { val DEPRECATED_SINCE_KOTLIN_OUTSIDE_KOTLIN_SUBPACKAGE by error0(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val ANNOTATION_ON_SUPERCLASS by error0() val RESTRICTED_RETENTION_FOR_EXPRESSION_ANNOTATION by error0() + val WRONG_ANNOTATION_TARGET by error1() // Exposed visibility val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3(SourceElementPositioningStrategies.DECLARATION_NAME) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt index b6fc09d2a7e..f59b022711b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt @@ -9,13 +9,11 @@ import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression -import org.jetbrains.kotlin.fir.expressions.FirVarargArgumentsExpression -import org.jetbrains.kotlin.fir.expressions.argumentMapping +import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.FirErrorTypeRef import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -30,12 +28,8 @@ fun FirAnnotationCall.getRetention(session: FirSession): AnnotationRetention { fun FirRegularClass.getRetention(): AnnotationRetention { val retentionAnnotation = getRetentionAnnotation() ?: return AnnotationRetention.RUNTIME - val argumentMapping = retentionAnnotation.argumentMapping ?: return AnnotationRetention.RUNTIME - val retentionArgument = argumentMapping.keys.firstOrNull() as? FirQualifiedAccessExpression + val retentionArgument = retentionAnnotation.findSingleArgumentByName(RETENTION_PARAMETER_NAME) as? FirQualifiedAccessExpression ?: return AnnotationRetention.RUNTIME - if (argumentMapping[retentionArgument]?.name != RETENTION_PARAMETER_NAME) { - return AnnotationRetention.RUNTIME - } val retentionName = (retentionArgument.calleeReference as? FirResolvedNamedReference)?.name?.asString() ?: return AnnotationRetention.RUNTIME return AnnotationRetention.values().firstOrNull { it.name == retentionName } ?: AnnotationRetention.RUNTIME @@ -54,19 +48,20 @@ private val defaultAnnotationTargets = listOf( ) fun FirAnnotationCall.getAllowedAnnotationTargets(session: FirSession): List { + if (annotationTypeRef is FirErrorTypeRef) return AnnotationTarget.values().toList() val annotationClass = (this.annotationTypeRef.coneType as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass return annotationClass?.getAllowedAnnotationTargets() ?: defaultAnnotationTargets } fun FirRegularClass.getAllowedAnnotationTargets(): List { val targetAnnotation = getTargetAnnotation() ?: return defaultAnnotationTargets - val argumentMapping = targetAnnotation.argumentMapping ?: return defaultAnnotationTargets - val targetArgument = argumentMapping.keys.firstOrNull() as? FirVarargArgumentsExpression - ?: return defaultAnnotationTargets - if (argumentMapping[targetArgument]?.name != TARGET_PARAMETER_NAME) { - return defaultAnnotationTargets + val arguments = when (val targetArgument = targetAnnotation.findSingleArgumentByName(TARGET_PARAMETER_NAME)) { + is FirVarargArgumentsExpression -> targetArgument.arguments + is FirArrayOfCall -> targetArgument.arguments + else -> return defaultAnnotationTargets } - return targetArgument.arguments.mapNotNull { argument -> + + return arguments.mapNotNull { argument -> val targetExpression = argument as? FirQualifiedAccessExpression val targetName = (targetExpression?.calleeReference as? FirResolvedNamedReference)?.name?.asString() ?: return@mapNotNull null AnnotationTarget.values().firstOrNull { target -> target.name == targetName } @@ -87,3 +82,13 @@ fun FirAnnotatedDeclaration.getAnnotationByFqName(fqName: FqName): FirAnnotation } } +fun FirAnnotationCall.findSingleArgumentByName(name: Name): FirExpression? { + val argumentMapping = argumentMapping + if (argumentMapping != null) { + return argumentMapping.keys.firstOrNull()?.takeIf { argumentMapping[it]?.name == name } + } + // NB: we have to consider both cases, because deserializer does not create argument mapping + val firstArgument = argumentList.arguments.firstOrNull() as? FirNamedArgumentExpression ?: return null + return firstArgument.takeIf { it.name == name }?.expression +} + diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionAnnotationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionAnnotationChecker.kt index ce6e648c894..6757df6df21 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionAnnotationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionAnnotationChecker.kt @@ -5,19 +5,31 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression +import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets -import org.jetbrains.kotlin.fir.analysis.checkers.getRetention import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.expressions.FirBlock +import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirStatement object FirExpressionAnnotationChecker : FirBasicExpressionChecker() { override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { + // Declarations are checked separately + // See KT-33658 about annotations on non-expression statements + if (expression is FirDeclaration || + expression !is FirExpression || + expression is FirBlock && expression.source?.kind == FirFakeSourceElementKind.DesugaredForLoop + ) return for (annotation in expression.annotations) { withSuppressedDiagnostics(annotation, context) { + if (AnnotationTarget.EXPRESSION !in annotation.getAllowedAnnotationTargets(context.session)) { + reporter.reportOn(annotation.source, FirErrors.WRONG_ANNOTATION_TARGET, "expression", context) + } } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 27f7add5a51..a5f74505e62 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -328,6 +328,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIANCE_ON_TYPE_ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_ANNOTATION_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_OVERRIDDEN_BY_VAL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_TYPE_MISMATCH_ON_OVERRIDE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_ANNOTATION_TARGET import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_GETTER_RETURN_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_INVOCATION_KIND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_MODIFIER_TARGET @@ -476,6 +477,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { "DeprecatedSinceKotlin annotation cannot be used outside 'kotlin' subpackages" ) map.put(ANNOTATION_ON_SUPERCLASS, "Annotations on superclass are meaningless") + map.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING); // Exposed visibility group // # map.put( diff --git a/compiler/testData/diagnostics/tests/Casts.fir.kt b/compiler/testData/diagnostics/tests/Casts.fir.kt index eb6615ef52c..9c1a5774b9a 100644 --- a/compiler/testData/diagnostics/tests/Casts.fir.kt +++ b/compiler/testData/diagnostics/tests/Casts.fir.kt @@ -18,6 +18,6 @@ fun test() : Unit { val s = "" as Any ("" as String?)?.length (data@("" as String?))?.length - (@MustBeDocumented()( "" as String?))?.length + (@MustBeDocumented()( "" as String?))?.length Unit } diff --git a/compiler/testData/diagnostics/tests/annotations/options/functions.fir.kt b/compiler/testData/diagnostics/tests/annotations/options/functions.fir.kt index a0e1826f4ec..75c730eb87c 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/functions.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/functions.fir.kt @@ -33,8 +33,8 @@ fun foo(arg: Int) { // Function expression too val f = @FunAnn fun(): Int { return 42 } // But here, f and gav should be annotated instead - bar(@FunAnn f) - bar(@FunAnn ::gav) + bar(@FunAnn f) + bar(@FunAnn ::gav) // Function expression, ok fast(f) } diff --git a/compiler/testData/diagnostics/tests/annotations/options/prefix.fir.kt b/compiler/testData/diagnostics/tests/annotations/options/prefix.fir.kt deleted file mode 100644 index 8eb29e09ae3..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/options/prefix.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -@Target(AnnotationTarget.FUNCTION) -annotation class FunAnn - -@Target(AnnotationTarget.EXPRESSION) -@Retention(AnnotationRetention.SOURCE) -annotation class ExprAnn - -fun foo(): Int { - var x = 5 - @FunAnn ++x - @ExprAnn ++x - return x -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/options/prefix.kt b/compiler/testData/diagnostics/tests/annotations/options/prefix.kt index 1b77ce9d700..23516e6bc8a 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/prefix.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/prefix.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL @Target(AnnotationTarget.FUNCTION) annotation class FunAnn diff --git a/compiler/testData/diagnostics/tests/annotations/options/targets/empty.fir.kt b/compiler/testData/diagnostics/tests/annotations/options/targets/empty.fir.kt index 19674e7f39b..ca56a70c52c 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/targets/empty.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/targets/empty.fir.kt @@ -18,4 +18,4 @@ return local } -@empty val z = @empty 0 +@empty val z = @empty 0 diff --git a/compiler/testData/diagnostics/tests/annotations/options/targets/expr.fir.kt b/compiler/testData/diagnostics/tests/annotations/options/targets/expr.fir.kt index 0c3f82d9278..77b6e6a32f5 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/targets/expr.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/targets/expr.fir.kt @@ -4,10 +4,10 @@ annotation class base @Retention(AnnotationRetention.SOURCE) annotation class special -fun transform(i: Int, tr: (Int) -> Int): Int = @base @special tr(@special i) +fun transform(i: Int, tr: (Int) -> Int): Int = @base @special tr(@special i) @base @special fun foo(i: Int): Int { - val j = @base @special i + 1 - if (j == 1) return foo(@special @base 42) + val j = @base @special i + 1 + if (j == 1) return foo(@special @base 42) return transform(@special j, @base @special { @special it * 2 }) } diff --git a/compiler/testData/diagnostics/tests/annotations/options/targets/funtypeargs.fir.kt b/compiler/testData/diagnostics/tests/annotations/options/targets/funtypeargs.fir.kt index 5374da7895c..12abd2c8ec1 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/targets/funtypeargs.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/targets/funtypeargs.fir.kt @@ -10,5 +10,5 @@ fun transform(i: Int, tr: (@special Int) -> Int): Int = @special tr(@special i) fun foo(i: Int): Int { val j = @special i + 1 if (j == 1) return foo(@special 42) - return transform(@special j, @special { i: @base Int -> @base i * 2 }) + return transform(@special j, @special { i: @base Int -> @base i * 2 }) } diff --git a/compiler/testData/diagnostics/tests/annotations/options/targets/incorrect.fir.kt b/compiler/testData/diagnostics/tests/annotations/options/targets/incorrect.fir.kt index fe4219516fd..b9cc70894c0 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/targets/incorrect.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/targets/incorrect.fir.kt @@ -18,4 +18,4 @@ return local } -@incorrect val z = @incorrect 0 +@incorrect val z = @incorrect 0 diff --git a/compiler/testData/diagnostics/tests/annotations/options/targets/java.fir.kt b/compiler/testData/diagnostics/tests/annotations/options/targets/java.fir.kt index 7d9b683f27e..86245ec9a5b 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/targets/java.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/targets/java.fir.kt @@ -75,7 +75,7 @@ import test.AnnotationTargets.* ): @fieldann @parameter Int { @local @base @multiple @fieldann val j = i + 1 - @base @multiple return j + @base @multiple return j } @base @method @konstructor constructor(): this(0) diff --git a/compiler/testData/diagnostics/tests/when/AnnotatedWhenStatement.fir.kt b/compiler/testData/diagnostics/tests/when/AnnotatedWhenStatement.fir.kt new file mode 100644 index 00000000000..b6ca536bc6d --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/AnnotatedWhenStatement.fir.kt @@ -0,0 +1,17 @@ +/* + * KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE) + * + * SPEC VERSION: 0.1-313 + * PRIMARY LINKS: expressions, when-expression -> paragraph 9 -> sentence 2 + * expressions, when-expression -> paragraph 5 -> sentence 1 + * expressions, when-expression -> paragraph 6 -> sentence 5 + * annotations, annotation-targets -> paragraph 1 -> sentence 1 + */ +fun foo(a: Int) { + @ann + when (a) { + 1 -> {} + } +} + +annotation class ann diff --git a/compiler/testData/diagnostics/tests/when/AnnotatedWhenStatement.kt b/compiler/testData/diagnostics/tests/when/AnnotatedWhenStatement.kt index bf20a34f100..84ecf771803 100644 --- a/compiler/testData/diagnostics/tests/when/AnnotatedWhenStatement.kt +++ b/compiler/testData/diagnostics/tests/when/AnnotatedWhenStatement.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE) * diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 8d26fa1d2ab..bf0eed1b61d 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -613,6 +613,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.WRONG_ANNOTATION_TARGET) { firDiagnostic -> + WrongAnnotationTargetImpl( + firDiagnostic.a, + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic -> ExposedTypealiasExpandedTypeImpl( firDiagnostic.a, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 432467bb54d..6ccce2a267c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -438,6 +438,11 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = RestrictedRetentionForExpressionAnnotation::class } + abstract class WrongAnnotationTarget : KtFirDiagnostic() { + override val diagnosticClass get() = WrongAnnotationTarget::class + abstract val actualTarget: String + } + abstract class ExposedTypealiasExpandedType : KtFirDiagnostic() { override val diagnosticClass get() = ExposedTypealiasExpandedType::class abstract val elementVisibility: EffectiveVisibility diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index a095ba95778..f73ee85dca3 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -712,6 +712,14 @@ internal class RestrictedRetentionForExpressionAnnotationImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class WrongAnnotationTargetImpl( + override val actualTarget: String, + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.WrongAnnotationTarget(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ExposedTypealiasExpandedTypeImpl( override val elementVisibility: EffectiveVisibility, override val restrictingDeclaration: KtSymbol,