diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt index 83670155944..2f65b538860 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticL import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.* +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtAnnotationEntry @Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused") @@ -41,6 +42,9 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") { val OVERLOADS_LOCAL by error() val OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR by deprecationError(LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses) val OVERLOADS_PRIVATE by warning() + val DEPRECATED_JAVA_ANNOTATION by warning() { + parameter("kotlinName") + } } } diff --git a/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt b/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt index 83b36032ac6..3ae15d9f6b7 100644 --- a/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt +++ b/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt @@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.config.LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses import org.jetbrains.kotlin.fir.analysis.diagnostics.* import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtExpression @@ -37,5 +38,6 @@ object FirJvmErrors { val OVERLOADS_LOCAL by error0() val OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR by deprecationError0(ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses) val OVERLOADS_PRIVATE by warning0() + val DEPRECATED_JAVA_ANNOTATION by warning1() } diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmExpressionCheckers.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmExpressionCheckers.kt index f26428df98f..1cb43130a62 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmExpressionCheckers.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmExpressionCheckers.kt @@ -6,7 +6,9 @@ package org.jetbrains.kotlin.fir.analysis.jvm.checkers import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers +import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnnotationCallChecker import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker +import org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression.FirDeprecatedJavaAnnotationsChecker import org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression.FirJavaGenericVarianceViolationTypeChecker object JvmExpressionCheckers : ExpressionCheckers() { @@ -14,4 +16,9 @@ object JvmExpressionCheckers : ExpressionCheckers() { get() = setOf( FirJavaGenericVarianceViolationTypeChecker, ) + + override val annotationCallCheckers: Set + get() = setOf( + FirDeprecatedJavaAnnotationsChecker, + ) } diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirDeprecatedJavaAnnotationsChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirDeprecatedJavaAnnotationsChecker.kt new file mode 100644 index 00000000000..94174646e2d --- /dev/null +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirDeprecatedJavaAnnotationsChecker.kt @@ -0,0 +1,39 @@ +/* + * 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.fir.analysis.jvm.checkers.expression + +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.fir.FirRealSourceElementKind +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnnotationCallChecker +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors +import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn +import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall +import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.coneTypeSafe +import org.jetbrains.kotlin.load.java.JvmAnnotationNames +import org.jetbrains.kotlin.name.FqName + +object FirDeprecatedJavaAnnotationsChecker : FirAnnotationCallChecker() { + + private val javaToKotlinNameMap: Map = + mapOf( + JvmAnnotationNames.TARGET_ANNOTATION to StandardNames.FqNames.target, + JvmAnnotationNames.RETENTION_ANNOTATION to StandardNames.FqNames.retention, + JvmAnnotationNames.DEPRECATED_ANNOTATION to StandardNames.FqNames.deprecated, + JvmAnnotationNames.DOCUMENTED_ANNOTATION to StandardNames.FqNames.mustBeDocumented + ) + + override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) { + if (context.containingDeclarations.lastOrNull()?.source?.kind != FirRealSourceElementKind) return + + val lookupTag = expression.annotationTypeRef.coneTypeSafe()?.lookupTag ?: return + javaToKotlinNameMap[lookupTag.classId.asSingleFqName()]?.let { betterName -> + reporter.reportOn(expression.source, FirJvmErrors.DEPRECATED_JAVA_ANNOTATION, betterName, context) + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/AmbigiousAnnotationConstructor.fir.kt b/compiler/testData/diagnostics/tests/annotations/AmbigiousAnnotationConstructor.fir.kt index 50926c635e0..e5a449e5afc 100644 --- a/compiler/testData/diagnostics/tests/annotations/AmbigiousAnnotationConstructor.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/AmbigiousAnnotationConstructor.fir.kt @@ -2,4 +2,4 @@ import java.util.ArrayList @ArrayList(1, 1) fun b() {} @Xoo(x) fun c() {} -@java.lang.Deprecated(x) fun a() {} +@java.lang.Deprecated(x) fun a() {} diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotatedConstructorParams.fir.kt b/compiler/testData/diagnostics/tests/annotations/AnnotatedConstructorParams.fir.kt deleted file mode 100644 index f53a25d9ee4..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/AnnotatedConstructorParams.fir.kt +++ /dev/null @@ -1,15 +0,0 @@ -package a - -import java.lang.Deprecated as deprecated -import java.lang.SuppressWarnings as suppresswarnings - - -@deprecated @suppresswarnings val s: String = ""; - -@deprecated @suppresswarnings fun main() { - System.out.println("Hello, world!") -} - -class Test(@deprecated val s: String, - @suppresswarnings val x : Int) {} - diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotatedConstructorParams.kt b/compiler/testData/diagnostics/tests/annotations/AnnotatedConstructorParams.kt index b87476788ac..409d62c185a 100644 --- a/compiler/testData/diagnostics/tests/annotations/AnnotatedConstructorParams.kt +++ b/compiler/testData/diagnostics/tests/annotations/AnnotatedConstructorParams.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL package a import java.lang.Deprecated as deprecated diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationsForClasses.fir.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationsForClasses.fir.kt deleted file mode 100644 index b33157d0892..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/AnnotationsForClasses.fir.kt +++ /dev/null @@ -1 +0,0 @@ -annotation @java.lang.Deprecated class my diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationsForClasses.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationsForClasses.kt index a03105f2233..9b92e5f2130 100644 --- a/compiler/testData/diagnostics/tests/annotations/AnnotationsForClasses.kt +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationsForClasses.kt @@ -1 +1,2 @@ +// FIR_IDENTICAL annotation @java.lang.Deprecated class my diff --git a/compiler/testData/diagnostics/tests/annotations/Deprecated.fir.kt b/compiler/testData/diagnostics/tests/annotations/Deprecated.fir.kt deleted file mode 100644 index 9032870147a..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/Deprecated.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -import java.lang.Deprecated as deprecated - -@java.lang.Deprecated fun foo() {} - -@deprecated fun foo1() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/Deprecated.kt b/compiler/testData/diagnostics/tests/annotations/Deprecated.kt index 42fa80799e3..d5af5950778 100644 --- a/compiler/testData/diagnostics/tests/annotations/Deprecated.kt +++ b/compiler/testData/diagnostics/tests/annotations/Deprecated.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL import java.lang.Deprecated as deprecated @java.lang.Deprecated fun foo() {} diff --git a/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.fir.kt b/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.fir.kt deleted file mode 100644 index 0fa0d5677dc..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.fir.kt +++ /dev/null @@ -1,10 +0,0 @@ -import java.lang.annotation.Retention -import java.lang.annotation.Target -import java.lang.annotation.* - -@java.lang.annotation.Retention(RetentionPolicy.CLASS) -annotation class my - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR) -annotation class my1 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.kt b/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.kt index fa515cb895b..1b73ae40597 100644 --- a/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.kt +++ b/compiler/testData/diagnostics/tests/annotations/JavaAnnotationConstructors.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL import java.lang.annotation.Retention import java.lang.annotation.Target import java.lang.annotation.* diff --git a/compiler/testData/diagnostics/tests/annotations/options/javaKotlinTargetRetention.fir.kt b/compiler/testData/diagnostics/tests/annotations/options/javaKotlinTargetRetention.fir.kt deleted file mode 100644 index 878fb7ad602..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/options/javaKotlinTargetRetention.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -import java.lang.annotation.* - -@java.lang.annotation.Target(ElementType.PACKAGE) -@Target(AnnotationTarget.CLASS) -annotation class my - -@java.lang.annotation.Retention(RetentionPolicy.SOURCE) -@Retention(AnnotationRetention.BINARY) -annotation class your diff --git a/compiler/testData/diagnostics/tests/annotations/options/javaKotlinTargetRetention.kt b/compiler/testData/diagnostics/tests/annotations/options/javaKotlinTargetRetention.kt index b89c9ada80f..d5884039266 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/javaKotlinTargetRetention.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/javaKotlinTargetRetention.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL import java.lang.annotation.* @java.lang.annotation.Target(ElementType.PACKAGE) 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 cadb61b4abd..f5e57c7cef8 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 @@ -3525,4 +3525,11 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirJvmErrors.DEPRECATED_JAVA_ANNOTATION) { firDiagnostic -> + DeprecatedJavaAnnotationImpl( + firDiagnostic.a, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } } 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 928bc254a28..c47f6903036 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 @@ -2456,4 +2456,9 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = OverloadsPrivate::class } + abstract class DeprecatedJavaAnnotation : KtFirDiagnostic() { + override val diagnosticClass get() = DeprecatedJavaAnnotation::class + abstract val kotlinName: FqName + } + } 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 2df1ceed35a..0f5e9f65f2c 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 @@ -3978,3 +3978,11 @@ internal class OverloadsPrivateImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class DeprecatedJavaAnnotationImpl( + override val kotlinName: FqName, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.DeprecatedJavaAnnotation(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} +