Refactoring. Add type safety to resolution.

This commit is contained in:
Stanislav Erokhin
2016-04-12 03:22:45 +03:00
parent 51c6abdbed
commit 3b41fcb5ba
5 changed files with 257 additions and 173 deletions
@@ -38,7 +38,7 @@ import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl; import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.tasks.*; import org.jetbrains.kotlin.resolve.calls.tasks.*;
import org.jetbrains.kotlin.resolve.calls.tower.NewResolveOldInference; import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference;
import org.jetbrains.kotlin.resolve.calls.util.CallMaker; import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil; import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
@@ -58,6 +58,7 @@ import java.util.*;
import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS; import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE; import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE;
import static org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference.ResolutionKind.*;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE; import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
@SuppressWarnings("RedundantTypeArguments") @SuppressWarnings("RedundantTypeArguments")
@@ -67,7 +68,7 @@ public class CallResolver {
private ArgumentTypeResolver argumentTypeResolver; private ArgumentTypeResolver argumentTypeResolver;
private GenericCandidateResolver genericCandidateResolver; private GenericCandidateResolver genericCandidateResolver;
private CallCompleter callCompleter; private CallCompleter callCompleter;
private NewResolveOldInference newCallResolver; private NewResolutionOldInference newCallResolver;
private final KotlinBuiltIns builtIns; private final KotlinBuiltIns builtIns;
private static final PerformanceCounter callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter); private static final PerformanceCounter callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter);
@@ -110,7 +111,7 @@ public class CallResolver {
// component dependency cycle // component dependency cycle
@Inject @Inject
public void setCallCompleter(@NotNull NewResolveOldInference newCallResolver) { public void setCallCompleter(@NotNull NewResolutionOldInference newCallResolver) {
this.newCallResolver = newCallResolver; this.newCallResolver = newCallResolver;
} }
@@ -122,7 +123,7 @@ public class CallResolver {
Name referencedName = nameExpression.getReferencedNameAsName(); Name referencedName = nameExpression.getReferencedNameAsName();
return computeTasksAndResolveCall( return computeTasksAndResolveCall(
context, referencedName, nameExpression, context, referencedName, nameExpression,
ResolveKind.VARIABLE); Variable.INSTANCE);
} }
@NotNull @NotNull
@@ -132,7 +133,7 @@ public class CallResolver {
) { ) {
return computeTasksAndResolveCall( return computeTasksAndResolveCall(
context, nameExpression.getReferencedNameAsName(), nameExpression, context, nameExpression.getReferencedNameAsName(), nameExpression,
ResolveKind.CALLABLE_REFERENCE); CallableReference.INSTANCE);
} }
@NotNull @NotNull
@@ -145,7 +146,7 @@ public class CallResolver {
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS); BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
return computeTasksAndResolveCall( return computeTasksAndResolveCall(
callResolutionContext, name, functionReference, callResolutionContext, name, functionReference,
ResolveKind.FUNCTION); Function.INSTANCE);
} }
@NotNull @NotNull
@@ -155,7 +156,7 @@ public class CallResolver {
) { ) {
return computeTasksAndResolveCall( return computeTasksAndResolveCall(
context, OperatorNameConventions.INVOKE, tracing, context, OperatorNameConventions.INVOKE, tracing,
ResolveKind.INVOKE); Invoke.INSTANCE);
} }
@NotNull @NotNull
@@ -163,7 +164,7 @@ public class CallResolver {
@NotNull BasicCallResolutionContext context, @NotNull BasicCallResolutionContext context,
@NotNull Name name, @NotNull Name name,
@NotNull KtReferenceExpression referenceExpression, @NotNull KtReferenceExpression referenceExpression,
@NotNull ResolveKind kind @NotNull NewResolutionOldInference.ResolutionKind<D> kind
) { ) {
TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call); TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call);
return computeTasksAndResolveCall(context, name, tracing, kind); return computeTasksAndResolveCall(context, name, tracing, kind);
@@ -174,7 +175,7 @@ public class CallResolver {
@NotNull final BasicCallResolutionContext context, @NotNull final BasicCallResolutionContext context,
@NotNull final Name name, @NotNull final Name name,
@NotNull final TracingStrategy tracing, @NotNull final TracingStrategy tracing,
@NotNull final ResolveKind kind @NotNull final NewResolutionOldInference.ResolutionKind<D> kind
) { ) {
return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<D>>() { return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<D>>() {
@Override @Override
@@ -207,7 +208,7 @@ public class CallResolver {
@Override @Override
public OverloadResolutionResults<D> invoke() { public OverloadResolutionResults<D> invoke() {
ResolutionTask<D> resolutionTask = new ResolutionTask<D>( ResolutionTask<D> resolutionTask = new ResolutionTask<D>(
ResolveKind.GIVEN_CANDIDATES, null, candidates new NewResolutionOldInference.ResolutionKind.GivenCandidates<D>(), null, candidates
); );
return doResolveCallOrGetCachedResults(context, resolutionTask, tracing); return doResolveCallOrGetCachedResults(context, resolutionTask, tracing);
} }
@@ -256,7 +257,7 @@ public class CallResolver {
KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) context.call.getCallElement(); KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) context.call.getCallElement();
return computeTasksAndResolveCall( return computeTasksAndResolveCall(
context, name, arrayAccessExpression, context, name, arrayAccessExpression,
ResolveKind.FUNCTION); Function.INSTANCE);
} }
KtExpression calleeExpression = context.call.getCalleeExpression(); KtExpression calleeExpression = context.call.getCalleeExpression();
@@ -264,7 +265,7 @@ public class CallResolver {
KtSimpleNameExpression expression = (KtSimpleNameExpression) calleeExpression; KtSimpleNameExpression expression = (KtSimpleNameExpression) calleeExpression;
return computeTasksAndResolveCall( return computeTasksAndResolveCall(
context, expression.getReferencedNameAsName(), expression, context, expression.getReferencedNameAsName(), expression,
ResolveKind.FUNCTION); Function.INSTANCE);
} }
else if (calleeExpression instanceof KtConstructorCalleeExpression) { else if (calleeExpression instanceof KtConstructorCalleeExpression) {
return (OverloadResolutionResults) resolveCallForConstructor(context, (KtConstructorCalleeExpression) calleeExpression); return (OverloadResolutionResults) resolveCallForConstructor(context, (KtConstructorCalleeExpression) calleeExpression);
@@ -488,7 +489,7 @@ public class CallResolver {
ResolutionTask<FunctionDescriptor> resolutionTask = ResolutionTask<FunctionDescriptor> resolutionTask =
new ResolutionTask<FunctionDescriptor>( new ResolutionTask<FunctionDescriptor>(
ResolveKind.GIVEN_CANDIDATES, null, candidates new NewResolutionOldInference.ResolutionKind.GivenCandidates<FunctionDescriptor>(), null, candidates
); );
@@ -592,14 +593,13 @@ public class CallResolver {
} }
} }
if (resolutionTask.resolveKind != ResolveKind.GIVEN_CANDIDATES) { if (!(resolutionTask.resolutionKind instanceof GivenCandidates)) {
assert resolutionTask.name != null; assert resolutionTask.name != null;
return (OverloadResolutionResultsImpl<D>) return newCallResolver.runResolution(context, resolutionTask.name, resolutionTask.resolutionKind, tracing);
newCallResolver.runResolve(context, resolutionTask.name, resolutionTask.resolveKind, tracing);
} }
else { else {
assert resolutionTask.givenCandidates != null; assert resolutionTask.givenCandidates != null;
return newCallResolver.runResolveForGivenCandidates(context, tracing, resolutionTask.givenCandidates); return newCallResolver.runResolutionForGivenCandidates(context, tracing, resolutionTask.givenCandidates);
} }
} }
@@ -613,24 +613,17 @@ public class CallResolver {
final Collection<ResolutionCandidate<D>> givenCandidates; final Collection<ResolutionCandidate<D>> givenCandidates;
@NotNull @NotNull
final ResolveKind resolveKind; final NewResolutionOldInference.ResolutionKind<D> resolutionKind;
private ResolutionTask( private ResolutionTask(
@NotNull ResolveKind kind, @NotNull NewResolutionOldInference.ResolutionKind<D> kind,
@Nullable Name name, @Nullable Name name,
@Nullable Collection<ResolutionCandidate<D>> candidates @Nullable Collection<ResolutionCandidate<D>> candidates
) { ) {
this.name = name; this.name = name;
givenCandidates = candidates; givenCandidates = candidates;
resolveKind = kind; resolutionKind = kind;
} }
} }
public enum ResolveKind {
FUNCTION,
INVOKE,
VARIABLE,
CALLABLE_REFERENCE,
GIVEN_CANDIDATES,
}
} }
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.Call import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.CandidateResolver import org.jetbrains.kotlin.resolve.calls.CandidateResolver
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getUnaryPlusOrMinusOperatorFunctionName import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getUnaryPlusOrMinusOperatorFunctionName
@@ -51,7 +50,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.check import org.jetbrains.kotlin.utils.addToStdlib.check
import org.jetbrains.kotlin.utils.sure import org.jetbrains.kotlin.utils.sure
class NewResolveOldInference( class NewResolutionOldInference(
private val candidateResolver: CandidateResolver, private val candidateResolver: CandidateResolver,
private val towerResolver: TowerResolver, private val towerResolver: TowerResolver,
private val resolutionResultsHandler: ResolutionResultsHandler, private val resolutionResultsHandler: ResolutionResultsHandler,
@@ -59,23 +58,93 @@ class NewResolveOldInference(
private val syntheticScopes: SyntheticScopes private val syntheticScopes: SyntheticScopes
) { ) {
fun runResolve( sealed class ResolutionKind<D : CallableDescriptor> {
abstract internal fun createTowerProcessor(
outer: NewResolutionOldInference,
name: Name,
tracing: TracingStrategy,
scopeTower: ScopeTower,
explicitReceiver: Receiver?,
context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<D>>
object Function : ResolutionKind<FunctionDescriptor>() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<FunctionDescriptor>> {
val invokeContext = outer.InvokeContext(scopeTower, name, context, tracing)
return outer.createFunctionTowerProcessor(invokeContext, explicitReceiver)
}
}
object Variable : ResolutionKind<VariableDescriptor>() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<VariableDescriptor>> {
val simpleContext = outer.SimpleContext<VariableDescriptor>(scopeTower, name, context, tracing)
return createVariableProcessor(simpleContext, explicitReceiver)
}
}
object CallableReference : ResolutionKind<CallableDescriptor>() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<CallableDescriptor>> {
val simpleContextF = outer.SimpleContext<FunctionDescriptor>(scopeTower, name, context, tracing)
val simpleContextV = outer.SimpleContext<VariableDescriptor>(scopeTower, name, context, tracing)
return CompositeScopeTowerProcessor(
createFunctionProcessor(simpleContextF, explicitReceiver),
createVariableProcessor(simpleContextV, explicitReceiver)
)
}
}
object Invoke : ResolutionKind<FunctionDescriptor>() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<FunctionDescriptor>> {
val invokeContext = outer.InvokeContext(scopeTower, name, context, tracing)
// todo
val call = (context.call as? CallTransformer.CallForImplicitInvoke).sure {
"Call should be CallForImplicitInvoke, but it is: ${context.call}"
}
return outer.createProcessorWithReceiverValueOrEmpty(explicitReceiver) {
createCallTowerProcessorForExplicitInvoke(invokeContext, call.dispatchReceiver, it)
}
}
}
class GivenCandidates<D : CallableDescriptor> : ResolutionKind<D>() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate<D>> {
throw IllegalStateException("Should be not called")
}
}
}
fun <D : CallableDescriptor> runResolution(
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
name: Name, name: Name,
kind: CallResolver.ResolveKind, kind: ResolutionKind<D>,
tracing: TracingStrategy tracing: TracingStrategy
): OverloadResolutionResultsImpl<*> { ): OverloadResolutionResultsImpl<D> {
val explicitReceiver = context.call.explicitReceiver val explicitReceiver = context.call.explicitReceiver
val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor) val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor)
val scopeTower = ScopeTowerImpl(context, dynamicScope, syntheticScopes, context.call.createLookupLocation()) val scopeTower = ScopeTowerImpl(context, dynamicScope, syntheticScopes, context.call.createLookupLocation())
val baseContext = Context(scopeTower, name, context, tracing) var processor = kind.createTowerProcessor(this, name, tracing, scopeTower, explicitReceiver, context)
var processor = createResolveProcessor(kind, explicitReceiver, context, baseContext)
if (context.collectAllCandidates) { if (context.collectAllCandidates) {
return allCandidatesResult(towerResolver.collectAllCandidates(baseContext, processor)) return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor))
} }
// Temporary fix for code migration (unaryPlus()/unaryMinus()) // Temporary fix for code migration (unaryPlus()/unaryMinus())
val unaryConventionName = getUnaryPlusOrMinusOperatorFunctionName(context.call) val unaryConventionName = getUnaryPlusOrMinusOperatorFunctionName(context.call)
@@ -84,15 +153,16 @@ class NewResolveOldInference(
OperatorNameConventions.PLUS OperatorNameConventions.PLUS
else else
OperatorNameConventions.MINUS OperatorNameConventions.MINUS
val otherBaseContext = Context(scopeTower, deprecatedName, context, tracing)
processor = CompositeScopeTowerProcessor(processor, createResolveProcessor(kind, explicitReceiver, context, otherBaseContext)) val deprecatedProcessor = kind.createTowerProcessor(this, deprecatedName, tracing, scopeTower, explicitReceiver, context)
processor = CompositeScopeTowerProcessor(processor, deprecatedProcessor)
} }
val candidates = towerResolver.runResolve(baseContext, processor, useOrder = kind != CallResolver.ResolveKind.CALLABLE_REFERENCE) val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference)
return convertToOverloadResults(candidates, tracing, context) return convertToOverloadResults(candidates, tracing, context)
} }
fun <D : CallableDescriptor> runResolveForGivenCandidates( fun <D : CallableDescriptor> runResolutionForGivenCandidates(
basicCallContext: BasicCallResolutionContext, basicCallContext: BasicCallResolutionContext,
tracing: TracingStrategy, tracing: TracingStrategy,
candidates: Collection<ResolutionCandidate<D>> candidates: Collection<ResolutionCandidate<D>>
@@ -102,7 +172,7 @@ class NewResolveOldInference(
val resolvedCall = ResolvedCallImpl.create(candidate, candidateTrace, tracing, basicCallContext.dataFlowInfoForArguments) val resolvedCall = ResolvedCallImpl.create(candidate, candidateTrace, tracing, basicCallContext.dataFlowInfoForArguments)
if (candidate.descriptor.isHiddenInResolution()) { if (candidate.descriptor.isHiddenInResolution()) {
return@mapNotNull Candidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), resolvedCall) return@mapNotNull MyCandidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), resolvedCall)
} }
val callCandidateResolutionContext = CallCandidateResolutionContext.create( val callCandidateResolutionContext = CallCandidateResolutionContext.create(
@@ -113,65 +183,42 @@ class NewResolveOldInference(
val diagnostics = listOfNotNull(SynthesizedDescriptorDiagnostic.check { candidate.descriptor.isSynthesized }, val diagnostics = listOfNotNull(SynthesizedDescriptorDiagnostic.check { candidate.descriptor.isSynthesized },
createPreviousResolveError(resolvedCall.status)) createPreviousResolveError(resolvedCall.status))
Candidate(ResolutionCandidateStatus(diagnostics), resolvedCall) MyCandidate(ResolutionCandidateStatus(diagnostics), resolvedCall)
} }
if (basicCallContext.collectAllCandidates) { if (basicCallContext.collectAllCandidates) {
val allCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates), val allCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
TowerResolver.AllCandidatesCollector { it.candidateStatus }, useOrder = false) TowerResolver.AllCandidatesCollector { it.candidateStatus }, useOrder = false)
return allCandidatesResult(allCandidates) as OverloadResolutionResultsImpl<D> return allCandidatesResult(allCandidates)
} }
val processedCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates), val processedCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
TowerResolver.SuccessfulResultCollector { it.candidateStatus }, useOrder = true) TowerResolver.SuccessfulResultCollector { it.candidateStatus }, useOrder = true)
return convertToOverloadResults(processedCandidates, tracing, basicCallContext) as OverloadResolutionResultsImpl<D> return convertToOverloadResults(processedCandidates, tracing, basicCallContext)
} }
private fun allCandidatesResult(allCandidates: Collection<Candidate>) private fun <D: CallableDescriptor> allCandidatesResult(allCandidates: Collection<MyCandidate<D>>)
= OverloadResolutionResultsImpl.nameNotFound<CallableDescriptor>().apply { = OverloadResolutionResultsImpl.nameNotFound<D>().apply {
this.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall<CallableDescriptor> } this.allCandidates = allCandidates.map { it.resolvedCall }
} }
private fun createResolveProcessor( private fun <D : CallableDescriptor> createProcessorWithReceiverValueOrEmpty(
kind: CallResolver.ResolveKind,
explicitReceiver : Receiver?,
context: BasicCallResolutionContext,
baseContext: Context)
= when (kind) {
CallResolver.ResolveKind.VARIABLE -> createVariableProcessor(baseContext, explicitReceiver)
CallResolver.ResolveKind.FUNCTION -> createFunctionTowerProcessor(baseContext, explicitReceiver)
CallResolver.ResolveKind.CALLABLE_REFERENCE -> CompositeScopeTowerProcessor(
createFunctionProcessor(baseContext, explicitReceiver),
createVariableProcessor(baseContext, explicitReceiver)
)
CallResolver.ResolveKind.INVOKE -> {
// todo
val call = (context.call as? CallTransformer.CallForImplicitInvoke).sure {
"Call should be CallForImplicitInvoke, but it is: ${context.call}"
}
createProcessorWithReceiverValueOrEmpty(explicitReceiver) {
createCallTowerProcessorForExplicitInvoke(baseContext, call.dispatchReceiver, it)
}
}
CallResolver.ResolveKind.GIVEN_CANDIDATES -> {
throw UnsupportedOperationException("Kind $kind unsupported yet")
}
}
private fun createProcessorWithReceiverValueOrEmpty(
explicitReceiver: Receiver?, explicitReceiver: Receiver?,
create: (ReceiverValue?) -> ScopeTowerProcessor<Candidate> create: (ReceiverValue?) -> ScopeTowerProcessor<MyCandidate<D>>
): ScopeTowerProcessor<Candidate> { ): ScopeTowerProcessor<MyCandidate<D>> {
return if (explicitReceiver is QualifierReceiver) { return if (explicitReceiver is QualifierReceiver) {
(explicitReceiver as? ClassQualifier)?.classValueReceiver?.let(create) (explicitReceiver as? ClassQualifier)?.classValueReceiver?.let(create)
?: KnownResultProcessor<Candidate>(listOf()) ?: KnownResultProcessor<MyCandidate<D>>(listOf())
} }
else { else {
create(explicitReceiver as ReceiverValue?) create(explicitReceiver as ReceiverValue?)
} }
} }
private fun createFunctionTowerProcessor(baseContext: Context, explicitReceiver: Receiver?): CompositeScopeTowerProcessor<Candidate> { private fun createFunctionTowerProcessor(
baseContext: InvokeTowerContext<MyCandidate<FunctionDescriptor>, MyCandidate<VariableDescriptor>>,
explicitReceiver: Receiver?
): CompositeScopeTowerProcessor<MyCandidate<FunctionDescriptor>> {
// a.foo() -- simple function call // a.foo() -- simple function call
val simpleFunction = createFunctionProcessor(baseContext, explicitReceiver) val simpleFunction = createFunctionProcessor(baseContext, explicitReceiver)
@@ -185,11 +232,11 @@ class NewResolveOldInference(
} }
private fun convertToOverloadResults( private fun <D : CallableDescriptor> convertToOverloadResults(
candidates: Collection<Candidate>, candidates: Collection<MyCandidate<D>>,
tracing: TracingStrategy, tracing: TracingStrategy,
basicCallContext: BasicCallResolutionContext basicCallContext: BasicCallResolutionContext
): OverloadResolutionResultsImpl<*> { ): OverloadResolutionResultsImpl<D> {
val resolvedCalls = candidates.mapNotNull { val resolvedCalls = candidates.mapNotNull {
val (status, resolvedCall) = it val (status, resolvedCall) = it
if (resolvedCall is VariableAsFunctionResolvedCallImpl) { if (resolvedCall is VariableAsFunctionResolvedCallImpl) {
@@ -224,23 +271,33 @@ class NewResolveOldInference(
resolvedCall resolvedCall
} }
return resolutionResultsHandler.computeResultAndReportErrors<CallableDescriptor>(basicCallContext, tracing, resolvedCalls as List<MutableResolvedCall<CallableDescriptor>>) return resolutionResultsHandler.computeResultAndReportErrors(basicCallContext, tracing, resolvedCalls)
} }
private data class Candidate(val candidateStatus: ResolutionCandidateStatus, val resolvedCall: MutableResolvedCall<*>) internal data class MyCandidate<out D: CallableDescriptor>(
val candidateStatus: ResolutionCandidateStatus,
val resolvedCall: MutableResolvedCall<@UnsafeVariance D>
) : Candidate<D> {
override val descriptor: D
get() = resolvedCall.candidateDescriptor
private inner class Context( override val isSuccessful: Boolean
get() = candidateStatus.resultingApplicability.isSuccess
override val status: ResolutionCandidateStatus
get() = candidateStatus
}
private inner open class SimpleContext<D : CallableDescriptor>(
override val scopeTower: ScopeTower, override val scopeTower: ScopeTower,
override val name: Name, override val name: Name,
private val basicCallContext: BasicCallResolutionContext, protected val basicCallContext: BasicCallResolutionContext,
private val tracing: TracingStrategy protected val tracing: TracingStrategy
) : TowerContext<Candidate> { ) : TowerContext<D, MyCandidate<D>> {
override fun createCandidate( override fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver<*>, towerCandidate: CandidateWithBoundDispatchReceiver<D>,
explicitReceiverKind: ExplicitReceiverKind, explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValue? extensionReceiver: ReceiverValue?
): Candidate { ): MyCandidate<D> {
val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate") val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate")
val candidateCall = ResolvedCallImpl( val candidateCall = ResolvedCallImpl(
basicCallContext.call, towerCandidate.descriptor, basicCallContext.call, towerCandidate.descriptor,
@@ -252,11 +309,11 @@ class NewResolveOldInference(
// see spec-docs/dynamic-types.md // see spec-docs/dynamic-types.md
if (extensionReceiver != null && extensionReceiver.type.isDynamic() if (extensionReceiver != null && extensionReceiver.type.isDynamic()
&& !towerCandidate.descriptor.extensionReceiverParameter!!.value.type.isDynamic()) { && !towerCandidate.descriptor.extensionReceiverParameter!!.value.type.isDynamic()) {
return Candidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall) return MyCandidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall)
} }
if (towerCandidate.descriptor.isHiddenInResolution()) { if (towerCandidate.descriptor.isHiddenInResolution()) {
return Candidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), candidateCall) return MyCandidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), candidateCall)
} }
val callCandidateResolutionContext = CallCandidateResolutionContext.create( val callCandidateResolutionContext = CallCandidateResolutionContext.create(
@@ -268,7 +325,7 @@ class NewResolveOldInference(
val diagnostics = (towerCandidate.diagnostics + val diagnostics = (towerCandidate.diagnostics +
checkInfixAndOperator(basicCallContext.call, towerCandidate.descriptor) + checkInfixAndOperator(basicCallContext.call, towerCandidate.descriptor) +
createPreviousResolveError(candidateCall.status)).filterNotNull() // todo createPreviousResolveError(candidateCall.status)).filterNotNull() // todo
return Candidate(ResolutionCandidateStatus(diagnostics), candidateCall) return MyCandidate(ResolutionCandidateStatus(diagnostics), candidateCall)
} }
private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List<ResolutionDiagnostic> { private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List<ResolutionDiagnostic> {
@@ -282,38 +339,52 @@ class NewResolveOldInference(
return listOfNotNull(conventionError, infixError) return listOfNotNull(conventionError, infixError)
} }
override fun getStatus(candidate: Candidate): ResolutionCandidateStatus = candidate.candidateStatus }
override fun transformCandidate(variable: Candidate, invoke: Candidate): Candidate { private inner class InvokeContext(
scopeTower: ScopeTower,
name: Name,
basicCallContext: BasicCallResolutionContext,
tracing: TracingStrategy
) : InvokeTowerContext<MyCandidate<FunctionDescriptor>, MyCandidate<VariableDescriptor>>,
SimpleContext<FunctionDescriptor>(scopeTower, name, basicCallContext, tracing) {
override fun transformCandidate(
variable: MyCandidate<VariableDescriptor>,
invoke: MyCandidate<FunctionDescriptor>
): MyCandidate<FunctionDescriptor> {
val resolvedCallImpl = VariableAsFunctionResolvedCallImpl( val resolvedCallImpl = VariableAsFunctionResolvedCallImpl(
invoke.resolvedCall as MutableResolvedCall<FunctionDescriptor>, invoke.resolvedCall,
variable.resolvedCall as MutableResolvedCall<VariableDescriptor> variable.resolvedCall
) )
assert(variable.candidateStatus.resultingApplicability.isSuccess) { assert(variable.candidateStatus.resultingApplicability.isSuccess) {
"Variable call must be success: $variable" "Variable call must be success: $variable"
} }
return Candidate(ResolutionCandidateStatus(variable.candidateStatus.diagnostics + invoke.candidateStatus.diagnostics), resolvedCallImpl) return MyCandidate(ResolutionCandidateStatus(variable.candidateStatus.diagnostics + invoke.candidateStatus.diagnostics), resolvedCallImpl)
} }
override fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<Candidate> { override fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<VariableDescriptor, MyCandidate<VariableDescriptor>> {
val newCall = CallTransformer.stripCallArguments(basicCallContext.call).let { val newCall = CallTransformer.stripCallArguments(basicCallContext.call).let {
if (stripExplicitReceiver) CallTransformer.stripReceiver(it) else it if (stripExplicitReceiver) CallTransformer.stripReceiver(it) else it
} }
return Context(scopeTower, name, basicCallContext.replaceCall(newCall), tracing) return SimpleContext(scopeTower, name, basicCallContext.replaceCall(newCall), tracing)
} }
override fun contextForInvoke(variable: Candidate, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<Candidate>>? { override fun contextForInvoke(
variable: MyCandidate<VariableDescriptor>,
useExplicitReceiver: Boolean
): Pair<ReceiverValue, TowerContext<FunctionDescriptor, MyCandidate<FunctionDescriptor>>>? {
assert(variable.resolvedCall.status.possibleTransformToSuccess()) { assert(variable.resolvedCall.status.possibleTransformToSuccess()) {
"Incorrect status: ${variable.resolvedCall.status} for variable call: ${variable.resolvedCall} " + "Incorrect status: ${variable.resolvedCall.status} for variable call: ${variable.resolvedCall} " +
"and descriptor: ${variable.resolvedCall.candidateDescriptor}" "and descriptor: ${variable.resolvedCall.candidateDescriptor}"
} }
val calleeExpression = variable.resolvedCall.call.calleeExpression val calleeExpression = variable.resolvedCall.call.calleeExpression
val variableDescriptor = variable.resolvedCall.resultingDescriptor val variableDescriptor = variable.resolvedCall.resultingDescriptor
assert(variable.resolvedCall.status.possibleTransformToSuccess() && calleeExpression != null && variableDescriptor is VariableDescriptor) { assert(variable.resolvedCall.status.possibleTransformToSuccess() && calleeExpression != null) {
"Unexpected varialbe candidate: $variable" "Unexpected variable candidate: $variable"
} }
val variableType = (variableDescriptor as VariableDescriptor).type val variableType = variableDescriptor.type
if (variableType is DeferredType && variableType.isComputing) { if (variableType is DeferredType && variableType.isComputing) {
return null // todo: create special check that there is no invoke on variable return null // todo: create special check that there is no invoke on variable
@@ -333,7 +404,7 @@ class NewResolveOldInference(
.replaceContextDependency(ContextDependency.DEPENDENT) // todo .replaceContextDependency(ContextDependency.DEPENDENT) // todo
val newScopeTower = ScopeTowerImpl(basicCallResolutionContext, scopeTower.dynamicScope, scopeTower.syntheticScopes, scopeTower.location) val newScopeTower = ScopeTowerImpl(basicCallResolutionContext, scopeTower.dynamicScope, scopeTower.syntheticScopes, scopeTower.location)
val newContext = Context(newScopeTower, OperatorNameConventions.INVOKE, basicCallResolutionContext, tracingForInvoke) val newContext = SimpleContext<FunctionDescriptor>(newScopeTower, OperatorNameConventions.INVOKE, basicCallResolutionContext, tracingForInvoke)
return variableReceiver to newContext return variableReceiver to newContext
} }
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.builtins.isExtensionFunctionType import org.jetbrains.kotlin.builtins.isExtensionFunctionType
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
@@ -25,29 +26,29 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.* import java.util.*
abstract class AbstractInvokeTowerProcessor<C>( abstract class AbstractInvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
protected val functionContext: TowerContext<C>, protected val invokeContext: InvokeTowerContext<F, V>,
private val variableProcessor: ScopeTowerProcessor<C> private val variableProcessor: ScopeTowerProcessor<V>
) : ScopeTowerProcessor<C> { ) : ScopeTowerProcessor<F> {
// todo optimize it // todo optimize it
private val previousData = ArrayList<TowerData>() private val previousData = ArrayList<TowerData>()
private val invokeProcessors: MutableList<Collection<VariableInvokeProcessor>> = ArrayList() private val invokeProcessors: MutableList<Collection<VariableInvokeProcessor>> = ArrayList()
private inner class VariableInvokeProcessor(val variableCandidate: C): ScopeTowerProcessor<C> { private inner class VariableInvokeProcessor(val variableCandidate: V): ScopeTowerProcessor<F> {
val invokeProcessor: ScopeTowerProcessor<C> = createInvokeProcessor(variableCandidate) val invokeProcessor: ScopeTowerProcessor<F> = createInvokeProcessor(variableCandidate)
override fun process(data: TowerData) override fun process(data: TowerData)
= invokeProcessor.process(data).map { candidateGroup -> = invokeProcessor.process(data).map { candidateGroup ->
candidateGroup.map { functionContext.transformCandidate(variableCandidate, it) } candidateGroup.map { invokeContext.transformCandidate(variableCandidate, it) }
} }
} }
protected abstract fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> protected abstract fun createInvokeProcessor(variableCandidate: V): ScopeTowerProcessor<F>
override fun process(data: TowerData): List<Collection<C>> { override fun process(data: TowerData): List<Collection<F>> {
previousData.add(data) previousData.add(data)
val candidateGroups = ArrayList<Collection<C>>(0) val candidateGroups = ArrayList<Collection<F>>(0)
for (processorsGroup in invokeProcessors) { for (processorsGroup in invokeProcessors) {
candidateGroups.addAll(processorsGroup.processVariableGroup(data)) candidateGroups.addAll(processorsGroup.processVariableGroup(data))
@@ -55,7 +56,7 @@ abstract class AbstractInvokeTowerProcessor<C>(
for (variableCandidates in variableProcessor.process(data)) { for (variableCandidates in variableProcessor.process(data)) {
val successfulVariables = variableCandidates.filter { val successfulVariables = variableCandidates.filter {
functionContext.getStatus(it).resultingApplicability.isSuccess it.isSuccessful
} }
if (successfulVariables.isNotEmpty()) { if (successfulVariables.isNotEmpty()) {
@@ -71,7 +72,7 @@ abstract class AbstractInvokeTowerProcessor<C>(
return candidateGroups return candidateGroups
} }
private fun Collection<VariableInvokeProcessor>.processVariableGroup(data: TowerData): List<Collection<C>> { private fun Collection<VariableInvokeProcessor>.processVariableGroup(data: TowerData): List<Collection<F>> {
return when (size) { return when (size) {
0 -> emptyList() 0 -> emptyList()
1 -> single().process(data) 1 -> single().process(data)
@@ -84,44 +85,44 @@ abstract class AbstractInvokeTowerProcessor<C>(
} }
// todo KT-9522 Allow invoke convention for synthetic property // todo KT-9522 Allow invoke convention for synthetic property
class InvokeTowerProcessor<C>( class InvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
functionContext: TowerContext<C>, invokeContext: InvokeTowerContext<F, V>,
private val explicitReceiver: Receiver? private val explicitReceiver: Receiver?
) : AbstractInvokeTowerProcessor<C>( ) : AbstractInvokeTowerProcessor<F, V>(
functionContext, invokeContext,
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver) createVariableProcessor(invokeContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver)
) { ) {
// todo filter by operator // todo filter by operator
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> { override fun createInvokeProcessor(variableCandidate: V): ScopeTowerProcessor<F> {
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = false) val (variableReceiver, invokeContext) = invokeContext.contextForInvoke(variableCandidate, useExplicitReceiver = false)
?: return KnownResultProcessor(emptyList()) ?: return KnownResultProcessor(emptyList())
return ExplicitReceiverScopeTowerProcessor(invokeContext, variableReceiver, ScopeTowerLevel::getFunctions) return ExplicitReceiverScopeTowerProcessor(invokeContext, variableReceiver, ScopeTowerLevel::getFunctions)
} }
} }
class InvokeExtensionTowerProcessor<C>( class InvokeExtensionTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
functionContext: TowerContext<C>, invokeContext: InvokeTowerContext<F, V>,
private val explicitReceiver: ReceiverValue? private val explicitReceiver: ReceiverValue?
) : AbstractInvokeTowerProcessor<C>( ) : AbstractInvokeTowerProcessor<F, V>(
functionContext, invokeContext,
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null) createVariableProcessor(invokeContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null)
) { ) {
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> { override fun createInvokeProcessor(variableCandidate: V): ScopeTowerProcessor<F> {
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = true) val (variableReceiver, invokeContext) = invokeContext.contextForInvoke(variableCandidate, useExplicitReceiver = true)
?: return KnownResultProcessor(emptyList()) ?: return KnownResultProcessor(emptyList())
val invokeDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver) val invokeDescriptor = invokeContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
?: return KnownResultProcessor(emptyList()) ?: return KnownResultProcessor(emptyList())
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver) return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver)
} }
} }
private class InvokeExtensionScopeTowerProcessor<C>( private class InvokeExtensionScopeTowerProcessor<C : Candidate<FunctionDescriptor>>(
context: TowerContext<C>, context: TowerContext<FunctionDescriptor, C>,
private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>, private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>,
private val explicitReceiver: ReceiverValue? private val explicitReceiver: ReceiverValue?
) : AbstractSimpleScopeTowerProcessor<C>(context) { ) : AbstractSimpleScopeTowerProcessor<FunctionDescriptor, C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> { override fun simpleProcess(data: TowerData): Collection<C> {
if (explicitReceiver != null && data == TowerData.Empty) { if (explicitReceiver != null && data == TowerData.Empty) {
@@ -150,23 +151,23 @@ private fun ScopeTower.getExtensionInvokeCandidateDescriptor(
} }
// case 1.(foo())() or (foo())() // case 1.(foo())() or (foo())()
fun <C> createCallTowerProcessorForExplicitInvoke( fun <F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>> createCallTowerProcessorForExplicitInvoke(
contextForInvoke: TowerContext<C>, invokeContext: InvokeTowerContext<F, V>,
expressionForInvoke: ReceiverValue, expressionForInvoke: ReceiverValue,
explicitReceiver: ReceiverValue? explicitReceiver: ReceiverValue?
): ScopeTowerProcessor<C> { ): ScopeTowerProcessor<F> {
val invokeExtensionDescriptor = contextForInvoke.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke) val invokeExtensionDescriptor = invokeContext.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
if (explicitReceiver != null) { if (explicitReceiver != null) {
if (invokeExtensionDescriptor == null) { if (invokeExtensionDescriptor == null) {
// case 1.(foo())(), where foo() isn't extension function // case 1.(foo())(), where foo() isn't extension function
return KnownResultProcessor(emptyList()) return KnownResultProcessor(emptyList())
} }
else { else {
return InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = explicitReceiver) return InvokeExtensionScopeTowerProcessor(invokeContext, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
} }
} }
else { else {
val usualInvoke = ExplicitReceiverScopeTowerProcessor(contextForInvoke, expressionForInvoke, ScopeTowerLevel::getFunctions) // todo operator val usualInvoke = ExplicitReceiverScopeTowerProcessor(invokeContext, expressionForInvoke, ScopeTowerLevel::getFunctions) // todo operator
if (invokeExtensionDescriptor == null) { if (invokeExtensionDescriptor == null) {
return usualInvoke return usualInvoke
@@ -174,7 +175,7 @@ fun <C> createCallTowerProcessorForExplicitInvoke(
else { else {
return CompositeScopeTowerProcessor( return CompositeScopeTowerProcessor(
usualInvoke, usualInvoke,
InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = null) InvokeExtensionScopeTowerProcessor(invokeContext, invokeExtensionDescriptor, explicitReceiver = null)
) )
} }
} }
@@ -16,6 +16,9 @@
package org.jetbrains.kotlin.resolve.calls.tower package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
@@ -37,8 +40,8 @@ class CompositeScopeTowerProcessor<C>(
override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) } override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) }
} }
internal abstract class AbstractSimpleScopeTowerProcessor<C>( internal abstract class AbstractSimpleScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
val context: TowerContext<C> val context: TowerContext<D, C>
) : ScopeTowerProcessor<C> { ) : ScopeTowerProcessor<C> {
protected val name: Name get() = context.name protected val name: Name get() = context.name
@@ -47,11 +50,11 @@ internal abstract class AbstractSimpleScopeTowerProcessor<C>(
override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).check { it.isNotEmpty() }) override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).check { it.isNotEmpty() })
} }
internal class ExplicitReceiverScopeTowerProcessor<C>( internal class ExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
context: TowerContext<C>, context: TowerContext<D, C>,
val explicitReceiver: ReceiverValue, val explicitReceiver: ReceiverValue,
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>> val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
): AbstractSimpleScopeTowerProcessor<C>(context) { ): AbstractSimpleScopeTowerProcessor<D, C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> { override fun simpleProcess(data: TowerData): Collection<C> {
return when (data) { return when (data) {
TowerData.Empty -> resolveAsMember() TowerData.Empty -> resolveAsMember()
@@ -72,11 +75,11 @@ internal class ExplicitReceiverScopeTowerProcessor<C>(
} }
} }
private class QualifierScopeTowerProcessor<C>( private class QualifierScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
context: TowerContext<C>, context: TowerContext<D, C>,
val qualifier: QualifierReceiver, val qualifier: QualifierReceiver,
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>> val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
): AbstractSimpleScopeTowerProcessor<C>(context) { ): AbstractSimpleScopeTowerProcessor<D, C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> { override fun simpleProcess(data: TowerData): Collection<C> {
if (data != TowerData.Empty) return emptyList() if (data != TowerData.Empty) return emptyList()
@@ -87,10 +90,10 @@ private class QualifierScopeTowerProcessor<C>(
} }
} }
private class NoExplicitReceiverScopeTowerProcessor<C>( private class NoExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
context: TowerContext<C>, context: TowerContext<D, C>,
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>> val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
) : AbstractSimpleScopeTowerProcessor<C>(context) { ) : AbstractSimpleScopeTowerProcessor<D, C>(context) {
override fun simpleProcess(data: TowerData): Collection<C> override fun simpleProcess(data: TowerData): Collection<C>
= when(data) { = when(data) {
is TowerData.TowerLevel -> { is TowerData.TowerLevel -> {
@@ -107,10 +110,10 @@ private class NoExplicitReceiverScopeTowerProcessor<C>(
} }
} }
private fun <C> createSimpleProcessor( private fun <D : CallableDescriptor, C: Candidate<D>> createSimpleProcessor(
context: TowerContext<C>, context: TowerContext<D, C>,
explicitReceiver: Receiver?, explicitReceiver: Receiver?,
collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>> collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
) : ScopeTowerProcessor<C> { ) : ScopeTowerProcessor<C> {
if (explicitReceiver is ReceiverValue) { if (explicitReceiver is ReceiverValue) {
return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates) return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates)
@@ -133,8 +136,8 @@ private fun <C> createSimpleProcessor(
} }
} }
fun <C> createVariableProcessor(context: TowerContext<C>, explicitReceiver: Receiver?) fun <C : Candidate<VariableDescriptor>> createVariableProcessor(context: TowerContext<VariableDescriptor, C>, explicitReceiver: Receiver?)
= createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getVariables) = createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getVariables)
fun <C> createFunctionProcessor(context: TowerContext<C>, explicitReceiver: Receiver?) fun <C : Candidate<FunctionDescriptor>> createFunctionProcessor(context: TowerContext<FunctionDescriptor, C>, explicitReceiver: Receiver?)
= createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getFunctions) = createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getFunctions)
@@ -16,6 +16,9 @@
package org.jetbrains.kotlin.resolve.calls.tower package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -26,25 +29,35 @@ import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
import org.jetbrains.kotlin.utils.addToStdlib.check import org.jetbrains.kotlin.utils.addToStdlib.check
import java.util.* import java.util.*
interface TowerContext<C> { interface Candidate<out D : CallableDescriptor> {
val descriptor: D
// this operation should be very fast
val isSuccessful: Boolean
val status: ResolutionCandidateStatus
}
interface TowerContext<D : CallableDescriptor, C: Candidate<D>> {
val name: Name val name: Name
val scopeTower: ScopeTower val scopeTower: ScopeTower
fun createCandidate( fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver<*>, towerCandidate: CandidateWithBoundDispatchReceiver<D>,
explicitReceiverKind: ExplicitReceiverKind, explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValue? extensionReceiver: ReceiverValue?
): C ): C
}
fun getStatus(candidate: C): ResolutionCandidateStatus interface InvokeTowerContext<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>: TowerContext<FunctionDescriptor, F> {
fun transformCandidate(variable: C, invoke: C): C fun transformCandidate(variable: V, invoke: F): F
fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<C> fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<VariableDescriptor, V>
// foo() -> ReceiverValue(foo), context for invoke // foo() -> ReceiverValue(foo), context for invoke
// null means that there is no invoke on variable // null means that there is no invoke on variable
fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<C>>? fun contextForInvoke(variable: V, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<FunctionDescriptor, F>>?
} }
sealed class TowerData { sealed class TowerData {
@@ -54,21 +67,24 @@ sealed class TowerData {
class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValue) : TowerData() class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValue) : TowerData()
} }
interface ScopeTowerProcessor<C> { interface ScopeTowerProcessor<out C> {
// Candidates with matched receivers (dispatch receiver was already matched in ScopeTowerLevel) // Candidates with matched receivers (dispatch receiver was already matched in ScopeTowerLevel)
// Candidates in one groups have same priority, first group has highest priority. // Candidates in one groups have same priority, first group has highest priority.
fun process(data: TowerData): List<Collection<C>> fun process(data: TowerData): List<Collection<C>>
} }
class TowerResolver { class TowerResolver {
fun <C> runResolve( fun <C: Candidate<*>> runResolve(
context: TowerContext<C>, scopeTower: ScopeTower,
processor: ScopeTowerProcessor<C>, processor: ScopeTowerProcessor<C>,
useOrder: Boolean useOrder: Boolean
): Collection<C> = context.scopeTower.run(processor, SuccessfulResultCollector { context.getStatus(it) }, useOrder) ): Collection<C> = scopeTower.run(processor, SuccessfulResultCollector { it.status }, useOrder)
fun <C> collectAllCandidates(context: TowerContext<C>, processor: ScopeTowerProcessor<C>): Collection<C> fun <C: Candidate<*>> collectAllCandidates(
= context.scopeTower.run(processor, AllCandidatesCollector { context.getStatus(it) }, false) scopeTower: ScopeTower,
processor: ScopeTowerProcessor<C>
): Collection<C>
= scopeTower.run(processor, AllCandidatesCollector { it.status }, false)
private fun ScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> { private fun ScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
val result = ArrayList<ScopeTowerLevel>() val result = ArrayList<ScopeTowerLevel>()