From e4246e8f51e0c4bc35b2baa7bb737abd5b6f37df Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Tue, 18 Jul 2023 07:38:40 +0300 Subject: [PATCH] [FIR] Support ENUM_CLASS_CONSTRUCTOR_CALL ^KT-59411 Fixed --- .../diagnostics/KtFirDataClassConverters.kt | 6 ++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 4 +++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 5 +++ .../diagnostics/FirDiagnosticsList.kt | 1 + .../fir/analysis/diagnostics/FirErrors.kt | 1 + .../expression/FirConstructorCallChecker.kt | 35 +++++++++++-------- .../diagnostics/FirErrorsDefaultMessages.kt | 2 ++ .../enum/ConstructorCallFromOutside.fir.kt | 2 +- .../tests/enum/ExplicitConstructorCall.fir.kt | 10 ------ .../tests/enum/ExplicitConstructorCall.kt | 1 + .../enum/InsideEntryConstructorCall.fir.kt | 15 -------- .../tests/enum/InsideEntryConstructorCall.kt | 1 + .../InsideSecondaryConstructorCall.fir.kt | 13 ------- .../enum/InsideSecondaryConstructorCall.kt | 1 + .../typeAliasConstructorWrongClass.fir.kt | 4 +-- 15 files changed, 46 insertions(+), 55 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/enum/ExplicitConstructorCall.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/enum/InsideEntryConstructorCall.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/enum/InsideSecondaryConstructorCall.fir.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index 47feeb107a3..eafffc788ff 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -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, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 6a0cf061688..73bd7a9e581 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -635,6 +635,10 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = AnnotationClassConstructorCall::class } + interface EnumClassConstructorCall : KtFirDiagnostic { + override val diagnosticClass get() = EnumClassConstructorCall::class + } + interface NotAnAnnotationClass : KtFirDiagnostic { override val diagnosticClass get() = NotAnAnnotationClass::class val annotationName: String diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 09fa4f72f46..642e1b9774f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -756,6 +756,11 @@ internal class AnnotationClassConstructorCallImpl( token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.AnnotationClassConstructorCall +internal class EnumClassConstructorCallImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.EnumClassConstructorCall + internal class NotAnAnnotationClassImpl( override val annotationName: String, firDiagnostic: KtPsiDiagnostic, 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 7f9d75dbf1e..7715d6a83b5 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 @@ -290,6 +290,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by error() val CYCLE_IN_ANNOTATION_PARAMETER by deprecationError(LanguageFeature.ProhibitCyclesInAnnotations) val ANNOTATION_CLASS_CONSTRUCTOR_CALL by error() + val ENUM_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 c49aa7065e1..5ed2d66378b 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 @@ -248,6 +248,7 @@ object FirErrors { val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by error0() val CYCLE_IN_ANNOTATION_PARAMETER by deprecationError0(ProhibitCyclesInAnnotations) val ANNOTATION_CLASS_CONSTRUCTOR_CALL by error0() + val ENUM_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 41e8175d291..55de756a767 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 @@ -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 + ) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index c6ac314f559..f92a545fc9b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -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( diff --git a/compiler/testData/diagnostics/tests/enum/ConstructorCallFromOutside.fir.kt b/compiler/testData/diagnostics/tests/enum/ConstructorCallFromOutside.fir.kt index d2544fefb87..540885965d8 100644 --- a/compiler/testData/diagnostics/tests/enum/ConstructorCallFromOutside.fir.kt +++ b/compiler/testData/diagnostics/tests/enum/ConstructorCallFromOutside.fir.kt @@ -6,5 +6,5 @@ enum class A(val c: Int) { fun createA(): A { // Error should be here! - return A(10) + return A(10) } diff --git a/compiler/testData/diagnostics/tests/enum/ExplicitConstructorCall.fir.kt b/compiler/testData/diagnostics/tests/enum/ExplicitConstructorCall.fir.kt deleted file mode 100644 index 9270790103b..00000000000 --- a/compiler/testData/diagnostics/tests/enum/ExplicitConstructorCall.fir.kt +++ /dev/null @@ -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) - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/enum/ExplicitConstructorCall.kt b/compiler/testData/diagnostics/tests/enum/ExplicitConstructorCall.kt index 53374c1f66f..d803f5290fb 100644 --- a/compiler/testData/diagnostics/tests/enum/ExplicitConstructorCall.kt +++ b/compiler/testData/diagnostics/tests/enum/ExplicitConstructorCall.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // KT-7753: attempt to call enum constructor explicitly enum class A(val c: Int) { ONE(1), diff --git a/compiler/testData/diagnostics/tests/enum/InsideEntryConstructorCall.fir.kt b/compiler/testData/diagnostics/tests/enum/InsideEntryConstructorCall.fir.kt deleted file mode 100644 index 5cb64b5db2d..00000000000 --- a/compiler/testData/diagnostics/tests/enum/InsideEntryConstructorCall.fir.kt +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/enum/InsideEntryConstructorCall.kt b/compiler/testData/diagnostics/tests/enum/InsideEntryConstructorCall.kt index 5660949f479..16ac557ad42 100644 --- a/compiler/testData/diagnostics/tests/enum/InsideEntryConstructorCall.kt +++ b/compiler/testData/diagnostics/tests/enum/InsideEntryConstructorCall.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // KT-7753: attempt to call enum constructor explicitly enum class A(val c: Int) { ONE(1) { diff --git a/compiler/testData/diagnostics/tests/enum/InsideSecondaryConstructorCall.fir.kt b/compiler/testData/diagnostics/tests/enum/InsideSecondaryConstructorCall.fir.kt deleted file mode 100644 index c10af850cea..00000000000 --- a/compiler/testData/diagnostics/tests/enum/InsideSecondaryConstructorCall.fir.kt +++ /dev/null @@ -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) - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/enum/InsideSecondaryConstructorCall.kt b/compiler/testData/diagnostics/tests/enum/InsideSecondaryConstructorCall.kt index 642a321bd6e..76b65a0be8b 100644 --- a/compiler/testData/diagnostics/tests/enum/InsideSecondaryConstructorCall.kt +++ b/compiler/testData/diagnostics/tests/enum/InsideSecondaryConstructorCall.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // KT-7753: attempt to call enum constructor explicitly enum class A(val c: Int) { ONE(1), diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.fir.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.fir.kt index aeef821cb1a..13cd1f54c0c 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.fir.kt @@ -12,8 +12,8 @@ val test2a = AnnotationClass() enum class EnumClass { VALUE1, VALUE2 } typealias Test3 = EnumClass -val test3 = Test3() -val test3a = EnumClass() +val test3 = Test3() +val test3a = EnumClass() sealed class SealedClass typealias Test4 = SealedClass