From 6b453d9b23369059447e5a360eff3f4f7253d5e7 Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Tue, 16 Feb 2021 14:04:34 -0800 Subject: [PATCH] FIR: implement checker for open members Specifically, 1. NON_FINAL_MEMBER_IN_FINAL_CLASS 2. NON_FINAL_MEMBER_IN_OBJECT --- .../RedundantModalityModifierChecker.kt | 2 +- .../diagnostics/FirDiagnosticsList.kt | 2 + .../fir/analysis/diagnostics/FirErrors.kt | 2 + .../declaration/FirDeclarationCheckerUtils.kt | 6 +++ .../declaration/FirOpenMemberChecker.kt | 49 +++++++++++++++++++ .../diagnostics/FirDefaultErrorMessages.kt | 4 ++ .../fir/checkers/CommonDeclarationCheckers.kt | 1 + .../inlineClassDeclarationCheck.fir.kt | 2 +- .../tests/modifiers/IllegalModifiers.fir.kt | 48 +++++++++--------- .../tests/modifiers/IllegalModifiers.kt | 46 ++++++++--------- .../tests/objects/OpenInObject.fir.kt | 9 ---- .../diagnostics/tests/objects/OpenInObject.kt | 1 + .../overrideMemberFromFinalClass.fir.kt | 4 +- .../valueClassDeclarationCheck.fir.kt | 2 +- .../annotations/jvmField/interface13.fir.kt | 2 +- .../jvmStatic/finalAndAbstract.fir.kt | 6 +-- .../annotations/jvmStatic/property.fir.kt | 4 +- .../jvmStatic/property_LL13.fir.kt | 4 +- .../diagnostics/KtFirDataClassConverters.kt | 12 +++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 8 +++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 14 ++++++ 21 files changed, 159 insertions(+), 69 deletions(-) create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOpenMemberChecker.kt delete mode 100644 compiler/testData/diagnostics/tests/objects/OpenInObject.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantModalityModifierChecker.kt b/compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantModalityModifierChecker.kt index 29ef5c58d94..bf353fc648e 100644 --- a/compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantModalityModifierChecker.kt +++ b/compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantModalityModifierChecker.kt @@ -47,7 +47,7 @@ class FinalDerived : Base() { // Redundant final override final fun bar() {} // Non-final member in final class - override open val gav = 13 + override open val gav = 13 } // Open open class OpenDerived : Base() { 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 19d4e6c1d21..8cb30a29927 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 @@ -243,6 +243,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() { parameter("overridingDeclaration") parameter("overriddenDeclaration") } + val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning(PositioningStrategy.OPEN_MODIFIER) + val NON_FINAL_MEMBER_IN_OBJECT by warning(PositioningStrategy.OPEN_MODIFIER) } val REDECLARATIONS by object : DiagnosticGroup("Redeclarations") { 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 63d73dd4a21..0133cf8126a 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 @@ -176,6 +176,8 @@ object FirErrors { val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE) val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE) val VAR_OVERRIDDEN_BY_VAL by error2(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) + val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning0(SourceElementPositioningStrategies.OPEN_MODIFIER) + val NON_FINAL_MEMBER_IN_OBJECT by warning0(SourceElementPositioningStrategies.OPEN_MODIFIER) // Redeclarations val MANY_COMPANION_OBJECTS by error0() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt index 6b4ac794100..e7f8c001381 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt @@ -5,9 +5,12 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.modality import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn @@ -123,3 +126,6 @@ internal fun checkPropertyInitializer( private val FirProperty.hasAccessorImplementation: Boolean get() = (getter !is FirDefaultPropertyAccessor && getter?.hasBody == true) || (setter !is FirDefaultPropertyAccessor && setter?.hasBody == true) + + +internal val FirClass<*>.canHaveOpenMembers: Boolean get() = modality() != Modality.FINAL || classKind == ClassKind.ENUM_CLASS diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOpenMemberChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOpenMemberChecker.kt new file mode 100644 index 00000000000..715c3871fd0 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOpenMemberChecker.kt @@ -0,0 +1,49 @@ +/* + * 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.declaration + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.fir.FirFakeSourceElementKind +import org.jetbrains.kotlin.fir.FirRealSourceElementKind +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirModifierList.Companion.getModifierList +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.FirCallableMemberDeclaration +import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.FirConstructor +import org.jetbrains.kotlin.fir.declarations.isOpen +import org.jetbrains.kotlin.lexer.KtTokens + +object FirOpenMemberChecker : FirClassChecker() { + override fun check(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) { + if (declaration.canHaveOpenMembers) return + for (memberDeclaration in declaration.declarations) { + if (memberDeclaration !is FirCallableMemberDeclaration<*> || + // Marking a constructor `open` is an error covered by diagnostic code WRONG_MODIFIER_TARGET + memberDeclaration is FirConstructor + ) continue + val source = memberDeclaration.source ?: continue + if (memberDeclaration.isOpen || (source.hasOpenModifierInSource && source.shouldReportOpenFromSource)) { + if (declaration.classKind == ClassKind.OBJECT) { + reporter.reportOn(source, FirErrors.NON_FINAL_MEMBER_IN_OBJECT, context) + } else { + reporter.reportOn(source, FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS, context) + } + } + } + } + + private val FirSourceElement.hasOpenModifierInSource: Boolean get() = getModifierList()?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true + private val FirSourceElement.shouldReportOpenFromSource: Boolean + get() = when (kind) { + FirRealSourceElementKind, + FirFakeSourceElementKind.PropertyFromParameter -> true + else -> false + } +} 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 9ab8f8b7901..fd78a00d225 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 @@ -99,6 +99,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_COMPANION_OB import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_OBJECT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MEMBER_FUNCTION_NO_BODY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED @@ -394,6 +396,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { FQ_NAMES_IN_TYPES, FQ_NAMES_IN_TYPES ) + map.put(NON_FINAL_MEMBER_IN_FINAL_CLASS, "'open' has no effect in a final class") + map.put(NON_FINAL_MEMBER_IN_OBJECT, "'open' has no effect in an object") map.put( GENERIC_THROWABLE_SUBCLASS, "Subclass of 'Throwable' may not have type parameters" diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt index a158c5d35d9..3c39382aa5d 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt @@ -39,6 +39,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() { override val classCheckers: Set = setOf( FirOverrideChecker, FirThrowableSubclassChecker, + FirOpenMemberChecker, ) override val regularClassCheckers: Set = setOf( diff --git a/compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.fir.kt b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.fir.kt index 5911eaa8f3e..ea47b0e4e21 100644 --- a/compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.fir.kt @@ -10,7 +10,7 @@ inline class A4(var x: Int) inline class A5(val x: Int, val y: Int) inline class A6(x: Int, val y: Int) inline class A7(vararg val x: Int) -inline class A8(open val x: Int) +inline class A8(open val x: Int) inline class A9(final val x: Int) class B1 { diff --git a/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt b/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt index 32ff714f8dd..bf5893bc6a8 100644 --- a/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt @@ -7,14 +7,14 @@ abstract class A() { final open fun h() {} open var r: String - get - abstract protected set + get + abstract protected set } final interface T {} class FinalClass() { - open fun foo() {} + open fun foo() {} val i: Int = 1 open get(): Int = field var j: Int = 1 @@ -32,13 +32,13 @@ class LegalModifier(val a: Int, @annotated private var b: String, @annotated var //Check illegal modifier in constructor parameters class IllegalModifiers1( - in - out - reified - enum - private - const - a: Int) + in + out + reified + enum + private + const + a: Int) //Check multiple illegal modifiers in constructor class IllegalModifiers2(private abstract a: Int) @@ -53,26 +53,26 @@ class IllegalModifiers4(val a: Int, @annotated("a text") protected vararg v: Int //Check illegal modifiers for functions and catch block abstract class IllegalModifiers5() { - //Check illegal modifier in function parameter - abstract fun foo(public a: Int, vararg v: String) + //Check illegal modifier in function parameter + abstract fun foo(public a: Int, vararg v: String) - //Check multiple illegal modifiers in function parameter - abstract fun bar(public abstract a: Int, vararg v: String) + //Check multiple illegal modifiers in function parameter + abstract fun bar(public abstract a: Int, vararg v: String) - //Check annotations with illegal modifiers - abstract fun baz(@annotated("a text") public abstract a: Int) + //Check annotations with illegal modifiers + abstract fun baz(@annotated("a text") public abstract a: Int) - private fun qux() { + private fun qux() { - //Check illegal modifier in catch block - try {} catch (in out reified enum public e: Exception) {} + //Check illegal modifier in catch block + try {} catch (in out reified enum public e: Exception) {} - //Check multiple illegal modifiers in catch block - try {} catch (in out reified enum abstract public e: Exception) {} + //Check multiple illegal modifiers in catch block + try {} catch (in out reified enum abstract public e: Exception) {} - //Check annotations with illegal modifiers - try {} catch (@annotated("a text") abstract public e: Exception) {} - } + //Check annotations with illegal modifiers + try {} catch (@annotated("a text") abstract public e: Exception) {} + } } //Check illegal modifiers on anonymous initializers diff --git a/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.kt b/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.kt index eac597e4a5d..4b5c2de73fd 100644 --- a/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.kt +++ b/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.kt @@ -7,8 +7,8 @@ abstract class A() { final open fun h() {} open var r: String - get - abstract protected set + get + abstract protected set } final interface T {} @@ -32,13 +32,13 @@ class LegalModifier(val a: Int, @annotated private var b: String, @annotated var //Check illegal modifier in constructor parameters class IllegalModifiers1( - in - out - reified - enum - private - const - a: Int) + in + out + reified + enum + private + const + a: Int) //Check multiple illegal modifiers in constructor class IllegalModifiers2(private abstract a: Int) @@ -53,26 +53,26 @@ class IllegalModifiers4(val a: Int, @annotated("a text") public a: Int, vararg v: String) + //Check illegal modifier in function parameter + abstract fun foo(public a: Int, vararg v: String) - //Check multiple illegal modifiers in function parameter - abstract fun bar(public abstract a: Int, vararg v: String) + //Check multiple illegal modifiers in function parameter + abstract fun bar(public abstract a: Int, vararg v: String) - //Check annotations with illegal modifiers - abstract fun baz(@annotated("a text") public abstract a: Int) + //Check annotations with illegal modifiers + abstract fun baz(@annotated("a text") public abstract a: Int) - private fun qux() { + private fun qux() { - //Check illegal modifier in catch block - try {} catch (in out reified enum public e: Exception) {} + //Check illegal modifier in catch block + try {} catch (in out reified enum public e: Exception) {} - //Check multiple illegal modifiers in catch block - try {} catch (in out reified enum abstract public e: Exception) {} + //Check multiple illegal modifiers in catch block + try {} catch (in out reified enum abstract public e: Exception) {} - //Check annotations with illegal modifiers - try {} catch (@annotated("a text") abstract public e: Exception) {} - } + //Check annotations with illegal modifiers + try {} catch (@annotated("a text") abstract public e: Exception) {} + } } //Check illegal modifiers on anonymous initializers diff --git a/compiler/testData/diagnostics/tests/objects/OpenInObject.fir.kt b/compiler/testData/diagnostics/tests/objects/OpenInObject.fir.kt deleted file mode 100644 index ca357cdd3c7..00000000000 --- a/compiler/testData/diagnostics/tests/objects/OpenInObject.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -object Obj { - fun foo() {} - - open fun bar() {} - - var x: Int = 0 - - open var y: Int = 1 -} diff --git a/compiler/testData/diagnostics/tests/objects/OpenInObject.kt b/compiler/testData/diagnostics/tests/objects/OpenInObject.kt index 0d032133499..356b5d97f9b 100644 --- a/compiler/testData/diagnostics/tests/objects/OpenInObject.kt +++ b/compiler/testData/diagnostics/tests/objects/OpenInObject.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL object Obj { fun foo() {} diff --git a/compiler/testData/diagnostics/tests/override/overrideMemberFromFinalClass.fir.kt b/compiler/testData/diagnostics/tests/override/overrideMemberFromFinalClass.fir.kt index 6585b36718a..1de65fcccc4 100644 --- a/compiler/testData/diagnostics/tests/override/overrideMemberFromFinalClass.fir.kt +++ b/compiler/testData/diagnostics/tests/override/overrideMemberFromFinalClass.fir.kt @@ -1,5 +1,5 @@ class Foo { - open fun openFoo() {} + open fun openFoo() {} fun finalFoo() {} } @@ -25,4 +25,4 @@ abstract class A2 { class B2 : A2() class C2 : B2() { override fun foo() {} -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/valueClasses/valueClassDeclarationCheck.fir.kt b/compiler/testData/diagnostics/tests/valueClasses/valueClassDeclarationCheck.fir.kt index a555bccb1bf..a7683e9acda 100644 --- a/compiler/testData/diagnostics/tests/valueClasses/valueClassDeclarationCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/valueClasses/valueClassDeclarationCheck.fir.kt @@ -24,7 +24,7 @@ value class A6(x: Int, val y: Int) @JvmInline value class A7(vararg val x: Int) @JvmInline -value class A8(open val x: Int) +value class A8(open val x: Int) @JvmInline value class A9(final val x: Int) diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.fir.kt index 79b17440a69..c79dc2e47fc 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/interface13.fir.kt @@ -54,6 +54,6 @@ interface E { interface F { companion object { @JvmField - open val a = 3 + open val a = 3 } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/finalAndAbstract.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/finalAndAbstract.fir.kt index a37ff0e192d..2f4126ab0a3 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/finalAndAbstract.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/finalAndAbstract.fir.kt @@ -16,7 +16,7 @@ object B: A() { @JvmStatic final override fun c() {} - @JvmStatic open fun d() {} + @JvmStatic open fun d() {} } class C { @@ -28,6 +28,6 @@ class C { @JvmStatic final override fun c() {} - @JvmStatic open fun d() {} + @JvmStatic open fun d() {} } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/property.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/property.fir.kt index 5913ec6959e..30203bc6838 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/property.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/property.fir.kt @@ -30,7 +30,7 @@ class A { @JvmStatic override val base1: Int = 0 - @JvmStatic open fun f() {} + @JvmStatic open fun f() {} override val base2: Int = 0 @JvmStatic get @@ -42,4 +42,4 @@ class A { } @JvmStatic val z2 = 1; -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/property_LL13.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/property_LL13.fir.kt index 3d44a883fa3..d4e2e84617d 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/property_LL13.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmStatic/property_LL13.fir.kt @@ -30,7 +30,7 @@ class A { @JvmStatic override val base1: Int = 0 - @JvmStatic open fun f() {} + @JvmStatic open fun f() {} override val base2: Int = 0 @JvmStatic get @@ -42,4 +42,4 @@ class A { } @JvmStatic val z2 = 1; -} \ No newline at end of file +} 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 12e35474fc9..ed2d4f80ff2 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 @@ -723,6 +723,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS) { firDiagnostic -> + NonFinalMemberInFinalClassImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } + add(FirErrors.NON_FINAL_MEMBER_IN_OBJECT) { firDiagnostic -> + NonFinalMemberInObjectImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.MANY_COMPANION_OBJECTS) { firDiagnostic -> ManyCompanionObjectsImpl( firDiagnostic as FirPsiDiagnostic<*>, 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 5c3d07e9d6b..59e6aea5ba1 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 @@ -515,6 +515,14 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val overriddenDeclaration: KtSymbol } + abstract class NonFinalMemberInFinalClass : KtFirDiagnostic() { + override val diagnosticClass get() = NonFinalMemberInFinalClass::class + } + + abstract class NonFinalMemberInObject : KtFirDiagnostic() { + override val diagnosticClass get() = NonFinalMemberInObject::class + } + abstract class ManyCompanionObjects : KtFirDiagnostic() { override val diagnosticClass get() = ManyCompanionObjects::class } 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 d930ad9ee43..18d7cad5c93 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 @@ -822,6 +822,20 @@ internal class VarOverriddenByValImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class NonFinalMemberInFinalClassImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.NonFinalMemberInFinalClass(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + +internal class NonFinalMemberInObjectImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.NonFinalMemberInObject(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ManyCompanionObjectsImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -- GitLab