FIR: add getter visibility and setter return type checks

This commit is contained in:
yantimirov-timur
2021-01-31 22:02:46 +03:00
committed by Mikhail Glukhikh
parent eedc4d8c3f
commit 1dfc3c0520
11 changed files with 71 additions and 37 deletions
@@ -75,7 +75,7 @@ open class J {
} }
var buf = 0 var buf = 0
private get() = 42 <!GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY!>private<!> get() = 42
protected set(value) { protected set(value) {
field = value field = value
} }
@@ -547,6 +547,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
parameter<ConeKotlinType>("expected") parameter<ConeKotlinType>("expected")
parameter<ConeKotlinType>("actual") parameter<ConeKotlinType>("actual")
} }
val GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY by error<KtModifierListOwner>(PositioningStrategy.VISIBILITY_MODIFIER)
val WRONG_SETTER_RETURN_TYPE by error<KtProperty>()
} }
val MPP_PROJECTS by object : DiagnosticGroup("Multi-platform projects") { val MPP_PROJECTS by object : DiagnosticGroup("Multi-platform projects") {
@@ -338,6 +338,8 @@ object FirErrors {
val CONST_VAL_WITH_NON_CONST_INITIALIZER by error0<KtExpression>() val CONST_VAL_WITH_NON_CONST_INITIALIZER by error0<KtExpression>()
val WRONG_SETTER_PARAMETER_TYPE by error2<KtTypeReference, ConeKotlinType, ConeKotlinType>() val WRONG_SETTER_PARAMETER_TYPE by error2<KtTypeReference, ConeKotlinType, ConeKotlinType>()
val INITIALIZER_TYPE_MISMATCH by error2<KtProperty, ConeKotlinType, ConeKotlinType>(SourceElementPositioningStrategies.ASSIGNMENT_VALUE) val INITIALIZER_TYPE_MISMATCH by error2<KtProperty, ConeKotlinType, ConeKotlinType>(SourceElementPositioningStrategies.ASSIGNMENT_VALUE)
val GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val WRONG_SETTER_RETURN_TYPE by error0<KtProperty>()
// Multi-platform projects // Multi-platform projects
val EXPECTED_DECLARATION_WITH_BODY by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val EXPECTED_DECLARATION_WITH_BODY by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
@@ -11,14 +11,26 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.visibility
import org.jetbrains.kotlin.fir.types.ConeClassErrorType import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isUnit
object FirPropertyAccessorChecker : FirPropertyChecker() { object FirPropertyAccessorChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
checkGetter(declaration, context, reporter)
checkSetter(declaration, context, reporter) checkSetter(declaration, context, reporter)
} }
private fun checkGetter(property: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
val getter = property.getter ?: return
withSuppressedDiagnostics(getter, context) {
if (getter.visibility != property.visibility) {
reporter.reportOn(getter.source, FirErrors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, context)
}
}
}
private fun checkSetter(property: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { private fun checkSetter(property: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
val setter = property.setter ?: return val setter = property.setter ?: return
@@ -43,6 +55,15 @@ object FirPropertyAccessorChecker : FirPropertyChecker() {
reporter.reportOn(valueSetterTypeSource, FirErrors.WRONG_SETTER_PARAMETER_TYPE, propertyType, valueSetterType, context) reporter.reportOn(valueSetterTypeSource, FirErrors.WRONG_SETTER_PARAMETER_TYPE, propertyType, valueSetterType, context)
} }
} }
val setterReturnType = setter.returnTypeRef.coneType
if (propertyType is ConeClassErrorType || valueSetterType is ConeClassErrorType) {
return
}
if (!setterReturnType.isUnit) {
reporter.reportOn(setter.returnTypeRef.source, FirErrors.WRONG_SETTER_RETURN_TYPE, context)
}
} }
} }
} }
@@ -28,8 +28,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirExposedVisibilityDeclarationChecker, FirExposedVisibilityDeclarationChecker,
FirSealedSupertypeChecker, FirSealedSupertypeChecker,
FirTypeAliasChecker, FirTypeAliasChecker,
FirCyclicTypeBoundsChecker, FirCyclicTypeBoundsChecker,
) )
override val functionCheckers: Set<FirFunctionChecker> override val functionCheckers: Set<FirFunctionChecker>
get() = setOf( get() = setOf(
@@ -40,8 +40,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker> override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
get() = setOf( get() = setOf(
FirFunctionNameChecker, FirFunctionNameChecker,
FirFunctionTypeParametersChecker, FirFunctionTypeParametersChecker,
) )
override val propertyCheckers: Set<FirPropertyChecker> override val propertyCheckers: Set<FirPropertyChecker>
get() = setOf( get() = setOf(
@@ -110,7 +110,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
override val typeParameterCheckers: Set<FirTypeParameterChecker> override val typeParameterCheckers: Set<FirTypeParameterChecker>
get() = setOf( get() = setOf(
FirTypeParameterBoundsChecker, FirTypeParameterBoundsChecker,
FirTypeParameterVarianceChecker, FirTypeParameterVarianceChecker,
FirReifiedTypeParameterChecker, FirReifiedTypeParameterChecker,
) )
} }
@@ -4,14 +4,14 @@ abstract class My {
<!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
abstract val y: Int abstract val y: Int
protected get <!GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY!>protected<!> get
abstract protected var z: Int abstract protected var z: Int
internal get <!GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY!>internal<!> get
<!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set <!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
abstract internal val w: Int abstract internal val w: Int
protected get <!GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY!>protected<!> get
abstract var u: Int abstract var u: Int
protected set protected set
@@ -1,26 +0,0 @@
// KT-7042 Providing return type for property setter is not reported as error
var x: Int = 1
// No backing field!
var y: Int
get() = x
set(value): Any {
x = value
}
var z: Int
get() = x
set(value): Unit {
x = value
}
var u: String = ""
set(value): Unit {
field = value
}
var v: String = ""
set(value): String {
field = value
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// KT-7042 Providing return type for property setter is not reported as error // KT-7042 Providing return type for property setter is not reported as error
var x: Int = 1 var x: Int = 1
@@ -1581,6 +1581,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token, token,
) )
} }
add(FirErrors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY) { firDiagnostic ->
GetterVisibilityDiffersFromPropertyVisibilityImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.WRONG_SETTER_RETURN_TYPE) { firDiagnostic ->
WrongSetterReturnTypeImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPECTED_DECLARATION_WITH_BODY) { firDiagnostic -> add(FirErrors.EXPECTED_DECLARATION_WITH_BODY) { firDiagnostic ->
ExpectedDeclarationWithBodyImpl( ExpectedDeclarationWithBodyImpl(
firDiagnostic as FirPsiDiagnostic<*>, firDiagnostic as FirPsiDiagnostic<*>,
@@ -1112,6 +1112,14 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val actual: KtType abstract val actual: KtType
} }
abstract class GetterVisibilityDiffersFromPropertyVisibility : KtFirDiagnostic<KtModifierListOwner>() {
override val diagnosticClass get() = GetterVisibilityDiffersFromPropertyVisibility::class
}
abstract class WrongSetterReturnType : KtFirDiagnostic<KtProperty>() {
override val diagnosticClass get() = WrongSetterReturnType::class
}
abstract class ExpectedDeclarationWithBody : KtFirDiagnostic<KtDeclaration>() { abstract class ExpectedDeclarationWithBody : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = ExpectedDeclarationWithBody::class override val diagnosticClass get() = ExpectedDeclarationWithBody::class
} }
@@ -1803,6 +1803,20 @@ internal class InitializerTypeMismatchImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
} }
internal class GetterVisibilityDiffersFromPropertyVisibilityImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.GetterVisibilityDiffersFromPropertyVisibility(), KtAbstractFirDiagnostic<KtModifierListOwner> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class WrongSetterReturnTypeImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.WrongSetterReturnType(), KtAbstractFirDiagnostic<KtProperty> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExpectedDeclarationWithBodyImpl( internal class ExpectedDeclarationWithBodyImpl(
firDiagnostic: FirPsiDiagnostic<*>, firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken, override val token: ValidityToken,