Refactoring: simplified resolveFunctionCall
Extracted resolveCallForConstructor, resolveCallForThisExpression
This commit is contained in:
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.calls;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -44,7 +43,6 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -181,6 +179,19 @@ public class CallResolver {
|
||||
return doResolveCallOrGetCachedResults(context, tasks, callTransformer, tracing);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksFromCandidatesAndResolvedCall(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull JetReferenceExpression referenceExpression,
|
||||
@NotNull Collection<ResolutionCandidate<D>> candidates,
|
||||
@NotNull CallTransformer<D, F> callTransformer
|
||||
) {
|
||||
TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call);
|
||||
List<ResolutionTask<D, F>> prioritizedTasks =
|
||||
taskPrioritizer.<D, F>computePrioritizedTasksFromCandidates(context, candidates, tracing);
|
||||
return doResolveCallOrGetCachedResults(context, prioritizedTasks, callTransformer, tracing);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolutionResults<FunctionDescriptor> resolveBinaryCall(
|
||||
ExpressionTypingContext context,
|
||||
@@ -214,94 +225,88 @@ public class CallResolver {
|
||||
|
||||
@NotNull
|
||||
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
|
||||
|
||||
ProgressIndicatorProvider.checkCanceled();
|
||||
|
||||
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks;
|
||||
|
||||
JetExpression calleeExpression = context.call.getCalleeExpression();
|
||||
JetReferenceExpression functionReference;
|
||||
if (calleeExpression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
|
||||
Name name = expression.getReferencedNameAsName();
|
||||
return computeTasksAndResolveCall(context, name, expression, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES,
|
||||
CallTransformer.FUNCTION_CALL_TRANSFORMER);
|
||||
return computeTasksAndResolveCall(
|
||||
context, expression.getReferencedNameAsName(), expression,
|
||||
CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
|
||||
}
|
||||
else {
|
||||
JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
|
||||
PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList;
|
||||
if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||
assert !context.call.getExplicitReceiver().exists();
|
||||
|
||||
JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression;
|
||||
functionReference = expression.getConstructorReferenceExpression();
|
||||
if (functionReference == null) {
|
||||
return checkArgumentTypesAndFail(context); // No type there
|
||||
}
|
||||
JetTypeReference typeReference = expression.getTypeReference();
|
||||
assert typeReference != null;
|
||||
JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
|
||||
|
||||
if (constructedType.isError()) {
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
|
||||
DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
|
||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
|
||||
if (constructors.isEmpty()) {
|
||||
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
Collection<ResolutionCandidate<CallableDescriptor>> candidates =
|
||||
taskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(
|
||||
context.scope, constructors, context.call);
|
||||
prioritizedTasks = taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
|
||||
context, candidates, TracingStrategyImpl.create(functionReference, context.call));
|
||||
}
|
||||
else {
|
||||
context.trace.report(NOT_A_CLASS.on(calleeExpression));
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
}
|
||||
else if (calleeExpression instanceof JetThisReferenceExpression) {
|
||||
functionReference = (JetThisReferenceExpression) calleeExpression;
|
||||
DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof ConstructorDescriptor) {
|
||||
containingDeclaration = containingDeclaration.getContainingDeclaration();
|
||||
}
|
||||
assert containingDeclaration instanceof ClassDescriptor;
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||
|
||||
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
|
||||
if (constructors.isEmpty()) {
|
||||
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
List<ResolutionCandidate<CallableDescriptor>> candidates =
|
||||
ResolutionCandidate.<CallableDescriptor>convertCollection(context.call, constructors);
|
||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! 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(context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
||||
ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
|
||||
|
||||
Call call = new CallTransformer.CallForImplicitInvoke(
|
||||
context.call.getExplicitReceiver(), expressionReceiver, context.call);
|
||||
TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(
|
||||
calleeExpression, call, calleeType);
|
||||
return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
|
||||
}
|
||||
else {
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||
return resolveCallForConstructor(context, (JetConstructorCalleeExpression) calleeExpression);
|
||||
}
|
||||
else if (calleeExpression instanceof JetThisReferenceExpression) {
|
||||
return resolveCallForThisExpression(context, (JetThisReferenceExpression) calleeExpression);
|
||||
}
|
||||
else if (calleeExpression == null) {
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
|
||||
TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
|
||||
return doResolveCallOrGetCachedResults(context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
|
||||
// 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(
|
||||
context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
||||
ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
|
||||
|
||||
Call call = new CallTransformer.CallForImplicitInvoke(context.call.getExplicitReceiver(), expressionReceiver, context.call);
|
||||
TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, call, calleeType);
|
||||
return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
|
||||
}
|
||||
|
||||
private OverloadResolutionResults<FunctionDescriptor> resolveCallForConstructor(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull JetConstructorCalleeExpression expression
|
||||
) {
|
||||
assert !context.call.getExplicitReceiver().exists() :
|
||||
"Constructor can't be invoked with explicit receiver: " + context.call.getCallElement().getText();
|
||||
|
||||
JetReferenceExpression functionReference = expression.getConstructorReferenceExpression();
|
||||
JetTypeReference typeReference = expression.getTypeReference();
|
||||
if (functionReference == null || typeReference == null) {
|
||||
return checkArgumentTypesAndFail(context); // No type there
|
||||
}
|
||||
JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
|
||||
if (constructedType.isError()) {
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
|
||||
DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
|
||||
if (!(declarationDescriptor instanceof ClassDescriptor)) {
|
||||
context.trace.report(NOT_A_CLASS.on(expression));
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
|
||||
if (constructors.isEmpty()) {
|
||||
context.trace.report(NO_CONSTRUCTOR.on(CallUtilPackage.getValueArgumentListOrElement(context.call)));
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
Collection<ResolutionCandidate<CallableDescriptor>> candidates =
|
||||
taskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(context.scope, constructors, context.call);
|
||||
|
||||
return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER);
|
||||
}
|
||||
|
||||
private OverloadResolutionResults<FunctionDescriptor> resolveCallForThisExpression(
|
||||
@NotNull BasicCallResolutionContext context,
|
||||
@NotNull JetThisReferenceExpression calleeExpression
|
||||
) {
|
||||
DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof ConstructorDescriptor) {
|
||||
containingDeclaration = containingDeclaration.getContainingDeclaration();
|
||||
}
|
||||
assert containingDeclaration instanceof ClassDescriptor;
|
||||
|
||||
Collection<ConstructorDescriptor> constructors = ((ClassDescriptor) containingDeclaration).getConstructors();
|
||||
if (constructors.isEmpty()) {
|
||||
context.trace.report(NO_CONSTRUCTOR.on(CallUtilPackage.getValueArgumentListOrElement(context.call)));
|
||||
return checkArgumentTypesAndFail(context);
|
||||
}
|
||||
List<ResolutionCandidate<CallableDescriptor>> candidates =
|
||||
ResolutionCandidate.<CallableDescriptor>convertCollection(context.call, constructors);
|
||||
|
||||
return computeTasksFromCandidatesAndResolvedCall(context, calleeExpression, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER);
|
||||
}
|
||||
|
||||
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
|
||||
@@ -315,9 +320,9 @@ public class CallResolver {
|
||||
BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
|
||||
|
||||
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
|
||||
taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(basicCallResolutionContext, Collections.singleton(candidate), tracing);
|
||||
return doResolveCallOrGetCachedResults(
|
||||
basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
|
||||
taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
|
||||
basicCallResolutionContext, Collections.singleton(candidate), tracing);
|
||||
return doResolveCallOrGetCachedResults(basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
|
||||
}
|
||||
|
||||
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
|
||||
|
||||
+2
-8
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.descriptorUtil.DescriptorUtilPackage;
|
||||
@@ -66,14 +67,7 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
|
||||
|
||||
@Override
|
||||
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
|
||||
JetElement reportOn;
|
||||
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
||||
if (valueArgumentList != null) {
|
||||
reportOn = valueArgumentList;
|
||||
}
|
||||
else {
|
||||
reportOn = reference;
|
||||
}
|
||||
JetElement reportOn = CallUtilPackage.getValueArgumentListOrElement(call);
|
||||
trace.report(NO_VALUE_FOR_PARAMETER.on(reportOn, valueParameter));
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.jetbrains.jet.lang.psi.JetCallExpression
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralArgument
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral
|
||||
import org.jetbrains.jet.lang.psi.JetValueArgumentList
|
||||
|
||||
// resolved call
|
||||
|
||||
@@ -95,6 +96,8 @@ public fun Call.getValueArgumentsInParentheses(): List<ValueArgument> = getValue
|
||||
|
||||
public fun JetCallExpression.getValueArgumentsInParentheses(): List<ValueArgument> = getValueArguments().filterArgsInParentheses()
|
||||
|
||||
public fun Call.getValueArgumentListOrElement(): JetElement = getValueArgumentList() ?: getCalleeExpression() ?: getCallElement()
|
||||
|
||||
[suppress("UNCHECKED_CAST")]
|
||||
private fun List<ValueArgument?>.filterArgsInParentheses() = filter { it !is JetFunctionLiteralArgument } as List<ValueArgument>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user