[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
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
matchActualCallableAgainstPotentialExpects(actual, candidates, container, context)
|
||||
}
|
||||
is ClassifierDescriptorWithTypeParameters -> {
|
||||
context.findClassifiersFromModule(actual.classId, actual.module, moduleFilter).filter { declaration ->
|
||||
actual != declaration && declaration is ClassDescriptor && declaration.isExpect
|
||||
}.groupBy { expected ->
|
||||
AbstractExpectActualCompatibilityChecker.getClassifiersCompatibility(
|
||||
expected as ClassDescriptor,
|
||||
actual,
|
||||
context
|
||||
)
|
||||
}
|
||||
val candidates = context.findClassifiersFromModule(actual.classId, actual.module, moduleFilter)
|
||||
matchActualClassAgainstPotentialExpects(actual, candidates, context)
|
||||
}
|
||||
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(
|
||||
context: ClassicExpectActualMatchingContext,
|
||||
module: ModuleDescriptor,
|
||||
|
||||
Reference in New Issue
Block a user