[FE] Relax rules of matching @Target annotation on expect and actual
Allow `expect` targets to be subset of `actual`. ^KT-58551
This commit is contained in:
committed by
Space Team
parent
ad84c83ee9
commit
6611a55a60
+17
-3
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.calls.mpp
|
||||
|
||||
import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker
|
||||
import org.jetbrains.kotlin.mpp.TypeAliasSymbolMarker
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
object AbstractExpectActualAnnotationMatchChecker {
|
||||
@@ -46,17 +47,30 @@ object AbstractExpectActualAnnotationMatchChecker {
|
||||
val actualAnnotationsByName = actualSymbol.annotations.groupBy { it.classId }
|
||||
|
||||
for (expectAnnotation in expectSymbol.annotations) {
|
||||
if (expectAnnotation.classId in SKIPPED_CLASS_IDS || expectAnnotation.isOptIn) {
|
||||
val expectClassId = expectAnnotation.classId ?: continue
|
||||
if (expectClassId in SKIPPED_CLASS_IDS || expectAnnotation.isOptIn) {
|
||||
continue
|
||||
}
|
||||
if (expectAnnotation.isRetentionSource && skipSourceAnnotations) {
|
||||
continue
|
||||
}
|
||||
val actualAnnotationsWithSameClassId = actualAnnotationsByName[expectAnnotation.classId] ?: emptyList()
|
||||
if (actualAnnotationsWithSameClassId.none { areAnnotationArgumentsEqual(expectAnnotation, it) }) {
|
||||
val actualAnnotationsWithSameClassId = actualAnnotationsByName[expectClassId] ?: emptyList()
|
||||
val collectionCompatibilityChecker = getAnnotationCollectionArgumentsCompatibilityChecker(expectClassId)
|
||||
if (actualAnnotationsWithSameClassId.none {
|
||||
areAnnotationArgumentsEqual(expectAnnotation, it, collectionCompatibilityChecker)
|
||||
}) {
|
||||
return Incompatibility(expectSymbol, actualSymbol)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getAnnotationCollectionArgumentsCompatibilityChecker(annotationClassId: ClassId):
|
||||
ExpectActualCollectionArgumentsCompatibilityCheckStrategy {
|
||||
return if (annotationClassId == StandardClassIds.Annotations.Target) {
|
||||
ExpectActualCollectionArgumentsCompatibilityCheckStrategy.ExpectIsSubsetOfActual
|
||||
} else {
|
||||
ExpectActualCollectionArgumentsCompatibilityCheckStrategy.Default
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.resolve.calls.mpp
|
||||
|
||||
|
||||
sealed class ExpectActualCollectionArgumentsCompatibilityCheckStrategy {
|
||||
abstract fun <T> areCompatible(
|
||||
expectArg: Collection<T>,
|
||||
actualArg: Collection<T>,
|
||||
elementsEqual: (T, T) -> Boolean,
|
||||
): Boolean
|
||||
|
||||
internal data object Default : ExpectActualCollectionArgumentsCompatibilityCheckStrategy() {
|
||||
override fun <T> areCompatible(
|
||||
expectArg: Collection<T>,
|
||||
actualArg: Collection<T>,
|
||||
elementsEqual: (T, T) -> Boolean,
|
||||
): Boolean {
|
||||
return expectArg.size == actualArg.size && expectArg.zip(actualArg).all { (e1, e2) -> elementsEqual(e1, e2) }
|
||||
}
|
||||
}
|
||||
|
||||
internal data object ExpectIsSubsetOfActual : ExpectActualCollectionArgumentsCompatibilityCheckStrategy() {
|
||||
override fun <T> areCompatible(
|
||||
expectArg: Collection<T>,
|
||||
actualArg: Collection<T>,
|
||||
elementsEqual: (T, T) -> Boolean,
|
||||
): Boolean {
|
||||
return expectArg.all { e1 ->
|
||||
actualArg.any { e2 -> elementsEqual(e1, e2) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -160,7 +160,11 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
||||
|
||||
val DeclarationSymbolMarker.annotations: List<AnnotationCallInfo>
|
||||
|
||||
fun areAnnotationArgumentsEqual(annotation1: AnnotationCallInfo, annotation2: AnnotationCallInfo): Boolean
|
||||
fun areAnnotationArgumentsEqual(
|
||||
annotation1: AnnotationCallInfo,
|
||||
annotation2: AnnotationCallInfo,
|
||||
collectionArgumentsCompatibilityCheckStrategy: ExpectActualCollectionArgumentsCompatibilityCheckStrategy,
|
||||
): Boolean
|
||||
|
||||
val DeclarationSymbolMarker.hasSourceAnnotationsErased: Boolean
|
||||
|
||||
|
||||
Reference in New Issue
Block a user