提交 6b453d9b 编写于 作者: T Tianyu Geng 提交者: Mikhail Glukhikh

FIR: implement checker for open members

Specifically,

1. NON_FINAL_MEMBER_IN_FINAL_CLASS
2. NON_FINAL_MEMBER_IN_OBJECT
上级 3e9ff3ec
...@@ -47,7 +47,7 @@ class FinalDerived : Base() { ...@@ -47,7 +47,7 @@ class FinalDerived : Base() {
// Redundant final // Redundant final
override <!REDUNDANT_MODALITY_MODIFIER!>final<!> fun bar() {} override <!REDUNDANT_MODALITY_MODIFIER!>final<!> fun bar() {}
// Non-final member in final class // Non-final member in final class
override open val gav = 13 override <!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> val gav = 13
} }
// Open // Open
open class OpenDerived : Base() { open class OpenDerived : Base() {
......
...@@ -243,6 +243,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() { ...@@ -243,6 +243,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
parameter<FirMemberDeclaration>("overridingDeclaration") parameter<FirMemberDeclaration>("overridingDeclaration")
parameter<FirMemberDeclaration>("overriddenDeclaration") parameter<FirMemberDeclaration>("overriddenDeclaration")
} }
val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.OPEN_MODIFIER)
val NON_FINAL_MEMBER_IN_OBJECT by warning<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.OPEN_MODIFIER)
} }
val REDECLARATIONS by object : DiagnosticGroup("Redeclarations") { val REDECLARATIONS by object : DiagnosticGroup("Redeclarations") {
......
...@@ -176,6 +176,8 @@ object FirErrors { ...@@ -176,6 +176,8 @@ object FirErrors {
val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE) val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE) val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
val VAR_OVERRIDDEN_BY_VAL by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) val VAR_OVERRIDDEN_BY_VAL by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.OPEN_MODIFIER)
val NON_FINAL_MEMBER_IN_OBJECT by warning0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.OPEN_MODIFIER)
// Redeclarations // Redeclarations
val MANY_COMPANION_OBJECTS by error0<FirSourceElement, PsiElement>() val MANY_COMPANION_OBJECTS by error0<FirSourceElement, PsiElement>()
......
...@@ -5,9 +5,12 @@ ...@@ -5,9 +5,12 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration 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.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext 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.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
...@@ -123,3 +126,6 @@ internal fun checkPropertyInitializer( ...@@ -123,3 +126,6 @@ internal fun checkPropertyInitializer(
private val FirProperty.hasAccessorImplementation: Boolean private val FirProperty.hasAccessorImplementation: Boolean
get() = (getter !is FirDefaultPropertyAccessor && getter?.hasBody == true) || get() = (getter !is FirDefaultPropertyAccessor && getter?.hasBody == true) ||
(setter !is FirDefaultPropertyAccessor && setter?.hasBody == true) (setter !is FirDefaultPropertyAccessor && setter?.hasBody == true)
internal val FirClass<*>.canHaveOpenMembers: Boolean get() = modality() != Modality.FINAL || classKind == ClassKind.ENUM_CLASS
/*
* 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
}
}
...@@ -99,6 +99,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_COMPANION_OB ...@@ -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.MISSING_VAL_ON_ANNOTATION_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE 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_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_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_CONSTRUCTOR_IN_ENUM
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED
...@@ -394,6 +396,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { ...@@ -394,6 +396,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
FQ_NAMES_IN_TYPES, FQ_NAMES_IN_TYPES,
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( map.put(
GENERIC_THROWABLE_SUBCLASS, GENERIC_THROWABLE_SUBCLASS,
"Subclass of 'Throwable' may not have type parameters" "Subclass of 'Throwable' may not have type parameters"
......
...@@ -39,6 +39,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() { ...@@ -39,6 +39,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
override val classCheckers: Set<FirClassChecker> = setOf( override val classCheckers: Set<FirClassChecker> = setOf(
FirOverrideChecker, FirOverrideChecker,
FirThrowableSubclassChecker, FirThrowableSubclassChecker,
FirOpenMemberChecker,
) )
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf( override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
......
...@@ -10,7 +10,7 @@ inline class A4(var x: Int) ...@@ -10,7 +10,7 @@ inline class A4(var x: Int)
inline class A5(val x: Int, val y: Int) inline class A5(val x: Int, val y: Int)
inline class A6(x: Int, val y: Int) inline class A6(x: Int, val y: Int)
inline class A7(vararg val x: Int) inline class A7(vararg val x: Int)
inline class A8(open val x: Int) inline class A8(<!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> val x: Int)
inline class A9(final val x: Int) inline class A9(final val x: Int)
class B1 { class B1 {
......
...@@ -7,14 +7,14 @@ abstract class A() { ...@@ -7,14 +7,14 @@ abstract class A() {
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {} <!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {}
open var r: String open var r: String
get get
abstract protected set abstract protected set
} }
final interface T {} final interface T {}
class FinalClass() { class FinalClass() {
open fun foo() {} <!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> fun foo() {}
val i: Int = 1 val i: Int = 1
open get(): Int = field open get(): Int = field
var j: Int = 1 var j: Int = 1
...@@ -32,13 +32,13 @@ class LegalModifier(val a: Int, @annotated private var b: String, @annotated var ...@@ -32,13 +32,13 @@ class LegalModifier(val a: Int, @annotated private var b: String, @annotated var
//Check illegal modifier in constructor parameters //Check illegal modifier in constructor parameters
class IllegalModifiers1( class IllegalModifiers1(
<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>in<!>
<!INCOMPATIBLE_MODIFIERS!>out<!> <!INCOMPATIBLE_MODIFIERS!>out<!>
reified reified
enum enum
private private
const const
a: Int) a: Int)
//Check multiple illegal modifiers in constructor //Check multiple illegal modifiers in constructor
class IllegalModifiers2(<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> a: Int) class IllegalModifiers2(<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> a: Int)
...@@ -53,26 +53,26 @@ class IllegalModifiers4(val a: Int, @annotated("a text") protected vararg v: 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 //Check illegal modifiers for functions and catch block
abstract class IllegalModifiers5() { abstract class IllegalModifiers5() {
//Check illegal modifier in function parameter //Check illegal modifier in function parameter
abstract fun foo(public a: Int, vararg v: String) abstract fun foo(public a: Int, vararg v: String)
//Check multiple illegal modifiers in function parameter //Check multiple illegal modifiers in function parameter
abstract fun bar(public abstract a: Int, vararg v: String) abstract fun bar(public abstract a: Int, vararg v: String)
//Check annotations with illegal modifiers //Check annotations with illegal modifiers
abstract fun baz(@annotated("a text") public abstract a: Int) abstract fun baz(@annotated("a text") public abstract a: Int)
private fun qux() { private fun qux() {
//Check illegal modifier in catch block //Check illegal modifier in catch block
try {} catch (<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> reified enum public e: Exception) {} try {} catch (<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> reified enum public e: Exception) {}
//Check multiple illegal modifiers in catch block //Check multiple illegal modifiers in catch block
try {} catch (<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> reified enum abstract public e: Exception) {} try {} catch (<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> reified enum abstract public e: Exception) {}
//Check annotations with illegal modifiers //Check annotations with illegal modifiers
try {} catch (@annotated("a text") abstract public e: Exception) {} try {} catch (@annotated("a text") abstract public e: Exception) {}
} }
} }
//Check illegal modifiers on anonymous initializers //Check illegal modifiers on anonymous initializers
......
...@@ -7,8 +7,8 @@ abstract class A() { ...@@ -7,8 +7,8 @@ abstract class A() {
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {} <!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {}
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>open var r: String<!> <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>open var r: String<!>
get get
<!WRONG_MODIFIER_TARGET!>abstract<!> protected set <!WRONG_MODIFIER_TARGET!>abstract<!> protected set
} }
<!WRONG_MODIFIER_TARGET!>final<!> interface T {} <!WRONG_MODIFIER_TARGET!>final<!> interface T {}
...@@ -32,13 +32,13 @@ class LegalModifier(val a: Int, @annotated private var b: String, @annotated var ...@@ -32,13 +32,13 @@ class LegalModifier(val a: Int, @annotated private var b: String, @annotated var
//Check illegal modifier in constructor parameters //Check illegal modifier in constructor parameters
class IllegalModifiers1( class IllegalModifiers1(
<!WRONG_MODIFIER_TARGET!>in<!> <!WRONG_MODIFIER_TARGET!>in<!>
<!INCOMPATIBLE_MODIFIERS!>out<!> <!INCOMPATIBLE_MODIFIERS!>out<!>
<!WRONG_MODIFIER_TARGET!>reified<!> <!WRONG_MODIFIER_TARGET!>reified<!>
<!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>enum<!>
<!WRONG_MODIFIER_TARGET!>private<!> <!WRONG_MODIFIER_TARGET!>private<!>
<!WRONG_MODIFIER_TARGET!>const<!> <!WRONG_MODIFIER_TARGET!>const<!>
<!UNUSED_PARAMETER!>a<!>: Int) <!UNUSED_PARAMETER!>a<!>: Int)
//Check multiple illegal modifiers in constructor //Check multiple illegal modifiers in constructor
class IllegalModifiers2(<!WRONG_MODIFIER_TARGET!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> <!UNUSED_PARAMETER!>a<!>: Int) class IllegalModifiers2(<!WRONG_MODIFIER_TARGET!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> <!UNUSED_PARAMETER!>a<!>: Int)
...@@ -53,26 +53,26 @@ class IllegalModifiers4(val a: Int, @annotated("a text") <!WRONG_MODIFIER_TARGET ...@@ -53,26 +53,26 @@ class IllegalModifiers4(val a: Int, @annotated("a text") <!WRONG_MODIFIER_TARGET
//Check illegal modifiers for functions and catch block //Check illegal modifiers for functions and catch block
abstract class IllegalModifiers5() { abstract class IllegalModifiers5() {
//Check illegal modifier in function parameter //Check illegal modifier in function parameter
abstract fun foo(<!WRONG_MODIFIER_TARGET!>public<!> a: Int, vararg v: String) abstract fun foo(<!WRONG_MODIFIER_TARGET!>public<!> a: Int, vararg v: String)
//Check multiple illegal modifiers in function parameter //Check multiple illegal modifiers in function parameter
abstract fun bar(<!WRONG_MODIFIER_TARGET!>public<!> <!WRONG_MODIFIER_TARGET!>abstract<!> a: Int, vararg v: String) abstract fun bar(<!WRONG_MODIFIER_TARGET!>public<!> <!WRONG_MODIFIER_TARGET!>abstract<!> a: Int, vararg v: String)
//Check annotations with illegal modifiers //Check annotations with illegal modifiers
abstract fun baz(@annotated("a text") <!WRONG_MODIFIER_TARGET!>public<!> <!WRONG_MODIFIER_TARGET!>abstract<!> a: Int) abstract fun baz(@annotated("a text") <!WRONG_MODIFIER_TARGET!>public<!> <!WRONG_MODIFIER_TARGET!>abstract<!> a: Int)
private fun qux() { private fun qux() {
//Check illegal modifier in catch block //Check illegal modifier in catch block
try {} catch (<!WRONG_MODIFIER_TARGET!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> <!WRONG_MODIFIER_TARGET!>reified<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {} try {} catch (<!WRONG_MODIFIER_TARGET!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> <!WRONG_MODIFIER_TARGET!>reified<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {}
//Check multiple illegal modifiers in catch block //Check multiple illegal modifiers in catch block
try {} catch (<!WRONG_MODIFIER_TARGET!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> <!WRONG_MODIFIER_TARGET!>reified<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>abstract<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {} try {} catch (<!WRONG_MODIFIER_TARGET!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> <!WRONG_MODIFIER_TARGET!>reified<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>abstract<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {}
//Check annotations with illegal modifiers //Check annotations with illegal modifiers
try {} catch (@annotated("a text") <!WRONG_MODIFIER_TARGET!>abstract<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {} try {} catch (@annotated("a text") <!WRONG_MODIFIER_TARGET!>abstract<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {}
} }
} }
//Check illegal modifiers on anonymous initializers //Check illegal modifiers on anonymous initializers
......
object Obj {
fun foo() {}
open fun bar() {}
var x: Int = 0
open var y: Int = 1
}
// FIR_IDENTICAL
object Obj { object Obj {
fun foo() {} fun foo() {}
......
class Foo { class Foo {
open fun openFoo() {} <!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> fun openFoo() {}
fun finalFoo() {} fun finalFoo() {}
} }
...@@ -25,4 +25,4 @@ abstract class A2 { ...@@ -25,4 +25,4 @@ abstract class A2 {
class B2 : A2() class B2 : A2()
class C2 : B2() { class C2 : B2() {
override fun foo() {} override fun foo() {}
} }
\ No newline at end of file
...@@ -24,7 +24,7 @@ value class A6(x: Int, val y: Int) ...@@ -24,7 +24,7 @@ value class A6(x: Int, val y: Int)
@JvmInline @JvmInline
value class A7(vararg val x: Int) value class A7(vararg val x: Int)
@JvmInline @JvmInline
value class A8(open val x: Int) value class A8(<!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> val x: Int)
@JvmInline @JvmInline
value class A9(final val x: Int) value class A9(final val x: Int)
......
...@@ -54,6 +54,6 @@ interface E { ...@@ -54,6 +54,6 @@ interface E {
interface F { interface F {
companion object { companion object {
@JvmField @JvmField
open val a = 3 <!NON_FINAL_MEMBER_IN_OBJECT!>open<!> val a = 3
} }
} }
...@@ -16,7 +16,7 @@ object B: A() { ...@@ -16,7 +16,7 @@ object B: A() {
@JvmStatic final override fun c() {} @JvmStatic final override fun c() {}
@JvmStatic open fun d() {} @JvmStatic <!NON_FINAL_MEMBER_IN_OBJECT!>open<!> fun d() {}
} }
class C { class C {
...@@ -28,6 +28,6 @@ class C { ...@@ -28,6 +28,6 @@ class C {
@JvmStatic final override fun c() {} @JvmStatic final override fun c() {}
@JvmStatic open fun d() {} @JvmStatic <!NON_FINAL_MEMBER_IN_OBJECT!>open<!> fun d() {}
} }
} }
\ No newline at end of file
...@@ -30,7 +30,7 @@ class A { ...@@ -30,7 +30,7 @@ class A {
@JvmStatic override val base1: Int = 0 @JvmStatic override val base1: Int = 0
@JvmStatic open fun f() {} @JvmStatic <!NON_FINAL_MEMBER_IN_OBJECT!>open<!> fun f() {}
override val base2: Int = 0 override val base2: Int = 0
@JvmStatic get @JvmStatic get
...@@ -42,4 +42,4 @@ class A { ...@@ -42,4 +42,4 @@ class A {
} }
@JvmStatic val z2 = 1; @JvmStatic val z2 = 1;
} }
\ No newline at end of file
...@@ -30,7 +30,7 @@ class A { ...@@ -30,7 +30,7 @@ class A {
@JvmStatic override val base1: Int = 0 @JvmStatic override val base1: Int = 0
@JvmStatic open fun f() {} @JvmStatic <!NON_FINAL_MEMBER_IN_OBJECT!>open<!> fun f() {}
override val base2: Int = 0 override val base2: Int = 0
@JvmStatic get @JvmStatic get
...@@ -42,4 +42,4 @@ class A { ...@@ -42,4 +42,4 @@ class A {
} }
@JvmStatic val z2 = 1; @JvmStatic val z2 = 1;
} }
\ No newline at end of file
...@@ -723,6 +723,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert ...@@ -723,6 +723,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token, 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 -> add(FirErrors.MANY_COMPANION_OBJECTS) { firDiagnostic ->
ManyCompanionObjectsImpl( ManyCompanionObjectsImpl(
firDiagnostic as FirPsiDiagnostic<*>, firDiagnostic as FirPsiDiagnostic<*>,
......
...@@ -515,6 +515,14 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> { ...@@ -515,6 +515,14 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val overriddenDeclaration: KtSymbol abstract val overriddenDeclaration: KtSymbol
} }
abstract class NonFinalMemberInFinalClass : KtFirDiagnostic<KtNamedDeclaration>() {
override val diagnosticClass get() = NonFinalMemberInFinalClass::class
}
abstract class NonFinalMemberInObject : KtFirDiagnostic<KtNamedDeclaration>() {
override val diagnosticClass get() = NonFinalMemberInObject::class
}
abstract class ManyCompanionObjects : KtFirDiagnostic<PsiElement>() { abstract class ManyCompanionObjects : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = ManyCompanionObjects::class override val diagnosticClass get() = ManyCompanionObjects::class
} }
......
...@@ -822,6 +822,20 @@ internal class VarOverriddenByValImpl( ...@@ -822,6 +822,20 @@ internal class VarOverriddenByValImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
} }
internal class NonFinalMemberInFinalClassImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.NonFinalMemberInFinalClass(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class NonFinalMemberInObjectImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.NonFinalMemberInObject(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ManyCompanionObjectsImpl( internal class ManyCompanionObjectsImpl(
firDiagnostic: FirPsiDiagnostic<*>, firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken, override val token: ValidityToken,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册