Resolution task is itself a context
This commit is contained in:
@@ -35,16 +35,15 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
|||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lexer.JetToken;
|
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.*;
|
import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_CANDIDATE;
|
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_CANDIDATE;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_RESULT;
|
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_RESULT;
|
||||||
@@ -109,8 +108,8 @@ public class CallResolver {
|
|||||||
else {
|
else {
|
||||||
task_prioritizer = TaskPrioritizers.VARIABLE_TASK_PRIORITIZER;
|
task_prioritizer = TaskPrioritizers.VARIABLE_TASK_PRIORITIZER;
|
||||||
}
|
}
|
||||||
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = task_prioritizer.computePrioritizedTasks(context.scope, context.call, referencedName, context.trace.getBindingContext(), context.dataFlowInfo);
|
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = task_prioritizer.computePrioritizedTasks(context, referencedName, nameExpression);
|
||||||
return resolveCallToDescriptor(context, prioritizedTasks, nameExpression);
|
return doResolveCall(context, prioritizedTasks, nameExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -119,7 +118,7 @@ public class CallResolver {
|
|||||||
@NotNull final JetReferenceExpression functionReference,
|
@NotNull final JetReferenceExpression functionReference,
|
||||||
@NotNull String name) {
|
@NotNull String name) {
|
||||||
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(
|
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(
|
||||||
context.scope, context.call, name, context.trace.getBindingContext(), context.dataFlowInfo);
|
context, name, functionReference);
|
||||||
return doResolveCall(context, tasks, functionReference);
|
return doResolveCall(context, tasks, functionReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +140,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 = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(context.scope, context.call, name, context.trace.getBindingContext(), context.dataFlowInfo);
|
prioritizedTasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(context, name, functionReference);
|
||||||
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) {
|
||||||
@@ -183,7 +182,8 @@ public class CallResolver {
|
|||||||
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
||||||
return checkArgumentTypesAndFail(context);
|
return checkArgumentTypesAndFail(context);
|
||||||
}
|
}
|
||||||
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(TaskPrioritizer.<FunctionDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors), context.call, DataFlowInfo.EMPTY));
|
Collection<ResolvedCallImpl<FunctionDescriptor>> candidates = TaskPrioritizer.<FunctionDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors);
|
||||||
|
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
context.trace.report(NOT_A_CLASS.on(calleeExpression));
|
context.trace.report(NOT_A_CLASS.on(calleeExpression));
|
||||||
@@ -204,7 +204,8 @@ public class CallResolver {
|
|||||||
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
||||||
return checkArgumentTypesAndFail(context);
|
return checkArgumentTypesAndFail(context);
|
||||||
}
|
}
|
||||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(ResolvedCallImpl.<FunctionDescriptor>convertCollection(constructors), context.call, DataFlowInfo.EMPTY));
|
List<ResolvedCallImpl<FunctionDescriptor>> candidates = ResolvedCallImpl.<FunctionDescriptor>convertCollection(constructors);
|
||||||
|
prioritizedTasks = Collections.singletonList(new ResolutionTask<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)
|
||||||
@@ -222,13 +223,13 @@ public class CallResolver {
|
|||||||
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
|
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
|
||||||
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
|
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
|
||||||
resolvedCall.setReceiverArgument(context.call.getExplicitReceiver());
|
resolvedCall.setReceiverArgument(context.call.getExplicitReceiver());
|
||||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(
|
|
||||||
Collections.singleton(resolvedCall), context.call, context.dataFlowInfo));
|
|
||||||
|
|
||||||
// strictly speaking, this is a hack:
|
// strictly speaking, this is a hack:
|
||||||
// we need to pass a reference, but there's no reference in the PSI,
|
// we need to pass a reference, but there's no reference in the PSI,
|
||||||
// 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(resolvedCall), functionReference, context));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// checkTypesWithNoCallee(trace, scope, call);
|
// checkTypesWithNoCallee(trace, scope, call);
|
||||||
@@ -236,7 +237,7 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveCallToDescriptor(context, prioritizedTasks, functionReference);
|
return doResolveCall(context, prioritizedTasks, functionReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) {
|
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) {
|
||||||
@@ -244,14 +245,6 @@ public class CallResolver {
|
|||||||
return OverloadResolutionResultsImpl.nameNotFound();
|
return OverloadResolutionResultsImpl.nameNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> resolveCallToDescriptor(
|
|
||||||
@NotNull BasicResolutionContext context,
|
|
||||||
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
|
|
||||||
@NotNull final JetReferenceExpression reference) {
|
|
||||||
return doResolveCall(context, prioritizedTasks, reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> doResolveCall(
|
private <D extends CallableDescriptor> OverloadResolutionResults<D> doResolveCall(
|
||||||
@NotNull final BasicResolutionContext context,
|
@NotNull final BasicResolutionContext context,
|
||||||
@@ -264,148 +257,11 @@ public class CallResolver {
|
|||||||
|
|
||||||
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
|
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
|
||||||
|
|
||||||
TracingStrategy tracing = new TracingStrategy() {
|
|
||||||
@Override
|
|
||||||
public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall) {
|
|
||||||
D descriptor = resolvedCall.getCandidateDescriptor();
|
|
||||||
// if (descriptor instanceof VariableAsFunctionDescriptor) {
|
|
||||||
// VariableAsFunctionDescriptor variableAsFunctionDescriptor = (VariableAsFunctionDescriptor) descriptor;
|
|
||||||
// trace.record(REFERENCE_TARGET, reference, variableAsFunctionDescriptor.getVariableDescriptor());
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// }
|
|
||||||
trace.record(RESOLVED_CALL, context.call.getCalleeExpression(), resolvedCall);
|
|
||||||
trace.record(REFERENCE_TARGET, reference, descriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallImpl<D>> candidates) {
|
|
||||||
Collection<D> descriptors = Sets.newHashSet();
|
|
||||||
for (ResolvedCallImpl<D> candidate : candidates) {
|
|
||||||
descriptors.add(candidate.getCandidateDescriptor());
|
|
||||||
}
|
|
||||||
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unresolvedReference(@NotNull BindingTrace trace) {
|
|
||||||
trace.report(UNRESOLVED_REFERENCE.on(reference));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
|
|
||||||
PsiElement reportOn;
|
|
||||||
JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
|
|
||||||
if (valueArgumentList != null) {
|
|
||||||
reportOn = valueArgumentList;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reportOn = reference;
|
|
||||||
}
|
|
||||||
trace.report(NO_VALUE_FOR_PARAMETER.on(reportOn, valueParameter));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {
|
|
||||||
trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument) {
|
|
||||||
if (receiverArgument instanceof ExpressionReceiver) {
|
|
||||||
ExpressionReceiver expressionReceiver = (ExpressionReceiver) receiverArgument;
|
|
||||||
trace.report(TYPE_MISMATCH.on(expressionReceiver.getExpression(), receiverParameter.getType(), receiverArgument.getType()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
trace.report(TYPE_MISMATCH.on(reference, receiverParameter.getType(), receiverArgument.getType()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void noReceiverAllowed(@NotNull BindingTrace trace) {
|
|
||||||
trace.report(NO_RECEIVER_ADMITTED.on(reference));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {
|
|
||||||
JetTypeArgumentList typeArgumentList = context.call.getTypeArgumentList();
|
|
||||||
if (typeArgumentList != null) {
|
|
||||||
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeArgumentList, expectedTypeArgumentCount));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(reference, expectedTypeArgumentCount));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {
|
|
||||||
trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(context.call.getCallElement(), descriptors));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {
|
|
||||||
trace.report(NONE_APPLICABLE.on(reference, descriptors));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {
|
|
||||||
trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(context.call.getCallElement()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status) {
|
|
||||||
assert !status.isSuccessful();
|
|
||||||
trace.report(TYPE_INFERENCE_FAILED.on(context.call.getCallElement(), status));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
|
|
||||||
ASTNode callOperationNode = context.call.getCallOperationNode();
|
|
||||||
if (callOperationNode != null) {
|
|
||||||
trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PsiElement callElement = context.call.getCallElement();
|
|
||||||
if (callElement instanceof JetBinaryExpression) {
|
|
||||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) callElement;
|
|
||||||
JetSimpleNameExpression operationReference = binaryExpression.getOperationReference();
|
|
||||||
|
|
||||||
String operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ?
|
|
||||||
operationReference.getText() :
|
|
||||||
OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
|
|
||||||
|
|
||||||
JetExpression right = binaryExpression.getRight();
|
|
||||||
if (right != null) {
|
|
||||||
trace.report(UNSAFE_INFIX_CALL.on(reference, binaryExpression.getLeft().getText(), operationString, right.getText()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
trace.report(UNSAFE_CALL.on(reference, type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
|
|
||||||
ASTNode callOperationNode = context.call.getCallOperationNode();
|
|
||||||
assert callOperationNode != null;
|
|
||||||
trace.report(UNNECESSARY_SAFE_CALL.on(callOperationNode.getPsi(), type));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void danglingFunctionLiteralArgumentSuspected(@NotNull BindingTrace trace, @NotNull List<JetExpression> functionLiteralArguments) {
|
|
||||||
for (JetExpression functionLiteralArgument : functionLiteralArguments) {
|
|
||||||
trace.report(DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED.on(functionLiteralArgument));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
|
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
|
||||||
OverloadResolutionResultsImpl<D> resultsForFirstNonemptyCandidateSet = null;
|
OverloadResolutionResultsImpl<D> resultsForFirstNonemptyCandidateSet = null;
|
||||||
for (ResolutionTask<D> task : prioritizedTasks) {
|
for (ResolutionTask<D> task : prioritizedTasks) {
|
||||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
|
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
|
||||||
BasicResolutionContext newContext = BasicResolutionContext.create(temporaryTrace, context.scope, task.getCall(), context.expectedType, context.dataFlowInfo);
|
OverloadResolutionResultsImpl<D> results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace));
|
||||||
OverloadResolutionResultsImpl<D> results = performResolutionGuardedForExtraFunctionLiteralArguments(new TaskResolutionContext<D>(task, tracing, newContext));
|
|
||||||
if (results.isSuccess()) {
|
if (results.isSuccess()) {
|
||||||
temporaryTrace.commit();
|
temporaryTrace.commit();
|
||||||
|
|
||||||
@@ -435,8 +291,8 @@ public class CallResolver {
|
|||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(TaskResolutionContext<D> context) {
|
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(ResolutionTask<D> task) {
|
||||||
OverloadResolutionResultsImpl<D> results = performResolution(context);
|
OverloadResolutionResultsImpl<D> results = performResolution(task);
|
||||||
|
|
||||||
// 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 {
|
||||||
@@ -455,27 +311,24 @@ public class CallResolver {
|
|||||||
// }
|
// }
|
||||||
EnumSet<OverloadResolutionResults.Code> someFailed = EnumSet.of(OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES,
|
EnumSet<OverloadResolutionResults.Code> someFailed = EnumSet.of(OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES,
|
||||||
OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
|
OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
|
||||||
if (someFailed.contains(results.getResultCode()) && !context.call.getFunctionLiteralArguments().isEmpty()) {
|
if (someFailed.contains(results.getResultCode()) && !task.call.getFunctionLiteralArguments().isEmpty()) {
|
||||||
// We have some candidates that failed for some reason
|
// We have some candidates that failed for some reason
|
||||||
// And we have a suspect: the function literal argument
|
// And we have a suspect: the function literal argument
|
||||||
// Now, we try to remove this argument and see if it helps
|
// Now, we try to remove this argument and see if it helps
|
||||||
Collection<ResolvedCallImpl<D>> newCandidates = Lists.newArrayList();
|
Collection<ResolvedCallImpl<D>> newCandidates = Lists.newArrayList();
|
||||||
for (ResolvedCallImpl<D> candidate : context.task.getCandidates()) {
|
for (ResolvedCallImpl<D> candidate : task.getCandidates()) {
|
||||||
newCandidates.add(ResolvedCallImpl.create(candidate.getCandidateDescriptor()));
|
newCandidates.add(ResolvedCallImpl.create(candidate.getCandidateDescriptor()));
|
||||||
}
|
}
|
||||||
ResolutionTask<D> newTask = new ResolutionTask<D>(newCandidates, new DelegatingCall(context.call) {
|
ResolutionTask<D> newContext = new ResolutionTask<D>(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();
|
||||||
}
|
}
|
||||||
}, context.dataFlowInfo);
|
}, task.expectedType, task.dataFlowInfo);
|
||||||
|
|
||||||
BasicResolutionContext newBasicContext = BasicResolutionContext.create(TemporaryBindingTrace.create(context.trace), context.scope, context.call, context.expectedType, context.dataFlowInfo);
|
|
||||||
TaskResolutionContext<D> newContext = new TaskResolutionContext<D>(newTask, context.tracing, newBasicContext);
|
|
||||||
OverloadResolutionResultsImpl<D> resultsWithFunctionLiteralsStripped = performResolution(newContext);
|
OverloadResolutionResultsImpl<D> resultsWithFunctionLiteralsStripped = performResolution(newContext);
|
||||||
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
|
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
|
||||||
context.tracing.danglingFunctionLiteralArgumentSuspected(context.trace, context.call.getFunctionLiteralArguments());
|
task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,13 +336,13 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(TaskResolutionContext<D> taskContext) {
|
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(ResolutionTask<D> task) {
|
||||||
for (ResolvedCallImpl<D> candidateCall : taskContext.task.getCandidates()) {
|
for (ResolvedCallImpl<D> candidateCall : task.getCandidates()) {
|
||||||
D candidate = candidateCall.getCandidateDescriptor();
|
D candidate = candidateCall.getCandidateDescriptor();
|
||||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(taskContext.trace);
|
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace);
|
||||||
candidateCall.setTrace(temporaryTrace);
|
candidateCall.setTrace(temporaryTrace);
|
||||||
|
|
||||||
CallResolutionContext<D> context = new CallResolutionContext<D>(candidateCall, taskContext, temporaryTrace, taskContext.tracing);
|
CallResolutionContext<D> context = new CallResolutionContext<D>(candidateCall, task, temporaryTrace, task.tracing);
|
||||||
|
|
||||||
context.tracing.bindReference(context.trace, candidateCall);
|
context.tracing.bindReference(context.trace, candidateCall);
|
||||||
|
|
||||||
@@ -555,7 +408,7 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
taskContext.task.performAdvancedChecks(candidate, context.trace, context.tracing);
|
task.performAdvancedChecks(candidate, context.trace, context.tracing);
|
||||||
|
|
||||||
// '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
|
||||||
@@ -571,7 +424,7 @@ public class CallResolver {
|
|||||||
|
|
||||||
Set<ResolvedCallImpl<D>> successfulCandidates = Sets.newLinkedHashSet();
|
Set<ResolvedCallImpl<D>> successfulCandidates = Sets.newLinkedHashSet();
|
||||||
Set<ResolvedCallImpl<D>> failedCandidates = Sets.newLinkedHashSet();
|
Set<ResolvedCallImpl<D>> failedCandidates = Sets.newLinkedHashSet();
|
||||||
for (ResolvedCallImpl<D> candidateCall : taskContext.task.getCandidates()) {
|
for (ResolvedCallImpl<D> candidateCall : task.getCandidates()) {
|
||||||
ResolutionStatus status = candidateCall.getStatus();
|
ResolutionStatus status = candidateCall.getStatus();
|
||||||
if (status.isSuccess()) {
|
if (status.isSuccess()) {
|
||||||
successfulCandidates.add(candidateCall);
|
successfulCandidates.add(candidateCall);
|
||||||
@@ -582,9 +435,9 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OverloadResolutionResultsImpl<D> results = computeResultAndReportErrors(taskContext.trace, taskContext.tracing, successfulCandidates, failedCandidates);
|
OverloadResolutionResultsImpl<D> results = computeResultAndReportErrors(task.trace, task.tracing, successfulCandidates, failedCandidates);
|
||||||
if (!results.singleResult()) {
|
if (!results.singleResult()) {
|
||||||
checkTypesWithNoCallee(taskContext.toBasic());
|
checkTypesWithNoCallee(task.toBasic());
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@@ -1033,23 +886,12 @@ public class CallResolver {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TaskResolutionContext<D extends CallableDescriptor> extends ResolutionContext {
|
|
||||||
/*package*/ final ResolutionTask<D> task;
|
|
||||||
/*package*/ final TracingStrategy tracing;
|
|
||||||
|
|
||||||
public TaskResolutionContext(ResolutionTask<D> task, TracingStrategy tracing, BasicResolutionContext context) {
|
|
||||||
super(context.trace, context.scope, task.getCall(), context.expectedType, context.dataFlowInfo);
|
|
||||||
this.task = task;
|
|
||||||
this.tracing = tracing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class CallResolutionContext<D extends CallableDescriptor> extends ResolutionContext {
|
private static final class CallResolutionContext<D extends CallableDescriptor> extends ResolutionContext {
|
||||||
/*package*/ final ResolvedCallImpl<D> candidateCall;
|
/*package*/ final ResolvedCallImpl<D> candidateCall;
|
||||||
/*package*/ final TracingStrategy tracing;
|
/*package*/ final TracingStrategy tracing;
|
||||||
|
|
||||||
public CallResolutionContext(ResolvedCallImpl<D> candidateCall, TaskResolutionContext<D> taskResolutionContext, BindingTrace trace, TracingStrategy tracing) {
|
public CallResolutionContext(ResolvedCallImpl<D> candidateCall, ResolutionTask<D> task, BindingTrace trace, TracingStrategy tracing) {
|
||||||
super(trace, taskResolutionContext.scope, taskResolutionContext.task.getCall(), taskResolutionContext.expectedType, taskResolutionContext.dataFlowInfo);
|
super(trace, task.scope, task.call, task.expectedType, task.dataFlowInfo);
|
||||||
this.candidateCall = candidateCall;
|
this.candidateCall = candidateCall;
|
||||||
this.tracing = tracing;
|
this.tracing = tracing;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,39 +16,52 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.calls;
|
package org.jetbrains.jet.lang.resolve.calls;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.Call;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.inference.SolutionStatus;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
|
import org.jetbrains.jet.lexer.JetToken;
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
|
import static org.jetbrains.jet.lang.diagnostics.Errors.DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores candidates for call resolution.
|
* Stores candidates for call resolution.
|
||||||
*
|
*
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class ResolutionTask<D extends CallableDescriptor> {
|
public class ResolutionTask<D extends CallableDescriptor> extends ResolutionContext {
|
||||||
private final Call call;
|
|
||||||
private final Collection<ResolvedCallImpl<D>> candidates;
|
private final Collection<ResolvedCallImpl<D>> candidates;
|
||||||
private final DataFlowInfo dataFlowInfo;
|
/*package*/ final JetReferenceExpression reference;
|
||||||
private DescriptorCheckStrategy checkingStrategy;
|
private DescriptorCheckStrategy checkingStrategy;
|
||||||
|
|
||||||
|
public ResolutionTask(@NotNull Collection<ResolvedCallImpl<D>> candidates, @NotNull JetReferenceExpression reference,
|
||||||
public ResolutionTask(
|
BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo) {
|
||||||
@NotNull Collection<ResolvedCallImpl<D>> candidates,
|
super(trace, scope, call, expectedType, dataFlowInfo);
|
||||||
@NotNull Call call,
|
|
||||||
@NotNull DataFlowInfo dataFlowInfo
|
|
||||||
) {
|
|
||||||
this.candidates = candidates;
|
this.candidates = candidates;
|
||||||
this.call = call;
|
this.reference = reference;
|
||||||
this.dataFlowInfo = dataFlowInfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
public ResolutionTask(@NotNull Collection<ResolvedCallImpl<D>> candidates, @NotNull JetReferenceExpression reference, @NotNull BasicResolutionContext context) {
|
||||||
public DataFlowInfo getDataFlowInfo() {
|
this(candidates, reference, context.trace, context.scope, context.call, context.expectedType, context.dataFlowInfo);
|
||||||
return dataFlowInfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -56,11 +69,6 @@ public class ResolutionTask<D extends CallableDescriptor> {
|
|||||||
return candidates;
|
return candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Call getCall() {
|
|
||||||
return call;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
|
public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
|
||||||
checkingStrategy = strategy;
|
checkingStrategy = strategy;
|
||||||
}
|
}
|
||||||
@@ -72,7 +80,149 @@ public class ResolutionTask<D extends CallableDescriptor> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ResolutionTask<D> withTrace(BindingTrace newTrace) {
|
||||||
|
ResolutionTask<D> newTask = new ResolutionTask<D>(candidates, reference, newTrace, scope, call, expectedType, dataFlowInfo);
|
||||||
|
newTask.setCheckingStrategy(checkingStrategy);
|
||||||
|
return newTask;
|
||||||
|
}
|
||||||
|
|
||||||
public interface DescriptorCheckStrategy {
|
public interface DescriptorCheckStrategy {
|
||||||
<D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing);
|
<D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final TracingStrategy tracing = new TracingStrategy() {
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall) {
|
||||||
|
D descriptor = resolvedCall.getCandidateDescriptor();
|
||||||
|
// if (descriptor instanceof VariableAsFunctionDescriptor) {
|
||||||
|
// VariableAsFunctionDescriptor variableAsFunctionDescriptor = (VariableAsFunctionDescriptor) descriptor;
|
||||||
|
// trace.record(REFERENCE_TARGET, reference, variableAsFunctionDescriptor.getVariableDescriptor());
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// }
|
||||||
|
trace.record(RESOLVED_CALL, call.getCalleeExpression(), resolvedCall);
|
||||||
|
trace.record(REFERENCE_TARGET, reference, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallImpl<D>> candidates) {
|
||||||
|
Collection<D> descriptors = Sets.newHashSet();
|
||||||
|
for (ResolvedCallImpl<D> candidate : candidates) {
|
||||||
|
descriptors.add(candidate.getCandidateDescriptor());
|
||||||
|
}
|
||||||
|
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unresolvedReference(@NotNull BindingTrace trace) {
|
||||||
|
trace.report(UNRESOLVED_REFERENCE.on(reference));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
|
||||||
|
PsiElement reportOn;
|
||||||
|
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
||||||
|
if (valueArgumentList != null) {
|
||||||
|
reportOn = valueArgumentList;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reportOn = reference;
|
||||||
|
}
|
||||||
|
trace.report(NO_VALUE_FOR_PARAMETER.on(reportOn, valueParameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {
|
||||||
|
trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument) {
|
||||||
|
if (receiverArgument instanceof ExpressionReceiver) {
|
||||||
|
ExpressionReceiver expressionReceiver = (ExpressionReceiver) receiverArgument;
|
||||||
|
trace.report(TYPE_MISMATCH.on(expressionReceiver.getExpression(), receiverParameter.getType(), receiverArgument.getType()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.report(TYPE_MISMATCH.on(reference, receiverParameter.getType(), receiverArgument.getType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noReceiverAllowed(@NotNull BindingTrace trace) {
|
||||||
|
trace.report(NO_RECEIVER_ADMITTED.on(reference));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {
|
||||||
|
JetTypeArgumentList typeArgumentList = call.getTypeArgumentList();
|
||||||
|
if (typeArgumentList != null) {
|
||||||
|
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeArgumentList, expectedTypeArgumentCount));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(reference, expectedTypeArgumentCount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {
|
||||||
|
trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(call.getCallElement(), descriptors));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {
|
||||||
|
trace.report(NONE_APPLICABLE.on(reference, descriptors));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {
|
||||||
|
trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status) {
|
||||||
|
assert !status.isSuccessful();
|
||||||
|
trace.report(TYPE_INFERENCE_FAILED.on(call.getCallElement(), status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
|
||||||
|
ASTNode callOperationNode = call.getCallOperationNode();
|
||||||
|
if (callOperationNode != null) {
|
||||||
|
trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PsiElement callElement = call.getCallElement();
|
||||||
|
if (callElement instanceof JetBinaryExpression) {
|
||||||
|
JetBinaryExpression binaryExpression = (JetBinaryExpression) callElement;
|
||||||
|
JetSimpleNameExpression operationReference = binaryExpression.getOperationReference();
|
||||||
|
|
||||||
|
String operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ?
|
||||||
|
operationReference.getText() :
|
||||||
|
OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
|
||||||
|
|
||||||
|
JetExpression right = binaryExpression.getRight();
|
||||||
|
if (right != null) {
|
||||||
|
trace.report(UNSAFE_INFIX_CALL.on(reference, binaryExpression.getLeft().getText(), operationString, right.getText()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.report(UNSAFE_CALL.on(reference, type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
|
||||||
|
ASTNode callOperationNode = call.getCallOperationNode();
|
||||||
|
assert callOperationNode != null;
|
||||||
|
trace.report(UNNECESSARY_SAFE_CALL.on(callOperationNode.getPsi(), type));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void danglingFunctionLiteralArgumentSuspected(@NotNull BindingTrace trace, @NotNull List<JetExpression> functionLiteralArguments) {
|
||||||
|
for (JetExpression functionLiteralArgument : functionLiteralArguments) {
|
||||||
|
trace.report(DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED.on(functionLiteralArgument));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,10 @@ import com.google.common.collect.Lists;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.Call;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetSuperExpression;
|
import org.jetbrains.jet.lang.psi.JetSuperExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastService;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
@@ -76,21 +74,24 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull Call call, @NotNull String name,
|
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull BasicResolutionContext context, @NotNull String name,
|
||||||
@NotNull BindingContext bindingContext, @NotNull DataFlowInfo dataFlowInfo) {
|
@NotNull JetReferenceExpression functionReference) {
|
||||||
List<ResolutionTask<D>> result = Lists.newArrayList();
|
List<ResolutionTask<D>> result = Lists.newArrayList();
|
||||||
|
|
||||||
ReceiverDescriptor explicitReceiver = call.getExplicitReceiver();
|
ReceiverDescriptor explicitReceiver = context.call.getExplicitReceiver();
|
||||||
|
JetScope scope = context.scope;
|
||||||
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
|
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
|
||||||
|
// Receiver is a namespace
|
||||||
scope = explicitReceiver.getType().getMemberScope();
|
scope = explicitReceiver.getType().getMemberScope();
|
||||||
explicitReceiver = NO_RECEIVER;
|
explicitReceiver = NO_RECEIVER;
|
||||||
}
|
}
|
||||||
doComputeTasks(scope, explicitReceiver, call, name, result, new AutoCastServiceImpl(dataFlowInfo, bindingContext));
|
doComputeTasks(scope, explicitReceiver, name, result, context, functionReference);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, Call call, String name, List<ResolutionTask<D>> result, @NotNull AutoCastService autoCastService) {
|
private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, String name, List<ResolutionTask<D>> result, @NotNull BasicResolutionContext context, @NotNull JetReferenceExpression functionReference) {
|
||||||
|
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext());
|
||||||
DataFlowInfo dataFlowInfo = autoCastService.getDataFlowInfo();
|
DataFlowInfo dataFlowInfo = autoCastService.getDataFlowInfo();
|
||||||
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
|
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
|
||||||
scope.getImplicitReceiversHierarchy(implicitReceivers);
|
scope.getImplicitReceiversHierarchy(implicitReceivers);
|
||||||
@@ -113,21 +114,21 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
// If the call is of the form super.foo(), it can actually be only a member
|
// If the call is of the form super.foo(), it can actually be only a member
|
||||||
// But if there's no appropriate member, we would like to report that super cannot be a receiver for an extension
|
// But if there's no appropriate member, we would like to report that super cannot be a receiver for an extension
|
||||||
// Thus, put members first
|
// Thus, put members first
|
||||||
addTask(result, call, members, dataFlowInfo);
|
addTask(result, members, context, functionReference);
|
||||||
addTask(result, call, locals, dataFlowInfo);
|
addTask(result, locals, context, functionReference);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addTask(result, call, locals, dataFlowInfo);
|
addTask(result, locals, context, functionReference);
|
||||||
addTask(result, call, members, dataFlowInfo);
|
addTask(result, members, context, functionReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
|
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
|
||||||
Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
|
Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
|
||||||
List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver);
|
List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver);
|
||||||
addTask(result, call, convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver), dataFlowInfo);
|
addTask(result, convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver), context, functionReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
addTask(result, call, nonlocals, dataFlowInfo);
|
addTask(result, nonlocals, context, functionReference);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Collection<ResolvedCallImpl<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), getNonExtensionsByName(scope, name));
|
Collection<ResolvedCallImpl<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), getNonExtensionsByName(scope, name));
|
||||||
@@ -137,13 +138,13 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
//noinspection unchecked,RedundantTypeArguments
|
//noinspection unchecked,RedundantTypeArguments
|
||||||
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals);
|
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals);
|
||||||
|
|
||||||
addTask(result, call, locals, dataFlowInfo);
|
addTask(result, locals, context, functionReference);
|
||||||
|
|
||||||
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
|
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
|
||||||
doComputeTasks(scope, implicitReceiver, call, name, result, autoCastService);
|
doComputeTasks(scope, implicitReceiver, name, result, context, functionReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
addTask(result, call, nonlocals, dataFlowInfo);
|
addTask(result, nonlocals, context, functionReference);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,9 +212,9 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull Call call, @NotNull Collection<ResolvedCallImpl<D>> candidates, @NotNull DataFlowInfo dataFlowInfo) {
|
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull Collection<ResolvedCallImpl<D>> candidates, @NotNull BasicResolutionContext context, @NotNull JetReferenceExpression functionReference) {
|
||||||
if (candidates.isEmpty()) return;
|
if (candidates.isEmpty()) return;
|
||||||
result.add(new ResolutionTask<D>(candidates, call, dataFlowInfo));
|
result.add(new ResolutionTask<D>(candidates, functionReference, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
Reference in New Issue
Block a user