[FIR] Add DEPRECATED_JAVA_ANNOTATION diagnostic

This commit is contained in:
Andrey Zinovyev
2021-08-18 12:32:16 +03:00
committed by TeamCityServer
parent f9b601edae
commit ae558c0290
18 changed files with 78 additions and 41 deletions
@@ -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<KtAnnotationEntry>()
val OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR by deprecationError<KtAnnotationEntry>(LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses)
val OVERLOADS_PRIVATE by warning<KtAnnotationEntry>()
val DEPRECATED_JAVA_ANNOTATION by warning<KtAnnotationEntry>() {
parameter<FqName>("kotlinName")
}
}
}
@@ -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<KtAnnotationEntry>()
val OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR by deprecationError0<KtAnnotationEntry>(ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses)
val OVERLOADS_PRIVATE by warning0<KtAnnotationEntry>()
val DEPRECATED_JAVA_ANNOTATION by warning1<KtAnnotationEntry, FqName>()
}
@@ -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<FirAnnotationCallChecker>
get() = setOf(
FirDeprecatedJavaAnnotationsChecker,
)
}
@@ -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<FqName, FqName> =
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<ConeClassLikeType>()?.lookupTag ?: return
javaToKotlinNameMap[lookupTag.classId.asSingleFqName()]?.let { betterName ->
reporter.reportOn(expression.source, FirJvmErrors.DEPRECATED_JAVA_ANNOTATION, betterName, context)
}
}
}
@@ -2,4 +2,4 @@ import java.util.ArrayList
@<!NOT_AN_ANNOTATION_CLASS!>ArrayList<!><Int>(1, 1) fun b() {}
@<!UNRESOLVED_REFERENCE!>Xoo<!>(<!UNRESOLVED_REFERENCE!>x<!>) fun c() {}
@java.lang.Deprecated(<!TOO_MANY_ARGUMENTS, UNRESOLVED_REFERENCE!>x<!>) fun a() {}
<!DEPRECATED_JAVA_ANNOTATION!>@java.lang.Deprecated(<!TOO_MANY_ARGUMENTS, UNRESOLVED_REFERENCE!>x<!>)<!> fun a() {}
@@ -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) {}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
package a
import java.lang.Deprecated as deprecated
@@ -1 +0,0 @@
annotation @java.lang.Deprecated class my
@@ -1 +1,2 @@
// FIR_IDENTICAL
annotation <!DEPRECATED_JAVA_ANNOTATION!>@java.lang.Deprecated<!> class my
@@ -1,5 +0,0 @@
import java.lang.Deprecated as deprecated
@java.lang.Deprecated fun foo() {}
@deprecated fun foo1() {}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
import java.lang.Deprecated as deprecated
<!DEPRECATED_JAVA_ANNOTATION!>@java.lang.Deprecated<!> fun foo() {}
@@ -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
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
import java.lang.annotation.Retention
import java.lang.annotation.Target
import java.lang.annotation.*
@@ -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
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
import java.lang.annotation.*
<!DEPRECATED_JAVA_ANNOTATION!>@java.lang.annotation.Target(ElementType.PACKAGE)<!>
@@ -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,
)
}
}
@@ -2456,4 +2456,9 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = OverloadsPrivate::class
}
abstract class DeprecatedJavaAnnotation : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = DeprecatedJavaAnnotation::class
abstract val kotlinName: FqName
}
}
@@ -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<KtAnnotationEntry> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}