[FIR] Complete WRONG_SETTER_TYPE_PARAMETER checker
This commit is contained in:
committed by
Mikhail Glukhikh
parent
5472199bb1
commit
9e7f6332d1
+5
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+4
@@ -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)
|
||||
|
||||
+40
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-2
@@ -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")
|
||||
|
||||
+1
@@ -40,6 +40,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirInapplicableLateinitChecker,
|
||||
FirDestructuringDeclarationChecker,
|
||||
FirConstPropertyChecker,
|
||||
FirPropertyAccessorChecker
|
||||
)
|
||||
|
||||
override val classCheckers: Set<FirClassChecker> = setOf(
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-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
|
||||
|
||||
+15
@@ -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<*>,
|
||||
|
||||
+11
@@ -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
|
||||
}
|
||||
|
||||
+17
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user