[FE] Check annotations on actual class members including fake overrides

^KT-60668
^KT-60936
This commit is contained in:
Roman Efremov
2023-08-04 13:09:36 +02:00
committed by Space Team
parent d614f06259
commit ab1c0e3c48
30 changed files with 601 additions and 34 deletions
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo
import org.jetbrains.kotlin.resolve.checkers.OptInNames
import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
@@ -387,4 +386,35 @@ class ClassicExpectActualMatchingContext(
this !is K1SyntheticClassifierSymbolMarker &&
!(this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.SYNTHESIZED)
}
override val checkClassScopesForAnnotationCompatibility = true
override fun skipCheckingAnnotationsOfActualClassMember(actualMember: DeclarationSymbolMarker): Boolean =
(actualMember as MemberDescriptor).isActual
override fun findPotentialExpectClassMembersForActual(
expectClass: RegularClassSymbolMarker,
actualClass: RegularClassSymbolMarker,
actualMember: DeclarationSymbolMarker,
): Map<MemberDescriptor, ExpectActualCompatibility<*>> {
val compatibilityToExpects = ExpectedActualResolver.findExpectForActualClassMember(
actualMember as MemberDescriptor,
actualClass as ClassDescriptor,
expectClass as ClassDescriptor,
this,
)
return buildMap {
for ((compatibility, expectMembers) in compatibilityToExpects.entries) {
for (expectMember in expectMembers) {
val oldValue = put(expectMember, compatibility)
if (oldValue != null) {
error(
"Several incompatibilities correspond to the same expect symbol: symbol=$expectMember, " +
"compatibilities=$oldValue, $compatibility"
)
}
}
}
}
}
}
@@ -54,6 +54,35 @@ object ExpectedActualResolver {
}
}
fun findExpectForActualClassMember(
actual: MemberDescriptor,
actualClass: ClassDescriptor,
expectClass: ClassDescriptor,
context: ClassicExpectActualMatchingContext,
): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>> {
val candidates = with(context) {
expectClass.getMembersForExpectClass(actual.name)
}
return when (actual) {
is CallableMemberDescriptor -> {
matchActualCallableAgainstPotentialExpects(
actual,
candidates.filterIsInstance<CallableMemberDescriptor>(),
actualClass,
context
)
}
is ClassDescriptor -> {
matchActualClassAgainstPotentialExpects(
actual,
candidates.filterIsInstance<ClassifierDescriptorWithTypeParameters>(),
context
)
}
else -> emptyMap()
}
}
fun findExpectedForActual(
actual: MemberDescriptor,
moduleFilter: (ModuleDescriptor) -> Boolean = allModulesProvidingExpectsFor(actual.module),