Refactoring. Moved error checks (for abstract, super)

to CandidateResolver

 Added error SUPER_CANT_BE_EXTENSION_RECEIVER (it was SUPER_IS_NOT_AN_EXPRESSION)
This commit is contained in:
Svetlana Isakova
2014-12-22 15:07:53 +03:00
parent 62c8a6f79a
commit 179c9ef2d6
12 changed files with 59 additions and 70 deletions
@@ -418,6 +418,7 @@ public interface Errors {
// Super calls
DiagnosticFactory1<JetSuperExpression, String> SUPER_IS_NOT_AN_EXPRESSION = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetSuperExpression, String> SUPER_CANT_BE_EXTENSION_RECEIVER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<JetSuperExpression> SUPER_NOT_AVAILABLE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetSuperExpression> SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetSuperExpression> AMBIGUOUS_SUPER = DiagnosticFactory0.create(ERROR);
@@ -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");
@@ -79,7 +79,6 @@ public class CallExpressionResolver {
OverloadResolutionResults<FunctionDescriptor> 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,
@@ -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.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(
context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
@Override
public <D extends CallableDescriptor> 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();
@@ -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 <D extends CallableDescriptor> void checkAbstractAndSuper(@NotNull CallCandidateResolutionContext<D> context) {
MutableResolvedCall<D> 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) {
@@ -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,
@@ -40,7 +40,6 @@ import java.util.Collection;
public class ResolutionTask<D extends CallableDescriptor, F extends D> extends CallResolutionContext<ResolutionTask<D, F>> {
private final Function0<Collection<ResolutionCandidate<D>>> lazyCandidates;
private final Collection<MutableResolvedCall<F>> resolvedCalls;
private DescriptorCheckStrategy checkingStrategy;
public final TracingStrategy tracing;
private ResolutionTask(
@@ -106,17 +105,6 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> 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<D, F> create(
@NotNull BindingTrace trace,
@@ -127,12 +115,10 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
@NotNull ResolutionResultsCache resolutionResultsCache,
boolean collectAllCandidates
) {
ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(
return new ResolutionTask<D, F>(
lazyCandidates, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
resolutionResultsCache, dataFlowInfoForArguments, callResolverExtension, resolvedCalls, isAnnotationContext,
collectAllCandidates);
newTask.setCheckingStrategy(checkingStrategy);
return newTask;
}
public ResolutionTask<D, F> replaceContext(@NotNull BasicCallResolutionContext newContext) {
@@ -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,
@@ -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,
@@ -25,6 +25,6 @@ abstract class D(): A() {
super.<!ABSTRACT_SUPER_CALL!>i<!>
super.fff() //everything is ok
return super.<!ABSTRACT_SUPER_CALL!>foo()<!> //no error!!
return super.<!ABSTRACT_SUPER_CALL!>foo<!>() //no error!!
}
}
@@ -14,7 +14,7 @@ class C : T {
fun T.buzz() {}
fun T.buzz1() {}
super.foo() // OK
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.bar() // Error
<!SUPER_CANT_BE_EXTENSION_RECEIVER!>super<!>.bar() // Error
super.buzz() // OK, resolved to a member
super.buzz1(<!NO_VALUE_FOR_PARAMETER!>)<!> // Resolved to a member, but error: no parameter passed where required
}
@@ -1,6 +1,6 @@
// No supertype at all
class A1 {
fun test() {
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.identityEquals(null) // Call to an extension function
<!SUPER_CANT_BE_EXTENSION_RECEIVER!>super<!>.identityEquals(null) // Call to an extension function
}
}