Support "given candidates" mode in new resolution algorithm.

This commit is contained in:
Stanislav Erokhin
2016-02-17 15:45:20 +03:00
parent daee95f2c4
commit acdd807e91
5 changed files with 73 additions and 35 deletions
@@ -648,13 +648,16 @@ public class CallResolver {
}
}
if (contextForMigration.resolveKind != ResolveKind.GIVEN_CANDIDATES && useNewResolve) {
if (contextForMigration.resolveKind != ResolveKind.GIVEN_CANDIDATES) {
assert contextForMigration.name != null;
return (OverloadResolutionResultsImpl<F>)
newCallResolver.runResolve(context, contextForMigration.name, contextForMigration.resolveKind, tracing);
}
else {
return (OverloadResolutionResultsImpl<F>) newCallResolver.runResolveForGivenCandidates(context, tracing, contextForMigration.givenCandidates);
}
return doResolveCall(context, contextForMigration.lazyTasks.invoke(), contextForMigration.callTransformer, tracing);
//return doResolveCall(context, contextForMigration.lazyTasks.invoke(), contextForMigration.callTransformer, tracing);
}
@NotNull
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,10 +39,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyForInvoke
import org.jetbrains.kotlin.resolve.calls.tasks.*
import org.jetbrains.kotlin.resolve.isHiddenInResolution
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.resolve.scopes.receivers.*
@@ -77,10 +74,7 @@ class NewResolveOldInference(
var processor = createResolveProcessor(kind, explicitReceiver, context, baseContext)
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
return allCandidatesResult(towerResolver.collectAllCandidates(baseContext, processor))
}
// Temporary fix for code migration (unaryPlus()/unaryMinus())
val unaryConventionName = getUnaryPlusOrMinusOperatorFunctionName(context.call)
@@ -97,6 +91,46 @@ class NewResolveOldInference(
return convertToOverloadResults(candidates, tracing, context)
}
fun <D : CallableDescriptor> runResolveForGivenCandidates(
basicCallContext: BasicCallResolutionContext,
tracing: TracingStrategy,
candidates: Collection<ResolutionCandidate<D>>
): OverloadResolutionResultsImpl<D> {
val resolvedCandidates = candidates.mapNotNull { candidate ->
val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate")
val resolvedCall = ResolvedCallImpl.create(candidate, candidateTrace, tracing, basicCallContext.dataFlowInfoForArguments)
if (candidate.descriptor.isHiddenInResolution()) {
return@mapNotNull Candidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), resolvedCall)
}
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
resolvedCall, basicCallContext, candidateTrace, tracing, basicCallContext.call,
null, CandidateResolveMode.FULLY // todo
)
candidateResolver.performResolutionForCandidateCall(callCandidateResolutionContext, basicCallContext.checkArguments) // todo
val diagnostics = listOfNotNull(SynthesizedDescriptorDiagnostic.check { candidate.descriptor.isSynthesized },
createPreviousResolveError(resolvedCall.status))
Candidate(ResolutionCandidateStatus(diagnostics), resolvedCall)
}
if (basicCallContext.collectAllCandidates) {
val allCandidates = towerResolver.run(listOf(TowerData.Empty), KnownResultProcessor(resolvedCandidates),
TowerResolver.AllCandidatesCollector { it.candidateStatus }, useOrder = false)
return allCandidatesResult(allCandidates) as OverloadResolutionResultsImpl<D>
}
val processedCandidates = towerResolver.run(listOf(TowerData.Empty), KnownResultProcessor(resolvedCandidates),
TowerResolver.SuccessfulResultCollector { it.candidateStatus }, useOrder = true)
return convertToOverloadResults(processedCandidates, tracing, basicCallContext) as OverloadResolutionResultsImpl<D>
}
private fun allCandidatesResult(allCandidates: Collection<Candidate>)
= OverloadResolutionResultsImpl.nameNotFound<CallableDescriptor>().apply {
this.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall<CallableDescriptor> }
}
private fun createResolveProcessor(
kind: CallResolver.ResolveKind,
explicitReceiver : Receiver?,
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,18 +64,11 @@ class TowerResolver {
internal fun <C> runResolve(
context: TowerContext<C>,
processor: ScopeTowerProcessor<C>,
useOrder: Boolean = true
): Collection<C> {
return run(context, processor, useOrder, SuccessfulResultCollector(context))
}
useOrder: Boolean
): Collection<C> = run(context.scopeTower.createTowerDataList(), processor, SuccessfulResultCollector { context.getStatus(it) }, useOrder)
internal fun <C> collectAllCandidates(context: TowerContext<C>, processor: ScopeTowerProcessor<C>): Collection<C> {
return run(context, processor, false, AllCandidatesCollector(context))
}
private fun ScopeTower.createLocalLevels() = lexicalScope.parentsWithSelf.
filterIsInstance<LexicalScope>().filter { it.kind.withLocalDescriptors }.
map { ScopeBasedTowerLevel(this, it) }
internal fun <C> collectAllCandidates(context: TowerContext<C>, processor: ScopeTowerProcessor<C>): Collection<C>
= run(context.scopeTower.createTowerDataList(), processor, AllCandidatesCollector { context.getStatus(it) }, false)
private fun ScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
val result = ArrayList<ScopeTowerLevel>()
@@ -160,14 +153,14 @@ class TowerResolver {
return result
}
private fun <C> run(
context: TowerContext<C>,
internal fun <C> run(
towerDataList: List<TowerData>,
processor: ScopeTowerProcessor<C>,
useOrder: Boolean,
resultCollector: ResultCollector<C>
resultCollector: ResultCollector<C>,
useOrder: Boolean
): Collection<C> {
for (towerData in context.scopeTower.createTowerDataList()) {
for (towerData in towerDataList) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val candidatesGroups = if (useOrder) {
@@ -187,14 +180,14 @@ class TowerResolver {
}
internal abstract class ResultCollector<C>(val context: TowerContext<C>) {
internal abstract class ResultCollector<C>(protected val getStatus: (C) -> ResolutionCandidateStatus) {
abstract fun getSuccessfulCandidates(): Collection<C>?
abstract fun getFinalCandidates(): Collection<C>
fun pushCandidates(candidates: Collection<C>) {
val filteredCandidates = candidates.filter {
context.getStatus(it).resultingApplicability != ResolutionCandidateApplicability.HIDDEN
getStatus(it).resultingApplicability != ResolutionCandidateApplicability.HIDDEN
}
if (filteredCandidates.isNotEmpty()) addCandidates(filteredCandidates)
}
@@ -202,7 +195,7 @@ class TowerResolver {
protected abstract fun addCandidates(candidates: Collection<C>)
}
internal class AllCandidatesCollector<C>(context: TowerContext<C>): ResultCollector<C>(context) {
internal class AllCandidatesCollector<C>(getStatus: (C) -> ResolutionCandidateStatus): ResultCollector<C>(getStatus) {
private val allCandidates = ArrayList<C>()
override fun getSuccessfulCandidates(): Collection<C>? = null
@@ -212,10 +205,9 @@ class TowerResolver {
override fun addCandidates(candidates: Collection<C>) {
allCandidates.addAll(candidates)
}
}
internal class SuccessfulResultCollector<C>(context: TowerContext<C>): ResultCollector<C>(context) {
internal class SuccessfulResultCollector<C>(getStatus: (C) -> ResolutionCandidateStatus): ResultCollector<C>(getStatus) {
private var currentCandidates: Collection<C> = emptyList()
private var currentLevel: ResolutionCandidateApplicability? = null
@@ -234,10 +226,10 @@ class TowerResolver {
override fun getFinalCandidates() = getResolved() ?: getResolvedSynthetic() ?: getResolvedLowPriority() ?: getErrors() ?: emptyList()
override fun addCandidates(candidates: Collection<C>) {
val minimalLevel = candidates.map { context.getStatus(it).resultingApplicability }.min()!!
val minimalLevel = candidates.map { getStatus(it).resultingApplicability }.min()!!
if (currentLevel == null || currentLevel!! > minimalLevel) {
currentLevel = minimalLevel
currentCandidates = candidates.filter { context.getStatus(it).resultingApplicability == minimalLevel }
currentCandidates = candidates.filter { getStatus(it).resultingApplicability == minimalLevel }
}
}
}
@@ -19,3 +19,5 @@ public class Observable<T> {
import j.*
class K : Observable<String>({})
class J : Observable<String>(null)
@@ -1,5 +1,12 @@
package
public final class J : j.Observable<kotlin.String> {
public constructor J()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class K : j.Observable<kotlin.String> {
public constructor K()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean