[FIR] Introduce AnnotationUsedAsAnnotationArgumentChecker

This commit is contained in:
Julia
2021-04-09 20:34:18 +03:00
committed by Mikhail Glukhikh
parent 27ddc31f15
commit 387dafb8c5
18 changed files with 118 additions and 1 deletions
@@ -29,6 +29,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("annotationUsedAsAnnotationArgument.kt")
public void testAnnotationUsedAsAnnotationArgument() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.kt");
}
@TestMetadata("asImports.kt")
public void testAsImports() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/asImports.kt");
@@ -0,0 +1,27 @@
FILE: annotationUsedAsAnnotationArgument.kt
public final annotation class Ann : R|kotlin/Annotation| {
public constructor(): R|Ann| {
super<R|kotlin/Any|>()
}
}
public final annotation class Ann2 : R|kotlin/Annotation| {
public constructor(): R|Ann2| {
super<R|kotlin/Any|>()
}
}
public final annotation class Ann3 : R|kotlin/Annotation| {
public constructor(arg: R|kotlin/Int|, s: R|kotlin/String|): R|Ann3| {
super<R|kotlin/Any|>()
}
public final val arg: R|kotlin/Int| = R|<local>/arg|
public get(): R|kotlin/Int|
public final val s: R|kotlin/String| = R|<local>/s|
public get(): R|kotlin/String|
}
@R|Ann3|(@R|Ann3|(@R|Ann|() Int(5), String()) @R|Ann2|() Int(1), String()) public final val a: R|kotlin/Int| = Int(0)
public get(): R|kotlin/Int|
@@ -0,0 +1,11 @@
annotation class Ann
annotation class Ann2
annotation class Ann3(val arg: Int, val s: String)
@Ann3(
<!ANNOTATION_USED_AS_ANNOTATION_ARGUMENT!>@Ann3(
<!ANNOTATION_USED_AS_ANNOTATION_ARGUMENT!>@Ann<!> 5, ""
)<!> <!ANNOTATION_USED_AS_ANNOTATION_ARGUMENT!>@Ann2<!> 1, ""
) val a = 0
@@ -26,6 +26,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("annotationUsedAsAnnotationArgument.kt")
public void testAnnotationUsedAsAnnotationArgument() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.kt");
}
@Test
@TestMetadata("asImports.kt")
public void testAsImports() throws Exception {
@@ -26,6 +26,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("annotationUsedAsAnnotationArgument.kt")
public void testAnnotationUsedAsAnnotationArgument() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/annotationUsedAsAnnotationArgument.kt");
}
@Test
@TestMetadata("asImports.kt")
public void testAsImports() throws Exception {
@@ -24,6 +24,7 @@ fun main(args: Array<String>) {
alias<FirWhenExpression>("WhenExpressionChecker")
alias<FirReturnExpression>("ReturnExpressionChecker")
alias<FirBlock>("BlockChecker")
alias<FirAnnotationCall>("AnnotationCallChecker")
}
val declarationPackage = "org.jetbrains.kotlin.fir.analysis.checkers.declaration"
@@ -149,6 +149,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error<KtTypeReference>()
val VAR_ANNOTATION_PARAMETER by error<KtParameter>(PositioningStrategy.VAL_OR_VAR_NODE)
val SUPERTYPES_FOR_ANNOTATION_CLASS by error<KtClass>(PositioningStrategy.SUPERTYPES_LIST)
val ANNOTATION_USED_AS_ANNOTATION_ARGUMENT by error<KtAnnotation>()
}
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
@@ -29,6 +29,8 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() {
get() = _returnExpressionCheckers
override val blockCheckers: Set<FirBlockChecker>
get() = _blockCheckers
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
get() = _annotationCallCheckers
private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf()
private val _qualifiedAccessCheckers: MutableSet<FirQualifiedAccessChecker> = mutableSetOf()
@@ -38,6 +40,7 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() {
private val _whenExpressionCheckers: MutableSet<FirWhenExpressionChecker> = mutableSetOf()
private val _returnExpressionCheckers: MutableSet<FirReturnExpressionChecker> = mutableSetOf()
private val _blockCheckers: MutableSet<FirBlockChecker> = mutableSetOf()
private val _annotationCallCheckers: MutableSet<FirAnnotationCallChecker> = mutableSetOf()
@CheckersComponentInternal
internal fun register(checkers: ExpressionCheckers) {
@@ -49,5 +52,6 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() {
_whenExpressionCheckers += checkers.whenExpressionCheckers
_returnExpressionCheckers += checkers.returnExpressionCheckers
_blockCheckers += checkers.blockCheckers
_annotationCallCheckers += checkers.annotationCallCheckers
}
}
@@ -25,6 +25,7 @@ abstract class ExpressionCheckers {
open val whenExpressionCheckers: Set<FirWhenExpressionChecker> = emptySet()
open val returnExpressionCheckers: Set<FirReturnExpressionChecker> = emptySet()
open val blockCheckers: Set<FirBlockChecker> = emptySet()
open val annotationCallCheckers: Set<FirAnnotationCallChecker> = emptySet()
@CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> get() = basicExpressionCheckers
@CheckersComponentInternal internal val allQualifiedAccessCheckers: Set<FirQualifiedAccessChecker> get() = qualifiedAccessCheckers + basicExpressionCheckers
@@ -34,4 +35,5 @@ abstract class ExpressionCheckers {
@CheckersComponentInternal internal val allWhenExpressionCheckers: Set<FirWhenExpressionChecker> get() = whenExpressionCheckers + basicExpressionCheckers
@CheckersComponentInternal internal val allReturnExpressionCheckers: Set<FirReturnExpressionChecker> get() = returnExpressionCheckers + basicExpressionCheckers
@CheckersComponentInternal internal val allBlockCheckers: Set<FirBlockChecker> get() = blockCheckers + basicExpressionCheckers
@CheckersComponentInternal internal val allAnnotationCallCheckers: Set<FirAnnotationCallChecker> get() = annotationCallCheckers + basicExpressionCheckers
}
@@ -10,6 +10,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
* DO NOT MODIFY IT MANUALLY
*/
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
@@ -27,3 +28,4 @@ typealias FirTryExpressionChecker = FirExpressionChecker<FirTryExpression>
typealias FirWhenExpressionChecker = FirExpressionChecker<FirWhenExpression>
typealias FirReturnExpressionChecker = FirExpressionChecker<FirReturnExpression>
typealias FirBlockChecker = FirExpressionChecker<FirBlock>
typealias FirAnnotationCallChecker = FirExpressionChecker<FirAnnotationCall>
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotation
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtClass
@@ -155,6 +156,7 @@ object FirErrors {
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error0<KtTypeReference>()
val VAR_ANNOTATION_PARAMETER by error0<KtParameter>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val SUPERTYPES_FOR_ANNOTATION_CLASS by error0<KtClass>(SourceElementPositioningStrategies.SUPERTYPES_LIST)
val ANNOTATION_USED_AS_ANNOTATION_ARGUMENT by error0<KtAnnotation>()
// Exposed visibility
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<KtNamedDeclaration, EffectiveVisibility, FirMemberDeclaration, EffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
@@ -0,0 +1,23 @@
/*
* 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.checkers.expression
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
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.expressions.FirAnnotationCall
object FirAnnotationUsedAsAnnotationArgumentChecker : FirAnnotationCallChecker() {
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
val args = expression.argumentList.arguments
for (arg in args) {
for (ann in arg.annotations) {
reporter.reportOn(ann.source, FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, context)
}
}
}
}
@@ -34,7 +34,7 @@ class ExpressionCheckersDiagnosticComponent(
}
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: CheckerContext) {
checkers.allBasicExpressionCheckers.check(annotationCall, data, reporter)
checkers.allAnnotationCallCheckers.check(annotationCall, data, reporter)
}
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: CheckerContext) {
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CA
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_MEMBER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARGUMENT_PASSED_TWICE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARGUMENT_TYPE_MISMATCH
@@ -374,6 +375,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(DATA_CLASS_NOT_PROPERTY_PARAMETER, "Data class primary constructor must have only property (val / var) parameters")
// Annotations
map.put(ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, "An annotation can't be used as the annotations argument")
map.put(ANNOTATION_CLASS_MEMBER, "Members are not allowed in annotation class")
map.put(ANNOTATION_ARGUMENT_MUST_BE_CONST, "An annotation argument must be a compile-time constant")
map.put(
@@ -8,6 +8,11 @@ package org.jetbrains.kotlin.fir.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
object CommonExpressionCheckers : ExpressionCheckers() {
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
get() = setOf(
FirAnnotationUsedAsAnnotationArgumentChecker,
)
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = setOf(
FirAnonymousFunctionChecker,
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.KtAnnotation
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtClass
@@ -500,6 +501,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT) { firDiagnostic ->
AnnotationUsedAsAnnotationArgumentImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic ->
ExposedTypealiasExpandedTypeImpl(
firDiagnostic.a,
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotation
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtClass
@@ -361,6 +362,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = SupertypesForAnnotationClass::class
}
abstract class AnnotationUsedAsAnnotationArgument : KtFirDiagnostic<KtAnnotation>() {
override val diagnosticClass get() = AnnotationUsedAsAnnotationArgument::class
}
abstract class ExposedTypealiasExpandedType : KtFirDiagnostic<KtNamedDeclaration>() {
override val diagnosticClass get() = ExposedTypealiasExpandedType::class
abstract val elementVisibility: EffectiveVisibility
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotation
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtClass
@@ -581,6 +582,13 @@ internal class SupertypesForAnnotationClassImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class AnnotationUsedAsAnnotationArgumentImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.AnnotationUsedAsAnnotationArgument(), KtAbstractFirDiagnostic<KtAnnotation> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExposedTypealiasExpandedTypeImpl(
override val elementVisibility: EffectiveVisibility,
override val restrictingDeclaration: KtSymbol,