From 52ba8333dc19b39a7b60f5c5617a1b14e09ce6f7 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Sun, 15 Mar 2015 12:47:44 +0300 Subject: [PATCH] Refactor delegation call resolution - Move resolution logic from BodyResolver to CallResolver - Call resolveConstructorDelegationCall explicitly without resolveFunctionCall - Drop dead condition and unused method --- .../kotlin/resolve/BodyResolver.java | 18 ++---- .../kotlin/resolve/calls/CallResolver.java | 59 +++++++++++++------ 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index b2234a081e9..fd84f42e598 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -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 resolvedCall = results.getResultingCall(); recordConstructorDelegationCall(trace, descriptor, resolvedCall); return resolvedCall.getDataFlowInfoForArguments().getResultInfo(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index 5398d43efb2..b5c9698077a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -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 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 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 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 resolveCallWithKnownCandidate( @NotNull Call call, @NotNull TracingStrategy tracing,