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.ImmutableSet;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
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.*;
|
||||||
@@ -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.JetType;
|
||||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
|
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
|
||||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
||||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
|
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -181,6 +179,19 @@ public class CallResolver {
|
|||||||
return doResolveCallOrGetCachedResults(context, tasks, callTransformer, tracing);
|
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
|
@NotNull
|
||||||
public OverloadResolutionResults<FunctionDescriptor> resolveBinaryCall(
|
public OverloadResolutionResults<FunctionDescriptor> resolveBinaryCall(
|
||||||
ExpressionTypingContext context,
|
ExpressionTypingContext context,
|
||||||
@@ -214,94 +225,88 @@ public class CallResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
|
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
|
||||||
|
|
||||||
ProgressIndicatorProvider.checkCanceled();
|
ProgressIndicatorProvider.checkCanceled();
|
||||||
|
|
||||||
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks;
|
|
||||||
|
|
||||||
JetExpression calleeExpression = context.call.getCalleeExpression();
|
JetExpression calleeExpression = context.call.getCalleeExpression();
|
||||||
JetReferenceExpression functionReference;
|
|
||||||
if (calleeExpression instanceof JetSimpleNameExpression) {
|
if (calleeExpression instanceof JetSimpleNameExpression) {
|
||||||
JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
|
JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
|
||||||
Name name = expression.getReferencedNameAsName();
|
return computeTasksAndResolveCall(
|
||||||
return computeTasksAndResolveCall(context, name, expression, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES,
|
context, expression.getReferencedNameAsName(), expression,
|
||||||
CallTransformer.FUNCTION_CALL_TRANSFORMER);
|
CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
|
||||||
}
|
}
|
||||||
else {
|
if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||||
JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
|
return resolveCallForConstructor(context, (JetConstructorCalleeExpression) calleeExpression);
|
||||||
PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList;
|
}
|
||||||
if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
else if (calleeExpression instanceof JetThisReferenceExpression) {
|
||||||
assert !context.call.getExplicitReceiver().exists();
|
return resolveCallForThisExpression(context, (JetThisReferenceExpression) calleeExpression);
|
||||||
|
}
|
||||||
JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression;
|
else if (calleeExpression == null) {
|
||||||
functionReference = expression.getConstructorReferenceExpression();
|
return checkArgumentTypesAndFail(context);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
|
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
|
||||||
return doResolveCallOrGetCachedResults(context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
|
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(
|
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
|
||||||
@@ -315,9 +320,9 @@ public class CallResolver {
|
|||||||
BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
|
BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
|
||||||
|
|
||||||
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
|
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
|
||||||
taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(basicCallResolutionContext, Collections.singleton(candidate), tracing);
|
taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
|
||||||
return doResolveCallOrGetCachedResults(
|
basicCallResolutionContext, Collections.singleton(candidate), tracing);
|
||||||
basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
|
return doResolveCallOrGetCachedResults(basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
|
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.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
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.inference.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.descriptorUtil.DescriptorUtilPackage;
|
import org.jetbrains.jet.lang.resolve.descriptorUtil.DescriptorUtilPackage;
|
||||||
@@ -66,14 +67,7 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
|
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
|
||||||
JetElement reportOn;
|
JetElement reportOn = CallUtilPackage.getValueArgumentListOrElement(call);
|
||||||
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
|
||||||
if (valueArgumentList != null) {
|
|
||||||
reportOn = valueArgumentList;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reportOn = reference;
|
|
||||||
}
|
|
||||||
trace.report(NO_VALUE_FOR_PARAMETER.on(reportOn, valueParameter));
|
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.JetFunctionLiteralArgument
|
||||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression
|
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression
|
||||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral
|
import org.jetbrains.jet.lang.psi.JetFunctionLiteral
|
||||||
|
import org.jetbrains.jet.lang.psi.JetValueArgumentList
|
||||||
|
|
||||||
// resolved call
|
// resolved call
|
||||||
|
|
||||||
@@ -95,6 +96,8 @@ public fun Call.getValueArgumentsInParentheses(): List<ValueArgument> = getValue
|
|||||||
|
|
||||||
public fun JetCallExpression.getValueArgumentsInParentheses(): List<ValueArgument> = getValueArguments().filterArgsInParentheses()
|
public fun JetCallExpression.getValueArgumentsInParentheses(): List<ValueArgument> = getValueArguments().filterArgsInParentheses()
|
||||||
|
|
||||||
|
public fun Call.getValueArgumentListOrElement(): JetElement = getValueArgumentList() ?: getCalleeExpression() ?: getCallElement()
|
||||||
|
|
||||||
[suppress("UNCHECKED_CAST")]
|
[suppress("UNCHECKED_CAST")]
|
||||||
private fun List<ValueArgument?>.filterArgsInParentheses() = filter { it !is JetFunctionLiteralArgument } as List<ValueArgument>
|
private fun List<ValueArgument?>.filterArgsInParentheses() = filter { it !is JetFunctionLiteralArgument } as List<ValueArgument>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user