FIR checker: make member property checker robust to conflict modifiers
This commit is contained in:
committed by
Mikhail Glukhikh
parent
39df3e2b0a
commit
2e8b5f2380
+18
-7
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
// See old FE's [DeclarationsChecker]
|
// See old FE's [DeclarationsChecker]
|
||||||
object FirMemberPropertyChecker : FirRegularClassChecker() {
|
object FirMemberPropertyChecker : FirRegularClassChecker() {
|
||||||
@@ -28,9 +29,13 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkProperty(containingDeclaration: FirRegularClass, property: FirProperty, reporter: DiagnosticReporter) {
|
private fun checkProperty(containingDeclaration: FirRegularClass, property: FirProperty, reporter: DiagnosticReporter) {
|
||||||
|
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
|
||||||
|
// So, our source of truth should be the full modifier list retrieved from the source.
|
||||||
|
val modifierList = with(FirModifierList) { property.source.getModifierList() }
|
||||||
|
val isAbstract = property.isAbstract || modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true
|
||||||
if (containingDeclaration.isInterface &&
|
if (containingDeclaration.isInterface &&
|
||||||
Visibilities.isPrivate(property.visibility) &&
|
Visibilities.isPrivate(property.visibility) &&
|
||||||
!property.isAbstract &&
|
!isAbstract &&
|
||||||
(property.getter == null || property.getter is FirDefaultPropertyAccessor)
|
(property.getter == null || property.getter is FirDefaultPropertyAccessor)
|
||||||
) {
|
) {
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
@@ -38,7 +43,7 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property.isAbstract) {
|
if (isAbstract) {
|
||||||
if (!containingDeclaration.canHaveAbstractDeclaration) {
|
if (!containingDeclaration.canHaveAbstractDeclaration) {
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
reporter.report(it, FirErrors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS)
|
reporter.report(it, FirErrors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS)
|
||||||
@@ -68,9 +73,10 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPropertyInitializer(containingDeclaration, property, reporter)
|
checkPropertyInitializer(containingDeclaration, property, isAbstract, reporter)
|
||||||
|
|
||||||
if (property.isOpen) {
|
val isOpen = property.isOpen || modifierList?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true
|
||||||
|
if (isOpen) {
|
||||||
checkAccessor(property.setter, property.delegate) { src, symbol ->
|
checkAccessor(property.setter, property.delegate) { src, symbol ->
|
||||||
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
|
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
|
||||||
reporter.report(FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY.on(src, symbol))
|
reporter.report(FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY.on(src, symbol))
|
||||||
@@ -79,15 +85,20 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPropertyInitializer(containingDeclaration: FirRegularClass, property: FirProperty, reporter: DiagnosticReporter) {
|
private fun checkPropertyInitializer(
|
||||||
|
containingDeclaration: FirRegularClass,
|
||||||
|
property: FirProperty,
|
||||||
|
propertyIsAbstract: Boolean,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
property.initializer?.source?.let {
|
property.initializer?.source?.let {
|
||||||
if (property.isAbstract) {
|
if (propertyIsAbstract) {
|
||||||
reporter.report(FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER.on(it, property.initializer!!))
|
reporter.report(FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER.on(it, property.initializer!!))
|
||||||
} else if (containingDeclaration.isInterface) {
|
} else if (containingDeclaration.isInterface) {
|
||||||
reporter.report(FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE.on(it, property.initializer!!))
|
reporter.report(FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE.on(it, property.initializer!!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (property.isAbstract) {
|
if (propertyIsAbstract) {
|
||||||
if (property.initializer == null && property.delegate == null && property.returnTypeRef is FirImplicitTypeRef) {
|
if (property.initializer == null && property.delegate == null && property.returnTypeRef is FirImplicitTypeRef) {
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
reporter.report(FirErrors.PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(it, property.symbol))
|
reporter.report(FirErrors.PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(it, property.symbol))
|
||||||
|
|||||||
Reference in New Issue
Block a user