correspondence between CallableDescriptorCollector and CallTransformer (special treatment only for function invocations)

This commit is contained in:
Svetlana Isakova
2012-04-30 15:32:14 +04:00
parent 2fa8fd50fc
commit 24082a67d7
3 changed files with 80 additions and 76 deletions
@@ -102,16 +102,16 @@ public class CallResolver {
if (referencedName == null) { if (referencedName == null) {
return OverloadResolutionResultsImpl.nameNotFound(); return OverloadResolutionResultsImpl.nameNotFound();
} }
List<MemberPrioritizer<VariableDescriptor>> memberPrioritizers = Lists.newArrayList(); List<CallableDescriptorCollector<? extends VariableDescriptor>> callableDescriptorCollectors = Lists.newArrayList();
if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
referencedName = referencedName.substring(1); referencedName = referencedName.substring(1);
memberPrioritizers.add(MemberPrioritizers.PROPERTY_TASK_PRIORITIZER); callableDescriptorCollectors.add(CallableDescriptorCollectors.PROPERTIES);
} }
else { else {
memberPrioritizers.add(MemberPrioritizers.VARIABLE_TASK_PRIORITIZER); callableDescriptorCollectors.add(CallableDescriptorCollectors.VARIABLES);
} }
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, referencedName, nameExpression, memberPrioritizers); List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, referencedName, nameExpression, callableDescriptorCollectors);
return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.PROPERTY_CALL_TRANSFORMATION_STRATEGY, nameExpression); return doResolveCall(context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression);
} }
@NotNull @NotNull
@@ -119,9 +119,8 @@ public class CallResolver {
@NotNull BasicResolutionContext context, @NotNull BasicResolutionContext context,
@NotNull final JetReferenceExpression functionReference, @NotNull final JetReferenceExpression functionReference,
@NotNull String name) { @NotNull String name) {
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizer.computePrioritizedTasks( List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER)); return doResolveCall(context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
return doResolveCall(context, tasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference);
} }
@NotNull @NotNull
@@ -131,7 +130,7 @@ public class CallResolver {
@NotNull @NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicResolutionContext context) { public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicResolutionContext context) {
List<ResolutionTask<FunctionDescriptor>> prioritizedTasks; List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks;
JetExpression calleeExpression = context.call.getCalleeExpression(); JetExpression calleeExpression = context.call.getCalleeExpression();
final JetReferenceExpression functionReference; final JetReferenceExpression functionReference;
@@ -142,7 +141,7 @@ public class CallResolver {
String name = expression.getReferencedName(); String name = expression.getReferencedName();
if (name == null) return checkArgumentTypesAndFail(context); if (name == null) return checkArgumentTypesAndFail(context);
prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER)); prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
@Override @Override
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
@@ -184,8 +183,8 @@ public class CallResolver {
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context); return checkArgumentTypesAndFail(context);
} }
Collection<ResolutionCandidate<FunctionDescriptor>> candidates = TaskPrioritizer.<FunctionDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors); Collection<ResolutionCandidate<CallableDescriptor>> candidates = TaskPrioritizer.<CallableDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors);
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY prioritizedTasks.add(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
} }
else { else {
context.trace.report(NOT_A_CLASS.on(calleeExpression)); context.trace.report(NOT_A_CLASS.on(calleeExpression));
@@ -206,8 +205,8 @@ public class CallResolver {
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context); return checkArgumentTypesAndFail(context);
} }
List<ResolutionCandidate<FunctionDescriptor>> candidates = ResolutionCandidate.<FunctionDescriptor>convertCollection(constructors); List<ResolutionCandidate<CallableDescriptor>> candidates = ResolutionCandidate.<CallableDescriptor>convertCollection(constructors);
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
} }
else if (calleeExpression != null) { else if (calleeExpression != null) {
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2) // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
@@ -223,7 +222,7 @@ public class CallResolver {
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]"); FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER); FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
ResolutionCandidate<FunctionDescriptor> resolutionCandidate = ResolutionCandidate.<FunctionDescriptor>create(functionDescriptor); ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(functionDescriptor);
resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver()); resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver());
// strictly speaking, this is a hack: // strictly speaking, this is a hack:
@@ -231,7 +230,7 @@ public class CallResolver {
// so we wrap what we have into a fake reference and pass it on (unwrap on the other end) // so we wrap what we have into a fake reference and pass it on (unwrap on the other end)
functionReference = new JetFakeReference(calleeExpression); functionReference = new JetFakeReference(calleeExpression);
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(Collections.singleton(resolutionCandidate), functionReference, context)); prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(Collections.singleton(resolutionCandidate), functionReference, context));
} }
else { else {
// checkTypesWithNoCallee(trace, scope, call); // checkTypesWithNoCallee(trace, scope, call);
@@ -239,7 +238,7 @@ public class CallResolver {
} }
} }
return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference); return doResolveCall(context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
} }
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) { private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) {
@@ -248,10 +247,10 @@ public class CallResolver {
} }
@NotNull @NotNull
private <D extends CallableDescriptor> OverloadResolutionResults<D> doResolveCall( private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> doResolveCall(
@NotNull final BasicResolutionContext context, @NotNull final BasicResolutionContext context,
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority @NotNull final List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy, @NotNull CallTransformer<D, F> callTransformer,
@NotNull final JetReferenceExpression reference) { @NotNull final JetReferenceExpression reference) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create(); ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
@@ -265,10 +264,11 @@ public class CallResolver {
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks); debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null; TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
OverloadResolutionResultsImpl<D> resultsForFirstNonemptyCandidateSet = null; OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
for (ResolutionTask<D> task : prioritizedTasks) { for (ResolutionTask<D, F> task : prioritizedTasks) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
OverloadResolutionResultsImpl<D> results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace), callTransformationStrategy); OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace),
callTransformer);
if (results.isSuccess() || results.isAmbiguity()) { if (results.isSuccess() || results.isAmbiguity()) {
temporaryTrace.commit(); temporaryTrace.commit();
@@ -294,15 +294,15 @@ public class CallResolver {
context.trace.report(UNRESOLVED_REFERENCE.on(reference)); context.trace.report(UNRESOLVED_REFERENCE.on(reference));
checkTypesWithNoCallee(context); checkTypesWithNoCallee(context);
} }
return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.<D>nameNotFound(); return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.<F>nameNotFound();
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull @NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask<D> task, private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask<D, F> task,
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy) { @NotNull CallTransformer<D, F> callTransformer) {
OverloadResolutionResultsImpl<D> results = performResolution(task, callTransformationStrategy); OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);
// If resolution fails, we should check for some of the following situations: // If resolution fails, we should check for some of the following situations:
// class A { // class A {
@@ -329,14 +329,14 @@ public class CallResolver {
for (ResolutionCandidate<D> candidate : task.getCandidates()) { for (ResolutionCandidate<D> candidate : task.getCandidates()) {
newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor())); newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor()));
} }
ResolutionTask<D> newContext = new ResolutionTask<D>(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) { ResolutionTask<D, F> newContext = new ResolutionTask<D, F>(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) {
@NotNull @NotNull
@Override @Override
public List<JetExpression> getFunctionLiteralArguments() { public List<JetExpression> getFunctionLiteralArguments() {
return Collections.emptyList(); return Collections.emptyList();
} }
}, task.expectedType, task.dataFlowInfo); }, task.expectedType, task.dataFlowInfo);
OverloadResolutionResultsImpl<D> resultsWithFunctionLiteralsStripped = performResolution(newContext, callTransformationStrategy); OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newContext, callTransformer);
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) { if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments()); task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
} }
@@ -346,23 +346,28 @@ public class CallResolver {
} }
@NotNull @NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(@NotNull ResolutionTask<D> task, private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(@NotNull ResolutionTask<D, F> task,
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy) { @NotNull CallTransformer<D, F> callTransformer) {
for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) { for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace); TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace);
CallResolutionContext<D> context = callTransformationStrategy.createCallContext(resolutionCandidate, task, temporaryTrace, task.tracing); Collection<CallResolutionContext<D, F>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, temporaryTrace);
performResolutionForCandidateCall(context, task, temporaryTrace); Collection<ResolvedCallWithTrace<F>> calls = Lists.newArrayList();
for (CallResolutionContext<D, F> context : contexts) {
Collection<ResolvedCallImpl<D>> calls = callTransformationStrategy.transformResultCall(context, this, task); performResolutionForCandidateCall(context, task);
for (ResolvedCallImpl<D> call : calls) { calls.addAll(callTransformer.transformCall(context, this, task));
task.getResolvedCallMap().put(resolutionCandidate, call); }
for (ResolvedCallWithTrace<F> call : calls) {
task.tracing.bindResolvedCall(call.getTrace(), call);
task.getResolvedCalls().add(call);
} }
} }
Set<ResolvedCallImpl<D>> successfulCandidates = Sets.newLinkedHashSet(); Set<ResolvedCallWithTrace<F>> successfulCandidates = Sets.newLinkedHashSet();
Set<ResolvedCallImpl<D>> failedCandidates = Sets.newLinkedHashSet(); Set<ResolvedCallWithTrace<F>> failedCandidates = Sets.newLinkedHashSet();
for (ResolvedCallImpl<D> candidateCall : task.getResolvedCallMap().values()) { for (ResolvedCallWithTrace<F> candidateCall : task.getResolvedCalls()) {
ResolutionStatus status = candidateCall.getStatus(); ResolutionStatus status = candidateCall.getStatus();
if (status.isSuccess()) { if (status.isSuccess()) {
successfulCandidates.add(candidateCall); successfulCandidates.add(candidateCall);
@@ -373,23 +378,19 @@ public class CallResolver {
} }
} }
OverloadResolutionResultsImpl<D> results = computeResultAndReportErrors(task.trace, task.tracing, successfulCandidates, failedCandidates); OverloadResolutionResultsImpl<F> results = computeResultAndReportErrors(task.trace, task.tracing, successfulCandidates, failedCandidates);
if (!results.isSingleResult()) { if (!results.isSingleResult()) {
checkTypesWithNoCallee(task.toBasic()); checkTypesWithNoCallee(task.toBasic());
} }
return results; return results;
} }
private <D extends CallableDescriptor> void performResolutionForCandidateCall(@NotNull CallResolutionContext<D> context, private <D extends CallableDescriptor, F extends D> void performResolutionForCandidateCall(@NotNull CallResolutionContext<D, F> context,
@NotNull ResolutionTask<D> task, @NotNull ResolutionTask<D, F> task) {
@NotNull TemporaryBindingTrace temporaryTrace) {
ResolvedCallImpl<D> candidateCall = context.candidateCall; ResolvedCallImpl<D> candidateCall = context.candidateCall;
candidateCall.setTrace(temporaryTrace);
D candidate = candidateCall.getCandidateDescriptor(); D candidate = candidateCall.getCandidateDescriptor();
context.tracing.bindReference(context.trace, candidateCall);
if (ErrorUtils.isError(candidate)) { if (ErrorUtils.isError(candidate)) {
candidateCall.addStatus(SUCCESS); candidateCall.addStatus(SUCCESS);
checkTypesWithNoCallee(context.toBasic()); checkTypesWithNoCallee(context.toBasic());
@@ -477,7 +478,7 @@ public class CallResolver {
recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace()); recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
} }
private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallResolutionContext<D> context) { private <D extends CallableDescriptor, F extends D> ResolutionStatus inferTypeArguments(CallResolutionContext<D, F> context) {
ResolvedCallImpl<D> candidateCall = context.candidateCall; ResolvedCallImpl<D> candidateCall = context.candidateCall;
D candidate = candidateCall.getCandidateDescriptor(); D candidate = candidateCall.getCandidateDescriptor();
@@ -624,7 +625,7 @@ public class CallResolver {
} }
} }
private <D extends CallableDescriptor> ResolutionStatus checkAllValueArguments(CallResolutionContext<D> context) { private <D extends CallableDescriptor, F extends D> ResolutionStatus checkAllValueArguments(CallResolutionContext<D, F> context) {
ResolutionStatus result = checkValueArgumentTypes(context); ResolutionStatus result = checkValueArgumentTypes(context);
ResolvedCall candidateCall = context.candidateCall; ResolvedCall candidateCall = context.candidateCall;
result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument())); result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument()));
@@ -632,7 +633,7 @@ public class CallResolver {
return result; return result;
} }
private <D extends CallableDescriptor> ResolutionStatus checkReceiver(CallResolutionContext<D> context, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument) { private <D extends CallableDescriptor, F extends D> ResolutionStatus checkReceiver(CallResolutionContext<D, F> context, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument) {
ResolutionStatus result = SUCCESS; ResolutionStatus result = SUCCESS;
if (receiverParameter.exists() && receiverArgument.exists()) { if (receiverParameter.exists() && receiverArgument.exists()) {
ASTNode callOperationNode = context.call.getCallOperationNode(); ASTNode callOperationNode = context.call.getCallOperationNode();
@@ -660,7 +661,7 @@ public class CallResolver {
return result; return result;
} }
private <D extends CallableDescriptor> ResolutionStatus checkValueArgumentTypes(CallResolutionContext<D> context) { private <D extends CallableDescriptor, F extends D> ResolutionStatus checkValueArgumentTypes(CallResolutionContext<D, F> context) {
ResolutionStatus result = SUCCESS; ResolutionStatus result = SUCCESS;
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : context.candidateCall.getValueArguments().entrySet()) { for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : context.candidateCall.getValueArguments().entrySet()) {
ValueParameterDescriptor parameterDescriptor = entry.getKey(); ValueParameterDescriptor parameterDescriptor = entry.getKey();
@@ -734,8 +735,8 @@ public class CallResolver {
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> computeResultAndReportErrors( private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> computeResultAndReportErrors(
BindingTrace trace, BindingTrace trace,
TracingStrategy tracing, TracingStrategy tracing,
Set<ResolvedCallImpl<D>> successfulCandidates, Set<ResolvedCallWithTrace<D>> successfulCandidates,
Set<ResolvedCallImpl<D>> failedCandidates) { Set<ResolvedCallWithTrace<D>> failedCandidates) {
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific // TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
if (successfulCandidates.size() > 0) { if (successfulCandidates.size() > 0) {
@@ -756,8 +757,8 @@ public class CallResolver {
// and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable" // and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable"
// Used to be: weak errors. Generalized for future extensions // Used to be: weak errors. Generalized for future extensions
for (EnumSet<ResolutionStatus> severityLevel : SEVERITY_LEVELS) { for (EnumSet<ResolutionStatus> severityLevel : SEVERITY_LEVELS) {
Set<ResolvedCallImpl<D>> thisLevel = Sets.newLinkedHashSet(); Set<ResolvedCallWithTrace<D>> thisLevel = Sets.newLinkedHashSet();
for (ResolvedCallImpl<D> candidate : failedCandidates) { for (ResolvedCallWithTrace<D> candidate : failedCandidates) {
if (severityLevel.contains(candidate.getStatus())) { if (severityLevel.contains(candidate.getStatus())) {
thisLevel.add(candidate); thisLevel.add(candidate);
} }
@@ -777,7 +778,7 @@ public class CallResolver {
assert false : "Should not be reachable, cause every status must belong to some level"; assert false : "Should not be reachable, cause every status must belong to some level";
Set<ResolvedCallImpl<D>> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE); Set<ResolvedCallWithTrace<D>> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE);
if (noOverrides.size() != 1) { if (noOverrides.size() != 1) {
tracing.noneApplicable(trace, noOverrides); tracing.noneApplicable(trace, noOverrides);
tracing.recordAmbiguity(trace, noOverrides); tracing.recordAmbiguity(trace, noOverrides);
@@ -787,7 +788,7 @@ public class CallResolver {
failedCandidates = noOverrides; failedCandidates = noOverrides;
} }
ResolvedCallImpl<D> failed = failedCandidates.iterator().next(); ResolvedCallWithTrace<D> failed = failedCandidates.iterator().next();
failed.getTrace().commit(); failed.getTrace().commit();
return OverloadResolutionResultsImpl.singleFailedCandidate(failed); return OverloadResolutionResultsImpl.singleFailedCandidate(failed);
} }
@@ -797,18 +798,18 @@ public class CallResolver {
} }
} }
private static <D extends CallableDescriptor> boolean allClean(Collection<ResolvedCallImpl<D>> results) { private static <D extends CallableDescriptor> boolean allClean(Collection<ResolvedCallWithTrace<D>> results) {
for (ResolvedCallImpl<D> result : results) { for (ResolvedCallWithTrace<D> result : results) {
if (result.isDirty()) return false; if (result.isDirty()) return false;
} }
return true; return true;
} }
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(Set<ResolvedCallImpl<D>> candidates, boolean discriminateGenerics) { private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(Set<ResolvedCallWithTrace<D>> candidates, boolean discriminateGenerics) {
if (candidates.size() != 1) { if (candidates.size() != 1) {
Set<ResolvedCallImpl<D>> cleanCandidates = Sets.newLinkedHashSet(candidates); Set<ResolvedCallWithTrace<D>> cleanCandidates = Sets.newLinkedHashSet(candidates);
for (Iterator<ResolvedCallImpl<D>> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) { for (Iterator<ResolvedCallWithTrace<D>> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) {
ResolvedCallImpl<D> candidate = iterator.next(); ResolvedCallWithTrace<D> candidate = iterator.next();
if (candidate.isDirty()) { if (candidate.isDirty()) {
iterator.remove(); iterator.remove();
} }
@@ -817,27 +818,31 @@ public class CallResolver {
if (cleanCandidates.isEmpty()) { if (cleanCandidates.isEmpty()) {
cleanCandidates = candidates; cleanCandidates = candidates;
} }
ResolvedCallImpl<D> maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, false); ResolvedCallWithTrace<D> maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, false);
if (maximallySpecific != null) { if (maximallySpecific != null) {
return OverloadResolutionResultsImpl.success(maximallySpecific); return OverloadResolutionResultsImpl.success(maximallySpecific);
} }
if (discriminateGenerics) { if (discriminateGenerics) {
ResolvedCallImpl<D> maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, true); ResolvedCallWithTrace<D> maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, true);
if (maximallySpecificGenericsDiscriminated != null) { if (maximallySpecificGenericsDiscriminated != null) {
return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated); return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated);
} }
} }
Set<ResolvedCallImpl<D>> noOverrides = OverridingUtil.filterOverrides(candidates, MAP_TO_RESULT); Set<ResolvedCallWithTrace<D>> noOverrides = OverridingUtil.filterOverrides(candidates, MAP_TO_RESULT);
return OverloadResolutionResultsImpl.ambiguity(noOverrides); return OverloadResolutionResultsImpl.ambiguity(noOverrides);
} }
else { else {
ResolvedCallImpl<D> result = candidates.iterator().next(); ResolvedCallWithTrace<D> result = candidates.iterator().next();
TemporaryBindingTrace temporaryTrace = result.getTrace(); TemporaryBindingTrace temporaryTrace = result.getTrace();
temporaryTrace.commit(); temporaryTrace.commit();
if (result instanceof VariableAsFunctionResolvedCall) {
((VariableAsFunctionResolvedCall)result).getVariableCall().getTrace().commit();
}
return OverloadResolutionResultsImpl.success(result); return OverloadResolutionResultsImpl.success(result);
} }
} }
@@ -868,13 +873,12 @@ public class CallResolver {
BindingTraceContext trace = new BindingTraceContext(); BindingTraceContext trace = new BindingTraceContext();
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace); TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace);
Set<ResolvedCallImpl<FunctionDescriptor>> calls = Sets.newLinkedHashSet(); Set<ResolvedCallWithTrace<FunctionDescriptor>> calls = Sets.newLinkedHashSet();
for (ResolutionCandidate<FunctionDescriptor> candidate : candidates) { for (ResolutionCandidate<FunctionDescriptor> candidate : candidates) {
ResolvedCallImpl<FunctionDescriptor> call = ResolvedCallImpl.create(candidate); ResolvedCallImpl<FunctionDescriptor> call = ResolvedCallImpl.create(candidate, temporaryBindingTrace);
call.setTrace(temporaryBindingTrace);
calls.add(call); calls.add(call);
} }
return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.<ResolvedCallImpl<FunctionDescriptor>>emptySet()); return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.<ResolvedCallWithTrace<FunctionDescriptor>>emptySet());
} }
private List<ResolutionCandidate<FunctionDescriptor>> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, private List<ResolutionCandidate<FunctionDescriptor>> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver,
@@ -34,7 +34,7 @@ import java.util.Map;
* @author abreslav * @author abreslav
*/ */
public class ResolutionDebugInfo { public class ResolutionDebugInfo {
public static final WritableSlice<One, List<? extends ResolutionTask<? extends CallableDescriptor>>> TASKS = Slices.createSimpleSlice(); public static final WritableSlice<One, List<? extends ResolutionTask<? extends CallableDescriptor, ?>>> TASKS = Slices.createSimpleSlice();
public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice(); public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice();
public static final WritableSlice<ResolvedCall<? extends CallableDescriptor>, StringBuilder> ERRORS = Slices.createSimpleSlice(); public static final WritableSlice<ResolvedCall<? extends CallableDescriptor>, StringBuilder> ERRORS = Slices.createSimpleSlice();
@@ -31,7 +31,7 @@ import java.util.List;
/** /**
* @author svtk * @author svtk
*/ */
public class ResolutionTaskHolder<D extends CallableDescriptor> { public class ResolutionTaskHolder<D extends CallableDescriptor, F extends D> {
private final JetReferenceExpression reference; private final JetReferenceExpression reference;
private final BasicResolutionContext basicResolutionContext; private final BasicResolutionContext basicResolutionContext;
private final Predicate<ResolutionCandidate<D>> visibleStrategy; private final Predicate<ResolutionCandidate<D>> visibleStrategy;
@@ -40,7 +40,7 @@ public class ResolutionTaskHolder<D extends CallableDescriptor> {
private final Collection<Collection<ResolutionCandidate<D>>> members = Sets.newLinkedHashSet(); private final Collection<Collection<ResolutionCandidate<D>>> members = Sets.newLinkedHashSet();
private final Collection<Collection<ResolutionCandidate<D>>> nonLocalExtensions = Sets.newLinkedHashSet(); private final Collection<Collection<ResolutionCandidate<D>>> nonLocalExtensions = Sets.newLinkedHashSet();
private List<ResolutionTask<D>> tasks = null; private List<ResolutionTask<D, F>> tasks = null;
public ResolutionTaskHolder(@NotNull JetReferenceExpression reference, public ResolutionTaskHolder(@NotNull JetReferenceExpression reference,
@NotNull BasicResolutionContext basicResolutionContext, @NotNull BasicResolutionContext basicResolutionContext,
@@ -68,7 +68,7 @@ public class ResolutionTaskHolder<D extends CallableDescriptor> {
} }
} }
public List<ResolutionTask<D>> getTasks() { public List<ResolutionTask<D, F>> getTasks() {
if (tasks == null) { if (tasks == null) {
tasks = Lists.newArrayList(); tasks = Lists.newArrayList();
List<Collection<ResolutionCandidate<D>>> candidateList = Lists.newArrayList(); List<Collection<ResolutionCandidate<D>>> candidateList = Lists.newArrayList();
@@ -89,7 +89,7 @@ public class ResolutionTaskHolder<D extends CallableDescriptor> {
for (Collection<ResolutionCandidate<D>> candidates : candidateList) { for (Collection<ResolutionCandidate<D>> candidates : candidateList) {
Collection<ResolutionCandidate<D>> filteredCandidates = Collections2.filter(candidates, visibilityStrategy); Collection<ResolutionCandidate<D>> filteredCandidates = Collections2.filter(candidates, visibilityStrategy);
if (!filteredCandidates.isEmpty()) { if (!filteredCandidates.isEmpty()) {
tasks.add(new ResolutionTask<D>(filteredCandidates, reference, basicResolutionContext)); tasks.add(new ResolutionTask<D, F>(filteredCandidates, reference, basicResolutionContext));
} }
} }
} }