Refactoring. Add type safety to resolution.
This commit is contained in:
@@ -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.smartcasts.DataFlowInfo;
|
||||
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.descriptorUtil.DescriptorUtilsKt;
|
||||
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.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.tower.NewResolutionOldInference.ResolutionKind.*;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
@SuppressWarnings("RedundantTypeArguments")
|
||||
@@ -67,7 +68,7 @@ public class CallResolver {
|
||||
private ArgumentTypeResolver argumentTypeResolver;
|
||||
private GenericCandidateResolver genericCandidateResolver;
|
||||
private CallCompleter callCompleter;
|
||||
private NewResolveOldInference newCallResolver;
|
||||
private NewResolutionOldInference newCallResolver;
|
||||
private final KotlinBuiltIns builtIns;
|
||||
|
||||
private static final PerformanceCounter callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter);
|
||||
@@ -110,7 +111,7 @@ public class CallResolver {
|
||||
|
||||
// component dependency cycle
|
||||
@Inject
|
||||
public void setCallCompleter(@NotNull NewResolveOldInference newCallResolver) {
|
||||
public void setCallCompleter(@NotNull NewResolutionOldInference newCallResolver) {
|
||||
this.newCallResolver = newCallResolver;
|
||||
}
|
||||
|
||||
@@ -122,7 +123,7 @@ public class CallResolver {
|
||||
Name referencedName = nameExpression.getReferencedNameAsName();
|
||||
return computeTasksAndResolveCall(
|
||||
context, referencedName, nameExpression,
|
||||
ResolveKind.VARIABLE);
|
||||
Variable.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -132,7 +133,7 @@ public class CallResolver {
|
||||
) {
|
||||
return computeTasksAndResolveCall(
|
||||
context, nameExpression.getReferencedNameAsName(), nameExpression,
|
||||
ResolveKind.CALLABLE_REFERENCE);
|
||||
CallableReference.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -145,7 +146,7 @@ public class CallResolver {
|
||||
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
|
||||
return computeTasksAndResolveCall(
|
||||
callResolutionContext, name, functionReference,
|
||||
ResolveKind.FUNCTION);
|
||||
Function.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -155,7 +156,7 @@ public class CallResolver {
|
||||
) {
|
||||
return computeTasksAndResolveCall(
|
||||
context, OperatorNameConventions.INVOKE, tracing,
|
||||
ResolveKind.INVOKE);
|
||||
Invoke.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -163,7 +164,7 @@ public class CallResolver {
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull Name name,
|
||||
@NotNull KtReferenceExpression referenceExpression,
|
||||
@NotNull ResolveKind kind
|
||||
@NotNull NewResolutionOldInference.ResolutionKind<D> kind
|
||||
) {
|
||||
TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call);
|
||||
return computeTasksAndResolveCall(context, name, tracing, kind);
|
||||
@@ -174,7 +175,7 @@ public class CallResolver {
|
||||
@NotNull final BasicCallResolutionContext context,
|
||||
@NotNull final Name name,
|
||||
@NotNull final TracingStrategy tracing,
|
||||
@NotNull final ResolveKind kind
|
||||
@NotNull final NewResolutionOldInference.ResolutionKind<D> kind
|
||||
) {
|
||||
return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<D>>() {
|
||||
@Override
|
||||
@@ -207,7 +208,7 @@ public class CallResolver {
|
||||
@Override
|
||||
public OverloadResolutionResults<D> invoke() {
|
||||
ResolutionTask<D> resolutionTask = new ResolutionTask<D>(
|
||||
ResolveKind.GIVEN_CANDIDATES, null, candidates
|
||||
new NewResolutionOldInference.ResolutionKind.GivenCandidates<D>(), null, candidates
|
||||
);
|
||||
return doResolveCallOrGetCachedResults(context, resolutionTask, tracing);
|
||||
}
|
||||
@@ -256,7 +257,7 @@ public class CallResolver {
|
||||
KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) context.call.getCallElement();
|
||||
return computeTasksAndResolveCall(
|
||||
context, name, arrayAccessExpression,
|
||||
ResolveKind.FUNCTION);
|
||||
Function.INSTANCE);
|
||||
}
|
||||
|
||||
KtExpression calleeExpression = context.call.getCalleeExpression();
|
||||
@@ -264,7 +265,7 @@ public class CallResolver {
|
||||
KtSimpleNameExpression expression = (KtSimpleNameExpression) calleeExpression;
|
||||
return computeTasksAndResolveCall(
|
||||
context, expression.getReferencedNameAsName(), expression,
|
||||
ResolveKind.FUNCTION);
|
||||
Function.INSTANCE);
|
||||
}
|
||||
else if (calleeExpression instanceof KtConstructorCalleeExpression) {
|
||||
return (OverloadResolutionResults) resolveCallForConstructor(context, (KtConstructorCalleeExpression) calleeExpression);
|
||||
@@ -488,7 +489,7 @@ public class CallResolver {
|
||||
|
||||
ResolutionTask<FunctionDescriptor> resolutionTask =
|
||||
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;
|
||||
return (OverloadResolutionResultsImpl<D>)
|
||||
newCallResolver.runResolve(context, resolutionTask.name, resolutionTask.resolveKind, tracing);
|
||||
return newCallResolver.runResolution(context, resolutionTask.name, resolutionTask.resolutionKind, tracing);
|
||||
}
|
||||
else {
|
||||
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;
|
||||
|
||||
@NotNull
|
||||
final ResolveKind resolveKind;
|
||||
final NewResolutionOldInference.ResolutionKind<D> resolutionKind;
|
||||
|
||||
private ResolutionTask(
|
||||
@NotNull ResolveKind kind,
|
||||
@NotNull NewResolutionOldInference.ResolutionKind<D> kind,
|
||||
@Nullable Name name,
|
||||
@Nullable Collection<ResolutionCandidate<D>> candidates
|
||||
) {
|
||||
this.name = name;
|
||||
givenCandidates = candidates;
|
||||
resolveKind = kind;
|
||||
resolutionKind = kind;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ResolveKind {
|
||||
FUNCTION,
|
||||
INVOKE,
|
||||
VARIABLE,
|
||||
CALLABLE_REFERENCE,
|
||||
GIVEN_CANDIDATES,
|
||||
}
|
||||
}
|
||||
|
||||
+149
-78
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.Call
|
||||
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.CandidateResolver
|
||||
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.sure
|
||||
|
||||
class NewResolveOldInference(
|
||||
class NewResolutionOldInference(
|
||||
private val candidateResolver: CandidateResolver,
|
||||
private val towerResolver: TowerResolver,
|
||||
private val resolutionResultsHandler: ResolutionResultsHandler,
|
||||
@@ -59,23 +58,93 @@ class NewResolveOldInference(
|
||||
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,
|
||||
name: Name,
|
||||
kind: CallResolver.ResolveKind,
|
||||
kind: ResolutionKind<D>,
|
||||
tracing: TracingStrategy
|
||||
): OverloadResolutionResultsImpl<*> {
|
||||
): OverloadResolutionResultsImpl<D> {
|
||||
val explicitReceiver = context.call.explicitReceiver
|
||||
|
||||
val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor)
|
||||
val scopeTower = ScopeTowerImpl(context, dynamicScope, syntheticScopes, context.call.createLookupLocation())
|
||||
|
||||
val baseContext = Context(scopeTower, name, context, tracing)
|
||||
|
||||
var processor = createResolveProcessor(kind, explicitReceiver, context, baseContext)
|
||||
var processor = kind.createTowerProcessor(this, name, tracing, scopeTower, explicitReceiver, context)
|
||||
|
||||
if (context.collectAllCandidates) {
|
||||
return allCandidatesResult(towerResolver.collectAllCandidates(baseContext, processor))
|
||||
return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor))
|
||||
}
|
||||
// Temporary fix for code migration (unaryPlus()/unaryMinus())
|
||||
val unaryConventionName = getUnaryPlusOrMinusOperatorFunctionName(context.call)
|
||||
@@ -84,15 +153,16 @@ class NewResolveOldInference(
|
||||
OperatorNameConventions.PLUS
|
||||
else
|
||||
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)
|
||||
}
|
||||
|
||||
fun <D : CallableDescriptor> runResolveForGivenCandidates(
|
||||
fun <D : CallableDescriptor> runResolutionForGivenCandidates(
|
||||
basicCallContext: BasicCallResolutionContext,
|
||||
tracing: TracingStrategy,
|
||||
candidates: Collection<ResolutionCandidate<D>>
|
||||
@@ -102,7 +172,7 @@ class NewResolveOldInference(
|
||||
val resolvedCall = ResolvedCallImpl.create(candidate, candidateTrace, tracing, basicCallContext.dataFlowInfoForArguments)
|
||||
|
||||
if (candidate.descriptor.isHiddenInResolution()) {
|
||||
return@mapNotNull Candidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), resolvedCall)
|
||||
return@mapNotNull MyCandidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), resolvedCall)
|
||||
}
|
||||
|
||||
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
|
||||
@@ -113,65 +183,42 @@ class NewResolveOldInference(
|
||||
|
||||
val diagnostics = listOfNotNull(SynthesizedDescriptorDiagnostic.check { candidate.descriptor.isSynthesized },
|
||||
createPreviousResolveError(resolvedCall.status))
|
||||
Candidate(ResolutionCandidateStatus(diagnostics), resolvedCall)
|
||||
MyCandidate(ResolutionCandidateStatus(diagnostics), resolvedCall)
|
||||
}
|
||||
if (basicCallContext.collectAllCandidates) {
|
||||
val allCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
|
||||
TowerResolver.AllCandidatesCollector { it.candidateStatus }, useOrder = false)
|
||||
return allCandidatesResult(allCandidates) as OverloadResolutionResultsImpl<D>
|
||||
return allCandidatesResult(allCandidates)
|
||||
}
|
||||
|
||||
val processedCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
|
||||
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>)
|
||||
= OverloadResolutionResultsImpl.nameNotFound<CallableDescriptor>().apply {
|
||||
this.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall<CallableDescriptor> }
|
||||
private fun <D: CallableDescriptor> allCandidatesResult(allCandidates: Collection<MyCandidate<D>>)
|
||||
= OverloadResolutionResultsImpl.nameNotFound<D>().apply {
|
||||
this.allCandidates = allCandidates.map { it.resolvedCall }
|
||||
}
|
||||
|
||||
private fun createResolveProcessor(
|
||||
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(
|
||||
private fun <D : CallableDescriptor> createProcessorWithReceiverValueOrEmpty(
|
||||
explicitReceiver: Receiver?,
|
||||
create: (ReceiverValue?) -> ScopeTowerProcessor<Candidate>
|
||||
): ScopeTowerProcessor<Candidate> {
|
||||
create: (ReceiverValue?) -> ScopeTowerProcessor<MyCandidate<D>>
|
||||
): ScopeTowerProcessor<MyCandidate<D>> {
|
||||
return if (explicitReceiver is QualifierReceiver) {
|
||||
(explicitReceiver as? ClassQualifier)?.classValueReceiver?.let(create)
|
||||
?: KnownResultProcessor<Candidate>(listOf())
|
||||
?: KnownResultProcessor<MyCandidate<D>>(listOf())
|
||||
}
|
||||
else {
|
||||
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
|
||||
val simpleFunction = createFunctionProcessor(baseContext, explicitReceiver)
|
||||
|
||||
@@ -185,11 +232,11 @@ class NewResolveOldInference(
|
||||
}
|
||||
|
||||
|
||||
private fun convertToOverloadResults(
|
||||
candidates: Collection<Candidate>,
|
||||
private fun <D : CallableDescriptor> convertToOverloadResults(
|
||||
candidates: Collection<MyCandidate<D>>,
|
||||
tracing: TracingStrategy,
|
||||
basicCallContext: BasicCallResolutionContext
|
||||
): OverloadResolutionResultsImpl<*> {
|
||||
): OverloadResolutionResultsImpl<D> {
|
||||
val resolvedCalls = candidates.mapNotNull {
|
||||
val (status, resolvedCall) = it
|
||||
if (resolvedCall is VariableAsFunctionResolvedCallImpl) {
|
||||
@@ -224,23 +271,33 @@ class NewResolveOldInference(
|
||||
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 name: Name,
|
||||
private val basicCallContext: BasicCallResolutionContext,
|
||||
private val tracing: TracingStrategy
|
||||
) : TowerContext<Candidate> {
|
||||
|
||||
protected val basicCallContext: BasicCallResolutionContext,
|
||||
protected val tracing: TracingStrategy
|
||||
) : TowerContext<D, MyCandidate<D>> {
|
||||
override fun createCandidate(
|
||||
towerCandidate: CandidateWithBoundDispatchReceiver<*>,
|
||||
towerCandidate: CandidateWithBoundDispatchReceiver<D>,
|
||||
explicitReceiverKind: ExplicitReceiverKind,
|
||||
extensionReceiver: ReceiverValue?
|
||||
): Candidate {
|
||||
): MyCandidate<D> {
|
||||
val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate")
|
||||
val candidateCall = ResolvedCallImpl(
|
||||
basicCallContext.call, towerCandidate.descriptor,
|
||||
@@ -252,11 +309,11 @@ class NewResolveOldInference(
|
||||
// see spec-docs/dynamic-types.md
|
||||
if (extensionReceiver != null && extensionReceiver.type.isDynamic()
|
||||
&& !towerCandidate.descriptor.extensionReceiverParameter!!.value.type.isDynamic()) {
|
||||
return Candidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall)
|
||||
return MyCandidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall)
|
||||
}
|
||||
|
||||
if (towerCandidate.descriptor.isHiddenInResolution()) {
|
||||
return Candidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), candidateCall)
|
||||
return MyCandidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), candidateCall)
|
||||
}
|
||||
|
||||
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
|
||||
@@ -268,7 +325,7 @@ class NewResolveOldInference(
|
||||
val diagnostics = (towerCandidate.diagnostics +
|
||||
checkInfixAndOperator(basicCallContext.call, towerCandidate.descriptor) +
|
||||
createPreviousResolveError(candidateCall.status)).filterNotNull() // todo
|
||||
return Candidate(ResolutionCandidateStatus(diagnostics), candidateCall)
|
||||
return MyCandidate(ResolutionCandidateStatus(diagnostics), candidateCall)
|
||||
}
|
||||
|
||||
private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List<ResolutionDiagnostic> {
|
||||
@@ -282,38 +339,52 @@ class NewResolveOldInference(
|
||||
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(
|
||||
invoke.resolvedCall as MutableResolvedCall<FunctionDescriptor>,
|
||||
variable.resolvedCall as MutableResolvedCall<VariableDescriptor>
|
||||
invoke.resolvedCall,
|
||||
variable.resolvedCall
|
||||
)
|
||||
assert(variable.candidateStatus.resultingApplicability.isSuccess) {
|
||||
"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 {
|
||||
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()) {
|
||||
"Incorrect status: ${variable.resolvedCall.status} for variable call: ${variable.resolvedCall} " +
|
||||
"and descriptor: ${variable.resolvedCall.candidateDescriptor}"
|
||||
}
|
||||
val calleeExpression = variable.resolvedCall.call.calleeExpression
|
||||
val variableDescriptor = variable.resolvedCall.resultingDescriptor
|
||||
assert(variable.resolvedCall.status.possibleTransformToSuccess() && calleeExpression != null && variableDescriptor is VariableDescriptor) {
|
||||
"Unexpected varialbe candidate: $variable"
|
||||
assert(variable.resolvedCall.status.possibleTransformToSuccess() && calleeExpression != null) {
|
||||
"Unexpected variable candidate: $variable"
|
||||
}
|
||||
val variableType = (variableDescriptor as VariableDescriptor).type
|
||||
val variableType = variableDescriptor.type
|
||||
|
||||
if (variableType is DeferredType && variableType.isComputing) {
|
||||
return null // todo: create special check that there is no invoke on variable
|
||||
@@ -333,7 +404,7 @@ class NewResolveOldInference(
|
||||
.replaceContextDependency(ContextDependency.DEPENDENT) // todo
|
||||
|
||||
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
|
||||
}
|
||||
+38
-37
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||
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.createSynthesizedInvokes
|
||||
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 java.util.*
|
||||
|
||||
abstract class AbstractInvokeTowerProcessor<C>(
|
||||
protected val functionContext: TowerContext<C>,
|
||||
private val variableProcessor: ScopeTowerProcessor<C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
abstract class AbstractInvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
|
||||
protected val invokeContext: InvokeTowerContext<F, V>,
|
||||
private val variableProcessor: ScopeTowerProcessor<V>
|
||||
) : ScopeTowerProcessor<F> {
|
||||
// todo optimize it
|
||||
private val previousData = ArrayList<TowerData>()
|
||||
private val invokeProcessors: MutableList<Collection<VariableInvokeProcessor>> = ArrayList()
|
||||
|
||||
private inner class VariableInvokeProcessor(val variableCandidate: C): ScopeTowerProcessor<C> {
|
||||
val invokeProcessor: ScopeTowerProcessor<C> = createInvokeProcessor(variableCandidate)
|
||||
private inner class VariableInvokeProcessor(val variableCandidate: V): ScopeTowerProcessor<F> {
|
||||
val invokeProcessor: ScopeTowerProcessor<F> = createInvokeProcessor(variableCandidate)
|
||||
|
||||
override fun process(data: TowerData)
|
||||
= 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)
|
||||
|
||||
val candidateGroups = ArrayList<Collection<C>>(0)
|
||||
val candidateGroups = ArrayList<Collection<F>>(0)
|
||||
|
||||
for (processorsGroup in invokeProcessors) {
|
||||
candidateGroups.addAll(processorsGroup.processVariableGroup(data))
|
||||
@@ -55,7 +56,7 @@ abstract class AbstractInvokeTowerProcessor<C>(
|
||||
|
||||
for (variableCandidates in variableProcessor.process(data)) {
|
||||
val successfulVariables = variableCandidates.filter {
|
||||
functionContext.getStatus(it).resultingApplicability.isSuccess
|
||||
it.isSuccessful
|
||||
}
|
||||
|
||||
if (successfulVariables.isNotEmpty()) {
|
||||
@@ -71,7 +72,7 @@ abstract class AbstractInvokeTowerProcessor<C>(
|
||||
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) {
|
||||
0 -> emptyList()
|
||||
1 -> single().process(data)
|
||||
@@ -84,44 +85,44 @@ abstract class AbstractInvokeTowerProcessor<C>(
|
||||
}
|
||||
|
||||
// todo KT-9522 Allow invoke convention for synthetic property
|
||||
class InvokeTowerProcessor<C>(
|
||||
functionContext: TowerContext<C>,
|
||||
class InvokeTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
|
||||
invokeContext: InvokeTowerContext<F, V>,
|
||||
private val explicitReceiver: Receiver?
|
||||
) : AbstractInvokeTowerProcessor<C>(
|
||||
functionContext,
|
||||
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver)
|
||||
) : AbstractInvokeTowerProcessor<F, V>(
|
||||
invokeContext,
|
||||
createVariableProcessor(invokeContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver)
|
||||
) {
|
||||
|
||||
// todo filter by operator
|
||||
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
|
||||
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = false)
|
||||
override fun createInvokeProcessor(variableCandidate: V): ScopeTowerProcessor<F> {
|
||||
val (variableReceiver, invokeContext) = invokeContext.contextForInvoke(variableCandidate, useExplicitReceiver = false)
|
||||
?: return KnownResultProcessor(emptyList())
|
||||
return ExplicitReceiverScopeTowerProcessor(invokeContext, variableReceiver, ScopeTowerLevel::getFunctions)
|
||||
}
|
||||
}
|
||||
|
||||
class InvokeExtensionTowerProcessor<C>(
|
||||
functionContext: TowerContext<C>,
|
||||
class InvokeExtensionTowerProcessor<F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>>(
|
||||
invokeContext: InvokeTowerContext<F, V>,
|
||||
private val explicitReceiver: ReceiverValue?
|
||||
) : AbstractInvokeTowerProcessor<C>(
|
||||
functionContext,
|
||||
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null)
|
||||
) : AbstractInvokeTowerProcessor<F, V>(
|
||||
invokeContext,
|
||||
createVariableProcessor(invokeContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null)
|
||||
) {
|
||||
|
||||
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
|
||||
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = true)
|
||||
override fun createInvokeProcessor(variableCandidate: V): ScopeTowerProcessor<F> {
|
||||
val (variableReceiver, invokeContext) = invokeContext.contextForInvoke(variableCandidate, useExplicitReceiver = true)
|
||||
?: return KnownResultProcessor(emptyList())
|
||||
val invokeDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
|
||||
val invokeDescriptor = invokeContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
|
||||
?: return KnownResultProcessor(emptyList())
|
||||
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver)
|
||||
}
|
||||
}
|
||||
|
||||
private class InvokeExtensionScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
private class InvokeExtensionScopeTowerProcessor<C : Candidate<FunctionDescriptor>>(
|
||||
context: TowerContext<FunctionDescriptor, C>,
|
||||
private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>,
|
||||
private val explicitReceiver: ReceiverValue?
|
||||
) : AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
) : AbstractSimpleScopeTowerProcessor<FunctionDescriptor, C>(context) {
|
||||
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
if (explicitReceiver != null && data == TowerData.Empty) {
|
||||
@@ -150,23 +151,23 @@ private fun ScopeTower.getExtensionInvokeCandidateDescriptor(
|
||||
}
|
||||
|
||||
// case 1.(foo())() or (foo())()
|
||||
fun <C> createCallTowerProcessorForExplicitInvoke(
|
||||
contextForInvoke: TowerContext<C>,
|
||||
fun <F : Candidate<FunctionDescriptor>, V : Candidate<VariableDescriptor>> createCallTowerProcessorForExplicitInvoke(
|
||||
invokeContext: InvokeTowerContext<F, V>,
|
||||
expressionForInvoke: ReceiverValue,
|
||||
explicitReceiver: ReceiverValue?
|
||||
): ScopeTowerProcessor<C> {
|
||||
val invokeExtensionDescriptor = contextForInvoke.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
|
||||
): ScopeTowerProcessor<F> {
|
||||
val invokeExtensionDescriptor = invokeContext.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
|
||||
if (explicitReceiver != null) {
|
||||
if (invokeExtensionDescriptor == null) {
|
||||
// case 1.(foo())(), where foo() isn't extension function
|
||||
return KnownResultProcessor(emptyList())
|
||||
}
|
||||
else {
|
||||
return InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
|
||||
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
|
||||
}
|
||||
}
|
||||
else {
|
||||
val usualInvoke = ExplicitReceiverScopeTowerProcessor(contextForInvoke, expressionForInvoke, ScopeTowerLevel::getFunctions) // todo operator
|
||||
val usualInvoke = ExplicitReceiverScopeTowerProcessor(invokeContext, expressionForInvoke, ScopeTowerLevel::getFunctions) // todo operator
|
||||
|
||||
if (invokeExtensionDescriptor == null) {
|
||||
return usualInvoke
|
||||
@@ -174,7 +175,7 @@ fun <C> createCallTowerProcessorForExplicitInvoke(
|
||||
else {
|
||||
return CompositeScopeTowerProcessor(
|
||||
usualInvoke,
|
||||
InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = null)
|
||||
InvokeExtensionScopeTowerProcessor(invokeContext, invokeExtensionDescriptor, explicitReceiver = null)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+22
-19
@@ -16,6 +16,9 @@
|
||||
|
||||
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.resolve.calls.tasks.ExplicitReceiverKind
|
||||
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) }
|
||||
}
|
||||
|
||||
internal abstract class AbstractSimpleScopeTowerProcessor<C>(
|
||||
val context: TowerContext<C>
|
||||
internal abstract class AbstractSimpleScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
|
||||
val context: TowerContext<D, C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
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() })
|
||||
}
|
||||
|
||||
internal class ExplicitReceiverScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
internal class ExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
|
||||
context: TowerContext<D, C>,
|
||||
val explicitReceiver: ReceiverValue,
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
): AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
|
||||
): AbstractSimpleScopeTowerProcessor<D, C>(context) {
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
return when (data) {
|
||||
TowerData.Empty -> resolveAsMember()
|
||||
@@ -72,11 +75,11 @@ internal class ExplicitReceiverScopeTowerProcessor<C>(
|
||||
}
|
||||
}
|
||||
|
||||
private class QualifierScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
private class QualifierScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
|
||||
context: TowerContext<D, C>,
|
||||
val qualifier: QualifierReceiver,
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
): AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
|
||||
): AbstractSimpleScopeTowerProcessor<D, C>(context) {
|
||||
override fun simpleProcess(data: TowerData): Collection<C> {
|
||||
if (data != TowerData.Empty) return emptyList()
|
||||
|
||||
@@ -87,10 +90,10 @@ private class QualifierScopeTowerProcessor<C>(
|
||||
}
|
||||
}
|
||||
|
||||
private class NoExplicitReceiverScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
) : AbstractSimpleScopeTowerProcessor<C>(context) {
|
||||
private class NoExplicitReceiverScopeTowerProcessor<D : CallableDescriptor, C: Candidate<D>>(
|
||||
context: TowerContext<D, C>,
|
||||
val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
|
||||
) : AbstractSimpleScopeTowerProcessor<D, C>(context) {
|
||||
override fun simpleProcess(data: TowerData): Collection<C>
|
||||
= when(data) {
|
||||
is TowerData.TowerLevel -> {
|
||||
@@ -107,10 +110,10 @@ private class NoExplicitReceiverScopeTowerProcessor<C>(
|
||||
}
|
||||
}
|
||||
|
||||
private fun <C> createSimpleProcessor(
|
||||
context: TowerContext<C>,
|
||||
private fun <D : CallableDescriptor, C: Candidate<D>> createSimpleProcessor(
|
||||
context: TowerContext<D, C>,
|
||||
explicitReceiver: Receiver?,
|
||||
collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection<CandidateWithBoundDispatchReceiver<D>>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
if (explicitReceiver is ReceiverValue) {
|
||||
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)
|
||||
|
||||
fun <C> createFunctionProcessor(context: TowerContext<C>, explicitReceiver: Receiver?)
|
||||
fun <C : Candidate<FunctionDescriptor>> createFunctionProcessor(context: TowerContext<FunctionDescriptor, C>, explicitReceiver: Receiver?)
|
||||
= createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getFunctions)
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
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.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
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 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 scopeTower: ScopeTower
|
||||
|
||||
fun createCandidate(
|
||||
towerCandidate: CandidateWithBoundDispatchReceiver<*>,
|
||||
towerCandidate: CandidateWithBoundDispatchReceiver<D>,
|
||||
explicitReceiverKind: ExplicitReceiverKind,
|
||||
extensionReceiver: ReceiverValue?
|
||||
): 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
|
||||
// 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 {
|
||||
@@ -54,21 +67,24 @@ sealed class 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 in one groups have same priority, first group has highest priority.
|
||||
fun process(data: TowerData): List<Collection<C>>
|
||||
}
|
||||
|
||||
class TowerResolver {
|
||||
fun <C> runResolve(
|
||||
context: TowerContext<C>,
|
||||
fun <C: Candidate<*>> runResolve(
|
||||
scopeTower: ScopeTower,
|
||||
processor: ScopeTowerProcessor<C>,
|
||||
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>
|
||||
= context.scopeTower.run(processor, AllCandidatesCollector { context.getStatus(it) }, false)
|
||||
fun <C: Candidate<*>> collectAllCandidates(
|
||||
scopeTower: ScopeTower,
|
||||
processor: ScopeTowerProcessor<C>
|
||||
): Collection<C>
|
||||
= scopeTower.run(processor, AllCandidatesCollector { it.status }, false)
|
||||
|
||||
private fun ScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
|
||||
val result = ArrayList<ScopeTowerLevel>()
|
||||
|
||||
Reference in New Issue
Block a user