FIR: report ANNOTATION_CLASS_CONSTRUCTOR_CALL diagnostic
This commit is contained in:
+1
@@ -153,6 +153,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
val LOCAL_ANNOTATION_CLASS_ERROR by error<KtClassOrObject>()
|
||||
val MISSING_VAL_ON_ANNOTATION_PARAMETER by error<KtParameter>()
|
||||
val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by error<KtExpression>()
|
||||
val ANNOTATION_CLASS_CONSTRUCTOR_CALL by error<KtCallExpression>()
|
||||
val NOT_AN_ANNOTATION_CLASS by error<PsiElement> {
|
||||
parameter<String>("annotationName")
|
||||
}
|
||||
|
||||
@@ -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<KtClassOrObject>()
|
||||
val MISSING_VAL_ON_ANNOTATION_PARAMETER by error0<KtParameter>()
|
||||
val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by error0<KtExpression>()
|
||||
val ANNOTATION_CLASS_CONSTRUCTOR_CALL by error0<KtCallExpression>()
|
||||
val NOT_AN_ANNOTATION_CLASS by error1<PsiElement, String>()
|
||||
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error0<KtTypeReference>()
|
||||
val VAR_ANNOTATION_PARAMETER by error0<KtParameter>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
|
||||
|
||||
+16
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -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(
|
||||
|
||||
@@ -13,19 +13,19 @@ annotation class Ann4(val value: String)
|
||||
@Ann4("a") class MyClass
|
||||
|
||||
fun foo() {
|
||||
Ann()
|
||||
val a = Ann()
|
||||
<!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>
|
||||
val a = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>
|
||||
|
||||
Ann1(<!NO_VALUE_FOR_PARAMETER!>)<!>
|
||||
Ann1(1)
|
||||
bar(Ann())
|
||||
bar(a = Ann())
|
||||
<!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann1(1)<!>
|
||||
bar(<!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>)
|
||||
bar(a = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>)
|
||||
|
||||
val ann = javaClass<MyClass>().getAnnotation(javaClass<Ann4>())
|
||||
ann!!.value()
|
||||
}
|
||||
|
||||
fun bar(a: Ann = Ann()) {
|
||||
fun bar(a: Ann = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>) {
|
||||
if (<!USELESS_IS_CHECK!>a is Ann<!>) {}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@ val test1a = <!CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS!>AbstractClass()<!>
|
||||
|
||||
annotation class AnnotationClass
|
||||
typealias Test2 = AnnotationClass
|
||||
val test2 = Test2()
|
||||
val test2a = AnnotationClass()
|
||||
val test2 = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Test2()<!>
|
||||
val test2a = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>AnnotationClass()<!>
|
||||
|
||||
enum class EnumClass { VALUE1, VALUE2 }
|
||||
typealias Test3 = EnumClass
|
||||
|
||||
+1
-1
@@ -21,4 +21,4 @@ annotation class AnnAnn(val i: Array<Ann>)
|
||||
@AnnAnn(arrayOf(Ann(intArrayOf(1))))
|
||||
@AnnAnn(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>arrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>iAnn<!>)<!>)
|
||||
class TestAnn
|
||||
val iAnn = Ann(intArrayOf(1))
|
||||
val iAnn = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann(intArrayOf(1))<!>
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@Repeatable
|
||||
annotation class Ann(vararg val i: Int)
|
||||
|
||||
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>)
|
||||
@Ann(i2)
|
||||
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i3<!>)
|
||||
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>, i2, <!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i3<!>)
|
||||
@Ann(*<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>)<!>)
|
||||
@Ann(*intArrayOf(i2))
|
||||
@Ann(*<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i3<!>)<!>)
|
||||
@Ann(*<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>, i2, <!ANNOTATION_ARGUMENT_MUST_BE_CONST!>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(*<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>arrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>iAnn<!>)<!>)
|
||||
class TestAnn
|
||||
val iAnn = Ann(1)
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@Repeatable
|
||||
annotation class Ann(vararg val i: Int)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_COMPARISON
|
||||
package Test.SubTest.AnotherTest
|
||||
|
||||
open class TestClass {
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_COMPARISON
|
||||
package some
|
||||
|
||||
annotation class AnnComplete
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_COMPARISON
|
||||
package some
|
||||
|
||||
annotation class AnnComplete
|
||||
|
||||
+7
@@ -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,
|
||||
|
||||
+5
@@ -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<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = NonConstValUsedInConstantExpression::class
|
||||
}
|
||||
|
||||
abstract class AnnotationClassConstructorCall : KtFirDiagnostic<KtCallExpression>() {
|
||||
override val diagnosticClass get() = AnnotationClassConstructorCall::class
|
||||
}
|
||||
|
||||
abstract class NotAnAnnotationClass : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = NotAnAnnotationClass::class
|
||||
abstract val annotationName: String
|
||||
|
||||
+8
@@ -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<KtCallExpression> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class NotAnAnnotationClassImpl(
|
||||
override val annotationName: String,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
|
||||
Reference in New Issue
Block a user