Collect all candidates for completion

This commit is contained in:
Stanislav Erokhin
2015-11-27 18:33:55 +03:00
parent 2b66af29aa
commit 846fb397c4
2 changed files with 53 additions and 10 deletions
@@ -89,6 +89,13 @@ class NewResolveOldInference(
}
}
if (context.collectAllCandidates) {
val allCandidates = towerResolver.collectAllCandidates(baseContext, processor)
val result = OverloadResolutionResultsImpl.nameNotFound<CallableDescriptor>()
result.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall<CallableDescriptor> }
return result
}
val candidates = towerResolver.runResolve(baseContext, processor, useOrder = kind != CallResolver.ResolveKind.CALLABLE_REFERENCE)
return convertToOverloadResults(candidates, tracing, context)
}
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.utils.addToStdlib.check
import java.util.*
interface TowerContext<C> {
val name: Name
@@ -60,9 +61,19 @@ class TowerResolver {
processor: ScopeTowerProcessor<C>,
useOrder: Boolean = true
): Collection<C> {
return run(context, processor, useOrder, SuccessfulResultCollector(context))
}
val resultCollector = ResultCollector<C> { context.getStatus(it) }
internal fun <C> collectAllCandidates(context: TowerContext<C>, processor: ScopeTowerProcessor<C>): Collection<C> {
return run(context, processor, false, AllCandidatesCollector(context))
}
private fun <C> run(
context: TowerContext<C>,
processor: ScopeTowerProcessor<C>,
useOrder: Boolean,
resultCollector: ResultCollector<C>
): Collection<C> {
fun collectCandidates(data: TowerData): Collection<C>? {
val candidatesGroups = if (useOrder) {
processor.process(data)
@@ -96,12 +107,39 @@ class TowerResolver {
}
//todo collect all candidates
internal class ResultCollector<C>(private val getStatus: (C) -> ResolutionCandidateStatus) {
internal abstract class ResultCollector<C>(val context: TowerContext<C>) {
abstract fun getResolved(): Collection<C>?
abstract fun getFinalCandidates(): Collection<C>
fun pushCandidates(candidates: Collection<C>) {
val filteredCandidates = candidates.filter {
context.getStatus(it).resultingApplicability != ResolutionCandidateApplicability.HIDDEN
}
if (filteredCandidates.isNotEmpty()) addCandidates(filteredCandidates)
}
protected abstract fun addCandidates(candidates: Collection<C>)
}
internal class AllCandidatesCollector<C>(context: TowerContext<C>): ResultCollector<C>(context) {
private val allCandidates = ArrayList<C>()
override fun getResolved(): Collection<C>? = null
override fun getFinalCandidates(): Collection<C> = allCandidates
override fun addCandidates(candidates: Collection<C>) {
allCandidates.addAll(candidates)
}
}
internal class SuccessfulResultCollector<C>(context: TowerContext<C>): ResultCollector<C>(context) {
private var currentCandidates: Collection<C> = emptyList()
private var currentLevel: ResolutionCandidateApplicability? = null
fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED }
override fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED }
fun getSyntheticResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED }
@@ -109,15 +147,13 @@ class TowerResolver {
currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED
}
fun getFinalCandidates() = getResolved() ?: getSyntheticResolved() ?: getErrors() ?: emptyList()
override fun getFinalCandidates() = getResolved() ?: getSyntheticResolved() ?: getErrors() ?: emptyList()
fun pushCandidates(candidates: Collection<C>) {
val filteredCandidates = candidates.filter { getStatus(it).resultingApplicability != ResolutionCandidateApplicability.HIDDEN }
if (filteredCandidates.isEmpty()) return
val minimalLevel = filteredCandidates.map { getStatus(it).resultingApplicability }.min()!!
override fun addCandidates(candidates: Collection<C>) {
val minimalLevel = candidates.map { context.getStatus(it).resultingApplicability }.min()!!
if (currentLevel == null || currentLevel!! > minimalLevel) {
currentLevel = minimalLevel
currentCandidates = filteredCandidates.filter { getStatus(it).resultingApplicability == minimalLevel }
currentCandidates = candidates.filter { context.getStatus(it).resultingApplicability == minimalLevel }
}
}
}