[FIR] Support ENUM_CLASS_CONSTRUCTOR_CALL

^KT-59411 Fixed
This commit is contained in:
Nikolay Lunyak
2023-07-18 07:38:40 +03:00
committed by Space Team
parent f4ffd479cc
commit e4246e8f51
15 changed files with 46 additions and 55 deletions
@@ -863,6 +863,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.ENUM_CLASS_CONSTRUCTOR_CALL) { firDiagnostic ->
EnumClassConstructorCallImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.NOT_AN_ANNOTATION_CLASS) { firDiagnostic ->
NotAnAnnotationClassImpl(
firDiagnostic.a,
@@ -635,6 +635,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = AnnotationClassConstructorCall::class
}
interface EnumClassConstructorCall : KtFirDiagnostic<KtCallExpression> {
override val diagnosticClass get() = EnumClassConstructorCall::class
}
interface NotAnAnnotationClass : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = NotAnAnnotationClass::class
val annotationName: String
@@ -756,6 +756,11 @@ internal class AnnotationClassConstructorCallImpl(
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtCallExpression>(firDiagnostic, token), KtFirDiagnostic.AnnotationClassConstructorCall
internal class EnumClassConstructorCallImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtCallExpression>(firDiagnostic, token), KtFirDiagnostic.EnumClassConstructorCall
internal class NotAnAnnotationClassImpl(
override val annotationName: String,
firDiagnostic: KtPsiDiagnostic,
@@ -290,6 +290,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by error<KtExpression>()
val CYCLE_IN_ANNOTATION_PARAMETER by deprecationError<KtParameter>(LanguageFeature.ProhibitCyclesInAnnotations)
val ANNOTATION_CLASS_CONSTRUCTOR_CALL by error<KtCallExpression>()
val ENUM_CLASS_CONSTRUCTOR_CALL by error<KtCallExpression>()
val NOT_AN_ANNOTATION_CLASS by error<PsiElement> {
parameter<String>("annotationName")
}
@@ -248,6 +248,7 @@ object FirErrors {
val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by error0<KtExpression>()
val CYCLE_IN_ANNOTATION_PARAMETER by deprecationError0<KtParameter>(ProhibitCyclesInAnnotations)
val ANNOTATION_CLASS_CONSTRUCTOR_CALL by error0<KtCallExpression>()
val ENUM_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)
@@ -22,22 +22,29 @@ object FirConstructorCallChecker : FirFunctionCallChecker() {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
val constructorSymbol = expression.calleeReference.toResolvedConstructorSymbol() ?: return
val declarationClass = constructorSymbol.resolvedReturnTypeRef.coneType.toRegularClassSymbol(context.session)
?: return
if (declarationClass != null) {
if (declarationClass.classKind == ClassKind.ANNOTATION_CLASS &&
context.callsOrAssignments.all { call ->
call !is FirAnnotation
} &&
context.containingDeclarations.all { klass ->
klass !is FirRegularClass || klass.classKind != ClassKind.ANNOTATION_CLASS
}
) {
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.InstantiationOfAnnotationClasses)) reporter.reportOn(
expression.source,
FirErrors.ANNOTATION_CLASS_CONSTRUCTOR_CALL,
context
)
if (declarationClass.classKind == ClassKind.ANNOTATION_CLASS &&
context.callsOrAssignments.all { call ->
call !is FirAnnotation
} &&
context.containingDeclarations.all { klass ->
klass !is FirRegularClass || klass.classKind != ClassKind.ANNOTATION_CLASS
}
) {
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.InstantiationOfAnnotationClasses)) reporter.reportOn(
expression.source,
FirErrors.ANNOTATION_CLASS_CONSTRUCTOR_CALL,
context
)
}
if (declarationClass.classKind == ClassKind.ENUM_CLASS) {
reporter.reportOn(
expression.source,
FirErrors.ENUM_CLASS_CONSTRUCTOR_CALL,
context
)
}
}
}
@@ -194,6 +194,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DYNAMIC_UPPER_BOU
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ELSE_MISPLACED_IN_WHEN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_CHARACTER_LITERAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_RANGE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ENUM_CLASS_CONSTRUCTOR_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ENUM_ENTRY_AS_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EQUALITY_NOT_APPLICABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EQUALITY_NOT_APPLICABLE_WARNING
@@ -878,6 +879,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
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(ENUM_CLASS_CONSTRUCTOR_CALL, "Enum types 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(
@@ -6,5 +6,5 @@ enum class A(val c: Int) {
fun createA(): A {
// Error should be here!
return <!INVISIBLE_REFERENCE!>A<!>(10)
return <!ENUM_CLASS_CONSTRUCTOR_CALL!><!INVISIBLE_REFERENCE!>A<!>(10)<!>
}
@@ -1,10 +0,0 @@
// KT-7753: attempt to call enum constructor explicitly
enum class A(val c: Int) {
ONE(1),
TWO(2);
fun createA(): A {
// Error should be here!
return A(10)
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// KT-7753: attempt to call enum constructor explicitly
enum class A(val c: Int) {
ONE(1),
@@ -1,15 +0,0 @@
// KT-7753: attempt to call enum constructor explicitly
enum class A(val c: Int) {
ONE(1) {
override fun selfOrFriend(): A {
return this
}
},
TWO(2) {
override fun selfOrFriend(): A {
return A(42)
}
};
abstract fun selfOrFriend(): A
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// KT-7753: attempt to call enum constructor explicitly
enum class A(val c: Int) {
ONE(1) {
@@ -1,13 +0,0 @@
// KT-7753: attempt to call enum constructor explicitly
enum class A(val c: Int) {
ONE(1),
TWO(2),
THREE(3),
FORTY_TWO();
var last: A? = null
constructor(): this(42) {
last = A(13)
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// KT-7753: attempt to call enum constructor explicitly
enum class A(val c: Int) {
ONE(1),
@@ -12,8 +12,8 @@ val test2a = AnnotationClass()
enum class EnumClass { VALUE1, VALUE2 }
typealias Test3 = EnumClass
val test3 = <!INVISIBLE_REFERENCE!>Test3<!>()
val test3a = <!INVISIBLE_REFERENCE!>EnumClass<!>()
val test3 = <!ENUM_CLASS_CONSTRUCTOR_CALL!><!INVISIBLE_REFERENCE!>Test3<!>()<!>
val test3a = <!ENUM_CLASS_CONSTRUCTOR_CALL!><!INVISIBLE_REFERENCE!>EnumClass<!>()<!>
sealed class SealedClass
typealias Test4 = SealedClass