FIR: add 'withSuppressedDiagnostics' call to property checkers

This commit is contained in:
Mikhail Glukhikh
2021-05-07 13:23:49 +03:00
parent 6618b4ea57
commit 243114ef29
2 changed files with 76 additions and 70 deletions
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.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.analysis.diagnostics.withSuppressedDiagnostics
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.expressions.FirExpression
@@ -150,76 +151,78 @@ object FirMemberPropertiesChecker : FirRegularClassChecker() {
// So, our source of truth should be the full modifier list retrieved from the source.
val modifierList = property.source.getModifierList()
checkPropertyInitializer(
containingDeclaration,
property,
modifierList,
isInitialized,
reporter,
context
)
checkExpectDeclarationVisibilityAndBody(property, source, reporter, context)
withSuppressedDiagnostics(property, context) {
checkPropertyInitializer(
containingDeclaration,
property,
modifierList,
isInitialized,
reporter,
context
)
checkExpectDeclarationVisibilityAndBody(property, source, reporter, context)
val hasAbstractModifier = KtTokens.ABSTRACT_KEYWORD in modifierList
val isAbstract = property.isAbstract || hasAbstractModifier
if (containingDeclaration.isInterface &&
Visibilities.isPrivate(property.visibility) &&
!isAbstract &&
(property.getter == null || property.getter is FirDefaultPropertyAccessor)
) {
property.source?.let {
reporter.reportOn(it, FirErrors.PRIVATE_PROPERTY_IN_INTERFACE, context)
}
}
if (isAbstract) {
if (!containingDeclaration.canHaveAbstractDeclaration) {
val hasAbstractModifier = KtTokens.ABSTRACT_KEYWORD in modifierList
val isAbstract = property.isAbstract || hasAbstractModifier
if (containingDeclaration.isInterface &&
Visibilities.isPrivate(property.visibility) &&
!isAbstract &&
(property.getter == null || property.getter is FirDefaultPropertyAccessor)
) {
property.source?.let {
reporter.reportOn(
it,
FirErrors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS,
property,
containingDeclaration,
context
)
return
reporter.reportOn(it, FirErrors.PRIVATE_PROPERTY_IN_INTERFACE, context)
}
}
property.initializer?.source?.let {
reporter.reportOn(it, FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER, context)
}
property.delegate?.source?.let {
reporter.reportOn(it, FirErrors.ABSTRACT_DELEGATED_PROPERTY, context)
}
checkAccessor(property.getter, property.delegate) { src, _, hasBody ->
if (hasBody) reporter.reportOn(src, FirErrors.ABSTRACT_PROPERTY_WITH_GETTER, context)
}
checkAccessor(property.setter, property.delegate) { src, symbol, hasBody ->
when {
symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private ->
reporter.reportOn(src, FirErrors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY, context)
hasBody -> reporter.reportOn(src, FirErrors.ABSTRACT_PROPERTY_WITH_SETTER, context)
if (isAbstract) {
if (!containingDeclaration.canHaveAbstractDeclaration) {
property.source?.let {
reporter.reportOn(
it,
FirErrors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS,
property,
containingDeclaration,
context
)
return
}
}
property.initializer?.source?.let {
reporter.reportOn(it, FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER, context)
}
property.delegate?.source?.let {
reporter.reportOn(it, FirErrors.ABSTRACT_DELEGATED_PROPERTY, context)
}
checkAccessor(property.getter, property.delegate) { src, _, hasBody ->
if (hasBody) reporter.reportOn(src, FirErrors.ABSTRACT_PROPERTY_WITH_GETTER, context)
}
checkAccessor(property.setter, property.delegate) { src, symbol, hasBody ->
when {
symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private ->
reporter.reportOn(src, FirErrors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY, context)
hasBody -> reporter.reportOn(src, FirErrors.ABSTRACT_PROPERTY_WITH_SETTER, context)
}
}
}
}
val hasOpenModifier = KtTokens.OPEN_KEYWORD in modifierList
if (hasOpenModifier &&
containingDeclaration.isInterface &&
!hasAbstractModifier &&
property.isAbstract &&
!isInsideExpectClass(containingDeclaration, context)
) {
property.source?.let {
reporter.reportOn(it, FirErrors.REDUNDANT_OPEN_IN_INTERFACE, context)
val hasOpenModifier = KtTokens.OPEN_KEYWORD in modifierList
if (hasOpenModifier &&
containingDeclaration.isInterface &&
!hasAbstractModifier &&
property.isAbstract &&
!isInsideExpectClass(containingDeclaration, context)
) {
property.source?.let {
reporter.reportOn(it, FirErrors.REDUNDANT_OPEN_IN_INTERFACE, context)
}
}
}
val isOpen = property.isOpen || hasOpenModifier
if (isOpen) {
checkAccessor(property.setter, property.delegate) { src, symbol, _ ->
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
reporter.reportOn(src, FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY, context)
val isOpen = property.isOpen || hasOpenModifier
if (isOpen) {
checkAccessor(property.setter, property.delegate) { src, symbol, _ ->
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
reporter.reportOn(src, FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY, context)
}
}
}
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirProperty
@@ -29,14 +30,16 @@ object FirTopLevelPropertiesChecker : FirFileChecker() {
// So, our source of truth should be the full modifier list retrieved from the source.
val modifierList = source.getModifierList()
checkPropertyInitializer(
containingClass = null,
property,
modifierList,
isInitialized = property.initializer != null,
reporter,
context
)
checkExpectDeclarationVisibilityAndBody(property, source, reporter, context)
withSuppressedDiagnostics(property, context) {
checkPropertyInitializer(
containingClass = null,
property,
modifierList,
isInitialized = property.initializer != null,
reporter,
context
)
checkExpectDeclarationVisibilityAndBody(property, source, reporter, context)
}
}
}