[FE 1.0] Refactor: extract logic of matching actual against potential expects
Will be needed in subsequent commits for the annotation checker. `findExpectForActual` is not suitable for the checker because `findExpectForActual` searches expect class with same `ClassId` for actual class containing current member (see method `findClassifiersFromModule`), which is: 1. Unnecessary, since we already have expect class in annotation checker 2. Incorrect when class actualized via typealias and `ClassId` is different. So, it is needed to extract logic of searching potential expects for actual member and already known expect class. ^KT-60668 ^KT-60936
This commit is contained in:
committed by
Space Team
parent
8aa3ccd342
commit
d614f06259
+58
-40
@@ -77,53 +77,71 @@ object ExpectedActualResolver {
|
|||||||
else -> return null // do not report anything for incorrect code, e.g. 'actual' local function
|
else -> return null // do not report anything for incorrect code, e.g. 'actual' local function
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates.filter { declaration ->
|
matchActualCallableAgainstPotentialExpects(actual, candidates, container, context)
|
||||||
actual != declaration && declaration.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && declaration.isExpect
|
|
||||||
}.groupBy { declaration ->
|
|
||||||
// TODO: optimize by caching this per actual-expected class pair, do not create a new substitutor for each actual member
|
|
||||||
var expectedClass: ClassDescriptor? = null
|
|
||||||
var actualClass: ClassDescriptor? = null
|
|
||||||
val substitutor =
|
|
||||||
when (container) {
|
|
||||||
is ClassDescriptor -> {
|
|
||||||
actualClass = container
|
|
||||||
expectedClass = declaration.containingDeclaration as ClassDescriptor
|
|
||||||
// TODO: this might not work for members of inner generic classes
|
|
||||||
runIf(expectedClass.declaredTypeParameters.size == container.declaredTypeParameters.size) {
|
|
||||||
context.createExpectActualTypeParameterSubstitutor(
|
|
||||||
expectedClass.declaredTypeParameters,
|
|
||||||
container.declaredTypeParameters,
|
|
||||||
parentSubstitutor = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
AbstractExpectActualCompatibilityChecker.getCallablesCompatibility(
|
|
||||||
expectDeclaration = declaration,
|
|
||||||
actualDeclaration = actual,
|
|
||||||
parentSubstitutor = substitutor,
|
|
||||||
expectContainingClass = expectedClass,
|
|
||||||
actualContainingClass = actualClass,
|
|
||||||
context
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
is ClassifierDescriptorWithTypeParameters -> {
|
is ClassifierDescriptorWithTypeParameters -> {
|
||||||
context.findClassifiersFromModule(actual.classId, actual.module, moduleFilter).filter { declaration ->
|
val candidates = context.findClassifiersFromModule(actual.classId, actual.module, moduleFilter)
|
||||||
actual != declaration && declaration is ClassDescriptor && declaration.isExpect
|
matchActualClassAgainstPotentialExpects(actual, candidates, context)
|
||||||
}.groupBy { expected ->
|
|
||||||
AbstractExpectActualCompatibilityChecker.getClassifiersCompatibility(
|
|
||||||
expected as ClassDescriptor,
|
|
||||||
actual,
|
|
||||||
context
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun matchActualCallableAgainstPotentialExpects(
|
||||||
|
actual: CallableMemberDescriptor,
|
||||||
|
candidates: Collection<CallableMemberDescriptor>,
|
||||||
|
container: DeclarationDescriptor,
|
||||||
|
context: ClassicExpectActualMatchingContext,
|
||||||
|
): Map<ExpectActualCompatibility<MemberDescriptor>, List<CallableMemberDescriptor>> {
|
||||||
|
return candidates.filter { declaration ->
|
||||||
|
actual != declaration && declaration.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && declaration.isExpect
|
||||||
|
}.groupBy { declaration ->
|
||||||
|
// TODO: optimize by caching this per actual-expected class pair, do not create a new substitutor for each actual member
|
||||||
|
var expectedClass: ClassDescriptor? = null
|
||||||
|
var actualClass: ClassDescriptor? = null
|
||||||
|
val substitutor =
|
||||||
|
when (container) {
|
||||||
|
is ClassDescriptor -> {
|
||||||
|
actualClass = container
|
||||||
|
expectedClass = declaration.containingDeclaration as ClassDescriptor
|
||||||
|
// TODO: this might not work for members of inner generic classes
|
||||||
|
runIf(expectedClass.declaredTypeParameters.size == container.declaredTypeParameters.size) {
|
||||||
|
context.createExpectActualTypeParameterSubstitutor(
|
||||||
|
expectedClass.declaredTypeParameters,
|
||||||
|
container.declaredTypeParameters,
|
||||||
|
parentSubstitutor = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
AbstractExpectActualCompatibilityChecker.getCallablesCompatibility(
|
||||||
|
expectDeclaration = declaration,
|
||||||
|
actualDeclaration = actual,
|
||||||
|
parentSubstitutor = substitutor,
|
||||||
|
expectContainingClass = expectedClass,
|
||||||
|
actualContainingClass = actualClass,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun matchActualClassAgainstPotentialExpects(
|
||||||
|
actual: ClassifierDescriptorWithTypeParameters,
|
||||||
|
candidates: Collection<ClassifierDescriptorWithTypeParameters>,
|
||||||
|
context: ClassicExpectActualMatchingContext,
|
||||||
|
): Map<ExpectActualCompatibility<MemberDescriptor>, List<ClassifierDescriptorWithTypeParameters>> {
|
||||||
|
return candidates.filter { declaration ->
|
||||||
|
actual != declaration && declaration is ClassDescriptor && declaration.isExpect
|
||||||
|
}.groupBy { expected ->
|
||||||
|
AbstractExpectActualCompatibilityChecker.getClassifiersCompatibility(
|
||||||
|
expected as ClassDescriptor,
|
||||||
|
actual,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun CallableMemberDescriptor.findNamesakesFromModule(
|
private fun CallableMemberDescriptor.findNamesakesFromModule(
|
||||||
context: ClassicExpectActualMatchingContext,
|
context: ClassicExpectActualMatchingContext,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
|
|||||||
Reference in New Issue
Block a user