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

View File

@@ -75,7 +75,7 @@ open class J {
}
var buf = 0
private get() = 42
<!GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY!>private<!> get() = 42
protected set(value) {
field = value
}

View File

@@ -547,6 +547,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
parameter<ConeKotlinType>("expected")
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") {

View File

@@ -338,6 +338,8 @@ object FirErrors {
val CONST_VAL_WITH_NON_CONST_INITIALIZER by error0<KtExpression>()
val WRONG_SETTER_PARAMETER_TYPE by error2<KtTypeReference, ConeKotlinType, ConeKotlinType>()
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
val EXPECTED_DECLARATION_WITH_BODY by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)

View File

@@ -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.withSuppressedDiagnostics
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.coneType
import org.jetbrains.kotlin.fir.types.isUnit
object FirPropertyAccessorChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
checkGetter(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) {
val setter = property.setter ?: return
@@ -43,6 +55,15 @@ object FirPropertyAccessorChecker : FirPropertyChecker() {
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)
}
}
}
}

View File

@@ -28,8 +28,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirExposedVisibilityDeclarationChecker,
FirSealedSupertypeChecker,
FirTypeAliasChecker,
FirCyclicTypeBoundsChecker,
)
FirCyclicTypeBoundsChecker,
)
override val functionCheckers: Set<FirFunctionChecker>
get() = setOf(
@@ -40,8 +40,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
get() = setOf(
FirFunctionNameChecker,
FirFunctionTypeParametersChecker,
)
FirFunctionTypeParametersChecker,
)
override val propertyCheckers: Set<FirPropertyChecker>
get() = setOf(
@@ -110,7 +110,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
override val typeParameterCheckers: Set<FirTypeParameterChecker>
get() = setOf(
FirTypeParameterBoundsChecker,
FirTypeParameterVarianceChecker,
FirReifiedTypeParameterChecker,
)
FirTypeParameterVarianceChecker,
FirReifiedTypeParameterChecker,
)
}

View File

@@ -4,14 +4,14 @@ abstract class My {
<!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
abstract val y: Int
protected get
<!GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY!>protected<!> get
abstract protected var z: Int
internal get
<!GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY!>internal<!> get
<!PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY!>private<!> set
abstract internal val w: Int
protected get
<!GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY!>protected<!> get
abstract var u: Int
protected set

View File

@@ -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
}

View File

@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// KT-7042 Providing return type for property setter is not reported as error
var x: Int = 1

View File

@@ -1581,6 +1581,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
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 ->
ExpectedDeclarationWithBodyImpl(
firDiagnostic as FirPsiDiagnostic<*>,

View File

@@ -1112,6 +1112,14 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
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>() {
override val diagnosticClass get() = ExpectedDeclarationWithBody::class
}

View File

@@ -1803,6 +1803,20 @@ internal class InitializerTypeMismatchImpl(
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(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,