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:
@@ -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);
|
||||
|
||||
+1
@@ -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");
|
||||
|
||||
-19
@@ -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) {
|
||||
|
||||
+5
@@ -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,
|
||||
|
||||
+1
-15
@@ -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,
|
||||
|
||||
+5
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user