From 0d6bc7e7b241cd7ae44eeb0380d6f088ff49483a Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 11 May 2021 16:14:40 +0300 Subject: [PATCH] FIR: report ANNOTATION_CLASS_CONSTRUCTOR_CALL diagnostic --- .../diagnostics/FirDiagnosticsList.kt | 1 + .../fir/analysis/diagnostics/FirErrors.kt | 2 ++ .../expression/FirConstructorCallChecker.kt | 18 +++++++++++-- .../diagnostics/FirDefaultErrorMessages.kt | 2 ++ .../tests/annotations/ConstructorCall.fir.kt | 12 ++++----- .../typeAliasConstructorWrongClass.fir.kt | 4 +-- .../array.fir.kt | 2 +- .../vararg.fir.kt | 27 ------------------- .../vararg.kt | 1 + .../basic/common/ExtendQualifiedClassName.kt | 1 + .../basic/annotation/AnnotationInBrackets.kt | 1 + .../annotation/AnnotationInBrackets.kt.after | 1 + .../diagnostics/KtFirDataClassConverters.kt | 7 +++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 5 ++++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 8 ++++++ 15 files changed, 54 insertions(+), 38 deletions(-) delete mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.fir.kt 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 0749d331f0e..ebe0cdc78c1 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 @@ -153,6 +153,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val LOCAL_ANNOTATION_CLASS_ERROR by error() val MISSING_VAL_ON_ANNOTATION_PARAMETER by error() val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by error() + val ANNOTATION_CLASS_CONSTRUCTOR_CALL by error() val NOT_AN_ANNOTATION_CLASS by error { parameter("annotationName") } 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 525705d3a87..d04e0898f9f 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 @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.psi.KtAnnotation import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS +import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration @@ -162,6 +163,7 @@ object FirErrors { val LOCAL_ANNOTATION_CLASS_ERROR by error0() val MISSING_VAL_ON_ANNOTATION_PARAMETER by error0() val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by error0() + val ANNOTATION_CLASS_CONSTRUCTOR_CALL by error0() val NOT_AN_ANNOTATION_CLASS by error1() val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error0() val VAR_ANNOTATION_PARAMETER by error0(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt index fd7cd73b936..8078a41f797 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt @@ -11,7 +11,9 @@ import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass 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.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.isAbstract +import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol @@ -23,8 +25,20 @@ object FirConstructorCallChecker : FirFunctionCallChecker() { (expression.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol ?: return val declarationClass = constructorSymbol.fir.returnTypeRef.coneType.toRegularClass(context.session) - if (declarationClass != null && declarationClass.isAbstract && declarationClass.classKind == ClassKind.CLASS) { - reporter.reportOn(expression.source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context) + if (declarationClass != null) { + if (declarationClass.isAbstract && declarationClass.classKind == ClassKind.CLASS) { + reporter.reportOn(expression.source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context) + } + if (declarationClass.classKind == ClassKind.ANNOTATION_CLASS && + context.qualifiedAccessOrAnnotationCalls.all { call -> + call !is FirAnnotationCall + } && + context.containingDeclarations.all { klass -> + klass !is FirRegularClass || klass.classKind != ClassKind.ANNOTATION_CLASS + } + ) { + reporter.reportOn(expression.source, FirErrors.ANNOTATION_CLASS_CONSTRUCTOR_CALL, context) + } } } } \ No newline at end of file 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 4c0be3cd2f4..05eb20aac8a 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 @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACCESSOR_FOR_DELEGATED_PROPERTY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_CONSTRUCTOR_CALL 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 @@ -445,6 +446,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { map.put(NULLABLE_TYPE_OF_ANNOTATION_MEMBER, "An annotation parameter cannot be nullable") map.put(INVALID_TYPE_OF_ANNOTATION_MEMBER, "Invalid type of annotation member") map.put(VAR_ANNOTATION_PARAMETER, "An annotation parameter cannot be 'var'") + map.put(ANNOTATION_CLASS_CONSTRUCTOR_CALL, "Annotation class cannot be instantiated"); map.put(NOT_AN_ANNOTATION_CLASS, "Illegal annotation class: {0}", NULLABLE_STRING) map.put(SUPERTYPES_FOR_ANNOTATION_CLASS, "Annotation class cannot have supertypes") map.put( diff --git a/compiler/testData/diagnostics/tests/annotations/ConstructorCall.fir.kt b/compiler/testData/diagnostics/tests/annotations/ConstructorCall.fir.kt index 01a9f87e4d9..edaa2e8d534 100644 --- a/compiler/testData/diagnostics/tests/annotations/ConstructorCall.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/ConstructorCall.fir.kt @@ -13,19 +13,19 @@ annotation class Ann4(val value: String) @Ann4("a") class MyClass fun foo() { - Ann() - val a = Ann() + Ann() + val a = Ann() Ann1() - Ann1(1) - bar(Ann()) - bar(a = Ann()) + Ann1(1) + bar(Ann()) + bar(a = Ann()) val ann = javaClass().getAnnotation(javaClass()) ann!!.value() } -fun bar(a: Ann = Ann()) { +fun bar(a: Ann = Ann()) { if (a is Ann) {} } diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.fir.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.fir.kt index 1e5766db819..506603a148d 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.fir.kt @@ -7,8 +7,8 @@ val test1a = AbstractClass() annotation class AnnotationClass typealias Test2 = AnnotationClass -val test2 = Test2() -val test2a = AnnotationClass() +val test2 = Test2() +val test2a = AnnotationClass() enum class EnumClass { VALUE1, VALUE2 } typealias Test3 = EnumClass diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/array.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/array.fir.kt index e97514f7769..4f798a8a512 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/array.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/array.fir.kt @@ -21,4 +21,4 @@ annotation class AnnAnn(val i: Array) @AnnAnn(arrayOf(Ann(intArrayOf(1)))) @AnnAnn(arrayOf(iAnn)) class TestAnn -val iAnn = Ann(intArrayOf(1)) +val iAnn = Ann(intArrayOf(1)) diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.fir.kt deleted file mode 100644 index ac380240bc3..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.fir.kt +++ /dev/null @@ -1,27 +0,0 @@ -@Retention(AnnotationRetention.SOURCE) -@Repeatable -annotation class Ann(vararg val i: Int) - -@Ann(i) -@Ann(i2) -@Ann(i3) -@Ann(i, i2, i3) -@Ann(*intArrayOf(i)) -@Ann(*intArrayOf(i2)) -@Ann(*intArrayOf(i3)) -@Ann(*intArrayOf(i, i2, i3)) -class Test - -var i = 1 -const val i2 = 1 -val i3 = foo() - -fun foo(): Int = 1 - -@Retention(AnnotationRetention.SOURCE) -@Repeatable -annotation class AnnAnn(vararg val i: Ann) -@AnnAnn(*arrayOf(Ann(1))) -@AnnAnn(*arrayOf(iAnn)) -class TestAnn -val iAnn = Ann(1) diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.kt index 3d3670e3826..7dfee388236 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL @Retention(AnnotationRetention.SOURCE) @Repeatable annotation class Ann(vararg val i: Int) diff --git a/idea/idea-completion/testData/basic/common/ExtendQualifiedClassName.kt b/idea/idea-completion/testData/basic/common/ExtendQualifiedClassName.kt index 6221b1fd848..226c62296e9 100644 --- a/idea/idea-completion/testData/basic/common/ExtendQualifiedClassName.kt +++ b/idea/idea-completion/testData/basic/common/ExtendQualifiedClassName.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package Test.SubTest.AnotherTest open class TestClass { diff --git a/idea/idea-completion/testData/handlers/basic/annotation/AnnotationInBrackets.kt b/idea/idea-completion/testData/handlers/basic/annotation/AnnotationInBrackets.kt index 74262aa87d1..89431473d89 100644 --- a/idea/idea-completion/testData/handlers/basic/annotation/AnnotationInBrackets.kt +++ b/idea/idea-completion/testData/handlers/basic/annotation/AnnotationInBrackets.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package some annotation class AnnComplete diff --git a/idea/idea-completion/testData/handlers/basic/annotation/AnnotationInBrackets.kt.after b/idea/idea-completion/testData/handlers/basic/annotation/AnnotationInBrackets.kt.after index 5951d1a7618..f6bbf209be2 100644 --- a/idea/idea-completion/testData/handlers/basic/annotation/AnnotationInBrackets.kt.after +++ b/idea/idea-completion/testData/handlers/basic/annotation/AnnotationInBrackets.kt.after @@ -1,3 +1,4 @@ +// FIR_COMPARISON package some annotation class AnnComplete 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 5b71eaf8551..c7e67c964d2 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 @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.KtAnnotation import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS +import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration @@ -519,6 +520,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.ANNOTATION_CLASS_CONSTRUCTOR_CALL) { firDiagnostic -> + AnnotationClassConstructorCallImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.NOT_AN_ANNOTATION_CLASS) { firDiagnostic -> NotAnAnnotationClassImpl( 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 f05afe22e60..2bfdcd28b53 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 @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.KtAnnotation import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS +import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration @@ -374,6 +375,10 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = NonConstValUsedInConstantExpression::class } + abstract class AnnotationClassConstructorCall : KtFirDiagnostic() { + override val diagnosticClass get() = AnnotationClassConstructorCall::class + } + abstract class NotAnAnnotationClass : KtFirDiagnostic() { override val diagnosticClass get() = NotAnAnnotationClass::class abstract val annotationName: String 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 7e530d9587d..1bf06d6286a 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 @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.psi.KtAnnotation import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS +import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration @@ -603,6 +604,13 @@ internal class NonConstValUsedInConstantExpressionImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class AnnotationClassConstructorCallImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.AnnotationClassConstructorCall(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class NotAnAnnotationClassImpl( override val annotationName: String, firDiagnostic: FirPsiDiagnostic<*>,