Refactor delegation call resolution

- Move resolution logic from BodyResolver to CallResolver
- Call resolveConstructorDelegationCall explicitly without resolveFunctionCall
- Drop dead condition and unused method
This commit is contained in:
Denis Zharkov
2015-03-15 12:47:44 +03:00
parent 9cecd69a9e
commit 52ba8333dc
2 changed files with 45 additions and 32 deletions
@@ -168,21 +168,11 @@ public class BodyResolver {
@NotNull JetSecondaryConstructor constructor,
@NotNull ConstructorDescriptor descriptor
) {
JetConstructorDelegationCall call = constructor.getDelegationCall();
if (call == null || call.getCalleeExpression() == null) return null;
JetType superClassType = DescriptorUtils.getSuperClassType(descriptor.getContainingDeclaration());
OverloadResolutionResults<?> results = callResolver.resolveConstructorDelegationCall(
trace, scope, c.getOuterDataFlowInfo(),
descriptor, constructor.getDelegationCall());
if (descriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS && call.getCalleeExpression().isEmpty()) {
return null;
}
OverloadResolutionResults<?> results = callResolver.resolveFunctionCall(
trace, scope,
CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
superClassType != null ? superClassType : NO_EXPECTED_TYPE,
c.getOuterDataFlowInfo(), false);
if (results.isSingleResult()) {
if (results != null && results.isSingleResult()) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = results.getResultingCall();
recordConstructorDelegationCall(trace, descriptor, resolvedCall);
return resolvedCall.getDataFlowInfoForArguments().getResultInfo();
@@ -238,9 +238,6 @@ public class CallResolver {
if (calleeExpression instanceof JetConstructorCalleeExpression) {
return resolveCallForConstructor(context, (JetConstructorCalleeExpression) calleeExpression);
}
else if (calleeExpression instanceof JetConstructorDelegationReferenceExpression) {
return resolveConstructorDelegationCall(context, (JetConstructorDelegationReferenceExpression) calleeExpression);
}
else if (calleeExpression == null) {
return checkArgumentTypesAndFail(context);
}
@@ -289,22 +286,58 @@ public class CallResolver {
return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER);
}
@Nullable
public OverloadResolutionResults<FunctionDescriptor> resolveConstructorDelegationCall(
@NotNull BindingTrace trace, @NotNull JetScope scope, @NotNull DataFlowInfo dataFlowInfo,
@NotNull ConstructorDescriptor constructorDescriptor,
@Nullable JetConstructorDelegationCall call
) {
// Returns `null` when there is nothing to resolve in trivial cases like `null` call expression or
// when super call should be conventional enum constructor and super call should be empty
if (call == null) return null;
JetType superClassType = DescriptorUtils.getSuperClassType(constructorDescriptor.getContainingDeclaration());
BasicCallResolutionContext context = BasicCallResolutionContext.create(
trace, scope,
CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
superClassType != null ? superClassType : NO_EXPECTED_TYPE,
dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
expressionTypingServices.getCallChecker(), expressionTypingServices.getAdditionalTypeChecker(), false);
if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context);
if (constructorDescriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS &&
call.getCalleeExpression().isEmpty()) {
return null;
}
return resolveConstructorDelegationCall(
context,
call.getCalleeExpression(),
constructorDescriptor
);
}
@NotNull
private OverloadResolutionResults<FunctionDescriptor> resolveConstructorDelegationCall(
@NotNull BasicCallResolutionContext context,
@NotNull JetConstructorDelegationReferenceExpression calleeExpression
@NotNull JetConstructorDelegationReferenceExpression calleeExpression,
@NotNull ConstructorDescriptor calleeConstructor
) {
ClassDescriptor currentClassDescriptor = getClassDescriptorByConstructorContext(context);
if (currentClassDescriptor.getKind() == ClassKind.ENUM_CLASS && !calleeExpression.isThis()) {
ClassDescriptor currentClassDescriptor = calleeConstructor.getContainingDeclaration();
boolean isThisCall = calleeExpression.isThis();
if (currentClassDescriptor.getKind() == ClassKind.ENUM_CLASS && !isThisCall) {
context.trace.report(DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR.on((JetConstructorDelegationCall) calleeExpression.getParent()));
return checkArgumentTypesAndFail(context);
}
ClassDescriptor delegateClassDescriptor = calleeExpression.isThis() ? currentClassDescriptor :
ClassDescriptor delegateClassDescriptor = isThisCall ? currentClassDescriptor :
DescriptorUtilPackage.getSuperClassOrAny(currentClassDescriptor);
Collection<ConstructorDescriptor> constructors = delegateClassDescriptor.getConstructors();
if (!calleeExpression.isThis() && currentClassDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
if (!isThisCall && currentClassDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
context.trace.report(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(
(JetConstructorDelegationCall) calleeExpression.getParent()
));
@@ -330,16 +363,6 @@ public class CallResolver {
return computeTasksFromCandidatesAndResolvedCall(context, calleeExpression, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER);
}
@NotNull
private static ClassDescriptor getClassDescriptorByConstructorContext(@NotNull BasicCallResolutionContext context) {
DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration();
if (containingDeclaration instanceof ConstructorDescriptor) {
containingDeclaration = containingDeclaration.getContainingDeclaration();
}
assert containingDeclaration != null : "Grandparent of delegation call should be a class descriptor";
return (ClassDescriptor) containingDeclaration;
}
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
@NotNull Call call,
@NotNull TracingStrategy tracing,