Refactoring CallResolver to use context objects

This commit is contained in:
Andrey Breslav
2012-03-14 18:33:30 +04:00
parent 7ef65c0099
commit e6020725fe
7 changed files with 325 additions and 237 deletions
@@ -91,7 +91,7 @@ public class AnnotationResolver {
private OverloadResolutionResults<FunctionDescriptor> resolveType(@NotNull JetScope scope,
@NotNull JetAnnotationEntry entryElement,
@NotNull AnnotationDescriptor descriptor, BindingTrace trace) {
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCall(trace, scope, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, entryElement), NO_EXPECTED_TYPE, DataFlowInfo.EMPTY);
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(trace, scope, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, entryElement), NO_EXPECTED_TYPE, DataFlowInfo.EMPTY);
JetType annotationType = results.getResultingDescriptor().getReturnType();
if (results.isSuccess()) {
descriptor.setAnnotationType(annotationType);
@@ -23,6 +23,7 @@ import com.intellij.util.containers.Queue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.BasicResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
@@ -167,7 +168,7 @@ public class BodyResolver {
assert descriptor.getKind() == ClassKind.TRAIT;
return;
}
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCall(
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(
context.getTrace(), scopeForConstructor,
CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, DataFlowInfo.EMPTY);
if (results.isSuccess()) {
@@ -345,7 +346,7 @@ public class BodyResolver {
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) {
callResolver.resolveCall(context.getTrace(), scopeForSupertypeInitializers, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo);
callResolver.resolveFunctionCall(context.getTrace(), scopeForSupertypeInitializers, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo);
}
}
@@ -355,9 +356,9 @@ public class BodyResolver {
// TODO : check: if a this() call is present, no other initializers are allowed
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
callResolver.resolveCall(context.getTrace(),
scopeForSupertypeInitializers,
CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo);
callResolver.resolveFunctionCall(context.getTrace(),
scopeForSupertypeInitializers,
CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo);
// call.getThisReference(),
// classDescriptor,
// classDescriptor.getDefaultType(),
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class BasicResolutionContext extends ResolutionContext {
@NotNull
public static BasicResolutionContext create(@NotNull BindingTrace trace, @NotNull JetScope scope, @NotNull Call call, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo) {
return new BasicResolutionContext(trace, scope, call, expectedType, dataFlowInfo);
}
private BasicResolutionContext(BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo) {
super(trace, scope, call, expectedType, dataFlowInfo);
}
}
@@ -93,13 +93,8 @@ public class CallResolver {
@NotNull
public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@NotNull Call call,
@NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo) {
JetExpression calleeExpression = call.getCalleeExpression();
public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicResolutionContext context) {
JetExpression calleeExpression = context.call.getCalleeExpression();
assert calleeExpression instanceof JetSimpleNameExpression;
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
String referencedName = nameExpression.getReferencedName();
@@ -114,52 +109,39 @@ public class CallResolver {
else {
task_prioritizer = TaskPrioritizers.VARIABLE_TASK_PRIORITIZER;
}
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = task_prioritizer.computePrioritizedTasks(scope, call, referencedName, trace.getBindingContext(), dataFlowInfo);
return resolveCallToDescriptor(trace, scope, call, expectedType, prioritizedTasks, nameExpression, dataFlowInfo);
}
@NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveCall(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@NotNull Call call,
@NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo) {
return resolveSimpleCallToFunctionDescriptor(trace, scope, call, expectedType, dataFlowInfo);
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = task_prioritizer.computePrioritizedTasks(context.scope, context.call, referencedName, context.trace.getBindingContext(), context.dataFlowInfo);
return resolveCallToDescriptor(context, prioritizedTasks, nameExpression);
}
@NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@NotNull final Call call,
@NotNull BasicResolutionContext context,
@NotNull final JetReferenceExpression functionReference,
@NotNull String name,
@NotNull JetType expectedType, DataFlowInfo dataFlowInfo) {
@NotNull String name) {
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(
scope, call, name, trace.getBindingContext(), dataFlowInfo);
return doResolveCall(trace, scope, call, expectedType, tasks, functionReference, dataFlowInfo);
context.scope, context.call, name, context.trace.getBindingContext(), context.dataFlowInfo);
return doResolveCall(context, tasks, functionReference);
}
@NotNull
private OverloadResolutionResults<FunctionDescriptor> resolveSimpleCallToFunctionDescriptor(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@NotNull final Call call,
@NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo) {
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo) {
return resolveFunctionCall(BasicResolutionContext.create(trace, scope, call, expectedType, dataFlowInfo));
}
@NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicResolutionContext context) {
List<ResolutionTask<FunctionDescriptor>> prioritizedTasks;
JetExpression calleeExpression = call.getCalleeExpression();
JetExpression calleeExpression = context.call.getCalleeExpression();
final JetReferenceExpression functionReference;
if (calleeExpression instanceof JetSimpleNameExpression) {
JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
functionReference = expression;
String name = expression.getReferencedName();
if (name == null) return checkArgumentTypesAndFail(trace, scope, call);
if (name == null) return checkArgumentTypesAndFail(context);
prioritizedTasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, call, name, trace.getBindingContext(), dataFlowInfo);
prioritizedTasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(context.scope, context.call, name, context.trace.getBindingContext(), context.dataFlowInfo);
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
@Override
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
@@ -178,39 +160,39 @@ public class CallResolver {
}
}
else {
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
PsiElement reportAbsenceOn = valueArgumentList == null ? call.getCallElement() : valueArgumentList;
JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList;
if (calleeExpression instanceof JetConstructorCalleeExpression) {
assert !call.getExplicitReceiver().exists();
assert !context.call.getExplicitReceiver().exists();
prioritizedTasks = Lists.newArrayList();
JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression;
functionReference = expression.getConstructorReferenceExpression();
if (functionReference == null) {
return checkArgumentTypesAndFail(trace, scope, call); // No type there
return checkArgumentTypesAndFail(context); // No type there
}
JetTypeReference typeReference = expression.getTypeReference();
assert typeReference != null;
JetType constructedType = typeResolver.resolveType(scope, typeReference, trace, true);
JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
Set<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
if (constructors.isEmpty()) {
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(trace, scope, call);
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context);
}
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(TaskPrioritizer.<FunctionDescriptor>convertWithImpliedThis(scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors), call, DataFlowInfo.EMPTY));
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(TaskPrioritizer.<FunctionDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors), context.call, DataFlowInfo.EMPTY));
}
else {
trace.report(NOT_A_CLASS.on(calleeExpression));
return checkArgumentTypesAndFail(trace, scope, call);
context.trace.report(NOT_A_CLASS.on(calleeExpression));
return checkArgumentTypesAndFail(context);
}
}
else if (calleeExpression instanceof JetThisReferenceExpression) {
functionReference = (JetThisReferenceExpression) calleeExpression;
DeclarationDescriptor containingDeclaration = scope.getContainingDeclaration();
DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration();
if (containingDeclaration instanceof ConstructorDescriptor) {
containingDeclaration = containingDeclaration.getContainingDeclaration();
}
@@ -219,29 +201,29 @@ public class CallResolver {
Set<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
if (constructors.isEmpty()) {
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(trace, scope, call);
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context);
}
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(ResolvedCallImpl.<FunctionDescriptor>convertCollection(constructors), call, DataFlowInfo.EMPTY));
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(ResolvedCallImpl.<FunctionDescriptor>convertCollection(constructors), context.call, DataFlowInfo.EMPTY));
}
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)
JetType calleeType = expressionTypingServices.safeGetType(scope, calleeExpression, NO_EXPECTED_TYPE, trace); // We are actually expecting a function, but there seems to be no easy way of expressing this
JetType calleeType = expressionTypingServices.safeGetType(context.scope, calleeExpression, NO_EXPECTED_TYPE, context.trace); // We are actually expecting a function, but there seems to be no easy way of expressing this
if (!JetStandardClasses.isFunctionType(calleeType)) {
// checkTypesWithNoCallee(trace, scope, call);
if (!ErrorUtils.isErrorType(calleeType)) {
trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType));
context.trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType));
}
return checkArgumentTypesAndFail(trace, scope, call);
return checkArgumentTypesAndFail(context);
}
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
resolvedCall.setReceiverArgument(call.getExplicitReceiver());
resolvedCall.setReceiverArgument(context.call.getExplicitReceiver());
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(
Collections.singleton(resolvedCall), call, dataFlowInfo));
Collections.singleton(resolvedCall), context.call, context.dataFlowInfo));
// strictly speaking, this is a hack:
// we need to pass a reference, but there's no reference in the PSI,
@@ -250,43 +232,35 @@ public class CallResolver {
}
else {
// checkTypesWithNoCallee(trace, scope, call);
return checkArgumentTypesAndFail(trace, scope, call);
return checkArgumentTypesAndFail(context);
}
}
return resolveCallToDescriptor(trace, scope, call, expectedType, prioritizedTasks, functionReference, dataFlowInfo);
return resolveCallToDescriptor(context, prioritizedTasks, functionReference);
}
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BindingTrace trace, JetScope scope, Call call) {
checkTypesWithNoCallee(trace, scope, call);
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) {
checkTypesWithNoCallee(context);
return OverloadResolutionResultsImpl.nameNotFound();
}
@NotNull
private <D extends CallableDescriptor> OverloadResolutionResults<D> resolveCallToDescriptor(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@NotNull final Call call,
@NotNull JetType expectedType,
@NotNull BasicResolutionContext context,
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
@NotNull final JetReferenceExpression reference,
@NotNull DataFlowInfo dataFlowInfo) {
return doResolveCall(trace, scope, call, expectedType, prioritizedTasks, reference, dataFlowInfo);
@NotNull final JetReferenceExpression reference) {
return doResolveCall(context, prioritizedTasks, reference);
}
@NotNull
private <D extends CallableDescriptor> OverloadResolutionResults<D> doResolveCall(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@NotNull final Call call,
@NotNull JetType expectedType,
@NotNull final BasicResolutionContext context,
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
@NotNull final JetReferenceExpression reference,
@NotNull DataFlowInfo dataFlowInfo) {
@NotNull final JetReferenceExpression reference) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, call.getCallElement(), debugInfo);
trace.record(RESOLUTION_SCOPE, call.getCalleeExpression(), scope);
context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
@@ -300,7 +274,7 @@ public class CallResolver {
// }
// else {
// }
trace.record(RESOLVED_CALL, call.getCalleeExpression(), resolvedCall);
trace.record(RESOLVED_CALL, context.call.getCalleeExpression(), resolvedCall);
trace.record(REFERENCE_TARGET, reference, descriptor);
}
@@ -321,7 +295,7 @@ public class CallResolver {
@Override
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
PsiElement reportOn;
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
if (valueArgumentList != null) {
reportOn = valueArgumentList;
}
@@ -354,7 +328,7 @@ public class CallResolver {
@Override
public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {
JetTypeArgumentList typeArgumentList = call.getTypeArgumentList();
JetTypeArgumentList typeArgumentList = context.call.getTypeArgumentList();
if (typeArgumentList != null) {
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeArgumentList, expectedTypeArgumentCount));
}
@@ -365,7 +339,7 @@ public class CallResolver {
@Override
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {
trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(call.getCallElement(), descriptors));
trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(context.call.getCallElement(), descriptors));
}
@Override
@@ -375,23 +349,23 @@ public class CallResolver {
@Override
public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {
trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement()));
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(call.getCallElement(), status));
trace.report(TYPE_INFERENCE_FAILED.on(context.call.getCallElement(), status));
}
@Override
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
ASTNode callOperationNode = call.getCallOperationNode();
ASTNode callOperationNode = context.call.getCallOperationNode();
if (callOperationNode != null) {
trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type));
}
else {
PsiElement callElement = call.getCallElement();
PsiElement callElement = context.call.getCallElement();
if (callElement instanceof JetBinaryExpression) {
JetBinaryExpression binaryExpression = (JetBinaryExpression) callElement;
JetSimpleNameExpression operationReference = binaryExpression.getOperationReference();
@@ -413,7 +387,7 @@ public class CallResolver {
@Override
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
ASTNode callOperationNode = call.getCallOperationNode();
ASTNode callOperationNode = context.call.getCallOperationNode();
assert callOperationNode != null;
trace.report(UNNECESSARY_SAFE_CALL.on(callOperationNode.getPsi(), type));
}
@@ -429,8 +403,9 @@ public class CallResolver {
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
OverloadResolutionResultsImpl<D> resultsForFirstNonemptyCandidateSet = null;
for (ResolutionTask<D> task : prioritizedTasks) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
OverloadResolutionResultsImpl<D> results = performResolutionGuardedForExtraFunctionLiteralArguments(temporaryTrace, scope, expectedType, task, tracing, dataFlowInfo);
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
BasicResolutionContext newContext = BasicResolutionContext.create(temporaryTrace, context.scope, task.getCall(), context.expectedType, context.dataFlowInfo);
OverloadResolutionResultsImpl<D> results = performResolutionGuardedForExtraFunctionLiteralArguments(new TaskResolutionContext<D>(task, tracing, newContext));
if (results.isSuccess()) {
temporaryTrace.commit();
@@ -451,8 +426,8 @@ public class CallResolver {
}
}
else {
trace.report(UNRESOLVED_REFERENCE.on(reference));
checkTypesWithNoCallee(trace, scope, call);
context.trace.report(UNRESOLVED_REFERENCE.on(reference));
checkTypesWithNoCallee(context);
}
return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.<D>nameNotFound();
}
@@ -460,12 +435,8 @@ public class CallResolver {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(
@NotNull BindingTrace trace,
@NotNull JetScope scope, @NotNull JetType expectedType,
@NotNull ResolutionTask<D> task, @NotNull TracingStrategy tracing, @NotNull DataFlowInfo dataFlowInfo
) {
OverloadResolutionResultsImpl<D> results = performResolution(trace, scope, expectedType, task, tracing, dataFlowInfo);
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(TaskResolutionContext<D> context) {
OverloadResolutionResultsImpl<D> results = performResolution(context);
// If resolution fails, we should check for some of the following situations:
// class A {
@@ -484,24 +455,27 @@ public class CallResolver {
// }
EnumSet<OverloadResolutionResults.Code> someFailed = EnumSet.of(OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES,
OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
if (someFailed.contains(results.getResultCode()) && !task.getCall().getFunctionLiteralArguments().isEmpty()) {
if (someFailed.contains(results.getResultCode()) && !context.call.getFunctionLiteralArguments().isEmpty()) {
// We have some candidates that failed for some reason
// And we have a suspect: the function literal argument
// Now, we try to remove this argument and see if it helps
Collection<ResolvedCallImpl<D>> newCandidates = Lists.newArrayList();
for (ResolvedCallImpl<D> candidate : task.getCandidates()) {
for (ResolvedCallImpl<D> candidate : context.task.getCandidates()) {
newCandidates.add(ResolvedCallImpl.create(candidate.getCandidateDescriptor()));
}
ResolutionTask<D> newTask = new ResolutionTask<D>(newCandidates, new DelegatingCall(task.getCall()) {
ResolutionTask<D> newTask = new ResolutionTask<D>(newCandidates, new DelegatingCall(context.call) {
@NotNull
@Override
public List<JetExpression> getFunctionLiteralArguments() {
return Collections.emptyList();
}
}, task.getDataFlowInfo());
OverloadResolutionResultsImpl<D> resultsWithFunctionLiteralsStripped = performResolution(TemporaryBindingTrace.create(trace), scope, expectedType, newTask, tracing, dataFlowInfo);
}, context.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);
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
tracing.danglingFunctionLiteralArgumentSuspected(trace, task.getCall().getFunctionLiteralArguments());
context.tracing.danglingFunctionLiteralArgumentSuspected(context.trace, context.call.getFunctionLiteralArguments());
}
}
@@ -509,116 +483,36 @@ public class CallResolver {
}
@NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(
@NotNull BindingTrace trace,
@NotNull JetScope scope, @NotNull JetType expectedType,
@NotNull ResolutionTask<D> task, @NotNull TracingStrategy tracing, DataFlowInfo dataFlowInfo
) {
for (ResolvedCallImpl<D> candidateCall : task.getCandidates()) {
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(TaskResolutionContext<D> taskContext) {
for (ResolvedCallImpl<D> candidateCall : taskContext.task.getCandidates()) {
D candidate = candidateCall.getCandidateDescriptor();
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(taskContext.trace);
candidateCall.setTrace(temporaryTrace);
tracing.bindReference(temporaryTrace, candidateCall);
CallResolutionContext<D> context = new CallResolutionContext<D>(candidateCall, taskContext, temporaryTrace, taskContext.tracing);
context.tracing.bindReference(context.trace, candidateCall);
if (ErrorUtils.isError(candidate)) {
candidateCall.setStatus(SUCCESS);
checkTypesWithNoCallee(temporaryTrace, scope, task.getCall());
checkTypesWithNoCallee(context.toBasic());
continue;
}
boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(task, tracing, candidateCall);
boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing, candidateCall);
if (errorInArgumentMapping) {
candidateCall.setStatus(OTHER_ERROR);
checkTypesWithNoCallee(temporaryTrace, scope, task.getCall());
checkTypesWithNoCallee(context.toBasic());
continue;
}
List<JetTypeProjection> jetTypeArguments = task.getCall().getTypeArguments();
List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
if (jetTypeArguments.isEmpty()) {
if (!candidate.getTypeParameters().isEmpty()) {
// Type argument inference
ResolutionDebugInfo.Data debugInfo = trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, task.getCall().getCallElement());
ConstraintSystem constraintSystem = new ConstraintSystemWithPriorities(new DebugConstraintResolutionListener(candidateCall, debugInfo));
// If the call is recursive, e.g.
// fun foo<T>(t : T) : T = foo(t)
// we can't use same descriptor objects for T's as actual type values and same T's as unknowns,
// because constraints become trivial (T :< T), and inference fails
//
// Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion)
CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate);
for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
}
TypeSubstitutor substituteDontCare = ConstraintSystemImpl.makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
// Value parameters
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
ResolvedValueArgument valueArgument = entry.getValue();
ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor);
for (JetExpression expression : valueArgument.getArgumentExpressions()) {
// TODO : more attempts, with different expected types
// Here we type check expecting an error type (that is a subtype of any type and a supertype of any type
// and throw the results away
// We'll type check the arguments later, with the inferred types expected
TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(temporaryTrace);
JetType type = expressionTypingServices.getType(scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT), traceForUnknown);
if (type != null && !ErrorUtils.isErrorType(type)) {
constraintSystem.addSubtypingConstraint(VALUE_ARGUMENT.assertSubtyping(type, effectiveExpectedType));
}
else {
candidateCall.argumentHasNoType();
}
}
}
// Receiver
// Error is already reported if something is missing
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
if (receiverArgument.exists() && receiverParameter.exists()) {
constraintSystem.addSubtypingConstraint(RECEIVER.assertSubtyping(receiverArgument.getType(), receiverParameter.getType()));
}
// Return type
if (expectedType != NO_EXPECTED_TYPE) {
constraintSystem.addSubtypingConstraint(EXPECTED_TYPE.assertSubtyping(candidateWithFreshVariables.getReturnType(), expectedType));
}
// Solution
ConstraintSystemSolution solution = constraintSystem.solve();
if (solution.getStatus().isSuccessful()) {
D substitute = (D) candidateWithFreshVariables.substitute(solution.getSubstitutor());
assert substitute != null;
replaceValueParametersWithSubstitutedOnes(candidateCall, substitute);
candidateCall.setResultingDescriptor(substitute);
for (TypeParameterDescriptor typeParameterDescriptor : candidateCall.getCandidateDescriptor().getTypeParameters()) {
candidateCall.recordTypeArgument(typeParameterDescriptor, solution.getValue(candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex())));
}
// Here we type check the arguments with inferred types expected
checkValueArgumentTypes(scope, candidateCall, dataFlowInfo);
candidateCall.setStatus(SUCCESS);
}
else {
tracing.typeInferenceFailed(temporaryTrace, solution.getStatus());
candidateCall.setStatus(OTHER_ERROR.combine(checkAllValueArguments(scope, tracing, task, candidateCall, dataFlowInfo)));
}
candidateCall.setStatus(inferTypeArguments(context));
}
else {
candidateCall.setStatus(checkAllValueArguments(scope, tracing, task, candidateCall, dataFlowInfo));
candidateCall.setStatus(checkAllValueArguments(context));
}
}
else {
@@ -627,11 +521,11 @@ public class CallResolver {
List<JetType> typeArguments = new ArrayList<JetType>();
for (JetTypeProjection projection : jetTypeArguments) {
if (projection.getProjectionKind() != JetProjectionKind.NONE) {
temporaryTrace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
}
JetTypeReference typeReference = projection.getTypeReference();
if (typeReference != null) {
typeArguments.add(typeResolver.resolveType(scope, typeReference, temporaryTrace, true));
typeArguments.add(typeResolver.resolveType(context.scope, typeReference, context.trace, true));
}
else {
typeArguments.add(ErrorUtils.createErrorType("Star projection in a call"));
@@ -640,7 +534,7 @@ public class CallResolver {
int expectedTypeArgumentCount = candidate.getTypeParameters().size();
if (expectedTypeArgumentCount == jetTypeArguments.size()) {
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, temporaryTrace);
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
Map<TypeConstructor, TypeProjection> substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext));
@@ -653,21 +547,21 @@ public class CallResolver {
TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
candidateCall.recordTypeArgument(typeParameterDescriptor, typeArguments.get(i));
}
candidateCall.setStatus(checkAllValueArguments(scope, tracing, task, candidateCall, dataFlowInfo));
candidateCall.setStatus(checkAllValueArguments(context));
}
else {
candidateCall.setStatus(OTHER_ERROR);
tracing.wrongNumberOfTypeArguments(temporaryTrace, expectedTypeArgumentCount);
context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
}
}
task.performAdvancedChecks(candidate, temporaryTrace, tracing);
taskContext.task.performAdvancedChecks(candidate, context.trace, context.tracing);
// 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
// See TaskPrioritizer for more
JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
if (superExpression != null) {
temporaryTrace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
candidateCall.setStatus(OTHER_ERROR);
}
@@ -677,7 +571,7 @@ public class CallResolver {
Set<ResolvedCallImpl<D>> successfulCandidates = Sets.newLinkedHashSet();
Set<ResolvedCallImpl<D>> failedCandidates = Sets.newLinkedHashSet();
for (ResolvedCallImpl<D> candidateCall : task.getCandidates()) {
for (ResolvedCallImpl<D> candidateCall : taskContext.task.getCandidates()) {
ResolutionStatus status = candidateCall.getStatus();
if (status.isSuccess()) {
successfulCandidates.add(candidateCall);
@@ -688,13 +582,96 @@ public class CallResolver {
}
}
OverloadResolutionResultsImpl<D> results = computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates);
OverloadResolutionResultsImpl<D> results = computeResultAndReportErrors(taskContext.trace, taskContext.tracing, successfulCandidates, failedCandidates);
if (!results.singleResult()) {
checkTypesWithNoCallee(trace, scope, task.getCall());
checkTypesWithNoCallee(taskContext.toBasic());
}
return results;
}
private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallResolutionContext<D> context) {
ResolvedCallImpl<D> candidateCall = context.candidateCall;
D candidate = candidateCall.getCandidateDescriptor();
ResolutionDebugInfo.Data debugInfo = context.trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement());
ConstraintSystem constraintSystem = new ConstraintSystemWithPriorities(new DebugConstraintResolutionListener(candidateCall, debugInfo));
// If the call is recursive, e.g.
// fun foo<T>(t : T) : T = foo(t)
// we can't use same descriptor objects for T's as actual type values and same T's as unknowns,
// because constraints become trivial (T :< T), and inference fails
//
// Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion)
CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate);
for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
}
TypeSubstitutor substituteDontCare = ConstraintSystemImpl.makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
// Value parameters
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
ResolvedValueArgument valueArgument = entry.getValue();
ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor);
for (JetExpression expression : valueArgument.getArgumentExpressions()) {
// TODO : more attempts, with different expected types
// Here we type check expecting an error type (that is a subtype of any type and a supertype of any type
// and throw the results away
// We'll type check the arguments later, with the inferred types expected
TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(context.trace);
JetType type = expressionTypingServices.getType(context.scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT), traceForUnknown);
if (type != null && !ErrorUtils.isErrorType(type)) {
constraintSystem.addSubtypingConstraint(VALUE_ARGUMENT.assertSubtyping(type, effectiveExpectedType));
}
else {
candidateCall.argumentHasNoType();
}
}
}
// Receiver
// Error is already reported if something is missing
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
if (receiverArgument.exists() && receiverParameter.exists()) {
constraintSystem.addSubtypingConstraint(RECEIVER.assertSubtyping(receiverArgument.getType(), receiverParameter.getType()));
}
// Return type
if (context.expectedType != NO_EXPECTED_TYPE) {
constraintSystem.addSubtypingConstraint(EXPECTED_TYPE.assertSubtyping(candidateWithFreshVariables.getReturnType(), context.expectedType));
}
// Solution
ConstraintSystemSolution solution = constraintSystem.solve();
if (solution.getStatus().isSuccessful()) {
D substitute = (D) candidateWithFreshVariables.substitute(solution.getSubstitutor());
assert substitute != null;
replaceValueParametersWithSubstitutedOnes(candidateCall, substitute);
candidateCall.setResultingDescriptor(substitute);
for (TypeParameterDescriptor typeParameterDescriptor : candidateCall.getCandidateDescriptor().getTypeParameters()) {
candidateCall.recordTypeArgument(typeParameterDescriptor, solution.getValue(candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex())));
}
// Here we type check the arguments with inferred types expected
checkValueArgumentTypes(context);
return SUCCESS;
}
else {
context.tracing.typeInferenceFailed(context.trace, solution.getStatus());
return OTHER_ERROR.combine(checkAllValueArguments(context));
}
}
private static JetType getEffectiveExpectedType(ValueParameterDescriptor valueParameterDescriptor) {
JetType effectiveExpectedType = valueParameterDescriptor.getVarargElementType();
if (effectiveExpectedType == null) {
@@ -722,25 +699,25 @@ public class CallResolver {
}
}
private void checkTypesWithNoCallee(BindingTrace trace, JetScope scope, Call call) {
for (ValueArgument valueArgument : call.getValueArguments()) {
private void checkTypesWithNoCallee(BasicResolutionContext context) {
for (ValueArgument valueArgument : context.call.getValueArguments()) {
JetExpression argumentExpression = valueArgument.getArgumentExpression();
if (argumentExpression != null) {
expressionTypingServices.getType(scope, argumentExpression, NO_EXPECTED_TYPE, trace);
expressionTypingServices.getType(context.scope, argumentExpression, NO_EXPECTED_TYPE, context.trace);
}
}
for (JetExpression expression : call.getFunctionLiteralArguments()) {
expressionTypingServices.getType(scope, expression, NO_EXPECTED_TYPE, trace);
for (JetExpression expression : context.call.getFunctionLiteralArguments()) {
expressionTypingServices.getType(context.scope, expression, NO_EXPECTED_TYPE, context.trace);
}
for (JetTypeProjection typeProjection : call.getTypeArguments()) {
for (JetTypeProjection typeProjection : context.call.getTypeArguments()) {
JetTypeReference typeReference = typeProjection.getTypeReference();
if (typeReference == null) {
trace.report(Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeProjection));
context.trace.report(Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeProjection));
}
else {
typeResolver.resolveType(scope, typeReference, trace, true);
typeResolver.resolveType(context.scope, typeReference, context.trace, true);
}
}
}
@@ -763,24 +740,23 @@ public class CallResolver {
}
}
private <D extends CallableDescriptor> ResolutionStatus checkAllValueArguments(JetScope scope, TracingStrategy tracing, ResolutionTask<D> task, ResolvedCallImpl<D> candidateCall, DataFlowInfo dataFlowInfo) {
ResolutionStatus result = checkValueArgumentTypes(scope, candidateCall, dataFlowInfo);
result = result.combine(checkReceiver(tracing, candidateCall, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument(), task));
result = result.combine(checkReceiver(tracing, candidateCall, candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(), task));
private <D extends CallableDescriptor> ResolutionStatus checkAllValueArguments(CallResolutionContext<D> context) {
ResolutionStatus result = checkValueArgumentTypes(context);
ResolvedCall candidateCall = context.candidateCall;
result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument()));
result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject()));
return result;
}
private <D extends CallableDescriptor> ResolutionStatus checkReceiver(TracingStrategy tracing, ResolvedCallImpl<D> candidateCall,
ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument,
ResolutionTask<D> task) {
private <D extends CallableDescriptor> ResolutionStatus checkReceiver(CallResolutionContext<D> context, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument) {
ResolutionStatus result = SUCCESS;
if (receiverParameter.exists() && receiverArgument.exists()) {
ASTNode callOperationNode = task.getCall().getCallOperationNode();
ASTNode callOperationNode = context.call.getCallOperationNode();
boolean safeAccess = callOperationNode != null && callOperationNode.getElementType() == JetTokens.SAFE_ACCESS;
JetType receiverArgumentType = receiverArgument.getType();
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(task.getDataFlowInfo(), candidateCall.getTrace().getBindingContext());
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.candidateCall.getTrace().getBindingContext());
if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) {
tracing.unsafeCall(candidateCall.getTrace(), receiverArgumentType);
context.tracing.unsafeCall(context.candidateCall.getTrace(), receiverArgumentType);
result = UNSAFE_CALL_ERROR;
}
else {
@@ -788,21 +764,21 @@ public class CallResolver {
? TypeUtils.makeNotNullable(receiverArgumentType)
: receiverArgumentType;
if (!typeChecker.isSubtypeOf(effectiveReceiverArgumentType, receiverParameter.getType())) {
tracing.wrongReceiverType(candidateCall.getTrace(), receiverParameter, receiverArgument);
context.tracing.wrongReceiverType(context.candidateCall.getTrace(), receiverParameter, receiverArgument);
result = OTHER_ERROR;
}
}
if (safeAccess && (receiverParameter.getType().isNullable() || !receiverArgumentType.isNullable())) {
tracing.unnecessarySafeCall(candidateCall.getTrace(), receiverArgumentType);
context.tracing.unnecessarySafeCall(context.candidateCall.getTrace(), receiverArgumentType);
}
}
return result;
}
private <D extends CallableDescriptor> ResolutionStatus checkValueArgumentTypes(JetScope scope, ResolvedCallImpl<D> candidateCall, DataFlowInfo dataFlowInfo) {
private <D extends CallableDescriptor> ResolutionStatus checkValueArgumentTypes(CallResolutionContext<D> context) {
ResolutionStatus result = SUCCESS;
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : context.candidateCall.getValueArguments().entrySet()) {
ValueParameterDescriptor parameterDescriptor = entry.getKey();
ResolvedValueArgument resolvedArgument = entry.getValue();
@@ -810,9 +786,9 @@ public class CallResolver {
List<JetExpression> argumentExpressions = resolvedArgument.getArgumentExpressions();
for (JetExpression argumentExpression : argumentExpressions) {
JetType type = expressionTypingServices.getType(scope, argumentExpression, parameterType, dataFlowInfo, candidateCall.getTrace());
JetType type = expressionTypingServices.getType(context.scope, argumentExpression, parameterType, context.dataFlowInfo, context.candidateCall.getTrace());
if (type == null || ErrorUtils.isErrorType(type)) {
candidateCall.argumentHasNoType();
context.candidateCall.argumentHasNoType();
}
else if (!typeChecker.isSubtypeOf(type, parameterType)) {
// VariableDescriptor variableDescriptor = AutoCastUtils.getVariableDescriptorFromSimpleName(temporaryTrace.getBindingContext(), argumentExpression);
@@ -1056,4 +1032,26 @@ public class CallResolver {
}
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 {
/*package*/ final ResolvedCallImpl<D> candidateCall;
/*package*/ final TracingStrategy tracing;
public CallResolutionContext(ResolvedCallImpl<D> candidateCall, TaskResolutionContext<D> taskResolutionContext, BindingTrace trace, TracingStrategy tracing) {
super(trace, taskResolutionContext.scope, taskResolutionContext.task.getCall(), taskResolutionContext.expectedType, taskResolutionContext.dataFlowInfo);
this.candidateCall = candidateCall;
this.tracing = tracing;
}
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public abstract class ResolutionContext {
/*package*/ final BindingTrace trace;
/*package*/ final JetScope scope;
/*package*/ final Call call;
/*package*/ final JetType expectedType;
/*package*/ final DataFlowInfo dataFlowInfo;
protected ResolutionContext(BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo) {
this.trace = trace;
this.scope = scope;
this.call = call;
this.expectedType = expectedType;
this.dataFlowInfo = dataFlowInfo;
}
public BasicResolutionContext toBasic() {
return BasicResolutionContext.create(trace, scope, call, expectedType, dataFlowInfo);
}
}
@@ -38,7 +38,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
*/
/*package*/ class ValueArgumentsToParametersMapper {
public static <D extends CallableDescriptor> boolean mapValueArgumentsToParameters(
@NotNull ResolutionTask<D> task,
@NotNull Call call,
@NotNull TracingStrategy tracing,
@NotNull ResolvedCallImpl<D> candidateCall
) {
@@ -58,7 +58,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
parameterByName.put(valueParameter.getName(), valueParameter);
}
List<? extends ValueArgument> valueArguments = task.getCall().getValueArguments();
List<? extends ValueArgument> valueArguments = call.getValueArguments();
boolean error = false;
boolean someNamed = false;
@@ -117,7 +117,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
}
}
List<JetExpression> functionLiteralArguments = task.getCall().getFunctionLiteralArguments();
List<JetExpression> functionLiteralArguments = call.getFunctionLiteralArguments();
if (!functionLiteralArguments.isEmpty()) {
JetExpression possiblyLabeledFunctionLiteral = functionLiteralArguments.get(0);
@@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.BasicResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
@@ -153,9 +154,13 @@ public class ExpressionTypingContext {
////////// Call resolution utilities
private BasicResolutionContext makeResolutionContext(@NotNull Call call) {
return BasicResolutionContext.create(trace, scope, call, expectedType, dataFlowInfo);
}
@NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name) {
return expressionTypingServices.getCallResolver().resolveCallWithGivenName(trace, scope, call, functionReference, name, expectedType, dataFlowInfo);
return expressionTypingServices.getCallResolver().resolveCallWithGivenName(makeResolutionContext(call), functionReference, name);
}
@NotNull
@@ -166,14 +171,14 @@ public class ExpressionTypingContext {
@Nullable
public FunctionDescriptor resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) {
OverloadResolutionResults<FunctionDescriptor> results = expressionTypingServices.getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType, dataFlowInfo);
OverloadResolutionResults<FunctionDescriptor> results = expressionTypingServices.getCallResolver().resolveFunctionCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType, dataFlowInfo);
return results.singleResult() ? results.getResultingDescriptor() : null;
}
@NotNull
public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetSimpleNameExpression nameExpression) {
Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
return expressionTypingServices.getCallResolver().resolveSimpleProperty(trace, scope, call, expectedType, dataFlowInfo);
return expressionTypingServices.getCallResolver().resolveSimpleProperty(makeResolutionContext(call));
}
@NotNull