Convert TaskPrioritizer to kotlin.

This commit is contained in:
Stanislav Erokhin
2014-12-01 21:17:42 +03:00
parent f31ea8bd0e
commit 09250c89ed
3 changed files with 324 additions and 384 deletions
@@ -263,7 +263,7 @@ public class CallResolver {
return checkArgumentTypesAndFail(context); return checkArgumentTypesAndFail(context);
} }
Collection<ResolutionCandidate<CallableDescriptor>> candidates = Collection<ResolutionCandidate<CallableDescriptor>> candidates =
TaskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver( taskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(
context.scope, constructors, context.call); context.scope, constructors, context.call);
prioritizedTasks = taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates( prioritizedTasks = taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
context, candidates, TracingStrategyImpl.create(functionReference, context.call)); context, candidates, TracingStrategyImpl.create(functionReference, context.call));
@@ -38,7 +38,6 @@ import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowValue;
import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowValueFactory; import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils; import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils;
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask; import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer;
import org.jetbrains.jet.lang.resolve.calls.util.FakeCallableDescriptorForObject; import org.jetbrains.jet.lang.resolve.calls.util.FakeCallableDescriptorForObject;
import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil; import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
@@ -163,7 +162,7 @@ public class CandidateResolver {
// 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
// See TaskPrioritizer for more // See TaskPrioritizer for more
JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getExtensionReceiver()); JetSuperExpression superExpression = getReceiverSuper(candidateCall.getExtensionReceiver());
if (superExpression != null) { if (superExpression != null) {
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText())); context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
candidateCall.addStatus(OTHER_ERROR); candidateCall.addStatus(OTHER_ERROR);
@@ -205,6 +204,18 @@ public class CandidateResolver {
return DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, context.call.getCallElement(), candidateThis); return DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, context.call.getCallElement(), candidateThis);
} }
@Nullable
private static JetSuperExpression getReceiverSuper(@NotNull ReceiverValue receiver) {
if (receiver instanceof ExpressionReceiver) {
ExpressionReceiver expressionReceiver = (ExpressionReceiver) receiver;
JetExpression expression = expressionReceiver.getExpression();
if (expression instanceof JetSuperExpression) {
return (JetSuperExpression) expression;
}
}
return null;
}
@Nullable @Nullable
private static ClassDescriptor getDeclaringClass(@NotNull CallableDescriptor candidate) { private static ClassDescriptor getDeclaringClass(@NotNull CallableDescriptor candidate) {
ReceiverParameterDescriptor expectedThis = candidate.getDispatchReceiverParameter(); ReceiverParameterDescriptor expectedThis = candidate.getDispatchReceiverParameter();
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2013 JetBrains s.r.o. * Copyright 2010-2014 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -14,310 +14,270 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.jet.lang.resolve.calls.tasks; package org.jetbrains.jet.lang.resolve.calls.tasks
import com.google.common.collect.Lists; import com.google.common.collect.Lists
import com.google.common.collect.Sets; import com.google.common.collect.Sets
import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.progress.ProgressIndicatorProvider
import kotlin.Function0; import kotlin.Function0
import kotlin.Function1; import kotlin.Function1
import kotlin.KotlinPackage; import org.jetbrains.jet.lang.descriptors.*
import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.Call
import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetExpression
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.JetSuperExpression
import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils
import org.jetbrains.jet.lang.psi.JetSuperExpression; import org.jetbrains.jet.lang.resolve.calls.tasks.collectors.CallableDescriptorCollector
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.jet.lang.resolve.calls.tasks.collectors.CallableDescriptorCollectors
import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils; import org.jetbrains.jet.lang.resolve.name.Name
import org.jetbrains.jet.lang.resolve.calls.tasks.collectors.CallableDescriptorCollector; import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.lang.resolve.calls.tasks.collectors.CallableDescriptorCollectors; import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.QualifierReceiver
import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.types.ErrorUtils
import org.jetbrains.jet.lang.resolve.scopes.receivers.QualifierReceiver; import org.jetbrains.jet.lang.types.JetType
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.*
import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.checker.JetTypeChecker
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils
import org.jetbrains.jet.lang.types.TypesPackage; import org.jetbrains.jet.storage.StorageManager
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import org.jetbrains.jet.storage.StorageManager;
import java.util.ArrayList; import java.util.ArrayList
import java.util.Collection;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.isOrOverridesSynthesized; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.isOrOverridesSynthesized
import static org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind.*; import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind.*
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER
public class TaskPrioritizer { public class TaskPrioritizer(private val storageManager: StorageManager) {
@NotNull public fun <D : CallableDescriptor> splitLexicallyLocalDescriptors(
private final StorageManager storageManager; allDescriptors: Collection<ResolutionCandidate<D>>,
containerOfTheCurrentLocality: DeclarationDescriptor,
public TaskPrioritizer(@NotNull StorageManager manager) { local: MutableCollection<ResolutionCandidate<D>>,
storageManager = manager; nonlocal: MutableCollection<ResolutionCandidate<D>>
}
public static <D extends CallableDescriptor> void splitLexicallyLocalDescriptors(
@NotNull Collection<ResolutionCandidate<D>> allDescriptors,
@NotNull DeclarationDescriptor containerOfTheCurrentLocality,
@NotNull Collection<ResolutionCandidate<D>> local,
@NotNull Collection<ResolutionCandidate<D>> nonlocal
) { ) {
for (ResolutionCandidate<D> resolvedCall : allDescriptors) { for (resolvedCall in allDescriptors) {
if (ExpressionTypingUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) { if (ExpressionTypingUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) {
local.add(resolvedCall); local.add(resolvedCall)
} }
else { else {
nonlocal.add(resolvedCall); nonlocal.add(resolvedCall)
} }
} }
} }
@Nullable public fun <D : CallableDescriptor, F : D> computePrioritizedTasks(
public static JetSuperExpression getReceiverSuper(@NotNull ReceiverValue receiver) { context: BasicCallResolutionContext,
if (receiver instanceof ExpressionReceiver) { name: Name,
ExpressionReceiver expressionReceiver = (ExpressionReceiver) receiver; tracing: TracingStrategy,
JetExpression expression = expressionReceiver.getExpression(); callableDescriptorCollectors: CallableDescriptorCollectors<D>
if (expression instanceof JetSuperExpression) { ): List<ResolutionTask<D, F>> {
return (JetSuperExpression) expression; val explicitReceiver = context.call.getExplicitReceiver()
} val result = ResolutionTaskHolder<D, F>(storageManager, context, MyPriorityProvider<D>(context), tracing)
} val taskPrioritizerContext = TaskPrioritizerContext(name, result, context, context.scope, callableDescriptorCollectors)
return null;
}
@NotNull if (explicitReceiver is QualifierReceiver) {
public <D extends CallableDescriptor, F extends D> List<ResolutionTask<D, F>> computePrioritizedTasks( val qualifierReceiver = explicitReceiver : QualifierReceiver
@NotNull BasicCallResolutionContext context, doComputeTasks(NO_RECEIVER, taskPrioritizerContext.replaceScope(qualifierReceiver.getNestedClassesAndPackageMembersScope()))
@NotNull Name name, val classObjectReceiver = qualifierReceiver.getClassObjectReceiver()
@NotNull TracingStrategy tracing,
@NotNull CallableDescriptorCollectors<D> callableDescriptorCollectors
) {
ReceiverValue explicitReceiver = context.call.getExplicitReceiver();
ResolutionTaskHolder<D, F> result =
new ResolutionTaskHolder<D, F>(storageManager, context, new MyPriorityProvider<D>(context), tracing);
TaskPrioritizerContext<D, F> taskPrioritizerContext =
new TaskPrioritizerContext<D, F>(name, result, context, context.scope, callableDescriptorCollectors);
if (explicitReceiver instanceof QualifierReceiver) {
QualifierReceiver qualifierReceiver = (QualifierReceiver) explicitReceiver;
doComputeTasks(NO_RECEIVER, taskPrioritizerContext.replaceScope(qualifierReceiver.getNestedClassesAndPackageMembersScope()));
ReceiverValue classObjectReceiver = qualifierReceiver.getClassObjectReceiver();
if (classObjectReceiver.exists()) { if (classObjectReceiver.exists()) {
doComputeTasks(classObjectReceiver, taskPrioritizerContext); doComputeTasks(classObjectReceiver, taskPrioritizerContext)
} }
} }
else { else {
doComputeTasks(explicitReceiver, taskPrioritizerContext); doComputeTasks(explicitReceiver, taskPrioritizerContext)
} }
return result.getTasks(); return result.getTasks()
} }
private static <D extends CallableDescriptor, F extends D> void doComputeTasks( private fun <D : CallableDescriptor, F : D> doComputeTasks(receiver: ReceiverValue, c: TaskPrioritizerContext<D, F>) {
@NotNull ReceiverValue receiver, ProgressIndicatorProvider.checkCanceled()
@NotNull TaskPrioritizerContext<D, F> c
) {
ProgressIndicatorProvider.checkCanceled();
boolean resolveInvoke = c.context.call.getDispatchReceiver().exists(); val resolveInvoke = c.context.call.getDispatchReceiver().exists()
if (resolveInvoke) { if (resolveInvoke) {
addCandidatesForInvoke(receiver, c); addCandidatesForInvoke(receiver, c)
return; return
} }
Collection<ReceiverValue> implicitReceivers = Sets.newLinkedHashSet(JetScopeUtils.getImplicitReceiversHierarchyValues(c.scope)); val implicitReceivers = Sets.newLinkedHashSet<ReceiverValue>(JetScopeUtils.getImplicitReceiversHierarchyValues(c.scope))
if (receiver.exists()) { if (receiver.exists()) {
addCandidatesForExplicitReceiver(receiver, implicitReceivers, c, /*isExplicit=*/true); addCandidatesForExplicitReceiver(receiver, implicitReceivers, c, isExplicit = true)
addMembers(receiver, c, /*static=*/true, /*isExplicit=*/true); addMembers(receiver, c, staticMembers = true, isExplicit = true)
return; return
} }
addCandidatesForNoReceiver(implicitReceivers, c); addCandidatesForNoReceiver(implicitReceivers, c)
} }
private static <D extends CallableDescriptor, F extends D> void addCandidatesForExplicitReceiver( private fun <D : CallableDescriptor, F : D> addCandidatesForExplicitReceiver(
@NotNull ReceiverValue explicitReceiver, explicitReceiver: ReceiverValue,
@NotNull Collection<ReceiverValue> implicitReceivers, implicitReceivers: Collection<ReceiverValue>,
@NotNull TaskPrioritizerContext<D, F> c, c: TaskPrioritizerContext<D, F>,
boolean isExplicit isExplicit: Boolean
) { ) {
addMembers(explicitReceiver, c, /*static=*/false, isExplicit); addMembers(explicitReceiver, c, staticMembers = false, isExplicit = isExplicit)
if (TypesPackage.isDynamic(explicitReceiver.getType())) { if (explicitReceiver.getType().isDynamic()) {
addCandidatesForDynamicReceiver(explicitReceiver, implicitReceivers, c, isExplicit); addCandidatesForDynamicReceiver(explicitReceiver, implicitReceivers, c, isExplicit)
} }
else { else {
addExtensionCandidates(explicitReceiver, implicitReceivers, c, isExplicit); addExtensionCandidates(explicitReceiver, implicitReceivers, c, isExplicit)
} }
} }
private static <D extends CallableDescriptor, F extends D> void addExtensionCandidates( private fun <D : CallableDescriptor, F : D> addExtensionCandidates(
@NotNull final ReceiverValue explicitReceiver, explicitReceiver: ReceiverValue,
@NotNull Collection<ReceiverValue> implicitReceivers, implicitReceivers: Collection<ReceiverValue>,
@NotNull final TaskPrioritizerContext<D, F> c, c: TaskPrioritizerContext<D, F>,
final boolean isExplicit isExplicit: Boolean
) { ) {
for (final CallableDescriptorCollector<D> callableDescriptorCollector : c.callableDescriptorCollectors) { for (callableDescriptorCollector in c.callableDescriptorCollectors) {
//member extensions //member extensions
for (ReceiverValue implicitReceiver : implicitReceivers) { for (implicitReceiver in implicitReceivers) {
addMemberExtensionCandidates(implicitReceiver, explicitReceiver, addMemberExtensionCandidates(
callableDescriptorCollector, c, createKind(EXTENSION_RECEIVER, isExplicit)); implicitReceiver,
explicitReceiver,
callableDescriptorCollector,
c,
createKind(EXTENSION_RECEIVER, isExplicit)
)
} }
//extensions //extensions
c.result.addCandidates(new Function0<Collection<? extends ResolutionCandidate<D>>>() { c.result.addCandidates {
@Override convertWithImpliedThis(
public Collection<? extends ResolutionCandidate<D>> invoke() { c.scope,
return convertWithImpliedThis( explicitReceiver,
c.scope, explicitReceiver, callableDescriptorCollector.getExtensionsByName(c.scope, c.name, c.context.trace), callableDescriptorCollector.getExtensionsByName(c.scope, c.name, c.context.trace),
createKind(EXTENSION_RECEIVER, isExplicit), c.context.call); createKind(EXTENSION_RECEIVER, isExplicit),
} c.context.call
}); )
}
}
private static <D extends CallableDescriptor, F extends D> void addMembers(
final ReceiverValue explicitReceiver,
final TaskPrioritizerContext<D, F> c,
final boolean staticMembers,
final boolean isExplicit
) {
for (final CallableDescriptorCollector<D> callableDescriptorCollector : c.callableDescriptorCollectors) {
c.result.addCandidates(new Function0<Collection<? extends ResolutionCandidate<D>>>() {
@Override
public Collection<? extends ResolutionCandidate<D>> invoke() {
List<JetType> variantsForExplicitReceiver = SmartCastUtils.getSmartCastVariants(explicitReceiver, c.context);
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
for (JetType type : variantsForExplicitReceiver) {
Collection<D> membersForThisVariant =
staticMembers
? callableDescriptorCollector.getStaticMembersByName(type, c.name, c.context.trace)
: callableDescriptorCollector.getMembersByName(type, c.name, c.context.trace);
convertWithReceivers(membersForThisVariant, explicitReceiver,
NO_RECEIVER, members, createKind(DISPATCH_RECEIVER, isExplicit), c.context.call);
}
return members;
}
});
}
}
private static <D extends CallableDescriptor, F extends D> void addCandidatesForDynamicReceiver(
@NotNull final ReceiverValue explicitReceiver,
@NotNull Collection<ReceiverValue> implicitReceivers,
@NotNull final TaskPrioritizerContext<D, F> c,
boolean isExplicit
) {
TaskPrioritizerContext<D, F> onlyDynamicReceivers = c.replaceCollectors(TasksPackage.onlyDynamicReceivers(c.callableDescriptorCollectors));
addExtensionCandidates(explicitReceiver, implicitReceivers, onlyDynamicReceivers, isExplicit);
c.result.addCandidates(
new Function0<Collection<? extends ResolutionCandidate<D>>>() {
@Override
public Collection<? extends ResolutionCandidate<D>> invoke() {
JetScope dynamicScope = DynamicCallableDescriptors.createDynamicDescriptorScope(
c.context.call,
c.scope.getContainingDeclaration()
);
Collection<D> dynamicDescriptors = new ArrayList<D>();
for (CallableDescriptorCollector<D> collector : c.callableDescriptorCollectors) {
dynamicDescriptors.addAll(collector.getNonExtensionsByName(dynamicScope, c.name, c.context.trace));
}
return KotlinPackage.map(
dynamicDescriptors,
new Function1<D, ResolutionCandidate<D>>() {
@Override
public ResolutionCandidate<D> invoke(D dynamicDescriptor) {
ResolutionCandidate<D> dynamicCandidate = ResolutionCandidate.create(
c.context.call,
dynamicDescriptor
);
dynamicCandidate.setDispatchReceiver(explicitReceiver);
dynamicCandidate.setExplicitReceiverKind(DISPATCH_RECEIVER);
return dynamicCandidate;
}
}
);
}
}
);
}
private static ExplicitReceiverKind createKind(ExplicitReceiverKind kind, boolean isExplicit) {
if (isExplicit) return kind;
return ExplicitReceiverKind.NO_EXPLICIT_RECEIVER;
}
private static <D extends CallableDescriptor, F extends D> void addMemberExtensionCandidates(
@NotNull final ReceiverValue dispatchReceiver,
@NotNull final ReceiverValue receiverParameter,
@NotNull final CallableDescriptorCollector<D> callableDescriptorCollector,
@NotNull final TaskPrioritizerContext<D, F> c,
@NotNull final ExplicitReceiverKind receiverKind
) {
c.result.addCandidates(new Function0<Collection<? extends ResolutionCandidate<D>>>() {
@Override
public Collection<? extends ResolutionCandidate<D>> invoke() {
Collection<D> memberExtensions = callableDescriptorCollector.getExtensionsByName(
dispatchReceiver.getType().getMemberScope(), c.name, c.context.trace);
return convertWithReceivers(
memberExtensions, dispatchReceiver, receiverParameter, receiverKind, c.context.call);
} }
}); }
} }
private static <D extends CallableDescriptor, F extends D> void addCandidatesForNoReceiver( private fun <D : CallableDescriptor, F : D> addMembers(
@NotNull Collection<ReceiverValue> implicitReceivers, explicitReceiver: ReceiverValue,
@NotNull TaskPrioritizerContext<D, F> c c: TaskPrioritizerContext<D, F>,
staticMembers: Boolean,
isExplicit: Boolean
) { ) {
List<Collection<ResolutionCandidate<D>>> localsList = Lists.newArrayList(); for (callableDescriptorCollector in c.callableDescriptorCollectors) {
List<Collection<ResolutionCandidate<D>>> nonlocalsList = Lists.newArrayList(); c.result.addCandidates {
for (CallableDescriptorCollector<D> callableDescriptorCollector : c.callableDescriptorCollectors) { val variantsForExplicitReceiver = SmartCastUtils.getSmartCastVariants(explicitReceiver, c.context as ResolutionContext<*>) //workaround KT-1969
val members = Lists.newArrayList<ResolutionCandidate<D>>()
for (type in variantsForExplicitReceiver) {
val membersForThisVariant = if (staticMembers) {
callableDescriptorCollector.getStaticMembersByName(type, c.name, c.context.trace)
}
else {
callableDescriptorCollector.getMembersByName(type, c.name, c.context.trace)
}
convertWithReceivers(
membersForThisVariant,
explicitReceiver,
NO_RECEIVER,
members,
createKind(DISPATCH_RECEIVER, isExplicit),
c.context.call
)
}
members
}
}
}
Collection<ResolutionCandidate<D>> members = convertWithImpliedThisAndNoReceiver( private fun <D : CallableDescriptor, F : D> addCandidatesForDynamicReceiver(
c.scope, callableDescriptorCollector.getNonExtensionsByName(c.scope, c.name, c.context.trace), c.context.call); explicitReceiver: ReceiverValue,
implicitReceivers: Collection<ReceiverValue>,
c: TaskPrioritizerContext<D, F>,
isExplicit: Boolean
) {
val onlyDynamicReceivers = c.replaceCollectors(c.callableDescriptorCollectors.onlyDynamicReceivers<D>())
addExtensionCandidates(explicitReceiver, implicitReceivers, onlyDynamicReceivers, isExplicit)
List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList(); c.result.addCandidates {
List<ResolutionCandidate<D>> locals = Lists.newArrayList(); val dynamicScope = DynamicCallableDescriptors.createDynamicDescriptorScope(c.context.call, c.scope.getContainingDeclaration())
val dynamicDescriptors = ArrayList<D>()
for (collector in c.callableDescriptorCollectors) {
dynamicDescriptors.addAll(collector.getNonExtensionsByName(dynamicScope, c.name, c.context.trace))
}
dynamicDescriptors.map {
val dynamicCandidate = ResolutionCandidate.create<D>(c.context.call, it)
dynamicCandidate.setDispatchReceiver(explicitReceiver)
dynamicCandidate.setExplicitReceiverKind(DISPATCH_RECEIVER)
dynamicCandidate
}
}
}
private fun createKind(kind: ExplicitReceiverKind, isExplicit: Boolean): ExplicitReceiverKind {
if (isExplicit) return kind
return ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
}
private fun <D : CallableDescriptor, F : D> addMemberExtensionCandidates(
dispatchReceiver: ReceiverValue,
receiverParameter: ReceiverValue,
callableDescriptorCollector: CallableDescriptorCollector<D>,
c: TaskPrioritizerContext<D, F>,
receiverKind: ExplicitReceiverKind
) {
c.result.addCandidates {
val memberExtensions =
callableDescriptorCollector.getExtensionsByName(dispatchReceiver.getType().getMemberScope(), c.name, c.context.trace)
convertWithReceivers(memberExtensions, dispatchReceiver, receiverParameter, receiverKind, c.context.call)
}
}
private fun <D : CallableDescriptor, F : D> addCandidatesForNoReceiver(
implicitReceivers: Collection<ReceiverValue>,
c: TaskPrioritizerContext<D, F>
) {
val localsList = Lists.newArrayList<Collection<ResolutionCandidate<D>>>()
val nonlocalsList = Lists.newArrayList<Collection<ResolutionCandidate<D>>>()
for (callableDescriptorCollector in c.callableDescriptorCollectors) {
val members = convertWithImpliedThisAndNoReceiver(
c.scope,
callableDescriptorCollector.getNonExtensionsByName(c.scope, c.name, c.context.trace),
c.context.call
)
val nonlocals = Lists.newArrayList<ResolutionCandidate<D>>()
val locals = Lists.newArrayList<ResolutionCandidate<D>>()
//noinspection unchecked,RedundantTypeArguments //noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(members, c.scope.getContainingDeclaration(), locals, nonlocals); splitLexicallyLocalDescriptors(members, c.scope.getContainingDeclaration(), locals, nonlocals)
localsList.add(locals); localsList.add(locals)
nonlocalsList.add(nonlocals); nonlocalsList.add(nonlocals)
} }
//locals //locals
c.result.addCandidates(localsList); c.result.addCandidates(localsList)
//try all implicit receivers as explicit //try all implicit receivers as explicit
for (ReceiverValue implicitReceiver : implicitReceivers) { for (implicitReceiver in implicitReceivers) {
addCandidatesForExplicitReceiver(implicitReceiver, implicitReceivers, c, /*isExplicit=*/false); addCandidatesForExplicitReceiver(implicitReceiver, implicitReceivers, c, isExplicit = false)
} }
//nonlocals //nonlocals
c.result.addCandidates(nonlocalsList); c.result.addCandidates(nonlocalsList)
//static (only for better error reporting) //static (only for better error reporting)
for (ReceiverValue implicitReceiver : implicitReceivers) { for (implicitReceiver in implicitReceivers) {
addMembers(implicitReceiver, c, /*static=*/true, /*isExplicit=*/false); addMembers(implicitReceiver, c, staticMembers = true, isExplicit = false)
} }
} }
private static <D extends CallableDescriptor, F extends D> void addCandidatesForInvoke( private fun <D : CallableDescriptor, F : D> addCandidatesForInvoke(explicitReceiver: ReceiverValue, c: TaskPrioritizerContext<D, F>) {
@NotNull ReceiverValue explicitReceiver, val implicitReceivers = JetScopeUtils.getImplicitReceiversHierarchyValues(c.scope)
@NotNull TaskPrioritizerContext<D, F> c
) {
List<ReceiverValue> implicitReceivers = JetScopeUtils.getImplicitReceiversHierarchyValues(c.scope);
// For 'a.foo()' where foo has function type, // For 'a.foo()' where foo has function type,
// a is explicitReceiver, foo is variableReceiver. // a is explicitReceiver, foo is variableReceiver.
ReceiverValue variableReceiver = c.context.call.getDispatchReceiver(); val variableReceiver = c.context.call.getDispatchReceiver()
assert variableReceiver.exists() : "'Invoke' call hasn't got variable receiver"; assert(variableReceiver.exists(), "'Invoke' call hasn't got variable receiver")
// For invocation a.foo() explicit receiver 'a' // For invocation a.foo() explicit receiver 'a'
// can be a receiver for 'foo' variable // can be a receiver for 'foo' variable
@@ -325,7 +285,7 @@ public class TaskPrioritizer {
// (1) a.foo + foo.invoke() // (1) a.foo + foo.invoke()
if (!explicitReceiver.exists()) { if (!explicitReceiver.exists()) {
addCandidatesForExplicitReceiver(variableReceiver, implicitReceivers, c, /*isExplicit=*/true); addCandidatesForExplicitReceiver(variableReceiver, implicitReceivers, c, isExplicit = true)
} }
// (2) foo + a.invoke() // (2) foo + a.invoke()
@@ -336,176 +296,145 @@ public class TaskPrioritizer {
if (explicitReceiver.exists()) { if (explicitReceiver.exists()) {
//a.foo() //a.foo()
addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(variableReceiver, explicitReceiver, c, BOTH_RECEIVERS); addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(variableReceiver, explicitReceiver, c, BOTH_RECEIVERS)
return; return
} }
// with (a) { foo() } // with (a) { foo() }
for (ReceiverValue implicitReceiver : implicitReceivers) { for (implicitReceiver in implicitReceivers) {
addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(variableReceiver, implicitReceiver, c, DISPATCH_RECEIVER); addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(variableReceiver, implicitReceiver, c, DISPATCH_RECEIVER)
} }
} }
private static <D extends CallableDescriptor, F extends D> void addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver( private fun <D : CallableDescriptor, F : D> addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(
@NotNull ReceiverValue dispatchReceiver, dispatchReceiver: ReceiverValue,
@NotNull ReceiverValue receiverParameter, receiverParameter: ReceiverValue,
@NotNull TaskPrioritizerContext<D, F> c, c: TaskPrioritizerContext<D, F>,
@NotNull ExplicitReceiverKind receiverKind receiverKind: ExplicitReceiverKind
) { ) {
for (CallableDescriptorCollector<D> callableDescriptorCollector : c.callableDescriptorCollectors) { for (callableDescriptorCollector in c.callableDescriptorCollectors) {
addMemberExtensionCandidates(dispatchReceiver, receiverParameter, callableDescriptorCollector, c, receiverKind); addMemberExtensionCandidates(dispatchReceiver, receiverParameter, callableDescriptorCollector, c, receiverKind)
} }
} }
private static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithReceivers( private fun <D : CallableDescriptor> convertWithReceivers(
@NotNull Collection<D> descriptors, descriptors: Collection<D>,
@NotNull ReceiverValue dispatchReceiver, dispatchReceiver: ReceiverValue,
@NotNull ReceiverValue extensionReceiver, extensionReceiver: ReceiverValue,
@NotNull ExplicitReceiverKind explicitReceiverKind, explicitReceiverKind: ExplicitReceiverKind,
@NotNull Call call call: Call
) { ): Collection<ResolutionCandidate<D>> {
Collection<ResolutionCandidate<D>> result = Lists.newArrayList(); val result = Lists.newArrayList<ResolutionCandidate<D>>()
convertWithReceivers(descriptors, dispatchReceiver, extensionReceiver, result, explicitReceiverKind, call); convertWithReceivers(descriptors, dispatchReceiver, extensionReceiver, result, explicitReceiverKind, call)
return result; return result
} }
private static <D extends CallableDescriptor> void convertWithReceivers( private fun <D : CallableDescriptor> convertWithReceivers(
@NotNull Collection<D> descriptors, descriptors: Collection<D>,
@NotNull ReceiverValue dispatchReceiver, dispatchReceiver: ReceiverValue,
@NotNull ReceiverValue extensionReceiver, extensionReceiver: ReceiverValue,
@NotNull Collection<ResolutionCandidate<D>> result, result: MutableCollection<ResolutionCandidate<D>>,
@NotNull ExplicitReceiverKind explicitReceiverKind, explicitReceiverKind: ExplicitReceiverKind,
@NotNull Call call call: Call
) { ) {
for (D descriptor : descriptors) { for (descriptor in descriptors) {
ResolutionCandidate<D> candidate = ResolutionCandidate.create(call, descriptor); val candidate = ResolutionCandidate.create<D>(call, descriptor)
candidate.setDispatchReceiver(dispatchReceiver); candidate.setDispatchReceiver(dispatchReceiver)
candidate.setExtensionReceiver(extensionReceiver); candidate.setExtensionReceiver(extensionReceiver)
candidate.setExplicitReceiverKind(explicitReceiverKind); candidate.setExplicitReceiverKind(explicitReceiverKind)
result.add(candidate); result.add(candidate)
} }
} }
public static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithImpliedThisAndNoReceiver( public fun <D : CallableDescriptor> convertWithImpliedThisAndNoReceiver(
@NotNull JetScope scope, scope: JetScope,
@NotNull Collection<? extends D> descriptors, descriptors: Collection<D>,
@NotNull Call call call: Call
) { ): Collection<ResolutionCandidate<D>> {
return convertWithImpliedThis(scope, NO_RECEIVER, descriptors, NO_EXPLICIT_RECEIVER, call); return convertWithImpliedThis(scope, NO_RECEIVER, descriptors, NO_EXPLICIT_RECEIVER, call)
} }
public static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithImpliedThis( public fun <D : CallableDescriptor> convertWithImpliedThis(
@NotNull JetScope scope, scope: JetScope,
@NotNull ReceiverValue receiverParameter, receiverParameter: ReceiverValue,
@NotNull Collection<? extends D> descriptors, descriptors: Collection<D>,
@NotNull ExplicitReceiverKind receiverKind, receiverKind: ExplicitReceiverKind,
@NotNull Call call call: Call
) { ): Collection<ResolutionCandidate<D>> {
Collection<ResolutionCandidate<D>> result = Lists.newArrayList(); val result = Lists.newArrayList<ResolutionCandidate<D>>()
for (D descriptor : descriptors) { for (descriptor in descriptors) {
ResolutionCandidate<D> candidate = ResolutionCandidate.create(call, descriptor); val candidate = ResolutionCandidate.create<D>(call, descriptor)
candidate.setExtensionReceiver(receiverParameter); candidate.setExtensionReceiver(receiverParameter)
candidate.setExplicitReceiverKind(receiverKind); candidate.setExplicitReceiverKind(receiverKind)
if (setImpliedThis(scope, candidate)) { if (setImpliedThis(scope, candidate)) {
result.add(candidate); result.add(candidate)
} }
} }
return result; return result
} }
private static <D extends CallableDescriptor> boolean setImpliedThis( private fun <D : CallableDescriptor> setImpliedThis(
@NotNull JetScope scope, scope: JetScope,
@NotNull ResolutionCandidate<D> candidate candidate: ResolutionCandidate<D>
) { ): Boolean {
ReceiverParameterDescriptor dispatchReceiver = candidate.getDescriptor().getDispatchReceiverParameter(); val dispatchReceiver = candidate.getDescriptor().getDispatchReceiverParameter()
if (dispatchReceiver == null) return true; if (dispatchReceiver == null) return true
List<ReceiverParameterDescriptor> receivers = scope.getImplicitReceiversHierarchy(); val receivers = scope.getImplicitReceiversHierarchy()
for (ReceiverParameterDescriptor receiver : receivers) { for (receiver in receivers) {
if (JetTypeChecker.DEFAULT.isSubtypeOf(receiver.getType(), dispatchReceiver.getType())) { if (JetTypeChecker.DEFAULT.isSubtypeOf(receiver.getType(), dispatchReceiver.getType())) {
// TODO : Smartcasts & nullability // TODO : Smartcasts & nullability
candidate.setDispatchReceiver(dispatchReceiver.getValue()); candidate.setDispatchReceiver(dispatchReceiver.getValue())
return true; return true
} }
} }
return false; return false
} }
public <D extends CallableDescriptor, F extends D> List<ResolutionTask<D, F>> computePrioritizedTasksFromCandidates( public fun <D : CallableDescriptor, F : D> computePrioritizedTasksFromCandidates(
@NotNull BasicCallResolutionContext context, context: BasicCallResolutionContext,
@NotNull final Collection<ResolutionCandidate<D>> candidates, candidates: Collection<ResolutionCandidate<D>>,
@NotNull TracingStrategy tracing tracing: TracingStrategy
): List<ResolutionTask<D, F>> {
val result = ResolutionTaskHolder<D, F>(storageManager, context, MyPriorityProvider<D>(context), tracing)
result.addCandidates {
candidates
}
return result.getTasks()
}
private class MyPriorityProvider<D : CallableDescriptor>(private val context: BasicCallResolutionContext) :
ResolutionTaskHolder.PriorityProvider<ResolutionCandidate<D>> {
override fun getPriority(candidate: ResolutionCandidate<D>)
= (if (isVisible(candidate)) 2 else 0) + (if (isSynthesized(candidate)) 0 else 1)
override fun getMaxPriority() = 3
private fun isVisible(call: ResolutionCandidate<D>?): Boolean {
if (call == null) return false
val candidateDescriptor = call.getDescriptor()
if (ErrorUtils.isError(candidateDescriptor)) return true
return Visibilities.isVisible(candidateDescriptor, context.scope.getContainingDeclaration())
}
private fun isSynthesized(call: ResolutionCandidate<D>): Boolean {
val descriptor = call.getDescriptor()
return descriptor is CallableMemberDescriptor && isOrOverridesSynthesized(descriptor : CallableMemberDescriptor)
}
}
private class TaskPrioritizerContext<D : CallableDescriptor, F : D>(
val name: Name,
val result: ResolutionTaskHolder<D, F>,
val context: BasicCallResolutionContext,
val scope: JetScope,
val callableDescriptorCollectors: CallableDescriptorCollectors<D>
) { ) {
ResolutionTaskHolder<D, F> result = new ResolutionTaskHolder<D, F>( fun replaceScope(newScope: JetScope): TaskPrioritizerContext<D, F> {
storageManager, context, new MyPriorityProvider<D>(context), tracing); return TaskPrioritizerContext(name, result, context, newScope, callableDescriptorCollectors)
result.addCandidates(new Function0<Collection<? extends ResolutionCandidate<D>>>() {
@Override
public Collection<? extends ResolutionCandidate<D>> invoke() {
return candidates;
}
});
return result.getTasks();
}
private static class MyPriorityProvider<D extends CallableDescriptor>
implements ResolutionTaskHolder.PriorityProvider<ResolutionCandidate<D>> {
private final BasicCallResolutionContext context;
public MyPriorityProvider(BasicCallResolutionContext context) {
this.context = context;
} }
@Override fun replaceCollectors(newCollectors: CallableDescriptorCollectors<D>): TaskPrioritizerContext<D, F> {
public int getPriority(ResolutionCandidate<D> call) { return TaskPrioritizerContext(name, result, context, scope, newCollectors)
return (isVisible(call) ? 2 : 0) + (isSynthesized(call) ? 0 : 1);
} }
@Override
public int getMaxPriority() {
return 3;
}
private boolean isVisible(ResolutionCandidate<D> call) {
if (call == null) return false;
D candidateDescriptor = call.getDescriptor();
if (ErrorUtils.isError(candidateDescriptor)) return true;
return Visibilities.isVisible(candidateDescriptor, context.scope.getContainingDeclaration());
}
private boolean isSynthesized(ResolutionCandidate<D> call) {
D descriptor = call.getDescriptor();
return descriptor instanceof CallableMemberDescriptor &&
isOrOverridesSynthesized((CallableMemberDescriptor) descriptor);
}
}
private static class TaskPrioritizerContext<D extends CallableDescriptor, F extends D> {
@NotNull public final Name name;
@NotNull public final ResolutionTaskHolder<D, F> result;
@NotNull public final BasicCallResolutionContext context;
@NotNull public final JetScope scope;
@NotNull public final CallableDescriptorCollectors<D> callableDescriptorCollectors;
private TaskPrioritizerContext(
@NotNull Name name,
@NotNull ResolutionTaskHolder<D, F> result,
@NotNull BasicCallResolutionContext context,
@NotNull JetScope scope,
@NotNull CallableDescriptorCollectors<D> callableDescriptorCollectors
) {
this.name = name;
this.result = result;
this.context = context;
this.scope = scope;
this.callableDescriptorCollectors = callableDescriptorCollectors;
}
private TaskPrioritizerContext<D, F> replaceScope(JetScope newScope) {
return new TaskPrioritizerContext<D, F>(name, result, context, newScope, callableDescriptorCollectors);
}
private TaskPrioritizerContext<D, F> replaceCollectors(CallableDescriptorCollectors<D> newCollectors) {
return new TaskPrioritizerContext<D, F>(name, result, context, scope, newCollectors);
}
} }
} }