Resolve dynamic.extensionForDynamic() statically

This commit is contained in:
Andrey Breslav
2014-11-24 18:00:20 +03:00
parent 8ee00b70ee
commit d5fdfcb797
12 changed files with 175 additions and 19 deletions
@@ -137,15 +137,24 @@ public class TaskPrioritizer {
}
private static <D extends CallableDescriptor, F extends D> void addCandidatesForExplicitReceiver(
@NotNull ReceiverValue explicitReceiver,
@NotNull Collection<ReceiverValue> implicitReceivers,
@NotNull TaskPrioritizerContext<D, F> c,
boolean isExplicit
) {
addMembers(explicitReceiver, c, /*static=*/false, isExplicit);
addCandidatesForDynamicReceiver(explicitReceiver, implicitReceivers, c, isExplicit);
addExtensionCandidates(explicitReceiver, implicitReceivers, c, isExplicit);
}
private static <D extends CallableDescriptor, F extends D> void addExtensionCandidates(
@NotNull final ReceiverValue explicitReceiver,
@NotNull Collection<ReceiverValue> implicitReceivers,
@NotNull final TaskPrioritizerContext<D, F> c,
final boolean isExplicit
) {
addMembers(explicitReceiver, c, /*static=*/false, isExplicit);
addCandidatesForDynamicReceiver(explicitReceiver, c);
for (final CallableDescriptorCollector<D> callableDescriptorCollector : c.callableDescriptorCollectors) {
//member extensions
for (ReceiverValue implicitReceiver : implicitReceivers) {
@@ -191,14 +200,21 @@ public class TaskPrioritizer {
}
private static <D extends CallableDescriptor, F extends D> void addCandidatesForDynamicReceiver(
@NotNull final ReceiverValue receiver,
@NotNull final TaskPrioritizerContext<D, F> c
@NotNull final ReceiverValue explicitReceiver,
@NotNull Collection<ReceiverValue> implicitReceivers,
@NotNull final TaskPrioritizerContext<D, F> c,
boolean isExplicit
) {
if (!TypesPackage.isDynamic(explicitReceiver.getType())) return;
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() {
if (!TypesPackage.isDynamic(receiver.getType())) return Collections.emptyList();
//noinspection unchecked
D dynamicDescriptor = (D) DynamicCallableDescriptors.createCallableDescriptorForDynamicCall(
@@ -211,7 +227,7 @@ public class TaskPrioritizer {
c.context.call,
dynamicDescriptor
);
dynamicCandidate.setDispatchReceiver(receiver);
dynamicCandidate.setDispatchReceiver(explicitReceiver);
dynamicCandidate.setExplicitReceiverKind(DISPATCH_RECEIVER);
return Collections.singletonList(dynamicCandidate);
@@ -473,5 +489,11 @@ public class TaskPrioritizer {
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);
}
}
}
@@ -39,6 +39,10 @@ import org.jetbrains.jet.lang.types.JetType
import kotlin.platform.platformStatic
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.jet.lang.types.isDynamic
import org.jetbrains.jet.lang.resolve.calls.tasks.collectors.CallableDescriptorCollector
import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.lang.resolve.BindingTrace
import org.jetbrains.jet.lang.resolve.calls.tasks.collectors.CallableDescriptorCollectors
object DynamicCallableDescriptors {
@@ -132,3 +136,14 @@ fun DeclarationDescriptor.isDynamic(): Boolean {
return dispatchReceiverParameter != null && dispatchReceiverParameter.getType().isDynamic()
}
class CollectorForDynamicReceivers<D: CallableDescriptor>(val delegate: CallableDescriptorCollector<D>) : CallableDescriptorCollector<D> by delegate {
override fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<D> {
return delegate.getExtensionsByName(scope, name, bindingTrace).filter {
it.getExtensionReceiverParameter()?.getType()?.isDynamic() ?: false
}
}
}
fun <D: CallableDescriptor> CallableDescriptorCollectors<D>.onlyDynamicReceivers(): CallableDescriptorCollectors<D> {
return CallableDescriptorCollectors(* this.map { CollectorForDynamicReceivers(it) }.copyToArray())
}