[FE, IR] Check annotations compatibility on expect and actual value parameters

Comment was added to make it clear why whole declarations reported
in diagnostic instead of value parameter symbols (same will be done
with other targets in subsequent commits).

^KT-60671
This commit is contained in:
Roman Efremov
2023-08-02 14:37:11 +02:00
committed by Space Team
parent 4686a73c3b
commit 5c95f69aef
10 changed files with 106 additions and 10 deletions
@@ -926,6 +926,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt");
}
@Test
@TestMetadata("valueParameters.kt")
public void testValueParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/valueParameters.kt");
}
@Test
@TestMetadata("withAnnotationActualTypealias.kt")
public void testWithAnnotationActualTypealias() throws Exception {
@@ -926,6 +926,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt");
}
@Test
@TestMetadata("valueParameters.kt")
public void testValueParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/valueParameters.kt");
}
@Test
@TestMetadata("withAnnotationActualTypealias.kt")
public void testWithAnnotationActualTypealias() throws Exception {
@@ -28,6 +28,14 @@ object AbstractExpectActualAnnotationMatchChecker {
)
class Incompatibility(
/**
* [expectSymbol] and [actualSymbol] are declaration symbols where annotation been mismatched.
* They are needed for writing whole declarations in diagnostic text.
* They are not the same as symbols passed to checker as arguments in [areAnnotationsCompatible] in following cases:
* 1. If [actualSymbol] is typealias, it will be expanded.
* 2. If problem is in class member, [expectSymbol] will be mismatched member, not the original class.
* 3. If annotation mismatched on function value parameter, symbols will be whole functions, not value parameter symbols.
*/
val expectSymbol: DeclarationSymbolMarker,
val actualSymbol: DeclarationSymbolMarker,
val type: IncompatibilityType<ExpectActualMatchingContext.AnnotationCallInfo>,
@@ -63,6 +71,7 @@ object AbstractExpectActualAnnotationMatchChecker {
actualSymbol: CallableSymbolMarker,
): Incompatibility? {
commonForClassAndCallableChecks(expectSymbol, actualSymbol)?.let { return it }
areAnnotationsOnValueParametersCompatible(expectSymbol, actualSymbol)?.let { return it }
return null
}
@@ -100,6 +109,24 @@ object AbstractExpectActualAnnotationMatchChecker {
return null
}
context (ExpectActualMatchingContext<*>)
private fun areAnnotationsOnValueParametersCompatible(
expectSymbol: CallableSymbolMarker,
actualSymbol: CallableSymbolMarker,
): Incompatibility? {
val expectParams = expectSymbol.valueParameters
val actualParams = actualSymbol.valueParameters
if (expectParams.size != actualParams.size) return null
return expectParams.zip(actualParams).firstNotNullOfOrNull { (expectParam, actualParam) ->
areAnnotationsSetOnDeclarationsCompatible(expectParam, actualParam)?.let {
// Write containing declarations into diagnostic
Incompatibility(expectSymbol, actualSymbol, it.type)
}
}
}
context (ExpectActualMatchingContext<*>)
private fun areAnnotationsSetOnDeclarationsCompatible(
expectSymbol: DeclarationSymbolMarker,
@@ -1,24 +1,28 @@
// -- Module: <m1-common> --
// -- Module: <m1-jvm> --
/jvm.kt:29:14: warning: annotation `@Ann` is missing on actual declaration.
/jvm.kt:31: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:32:16: warning: annotation `@Ann` is missing on actual declaration.
/jvm.kt:34: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:37:18: warning: annotation `@Ann` is missing on actual declaration.
/jvm.kt:39: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:42:18: warning: annotation `@Ann` is missing on actual declaration.
/jvm.kt:44: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:45:12: warning: annotation `@WithArg(s = "str")` has different arguments on actual declaration: `@WithArg(s = "other str")`.
/jvm.kt:47: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:49: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) {}
^
@@ -1,14 +1,17 @@
/jvm.kt:(88,95): warning: Annotation `@Ann()` is missing on actual declaration.
/jvm.kt:(90,97): 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:(136,144): warning: Annotation `@Ann()` is missing on actual declaration.
/jvm.kt:(138,146): 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:(194,206): warning: Annotation `@Ann()` is missing on actual declaration.
/jvm.kt:(196,208): 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:(299,322): warning: Annotation `@Ann()` is missing on actual declaration.
/jvm.kt:(301,324): 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:(387,403): warning: Annotation `@WithArg(s = String(str))` has different arguments on actual declaration: `@WithArg(s = String(other str))`.
/jvm.kt:(389,405): 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:(423,435): 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.
@@ -24,6 +24,8 @@ annotation class WithArg(val s: String)
@WithArg("str")
expect fun withDifferentArg()
expect fun inValueParam(@Ann arg: String)
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClass<!><!>
@@ -43,3 +45,5 @@ class MemberScopeViaTypealiasImpl {
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@WithArg("other str")
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>withDifferentArg<!>() {}<!>
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inValueParam<!>(arg: String) {}<!>
@@ -24,6 +24,8 @@ annotation class WithArg(val s: String)
@WithArg("str")
expect fun withDifferentArg()
expect fun inValueParam(@Ann arg: String)
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClass<!>
@@ -43,3 +45,5 @@ actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>MemberScopeViaTypealias<
@WithArg("other str")
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>withDifferentArg<!>() {}
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inValueParam<!>(arg: String) {}
@@ -0,0 +1,18 @@
// MODULE: m1-common
// FILE: common.kt
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class Ann
expect fun inMethod(@Ann arg: String)
expect class InConstructor(@Ann arg: String)
<!INCOMPATIBLE_MATCHING{JVM}!>expect fun withIncopatibility(@Ann p1: String, @Ann p2: String)<!>
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inMethod<!>(arg: String) {}<!>
actual class InConstructor <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual constructor(arg: String)<!> {}
actual fun <!ACTUAL_WITHOUT_EXPECT!>withIncopatibility<!>(p1: String) {}
@@ -0,0 +1,18 @@
// MODULE: m1-common
// FILE: common.kt
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class Ann
expect fun inMethod(@Ann arg: String)
expect class InConstructor(@Ann arg: String)
expect fun withIncopatibility<!NO_ACTUAL_FOR_EXPECT{JVM}!>(@Ann p1: String, @Ann p2: String)<!>
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inMethod<!>(arg: String) {}
actual class InConstructor <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual constructor(arg: String)<!> {}
actual fun withIncopatibility<!ACTUAL_WITHOUT_EXPECT!>(p1: String)<!> {}
@@ -23921,6 +23921,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt");
}
@Test
@TestMetadata("valueParameters.kt")
public void testValueParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/valueParameters.kt");
}
@Test
@TestMetadata("withAnnotationActualTypealias.kt")
public void testWithAnnotationActualTypealias() throws Exception {