[FIR] Complete WRONG_SETTER_TYPE_PARAMETER checker

This commit is contained in:
yantimirov-timur
2021-03-03 17:46:26 +03:00
committed by Mikhail Glukhikh
parent 5472199bb1
commit 9e7f6332d1
18 changed files with 151 additions and 11 deletions
@@ -359,6 +359,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/sealedClass.kt");
}
@TestMetadata("settersGetters.kt")
public void testSettersGetters() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/settersGetters.kt");
}
@TestMetadata("simpleClass.kt")
public void testSimpleClass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/simpleClass.kt");
@@ -0,0 +1,13 @@
FILE: settersGetters.kt
public final class SomeClass : R|kotlin/Any| {
public constructor(): R|SomeClass| {
super<R|kotlin/Any|>()
}
public final var foo: R|kotlin/Int| = Int(0)
public get(): R|kotlin/Int|
public set(value: R|kotlin/String|): R|kotlin/Unit| {
this@R|/SomeClass|.F|/SomeClass.foo| = R|<local>/value|
}
}
@@ -0,0 +1,8 @@
class SomeClass {
var foo: Int = 0
set(value: <!WRONG_SETTER_PARAMETER_TYPE!>String<!>){
field = value
}
}
@@ -422,6 +422,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
runTest("compiler/fir/analysis-tests/testData/resolve/sealedClass.kt");
}
@Test
@TestMetadata("settersGetters.kt")
public void testSettersGetters() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/settersGetters.kt");
}
@Test
@TestMetadata("simpleClass.kt")
public void testSimpleClass() throws Exception {
@@ -425,6 +425,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/sealedClass.kt");
}
@Test
@TestMetadata("settersGetters.kt")
public void testSettersGetters() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/settersGetters.kt");
}
@Test
@TestMetadata("simpleClass.kt")
public void testSimpleClass() throws Exception {
@@ -468,6 +468,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT by error<FirSourceElement, KtProperty>(PositioningStrategy.CONST_MODIFIER)
val CONST_VAL_WITH_GETTER by error<FirSourceElement, KtProperty>()
val CONST_VAL_WITH_DELEGATE by error<FirSourceElement, KtPropertyDelegate>()
val WRONG_SETTER_PARAMETER_TYPE by error<FirSourceElement, KtTypeReference> {
parameter<ConeKotlinType>("expectedType")
parameter<ConeKotlinType>("actualType")
}
}
val MPP_PROJECTS by object : DiagnosticGroup("Multi-platform projects") {
@@ -293,6 +293,7 @@ object FirErrors {
val CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT by error0<FirSourceElement, KtProperty>(SourceElementPositioningStrategies.CONST_MODIFIER)
val CONST_VAL_WITH_GETTER by error0<FirSourceElement, KtProperty>()
val CONST_VAL_WITH_DELEGATE by error0<FirSourceElement, KtPropertyDelegate>()
val WRONG_SETTER_PARAMETER_TYPE by error2<FirSourceElement, KtTypeReference, ConeKotlinType, ConeKotlinType>()
// Multi-platform projects
val EXPECTED_DECLARATION_WITH_BODY by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
@@ -0,0 +1,40 @@
/*
* 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.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_PARAMETER_TYPE
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.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.coneType
object FirPropertyAccessorChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
val setter = declaration.setter ?: return
val valueSetterParameter = setter.valueParameters.first()
if (valueSetterParameter.isVararg) {
return
}
val valueSetterType = valueSetterParameter.returnTypeRef.coneType
val valueSetterTypeSource = valueSetterParameter.returnTypeRef.source
val propertyType = declaration.returnTypeRef.coneType
if (propertyType is ConeClassErrorType || valueSetterType is ConeClassErrorType) {
return
}
if (valueSetterType != propertyType) {
withSuppressedDiagnostics(setter, context) {
withSuppressedDiagnostics(valueSetterParameter, context) {
reporter.reportOn(valueSetterTypeSource, WRONG_SETTER_PARAMETER_TYPE, propertyType, valueSetterType, context)
}
}
}
}
}
@@ -239,6 +239,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_TYPE_MISMATCH
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_INVOCATION_KIND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_MODIFIER_TARGET
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_PARAMETER_TYPE
@Suppress("unused")
class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
@@ -469,7 +470,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(INLINE_CLASS_NOT_FINAL, "Inline classes can be only final")
map.put(ABSENCE_OF_PRIMARY_CONSTRUCTOR_FOR_INLINE_CLASS, "Primary constructor is required for inline class")
map.put(INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE, "Inline class must have exactly one primary constructor parameter")
map.put(INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER, "Value class primary constructor must have only final read-only (val) property parameter")
map.put(
INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER,
"Value class primary constructor must have only final read-only (val) property parameter"
)
map.put(PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS, "Inline class cannot have properties with backing fields")
map.put(DELEGATED_PROPERTY_INSIDE_INLINE_CLASS, "Inline class cannot have delegated properties")
map.put(INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE, "Inline class cannot have value parameter of type ''{0}''", TO_STRING)
@@ -477,7 +481,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(INLINE_CLASS_CANNOT_EXTEND_CLASSES, "Inline class cannot extend classes")
map.put(INLINE_CLASS_CANNOT_BE_RECURSIVE, "Inline class cannot be recursive")
map.put(RESERVED_MEMBER_INSIDE_INLINE_CLASS, "Member with the name ''{0}'' is reserved for future releases", TO_STRING)
map.put(SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS, "Secondary constructors with bodies are reserved for for future releases")
map.put(
SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS,
"Secondary constructors with bodies are reserved for for future releases"
)
map.put(INNER_CLASS_INSIDE_INLINE_CLASS, "Inline class cannot have inner classes")
map.put(VALUE_CLASS_CANNOT_BE_CLONEABLE, "Value class cannot be Cloneable")
@@ -635,6 +642,12 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY, "Private setters are not allowed for abstract properties")
map.put(PRIVATE_SETTER_FOR_OPEN_PROPERTY, "Private setters are not allowed for open properties")
map.put(VAL_WITH_SETTER, "A 'val'-property cannot have a setter")
map.put(
WRONG_SETTER_PARAMETER_TYPE,
"Setter parameter type must be equal to the type of the property, i.e. ''{0}''",
RENDER_TYPE,
RENDER_TYPE
)
// Multi-platform projects
map.put(EXPECTED_DECLARATION_WITH_BODY, "Expected declaration must not have a body")
@@ -40,6 +40,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirInapplicableLateinitChecker,
FirDestructuringDeclarationChecker,
FirConstPropertyChecker,
FirPropertyAccessorChecker
)
override val classCheckers: Set<FirClassChecker> = setOf(
+2 -2
View File
@@ -1,13 +1,13 @@
var x : Int = 1 + x
get() : Int = 1
set(value : Long) {
set(value : <!WRONG_SETTER_PARAMETER_TYPE!>Long<!>) {
field = value.toInt()
field = 1.toLong()
}
val xx : Int = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>1 + x<!>
get() : Int = 1
<!VAL_WITH_SETTER!>set(value : Long) {}<!>
<!VAL_WITH_SETTER!>set(value : <!WRONG_SETTER_PARAMETER_TYPE!>Long<!>) {}<!>
val p : Int = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>1<!>
get() = 1
@@ -18,7 +18,7 @@ fun test2(a: @Ann Array<in @Ann Int>) {
var test3: Int = 0
set(s: @Ann String) {}
set(s: <!WRONG_SETTER_PARAMETER_TYPE!>@Ann String<!>) {}
fun f4(fn: (@Ann Int, @Ann Int) -> Unit) {}
@@ -2,7 +2,7 @@
class A() {
var x: Int = 0
get() = "s"
set(value: String) {
set(value: <!WRONG_SETTER_PARAMETER_TYPE!>String<!>) {
field = value
}
val y: Int
@@ -13,7 +13,7 @@ class A() {
}
var a: Any = 1
set(v: String) {
set(v: <!WRONG_SETTER_PARAMETER_TYPE!>String<!>) {
field = v
}
val b: Int
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
@@ -440,6 +441,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.SUPERTYPES_FOR_ANNOTATION_CLASS) { firDiagnostic ->
SupertypesForAnnotationClassImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE) { firDiagnostic ->
ExposedTypealiasExpandedTypeImpl(
firDiagnostic.a.toVisibility(),
@@ -1324,6 +1331,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.WRONG_SETTER_PARAMETER_TYPE) { firDiagnostic ->
WrongSetterParameterTypeImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPECTED_DECLARATION_WITH_BODY) { firDiagnostic ->
ExpectedDeclarationWithBodyImpl(
firDiagnostic as FirPsiDiagnostic<*>,
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
@@ -319,6 +320,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = VarAnnotationParameter::class
}
abstract class SupertypesForAnnotationClass : KtFirDiagnostic<KtClass>() {
override val diagnosticClass get() = SupertypesForAnnotationClass::class
}
abstract class ExposedTypealiasExpandedType : KtFirDiagnostic<KtNamedDeclaration>() {
override val diagnosticClass get() = ExposedTypealiasExpandedType::class
abstract val elementVisibility: Visibility
@@ -937,6 +942,12 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = ConstValWithDelegate::class
}
abstract class WrongSetterParameterType : KtFirDiagnostic<KtTypeReference>() {
override val diagnosticClass get() = WrongSetterParameterType::class
abstract val expectedType: KtType
abstract val actualType: KtType
}
abstract class ExpectedDeclarationWithBody : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = ExpectedDeclarationWithBody::class
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
@@ -512,6 +513,13 @@ internal class VarAnnotationParameterImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class SupertypesForAnnotationClassImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.SupertypesForAnnotationClass(), KtAbstractFirDiagnostic<KtClass> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExposedTypealiasExpandedTypeImpl(
override val elementVisibility: Visibility,
override val restrictingDeclaration: KtSymbol,
@@ -1514,6 +1522,15 @@ internal class ConstValWithDelegateImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class WrongSetterParameterTypeImpl(
override val expectedType: KtType,
override val actualType: KtType,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.WrongSetterParameterType(), KtAbstractFirDiagnostic<KtTypeReference> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExpectedDeclarationWithBodyImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
+2 -2
View File
@@ -1,13 +1,13 @@
var x : Int = 1 + x
get() : Int = 1
set(value : Long) {
set(value : <error descr="[WRONG_SETTER_PARAMETER_TYPE] Setter parameter type must be equal to the type of the property, i.e. 'kotlin/Int'">Long</error>) {
field = value.toInt()
field = 1.toLong()
}
val xx : Int = <error descr="[PROPERTY_INITIALIZER_NO_BACKING_FIELD] Initializer is not allowed here because this property has no backing field">1 + x</error>
get() : Int = 1
<error descr="[VAL_WITH_SETTER] A 'val'-property cannot have a setter">set(value : Long) {}</error>
<error descr="[VAL_WITH_SETTER] A 'val'-property cannot have a setter">set(value : <error descr="[WRONG_SETTER_PARAMETER_TYPE] Setter parameter type must be equal to the type of the property, i.e. 'kotlin/Int'">Long</error>) {}</error>
val p : Int = <error descr="[PROPERTY_INITIALIZER_NO_BACKING_FIELD] Initializer is not allowed here because this property has no backing field">1</error>
get() = 1
+2 -2
View File
@@ -1,7 +1,7 @@
class A() {
var x: Int = 0
get() = "s"
set(value: String) {
set(value: <error descr="[WRONG_SETTER_PARAMETER_TYPE] Setter parameter type must be equal to the type of the property, i.e. 'kotlin/Int'">String</error>) {
field = value
}
val y: Int
@@ -12,7 +12,7 @@ class A() {
}
var a: Any = 1
set(v: String) {
set(v: <error descr="[WRONG_SETTER_PARAMETER_TYPE] Setter parameter type must be equal to the type of the property, i.e. 'kotlin/Any'">String</error>) {
field = v
}
val b: Int