[FE, IR] Check annotations compatibility on expect and actual getters and setters
^KT-60671
This commit is contained in:
committed by
Space Team
parent
8fb2935ef6
commit
e79851910e
+6
@@ -854,6 +854,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/floatNumbersComparison.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("gettersAndSetters.kt")
|
||||
public void testGettersAndSetters() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/gettersAndSetters.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intrinsicConstEvaluation.kt")
|
||||
public void testIntrinsicConstEvaluation() throws Exception {
|
||||
|
||||
+6
@@ -854,6 +854,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/floatNumbersComparison.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("gettersAndSetters.kt")
|
||||
public void testGettersAndSetters() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/gettersAndSetters.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intrinsicConstEvaluation.kt")
|
||||
public void testIntrinsicConstEvaluation() throws Exception {
|
||||
|
||||
+3
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.renderer.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
internal object FirExpectActualAnnotationIncompatibilityDiagnosticRenderers {
|
||||
@OptIn(SymbolInternals::class)
|
||||
@@ -26,6 +27,8 @@ internal object FirExpectActualAnnotationIncompatibilityDiagnosticRenderers {
|
||||
modifierRenderer = null,
|
||||
contractRenderer = null,
|
||||
).renderElementAsString(it.fir, trim = true)
|
||||
// Write property accessors on the same line as the property
|
||||
.run { replace(Printer.LINE_SEPARATOR, "") }
|
||||
}
|
||||
|
||||
val INCOMPATIBILITY = Renderer { incompatibilityType: ExpectActualAnnotationsIncompatibilityType<FirAnnotation> ->
|
||||
|
||||
+3
@@ -142,6 +142,9 @@ class FirExpectActualMatchingContextImpl private constructor(
|
||||
override val PropertySymbolMarker.isConst: Boolean
|
||||
get() = asSymbol().resolvedStatus.isConst
|
||||
|
||||
override val PropertySymbolMarker.getter: FunctionSymbolMarker?
|
||||
get() = asSymbol().getterSymbol
|
||||
|
||||
override val PropertySymbolMarker.setter: FunctionSymbolMarker?
|
||||
get() = asSymbol().setterSymbol
|
||||
|
||||
|
||||
+3
@@ -231,6 +231,9 @@ internal abstract class IrExpectActualMatchingContext(
|
||||
override val PropertySymbolMarker.isConst: Boolean
|
||||
get() = asIr().isConst
|
||||
|
||||
override val PropertySymbolMarker.getter: FunctionSymbolMarker?
|
||||
get() = asIr().getter?.symbol
|
||||
|
||||
override val PropertySymbolMarker.setter: FunctionSymbolMarker?
|
||||
get() = asIr().setter?.symbol
|
||||
|
||||
|
||||
+24
-1
@@ -80,6 +80,29 @@ object AbstractExpectActualAnnotationMatchChecker {
|
||||
commonForClassAndCallableChecks(expectSymbol, actualSymbol)?.let { return it }
|
||||
areAnnotationsOnValueParametersCompatible(expectSymbol, actualSymbol)?.let { return it }
|
||||
|
||||
if (expectSymbol is PropertySymbolMarker && actualSymbol is PropertySymbolMarker) {
|
||||
arePropertyGetterAndSetterAnnotationsCompatible(expectSymbol, actualSymbol)?.let { return it }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
context (ExpectActualMatchingContext<*>)
|
||||
private fun arePropertyGetterAndSetterAnnotationsCompatible(
|
||||
expectSymbol: PropertySymbolMarker,
|
||||
actualSymbol: PropertySymbolMarker,
|
||||
): Incompatibility? {
|
||||
listOf(
|
||||
expectSymbol.getter to actualSymbol.getter,
|
||||
expectSymbol.setter to actualSymbol.setter,
|
||||
).forEach { (expectAccessor, actualAccessor) ->
|
||||
if (expectAccessor != null && actualAccessor != null) {
|
||||
areAnnotationsSetOnDeclarationsCompatible(expectAccessor, actualAccessor)?.let {
|
||||
// Write containing declarations into diagnostic
|
||||
return Incompatibility(expectSymbol, actualSymbol, actualAccessor.getSourceElement(), it.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -165,7 +188,7 @@ object AbstractExpectActualAnnotationMatchChecker {
|
||||
expectSymbol: DeclarationSymbolMarker,
|
||||
actualSymbol: DeclarationSymbolMarker,
|
||||
): Incompatibility? {
|
||||
// TODO(Roman.Efremov, KT-58551): check other annotation targets (constructors, types, value parameters, etc)
|
||||
// TODO(Roman.Efremov, KT-60671): check annotations set on types
|
||||
|
||||
val skipSourceAnnotations = actualSymbol.hasSourceAnnotationsErased
|
||||
val actualAnnotationsByName = actualSymbol.annotations.groupBy { it.classId }
|
||||
|
||||
+1
@@ -99,6 +99,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
||||
val PropertySymbolMarker.isLateinit: Boolean
|
||||
val PropertySymbolMarker.isConst: Boolean
|
||||
|
||||
val PropertySymbolMarker.getter: FunctionSymbolMarker?
|
||||
val PropertySymbolMarker.setter: FunctionSymbolMarker?
|
||||
|
||||
fun createExpectActualTypeParameterSubstitutor(
|
||||
|
||||
+4
@@ -136,6 +136,10 @@ class ClassicExpectActualMatchingContext(
|
||||
get() = asDescriptor().isLateInit
|
||||
override val PropertySymbolMarker.isConst: Boolean
|
||||
get() = asDescriptor().isConst
|
||||
|
||||
override val PropertySymbolMarker.getter: FunctionSymbolMarker?
|
||||
get() = asDescriptor().getter
|
||||
|
||||
override val PropertySymbolMarker.setter: FunctionSymbolMarker?
|
||||
get() = asDescriptor().setter
|
||||
|
||||
|
||||
+11
-7
@@ -1,32 +1,36 @@
|
||||
// -- Module: <m1-common> --
|
||||
|
||||
// -- Module: <m1-jvm> --
|
||||
/jvm.kt:39:14: warning: annotation `@Ann` is missing on actual declaration.
|
||||
/jvm.kt:44:14: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `class OnClass defined in root package in file common.kt` must be present with the same arguments on actual `class OnClass defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
|
||||
actual class OnClass
|
||||
^
|
||||
/jvm.kt:42:16: warning: annotation `@Ann` is missing on actual declaration.
|
||||
/jvm.kt:47:16: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `fun onMember(): Unit defined in OnMember` must be present with the same arguments on actual `fun onMember(): Unit defined in OnMember`, otherwise they might behave incorrectly.
|
||||
actual fun onMember() {}
|
||||
^
|
||||
/jvm.kt:47:18: warning: annotation `@Ann` is missing on actual declaration.
|
||||
/jvm.kt:52:18: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `class ViaTypealias defined in root package in file common.kt` must be present with the same arguments on actual `class ViaTypealiasImpl defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
|
||||
actual typealias ViaTypealias = ViaTypealiasImpl
|
||||
^
|
||||
/jvm.kt:52:18: warning: annotation `@Ann` is missing on actual declaration.
|
||||
/jvm.kt:57:18: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `fun foo(): Unit defined in MemberScopeViaTypealias` must be present with the same arguments on actual `fun foo(): Unit defined in MemberScopeViaTypealiasImpl`, otherwise they might behave incorrectly.
|
||||
actual typealias MemberScopeViaTypealias = MemberScopeViaTypealiasImpl
|
||||
^
|
||||
/jvm.kt:55:12: warning: annotation `@WithArg(s = "str")` has different arguments on actual declaration: `@WithArg(s = "other str")`.
|
||||
/jvm.kt:60:12: warning: annotation `@WithArg(s = "str")` has different arguments on actual declaration: `@WithArg(s = "other str")`.
|
||||
All annotations from expect `fun withDifferentArg(): Unit defined in root package in file common.kt` must be present with the same arguments on actual `fun withDifferentArg(): Unit defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
|
||||
actual fun withDifferentArg() {}
|
||||
^
|
||||
/jvm.kt:57:12: warning: annotation `@Ann` is missing on actual declaration.
|
||||
/jvm.kt:62:12: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `fun inValueParam(arg: String): Unit defined in root package in file common.kt` must be present with the same arguments on actual `fun inValueParam(arg: String): Unit defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
|
||||
actual fun inValueParam(arg: String) {}
|
||||
^
|
||||
/jvm.kt:59:16: warning: annotation `@Ann` is missing on actual declaration.
|
||||
/jvm.kt:64:16: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `fun <T> inTypeParam(): Unit defined in root package in file common.kt` must be present with the same arguments on actual `fun <T> inTypeParam(): Unit defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
|
||||
actual fun <T> inTypeParam() {}
|
||||
^
|
||||
/jvm.kt:66:12: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `val onGetter: String defined in root package in file common.kt` must be present with the same arguments on actual `val onGetter: String defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
|
||||
actual val onGetter: String = ""
|
||||
^
|
||||
|
||||
|
||||
+10
-7
@@ -1,20 +1,23 @@
|
||||
/jvm.kt:(98,105): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
/jvm.kt:(103,110): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
All annotations from expect 'class OnClass : Any' must be present with the same arguments on actual 'class OnClass : Any', otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(146,154): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
/jvm.kt:(151,159): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
All annotations from expect 'fun onMember(): Unit' must be present with the same arguments on actual 'fun onMember(): Unit', otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(204,216): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
/jvm.kt:(209,221): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
All annotations from expect 'class ViaTypealias : Any' must be present with the same arguments on actual 'class ViaTypealiasImpl : Any', otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(309,332): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
/jvm.kt:(314,337): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
All annotations from expect 'fun foo(): Unit' must be present with the same arguments on actual 'fun foo(): Unit', otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(397,413): warning: Annotation `@WithArg(s = String(str))` has different arguments on actual declaration: `@WithArg(s = String(other str))`.
|
||||
/jvm.kt:(402,418): warning: Annotation `@WithArg(s = String(str))` has different arguments on actual declaration: `@WithArg(s = String(other str))`.
|
||||
All annotations from expect 'fun withDifferentArg(): Unit' must be present with the same arguments on actual 'fun withDifferentArg(): Unit', otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(431,443): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
/jvm.kt:(436,448): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
All annotations from expect 'fun inValueParam(arg: String): Unit' must be present with the same arguments on actual 'fun inValueParam(arg: String): Unit', otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(476,487): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
/jvm.kt:(481,492): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
All annotations from expect 'fun <T> inTypeParam(): Unit' must be present with the same arguments on actual 'fun <T> inTypeParam(): Unit', otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(510,518): warning: Annotation `@PROPERTY_GETTER:Ann()` is missing on actual declaration.
|
||||
All annotations from expect 'val onGetter: String get(): String' must be present with the same arguments on actual 'val onGetter: String get(): String', otherwise they might behave incorrectly.
|
||||
|
||||
Vendored
+7
@@ -6,6 +6,8 @@
|
||||
AnnotationTarget.CLASS,
|
||||
AnnotationTarget.VALUE_PARAMETER,
|
||||
AnnotationTarget.TYPE_PARAMETER,
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER,
|
||||
)
|
||||
annotation class Ann
|
||||
|
||||
@@ -34,6 +36,9 @@ expect fun inValueParam(@Ann arg: String)
|
||||
|
||||
expect fun <@Ann T> inTypeParam()
|
||||
|
||||
@get:Ann
|
||||
expect val onGetter: String
|
||||
|
||||
// MODULE: m1-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClass<!><!>
|
||||
@@ -57,3 +62,5 @@ actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>withDifferentArg<!>() {}<!>
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inValueParam<!>(arg: String) {}<!>
|
||||
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <T> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inTypeParam<!>() {}<!>
|
||||
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetter<!>: String = ""<!>
|
||||
|
||||
Vendored
+7
@@ -6,6 +6,8 @@
|
||||
AnnotationTarget.CLASS,
|
||||
AnnotationTarget.VALUE_PARAMETER,
|
||||
AnnotationTarget.TYPE_PARAMETER,
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER,
|
||||
)
|
||||
annotation class Ann
|
||||
|
||||
@@ -34,6 +36,9 @@ expect fun inValueParam(@Ann arg: String)
|
||||
|
||||
expect fun <@Ann T> inTypeParam()
|
||||
|
||||
@get:Ann
|
||||
expect val onGetter: String
|
||||
|
||||
// MODULE: m1-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClass<!>
|
||||
@@ -57,3 +62,5 @@ actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>withDifferentArg<!>() {}
|
||||
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inValueParam<!>(arg: String) {}
|
||||
|
||||
actual fun <T> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inTypeParam<!>() {}
|
||||
|
||||
actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetter<!>: String = ""
|
||||
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
|
||||
annotation class Ann
|
||||
|
||||
expect val onGetter: String
|
||||
@Ann get
|
||||
|
||||
expect val onGetterImplicit: String
|
||||
@Ann get
|
||||
|
||||
@get:Ann
|
||||
expect val onGetterWithExplicitTarget: String
|
||||
|
||||
@get:Ann
|
||||
expect val explicitTargetMatchesWithoutTarget: String
|
||||
|
||||
@get:Ann
|
||||
expect val setOnPropertyWithoutTargetNotMatch: String
|
||||
|
||||
expect var onSetter: String
|
||||
@Ann set
|
||||
|
||||
// MODULE: m1-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetter<!>: String
|
||||
get() = ""<!>
|
||||
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetterImplicit<!>: String = ""<!>
|
||||
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetterWithExplicitTarget<!>: String
|
||||
get() = ""<!>
|
||||
|
||||
actual val explicitTargetMatchesWithoutTarget: String
|
||||
@Ann get() = ""
|
||||
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann
|
||||
actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>setOnPropertyWithoutTargetNotMatch<!>: String = ""<!>
|
||||
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual var <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onSetter<!>: String
|
||||
get() = ""
|
||||
set(_) {}<!>
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
|
||||
annotation class Ann
|
||||
|
||||
expect val onGetter: String
|
||||
@Ann get
|
||||
|
||||
expect val onGetterImplicit: String
|
||||
@Ann get
|
||||
|
||||
@get:Ann
|
||||
expect val onGetterWithExplicitTarget: String
|
||||
|
||||
@get:Ann
|
||||
expect val explicitTargetMatchesWithoutTarget: String
|
||||
|
||||
@get:Ann
|
||||
expect val setOnPropertyWithoutTargetNotMatch: String
|
||||
|
||||
expect var onSetter: String
|
||||
@Ann set
|
||||
|
||||
// MODULE: m1-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetter<!>: String
|
||||
get() = ""
|
||||
|
||||
actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetterImplicit<!>: String = ""
|
||||
|
||||
actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetterWithExplicitTarget<!>: String
|
||||
get() = ""
|
||||
|
||||
actual val explicitTargetMatchesWithoutTarget: String
|
||||
@Ann get() = ""
|
||||
|
||||
@Ann
|
||||
actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>setOnPropertyWithoutTargetNotMatch<!>: String = ""
|
||||
|
||||
actual var <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onSetter<!>: String
|
||||
get() = ""
|
||||
set(_) {}
|
||||
Generated
+6
@@ -23849,6 +23849,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/floatNumbersComparison.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("gettersAndSetters.kt")
|
||||
public void testGettersAndSetters() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/gettersAndSetters.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intrinsicConstEvaluation.kt")
|
||||
public void testIntrinsicConstEvaluation() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user