Refactoring: do not store reference expression in resolution task

Sometimes there is no reference for the call (like '{ ... } ()').
A fake reference can be created, but the case when an error is reported on it can't be easily supported.

There were two usages of this reference: tracing and receiver for invoke.
Tracing strategy is created beforehand. Receiver for invoke uses the callee expression (from variable call), not the reference.
This commit is contained in:
Svetlana Isakova
2014-02-03 14:22:13 +04:00
parent 446aed5cf1
commit 495d6326e5
6 changed files with 76 additions and 63 deletions
@@ -110,11 +110,12 @@ public class CallResolver {
else {
callableDescriptorCollectors.add(CallableDescriptorCollectors.VARIABLES);
}
TracingStrategy tracing = TracingStrategyImpl.create(nameExpression, context.call);
List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks =
TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks(context, referencedName, nameExpression,
callableDescriptorCollectors);
TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks(
context, referencedName, tracing, callableDescriptorCollectors);
return doResolveCallOrGetCachedResults(ResolutionResultsCache.PROPERTY_MEMBER_TYPE,
context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression);
context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, tracing);
}
@NotNull
@@ -135,24 +136,33 @@ public class CallResolver {
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
@NotNull BasicCallResolutionContext context,
@NotNull JetReferenceExpression functionReference,
@NotNull Name name) {
return resolveCallWithGivenName(context, functionReference, name, true);
@NotNull Name name
) {
TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
return resolveCallWithGivenName(context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
}
@NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveCallForInvoke(
@NotNull BasicCallResolutionContext context,
@NotNull TracingStrategy tracing
) {
List<CallableDescriptorCollector<? extends CallableDescriptor>> collectors = Collections
.<CallableDescriptorCollector<? extends CallableDescriptor>>singletonList(CallableDescriptorCollectors.FUNCTIONS);
return resolveCallWithGivenName(context, Name.identifier("invoke"), tracing, collectors);
}
@NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
@NotNull BasicCallResolutionContext context,
@NotNull JetReferenceExpression functionReference,
@NotNull Name name,
boolean allowVariableWithInvoke
@NotNull TracingStrategy tracing,
@NotNull List<CallableDescriptorCollector<? extends CallableDescriptor>> collectors
) {
List<CallableDescriptorCollector<? extends CallableDescriptor>> collectors =
allowVariableWithInvoke ? CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES :
Collections.<CallableDescriptorCollector<? extends CallableDescriptor>>singletonList(CallableDescriptorCollectors.FUNCTIONS);
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, functionReference, collectors);
TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, tracing, collectors);
return doResolveCallOrGetCachedResults(ResolutionResultsCache.FUNCTION_MEMBER_TYPE,
context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
}
@NotNull
@@ -200,7 +210,9 @@ public class CallResolver {
Name name = expression.getReferencedNameAsName();
prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
TracingStrategy tracing = TracingStrategyImpl.create(expression, context.call);
prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(
context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
@Override
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
@@ -248,7 +260,7 @@ public class CallResolver {
Collection<ResolutionCandidate<CallableDescriptor>> candidates =
TaskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(context.scope, constructors);
prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
context, functionReference, candidates, null);
context, candidates, TracingStrategyImpl.create(functionReference, context.call));
}
else {
context.trace.report(NOT_A_CLASS.on(calleeExpression));
@@ -296,7 +308,8 @@ public class CallResolver {
// so we wrap what we have into a fake reference and pass it on (unwrap on the other end)
functionReference = new JetFakeReference(calleeExpression);
prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(Collections.singleton(resolutionCandidate), functionReference, context));
prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(
Collections.singleton(resolutionCandidate), functionReference, context));
}
else {
// checkTypesWithNoCallee(trace, scope, call);
@@ -304,9 +317,10 @@ public class CallResolver {
}
}
TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
OverloadResolutionResultsImpl<FunctionDescriptor> results = doResolveCallOrGetCachedResults(
ResolutionResultsCache.FUNCTION_MEMBER_TYPE, context, prioritizedTasks,
CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
if (calleeExpression instanceof JetSimpleNameExpression) {
ExpressionTypingUtils.checkCapturingInClosure((JetSimpleNameExpression) calleeExpression, context.trace, context.scope);
}
@@ -315,8 +329,7 @@ public class CallResolver {
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
@NotNull Call call,
@Nullable TracingStrategy tracing,
@NotNull JetReferenceExpression reference,
@NotNull TracingStrategy tracing,
@NotNull ResolutionContext<?> context,
@NotNull ResolutionCandidate<CallableDescriptor> candidate,
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
@@ -326,9 +339,9 @@ public class CallResolver {
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
basicCallResolutionContext, reference, Collections.singleton(candidate), tracing);
basicCallResolutionContext, Collections.singleton(candidate), tracing);
return doResolveCallOrGetCachedResults(ResolutionResultsCache.FUNCTION_MEMBER_TYPE, basicCallResolutionContext, tasks,
CallTransformer.FUNCTION_CALL_TRANSFORMER, reference);
CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
}
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
@@ -336,10 +349,9 @@ public class CallResolver {
@NotNull BasicCallResolutionContext context,
@NotNull List<ResolutionTask<D, F>> prioritizedTasks,
@NotNull CallTransformer<D, F> callTransformer,
@NotNull JetReferenceExpression reference
@NotNull TracingStrategy tracing
) {
OverloadResolutionResultsImpl<F> results = null;
TracingStrategy tracing = prioritizedTasks.isEmpty() ? TracingStrategy.EMPTY : prioritizedTasks.iterator().next().tracing;
TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
CallKey callKey = CallResolverUtil.createCallKey(context);
if (callKey != null) {
@@ -353,7 +365,7 @@ public class CallResolver {
}
if (results == null) {
BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
results = doResolveCall(newContext, prioritizedTasks, callTransformer, reference);
results = doResolveCall(newContext, prioritizedTasks, callTransformer, tracing);
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
if (deltasTraceForTypeInference != null) {
deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
@@ -471,8 +483,8 @@ public class CallResolver {
@NotNull BasicCallResolutionContext context,
@NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
@NotNull CallTransformer<D, F> callTransformer,
@NotNull JetReferenceExpression reference) {
@NotNull TracingStrategy tracing
) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
@@ -490,7 +502,7 @@ public class CallResolver {
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
for (ResolutionTask<D, F> task : prioritizedTasks) {
TemporaryBindingTrace taskTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.reference);
TemporaryBindingTrace taskTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(
task.replaceBindingTrace(taskTrace), callTransformer);
if (results.isSuccess() || results.isAmbiguity()) {
@@ -521,7 +533,7 @@ public class CallResolver {
}
}
else {
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
tracing.unresolvedReference(context.trace);
argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
}
return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.<F>nameNotFound();
@@ -40,7 +40,6 @@ import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind;
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.JetType;
@@ -176,9 +175,11 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
@NotNull
@Override
public Collection<ResolvedCallWithTrace<FunctionDescriptor>> transformCall(@NotNull CallCandidateResolutionContext<CallableDescriptor> context,
@NotNull CallResolver callResolver, @NotNull ResolutionTask<CallableDescriptor, FunctionDescriptor> task) {
public Collection<ResolvedCallWithTrace<FunctionDescriptor>> transformCall(
@NotNull CallCandidateResolutionContext<CallableDescriptor> context,
@NotNull CallResolver callResolver,
@NotNull ResolutionTask<CallableDescriptor, FunctionDescriptor> task
) {
CallableDescriptor descriptor = context.candidateCall.getCandidateDescriptor();
if (descriptor instanceof FunctionDescriptor) {
return super.transformCall(context, callResolver, task);
@@ -192,7 +193,11 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
final ResolvedCallWithTrace<VariableDescriptor> variableResolvedCall = (ResolvedCallWithTrace)context.candidateCall;
Call functionCall = new CallForImplicitInvoke(context.explicitExtensionReceiverForInvoke, task, returnType);
JetExpression calleeExpression = task.call.getCalleeExpression();
if (calleeExpression == null) return Collections.emptyList();
ExpressionReceiver variableReceiver = new ExpressionReceiver(calleeExpression, variableResolvedCall.getResultingDescriptor().getType());
Call functionCall = new CallForImplicitInvoke(context.explicitExtensionReceiverForInvoke, variableReceiver, task.call);
DelegatingBindingTrace variableCallTrace = context.candidateCall.getTrace();
BasicCallResolutionContext basicCallResolutionContext = BasicCallResolutionContext.create(
@@ -200,8 +205,8 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
functionCall, context.checkArguments, context.dataFlowInfoForArguments);
// 'invoke' call resolve
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCallWithGivenName(
basicCallResolutionContext, task.reference, Name.identifier("invoke"), false);
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCallForInvoke(
basicCallResolutionContext, context.tracing); //todo context.tracing is incorrect
Collection<ResolvedCallWithTrace<FunctionDescriptor>> calls = ((OverloadResolutionResultsImpl<FunctionDescriptor>)results).getResultingCalls();
return Collections2.transform(calls, new Function<ResolvedCallWithTrace<FunctionDescriptor>, ResolvedCallWithTrace<FunctionDescriptor>>() {
@@ -219,14 +224,18 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
final ExpressionReceiver calleeExpressionAsThisObject;
final JetSimpleNameExpression fakeInvokeExpression;
private CallForImplicitInvoke(ReceiverValue explicitExtensionReceiver,
ResolutionTask<CallableDescriptor, FunctionDescriptor> task, JetType returnType) {
super(task.call);
this.outerCall = task.call;
private CallForImplicitInvoke(
@NotNull ReceiverValue explicitExtensionReceiver,
@NotNull ExpressionReceiver calleeExpressionAsThisObject,
@NotNull Call call
) {
super(call);
this.outerCall = call;
this.explicitExtensionReceiver = explicitExtensionReceiver;
this.calleeExpressionAsThisObject = new ExpressionReceiver(task.reference, returnType);
this.fakeInvokeExpression = (JetSimpleNameExpression) JetPsiFactory.createExpression(task.call.getCallElement().getProject(), "invoke");
this.calleeExpressionAsThisObject = calleeExpressionAsThisObject;
this.fakeInvokeExpression = (JetSimpleNameExpression) JetPsiFactory.createExpression(call.getCallElement().getProject(), "invoke");
}
@NotNull
@Override
public ReceiverValue getExplicitReceiver() {
@@ -42,11 +42,10 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
private final Collection<ResolutionCandidate<D>> candidates;
private final Set<ResolvedCallWithTrace<F>> resolvedCalls = Sets.newLinkedHashSet();
private DescriptorCheckStrategy checkingStrategy;
public final JetReferenceExpression reference;
public final TracingStrategy tracing;
public ResolutionTask(
@NotNull Collection<ResolutionCandidate<D>> candidates, @NotNull JetReferenceExpression reference,
@NotNull Collection<ResolutionCandidate<D>> candidates,
@NotNull TracingStrategy tracing, BindingTrace trace, JetScope scope, Call call, JetType expectedType,
DataFlowInfo dataFlowInfo, ContextDependency contextDependency, CheckValueArgumentsMode checkArguments,
ResolutionResultsCache resolutionResultsCache, @NotNull LabelResolver labelResolver,
@@ -56,17 +55,15 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
labelResolver, dataFlowInfoForArguments, callResolverExtension, isAnnotationContext);
this.candidates = candidates;
this.reference = reference;
this.tracing = tracing;
}
public ResolutionTask(
@NotNull Collection<ResolutionCandidate<D>> candidates,
@NotNull JetReferenceExpression reference,
@NotNull BasicCallResolutionContext context,
@Nullable TracingStrategy tracing
@NotNull TracingStrategy tracing
) {
this(candidates, reference, tracing != null ? tracing : TracingStrategyImpl.create(reference, context.call),
this(candidates, tracing,
context.trace, context.scope, context.call,
context.expectedType, context.dataFlowInfo, context.contextDependency, context.checkArguments,
context.resolutionResultsCache, context.labelResolver, context.dataFlowInfoForArguments,
@@ -78,7 +75,7 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
@NotNull JetReferenceExpression reference,
@NotNull BasicCallResolutionContext context
) {
this(candidates, reference, context, null);
this(candidates, context, TracingStrategyImpl.create(reference, context.call));
}
@NotNull
@@ -113,7 +110,7 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
@NotNull LabelResolver labelResolver
) {
ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(
candidates, reference, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
candidates, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
resolutionResultsCache, labelResolver, dataFlowInfoForArguments, callResolverExtension, isAnnotationContext);
newTask.setCheckingStrategy(checkingStrategy);
return newTask;
@@ -121,7 +118,7 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
public ResolutionTask<D, F> replaceCall(@NotNull Call newCall) {
return new ResolutionTask<D, F>(
candidates, reference, tracing, trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments,
candidates, tracing, trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments,
resolutionResultsCache, labelResolver, dataFlowInfoForArguments, callResolverExtension, isAnnotationContext);
}
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.calls.tasks;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
@@ -31,7 +30,6 @@ import java.util.Collection;
import java.util.List;
public class ResolutionTaskHolder<D extends CallableDescriptor, F extends D> {
private final JetReferenceExpression reference;
private final BasicCallResolutionContext basicCallResolutionContext;
private final PriorityProvider<ResolutionCandidate<D>> priorityProvider;
private final TracingStrategy tracing;
@@ -41,12 +39,11 @@ public class ResolutionTaskHolder<D extends CallableDescriptor, F extends D> {
private List<ResolutionTask<D, F>> tasks = null;
public ResolutionTaskHolder(@NotNull JetReferenceExpression reference,
public ResolutionTaskHolder(
@NotNull BasicCallResolutionContext basicCallResolutionContext,
@NotNull PriorityProvider<ResolutionCandidate<D>> priorityProvider,
@Nullable TracingStrategy tracing
@NotNull TracingStrategy tracing
) {
this.reference = reference;
this.basicCallResolutionContext = basicCallResolutionContext;
this.priorityProvider = priorityProvider;
this.tracing = tracing;
@@ -86,7 +83,7 @@ public class ResolutionTaskHolder<D extends CallableDescriptor, F extends D> {
}
});
if (!filteredCandidates.isEmpty()) {
tasks.add(new ResolutionTask<D, F>(filteredCandidates, reference, basicCallResolutionContext, tracing));
tasks.add(new ResolutionTask<D, F>(filteredCandidates, basicCallResolutionContext, tracing));
}
}
}
@@ -79,7 +79,7 @@ public class TaskPrioritizer {
public static <D extends CallableDescriptor, F extends D> List<ResolutionTask<D, F>> computePrioritizedTasks(
@NotNull BasicCallResolutionContext context,
@NotNull Name name,
@NotNull JetReferenceExpression functionReference,
@NotNull TracingStrategy tracing,
@NotNull List<CallableDescriptorCollector<? extends D>> callableDescriptorCollectors
) {
List<Pair<JetScope, ReceiverValue>> variants = new ArrayList<Pair<JetScope, ReceiverValue>>(2);
@@ -98,7 +98,7 @@ public class TaskPrioritizer {
}
ResolutionTaskHolder<D, F> result =
new ResolutionTaskHolder<D, F>(functionReference, context, new MyPriorityProvider<D>(context), null);
new ResolutionTaskHolder<D, F>(context, new MyPriorityProvider<D>(context), tracing);
for (Pair<JetScope, ReceiverValue> pair : variants) {
doComputeTasks(pair.second, new TaskPrioritizerContext<D, F>(name, result, context, pair.first, callableDescriptorCollectors));
}
@@ -332,12 +332,11 @@ public class TaskPrioritizer {
public static <D extends CallableDescriptor, F extends D> List<ResolutionTask<D, F>> computePrioritizedTasksFromCandidates(
@NotNull BasicCallResolutionContext context,
@NotNull JetReferenceExpression functionReference,
@NotNull Collection<ResolutionCandidate<D>> candidates,
@Nullable TracingStrategy tracing
@NotNull TracingStrategy tracing
) {
ResolutionTaskHolder<D, F> result = new ResolutionTaskHolder<D, F>(
functionReference, context, new MyPriorityProvider<D>(context), tracing);
context, new MyPriorityProvider<D>(context), tracing);
result.addCandidates(candidates);
return result.getTasks();
}
@@ -72,13 +72,11 @@ public class ControlStructureTypingUtils {
) {
SimpleFunctionDescriptorImpl function = createFunctionDescriptorForSpecialConstruction(
constructionName.toUpperCase(), argumentNames, isArgumentNullable);
JetReferenceExpression reference = JetPsiFactory.createSimpleName(
expressionTypingServices.getProject(), "fake" + constructionName + "Call");
TracingStrategy tracing = createTracingForSpecialConstruction(call, constructionName);
ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(function, null);
CallResolver callResolver = expressionTypingServices.getCallResolver();
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCallWithKnownCandidate(
call, tracing, reference, context, resolutionCandidate, dataFlowInfoForArguments);
call, tracing, context, resolutionCandidate, dataFlowInfoForArguments);
assert results.isSingleResult() : "Not single result after resolving one known candidate";
return results.getResultingCall();
}
@@ -242,6 +240,7 @@ public class ControlStructureTypingUtils {
};
}
@NotNull
/*package*/ static TracingStrategy createTracingForSpecialConstruction(
final @NotNull Call call,
final @NotNull String constructionName