From 179c9ef2d6a152911df6fe95dbd0073382f13c20 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 22 Dec 2014 15:07:53 +0300 Subject: [PATCH] Refactoring. Moved error checks (for abstract, super) to CandidateResolver Added error SUPER_CANT_BE_EXTENSION_RECEIVER (it was SUPER_IS_NOT_AN_EXPRESSION) --- .../jet/lang/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../resolve/calls/CallExpressionResolver.java | 19 -------- .../jet/lang/resolve/calls/CallResolver.java | 24 +--------- .../lang/resolve/calls/CandidateResolver.java | 47 ++++++++++++++----- .../calls/tasks/AbstractTracingStrategy.java | 5 ++ .../resolve/calls/tasks/ResolutionTask.java | 16 +------ .../resolve/calls/tasks/TracingStrategy.java | 5 ++ .../ControlStructureTypingUtils.java | 5 ++ .../tests/declarationChecks/kt559.kt | 2 +- .../extensions/ExtensionsCalledOnSuper.kt | 2 +- .../superInExtensionFunctionCall.kt | 2 +- 12 files changed, 59 insertions(+), 70 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 5bf4fae7744..868afb9407b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -418,6 +418,7 @@ public interface Errors { // Super calls DiagnosticFactory1 SUPER_IS_NOT_AN_EXPRESSION = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 SUPER_CANT_BE_EXTENSION_RECEIVER = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 SUPER_NOT_AVAILABLE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 AMBIGUOUS_SUPER = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index cff92a6dc67..67178a4a873 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -298,6 +298,7 @@ public class DefaultErrorMessages { MAP.put(ASSIGNMENT_IN_EXPRESSION_CONTEXT, "Assignments are not expressions, and only expressions are allowed in this context"); MAP.put(PACKAGE_IS_NOT_AN_EXPRESSION, "'package' is not an expression, it can only be used on the left-hand side of a dot ('.')"); MAP.put(SUPER_IS_NOT_AN_EXPRESSION, "''{0}'' is not an expression, it can only be used on the left-hand side of a dot ('.')", STRING); + MAP.put(SUPER_CANT_BE_EXTENSION_RECEIVER, "''{0}'' is not an expression, it can not be used as a receiver for extension functions", STRING); MAP.put(DECLARATION_IN_ILLEGAL_CONTEXT, "Declarations are not allowed in this position"); MAP.put(SETTER_PARAMETER_WITH_DEFAULT_VALUE, "Setter parameters cannot have default values"); MAP.put(NO_THIS, "'this' is not defined in this context"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index b65b4be7d0d..744c00ec76d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -79,7 +79,6 @@ public class CallExpressionResolver { OverloadResolutionResults results = callResolver.resolveFunctionCall( BasicCallResolutionContext.create(context, call, checkArguments)); if (!results.isNothing()) { - checkSuper(call.getExplicitReceiver(), results, context.trace, callExpression); result[0] = true; return OverloadResolutionResultsUtil.getResultingCall(results, context.contextDependency); } @@ -108,7 +107,6 @@ public class CallExpressionResolver { if (!isQualifier) { result[0] = true; temporaryForVariable.commit(); - checkSuper(receiver, resolutionResult, context.trace, nameExpression); return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null; } } @@ -239,23 +237,6 @@ public class CallExpressionResolver { return false; } - private static void checkSuper( - @NotNull ReceiverValue receiverValue, - @NotNull OverloadResolutionResults results, - @NotNull BindingTrace trace, - @NotNull JetExpression expression - ) { - if (!results.isSingleResult()) return; - if (!(receiverValue instanceof ExpressionReceiver)) return; - JetExpression receiver = ((ExpressionReceiver) receiverValue).getExpression(); - CallableDescriptor descriptor = results.getResultingDescriptor(); - if (receiver instanceof JetSuperExpression && descriptor instanceof MemberDescriptor) { - if (((MemberDescriptor) descriptor).getModality() == Modality.ABSTRACT) { - trace.report(ABSTRACT_SUPER_CALL.on(expression)); - } - } - } - @NotNull private JetTypeInfo getSelectorReturnTypeInfo( @NotNull ReceiverValue receiver, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 0ccd424045d..d96c96d795f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -223,29 +223,9 @@ public class CallResolver { JetReferenceExpression functionReference; if (calleeExpression instanceof JetSimpleNameExpression) { JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression; - functionReference = expression; - Name name = expression.getReferencedNameAsName(); - - TracingStrategy tracing = TracingStrategyImpl.create(expression, context.call); - prioritizedTasks = taskPrioritizer.computePrioritizedTasks( - context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES); - ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { - @Override - public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { - if (descriptor instanceof ConstructorDescriptor) { - Modality modality = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality(); - if (modality == Modality.ABSTRACT) { - tracing.instantiationOfAbstractClass(trace); - return false; - } - } - return true; - } - }; - for (ResolutionTask task : prioritizedTasks) { - task.setCheckingStrategy(abstractConstructorCheck); - } + return computeTasksAndResolveCall(context, name, expression, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, + CallTransformer.FUNCTION_CALL_TRANSFORMER); } else { JetValueArgumentList valueArgumentList = context.call.getValueArgumentList(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index d7a099bde3a..568e4a8c94d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -28,7 +28,8 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.calls.context.*; -import org.jetbrains.jet.lang.resolve.calls.inference.*; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl; import org.jetbrains.jet.lang.resolve.calls.model.*; import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus; import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo; @@ -49,7 +50,7 @@ import javax.inject.Inject; import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT; -import static org.jetbrains.jet.lang.diagnostics.Errors.SUPER_IS_NOT_AN_EXPRESSION; +import static org.jetbrains.jet.lang.diagnostics.Errors.SUPER_CANT_BE_EXTENSION_RECEIVER; import static org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver.deparenthesizeArgument; import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS; import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS; @@ -159,15 +160,7 @@ public class CandidateResolver { candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status); } - 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 = getReceiverSuper(candidateCall.getExtensionReceiver()); - if (superExpression != null) { - context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText())); - candidateCall.addStatus(OTHER_ERROR); - } + checkAbstractAndSuper(context); } private static boolean checkDispatchReceiver(@NotNull CallCandidateResolutionContext context) { @@ -205,6 +198,38 @@ public class CandidateResolver { return DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, context.call.getCallElement(), candidateThis); } + private static void checkAbstractAndSuper(@NotNull CallCandidateResolutionContext context) { + MutableResolvedCall candidateCall = context.candidateCall; + CallableDescriptor descriptor = candidateCall.getCandidateDescriptor(); + JetExpression expression = context.candidateCall.getCall().getCalleeExpression(); + + if (expression instanceof JetSimpleNameExpression) { + // 'B' in 'class A: B()' is JetConstructorCalleeExpression + if (descriptor instanceof ConstructorDescriptor) { + Modality modality = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality(); + if (modality == Modality.ABSTRACT) { + context.tracing.instantiationOfAbstractClass(context.trace); + } + } + } + + JetSuperExpression superDispatchReceiver = getReceiverSuper(candidateCall.getDispatchReceiver()); + if (superDispatchReceiver != null) { + if (descriptor instanceof MemberDescriptor && ((MemberDescriptor) descriptor).getModality() == Modality.ABSTRACT) { + context.tracing.abstractSuperCall(context.trace); + candidateCall.addStatus(OTHER_ERROR); + } + } + + // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this + // See TaskPrioritizer for more + JetSuperExpression superExtensionReceiver = getReceiverSuper(candidateCall.getExtensionReceiver()); + if (superExtensionReceiver != null) { + context.trace.report(SUPER_CANT_BE_EXTENSION_RECEIVER.on(superExtensionReceiver, superExtensionReceiver.getText())); + candidateCall.addStatus(OTHER_ERROR); + } + } + @Nullable private static JetSuperExpression getReceiverSuper(@NotNull ReceiverValue receiver) { if (receiver instanceof ExpressionReceiver) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java index 8dd04f743fe..179577e1f3c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java @@ -132,6 +132,11 @@ public abstract class AbstractTracingStrategy implements TracingStrategy { trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement())); } + @Override + public void abstractSuperCall(@NotNull BindingTrace trace) { + trace.report(ABSTRACT_SUPER_CALL.on(reference)); + } + @Override public void nestedClassAccessViaInstanceReference( @NotNull BindingTrace trace, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionTask.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionTask.java index 01ec3c9529a..27da813adc3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionTask.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/ResolutionTask.java @@ -40,7 +40,6 @@ import java.util.Collection; public class ResolutionTask extends CallResolutionContext> { private final Function0>> lazyCandidates; private final Collection> resolvedCalls; - private DescriptorCheckStrategy checkingStrategy; public final TracingStrategy tracing; private ResolutionTask( @@ -106,17 +105,6 @@ public class ResolutionTask extends C return resolvedCalls; } - public void setCheckingStrategy(DescriptorCheckStrategy strategy) { - checkingStrategy = strategy; - } - - public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { - if (checkingStrategy != null && !checkingStrategy.performAdvancedChecks(descriptor, trace, tracing)) { - return false; - } - return true; - } - @Override protected ResolutionTask create( @NotNull BindingTrace trace, @@ -127,12 +115,10 @@ public class ResolutionTask extends C @NotNull ResolutionResultsCache resolutionResultsCache, boolean collectAllCandidates ) { - ResolutionTask newTask = new ResolutionTask( + return new ResolutionTask( lazyCandidates, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache, dataFlowInfoForArguments, callResolverExtension, resolvedCalls, isAnnotationContext, collectAllCandidates); - newTask.setCheckingStrategy(checkingStrategy); - return newTask; } public ResolutionTask replaceContext(@NotNull BasicCallResolutionContext newContext) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java index f14d808deb6..09a207cabe7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategy.java @@ -80,6 +80,9 @@ public interface TracingStrategy { @Override public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {} + @Override + public void abstractSuperCall(@NotNull BindingTrace trace) {} + @Override public void nestedClassAccessViaInstanceReference( @NotNull BindingTrace trace, @@ -136,6 +139,8 @@ public interface TracingStrategy { void instantiationOfAbstractClass(@NotNull BindingTrace trace); + void abstractSuperCall(@NotNull BindingTrace trace); + void nestedClassAccessViaInstanceReference( @NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java index fc575e839b7..ef0f0632a31 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingUtils.java @@ -471,6 +471,11 @@ public class ControlStructureTypingUtils { logError(); } + @Override + public void abstractSuperCall(@NotNull BindingTrace trace) { + logError(); + } + @Override public void nestedClassAccessViaInstanceReference( @NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor, diff --git a/compiler/testData/diagnostics/tests/declarationChecks/kt559.kt b/compiler/testData/diagnostics/tests/declarationChecks/kt559.kt index 029a2d5e330..a3e440caa9c 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/kt559.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/kt559.kt @@ -25,6 +25,6 @@ abstract class D(): A() { super.i super.fff() //everything is ok - return super.foo() //no error!! + return super.foo() //no error!! } } diff --git a/compiler/testData/diagnostics/tests/extensions/ExtensionsCalledOnSuper.kt b/compiler/testData/diagnostics/tests/extensions/ExtensionsCalledOnSuper.kt index 5dd144c7b1a..9f97b9eea92 100644 --- a/compiler/testData/diagnostics/tests/extensions/ExtensionsCalledOnSuper.kt +++ b/compiler/testData/diagnostics/tests/extensions/ExtensionsCalledOnSuper.kt @@ -14,7 +14,7 @@ class C : T { fun T.buzz() {} fun T.buzz1() {} super.foo() // OK - super.bar() // Error + super.bar() // Error super.buzz() // OK, resolved to a member super.buzz1() // Resolved to a member, but error: no parameter passed where required } diff --git a/compiler/testData/diagnostics/tests/thisAndSuper/superInExtensionFunctionCall.kt b/compiler/testData/diagnostics/tests/thisAndSuper/superInExtensionFunctionCall.kt index 14356527b2f..167cf9d3491 100644 --- a/compiler/testData/diagnostics/tests/thisAndSuper/superInExtensionFunctionCall.kt +++ b/compiler/testData/diagnostics/tests/thisAndSuper/superInExtensionFunctionCall.kt @@ -1,6 +1,6 @@ // No supertype at all class A1 { fun test() { - super.identityEquals(null) // Call to an extension function + super.identityEquals(null) // Call to an extension function } } \ No newline at end of file