diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt index cf8fa35b7a4..b97fac2e46b 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt @@ -208,14 +208,7 @@ class TowerResolver { abstract fun getFinalCandidates(): Collection - fun pushCandidates(candidates: Collection) { - val filteredCandidates = candidates.filter { - it.resultingApplicability != ResolutionCandidateApplicability.HIDDEN - } - if (filteredCandidates.isNotEmpty()) addCandidates(filteredCandidates) - } - - protected abstract fun addCandidates(candidates: Collection) + abstract fun pushCandidates(candidates: Collection) } class AllCandidatesCollector: ResultCollector() { @@ -225,33 +218,51 @@ class TowerResolver { override fun getFinalCandidates(): Collection = allCandidates - override fun addCandidates(candidates: Collection) { - allCandidates.addAll(candidates) - } - } - - class SuccessfulResultCollector: ResultCollector() { - private var currentCandidates: Collection = emptyList() - private var currentLevel: ResolutionCandidateApplicability? = null - - override fun getSuccessfulCandidates(): Collection? = getResolved() - - fun getResolved() = currentCandidates.takeIf { currentLevel == ResolutionCandidateApplicability.RESOLVED } - - fun getResolvedLowPriority() = currentCandidates.takeIf { currentLevel == ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY } - - fun getErrors() = currentCandidates.takeIf { - currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY - } - - override fun getFinalCandidates() = getResolved() ?: getResolvedLowPriority() ?: getErrors() ?: emptyList() - - override fun addCandidates(candidates: Collection) { - val minimalLevel = candidates.map { it.resultingApplicability }.min()!! - if (currentLevel == null || currentLevel!! > minimalLevel) { - currentLevel = minimalLevel - currentCandidates = candidates.filter { it.resultingApplicability == minimalLevel } + override fun pushCandidates(candidates: Collection) { + candidates.filterNotTo(allCandidates) { + it.resultingApplicability == ResolutionCandidateApplicability.HIDDEN } } } + + class SuccessfulResultCollector : ResultCollector() { + private var candidateGroups = arrayListOf>() + private var isSuccessful = false + + override fun getSuccessfulCandidates(): Collection? { + if (!isSuccessful) return null + val firstGroupWithResolved = candidateGroups.firstOrNull { + it.any { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED } + } ?: return null + + return firstGroupWithResolved.filter { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED } + } + + override fun pushCandidates(candidates: Collection) { + val thereIsSuccessful = candidates.any { it.isSuccessful } + if (!isSuccessful && !thereIsSuccessful) { + candidateGroups.add(candidates) + return + } + + if (!isSuccessful) { + candidateGroups.clear() + isSuccessful = true + } + if (thereIsSuccessful) { + candidateGroups.add(candidates.filter { it.isSuccessful }) + } + } + + override fun getFinalCandidates(): Collection { + val moreSuitableGroup = candidateGroups.minBy { it.groupApplicability } ?: return emptyList() + val groupApplicability = moreSuitableGroup.groupApplicability + if (groupApplicability == ResolutionCandidateApplicability.HIDDEN) return emptyList() + + return moreSuitableGroup.filter { it.resultingApplicability == groupApplicability } + } + + private val Collection.groupApplicability get() = + minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN + } }