Report errors when iterator() returns a nullable type

This commit is contained in:
Andrey Breslav
2012-08-24 19:20:53 +04:00
parent b6f15b518a
commit c0c2ca0ac2
11 changed files with 54 additions and 45 deletions
@@ -210,11 +210,15 @@ public interface Errors {
DiagnosticFactory1<JetSimpleNameExpression, ClassifierDescriptor> NO_CLASS_OBJECT = DiagnosticFactory1.create(ERROR);
SimpleDiagnosticFactory<PsiElement> NO_GENERICS_IN_SUPERTYPE_SPECIFIER = SimpleDiagnosticFactory.create(ERROR);
SimpleDiagnosticFactory<JetExpression> HAS_NEXT_MISSING = SimpleDiagnosticFactory.create(ERROR);
SimpleDiagnosticFactory<JetExpression> HAS_NEXT_FUNCTION_AMBIGUITY = SimpleDiagnosticFactory.create(ERROR);
DiagnosticFactory1<JetExpression, JetType> HAS_NEXT_MISSING = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetExpression, JetType> HAS_NEXT_FUNCTION_AMBIGUITY = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetExpression, JetType> HAS_NEXT_FUNCTION_NONE_APPLICABLE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetExpression, JetType> HAS_NEXT_FUNCTION_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR);
SimpleDiagnosticFactory<JetExpression> NEXT_AMBIGUITY = SimpleDiagnosticFactory.create(ERROR);
SimpleDiagnosticFactory<JetExpression> NEXT_MISSING = SimpleDiagnosticFactory.create(ERROR);
DiagnosticFactory1<JetExpression, JetType> NEXT_AMBIGUITY = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetExpression, JetType> NEXT_MISSING = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetExpression, JetType> NEXT_NONE_APPLICABLE = DiagnosticFactory1.create(ERROR);
SimpleDiagnosticFactory<JetExpression> ITERATOR_MISSING = SimpleDiagnosticFactory.create(ERROR);
AmbiguousDescriptorDiagnosticFactory ITERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create();
@@ -226,12 +226,16 @@ public class DefaultErrorMessages {
MAP.put(NO_CLASS_OBJECT, "Please specify constructor invocation; classifier ''{0}'' does not have a class object", NAME);
MAP.put(NO_GENERICS_IN_SUPERTYPE_SPECIFIER, "Generic arguments of the base type must be specified");
MAP.put(HAS_NEXT_MISSING, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
MAP.put(HAS_NEXT_FUNCTION_AMBIGUITY, "Function 'iterator().hasNext()' is ambiguous for this expression");
MAP.put(HAS_NEXT_MISSING, "hasNext() cannot be called on iterator() of type ''{0}''", RENDER_TYPE);
MAP.put(HAS_NEXT_FUNCTION_AMBIGUITY, "hasNext() is ambiguous for iterator() of type ''{0}''", RENDER_TYPE);
MAP.put(HAS_NEXT_FUNCTION_NONE_APPLICABLE, "None of the hasNext() functions is applicable for iterator() of type ''{0}''", RENDER_TYPE);
MAP.put(HAS_NEXT_FUNCTION_TYPE_MISMATCH, "The ''iterator().hasNext()'' function of the loop range must return jet.Boolean, but returns {0}",
RENDER_TYPE);
MAP.put(NEXT_AMBIGUITY, "Function 'iterator().next()' is ambiguous for this expression");
MAP.put(NEXT_MISSING, "Loop range must have an 'iterator().next()' function");
MAP.put(NEXT_MISSING, "next() cannot be called on iterator() of type ''{0}''", RENDER_TYPE);
MAP.put(NEXT_AMBIGUITY, "next() is ambiguous for iterator() of type ''{0}''", RENDER_TYPE);
MAP.put(NEXT_NONE_APPLICABLE, "None of the next() functions is applicable for iterator() of type ''{0}''", RENDER_TYPE);
MAP.put(ITERATOR_MISSING, "For-loop range must have an iterator() method");
MAP.put(ITERATOR_AMBIGUITY, "Method ''iterator()'' is ambiguous for this expression: {0}", AMBIGUOUS_CALLS);
@@ -25,8 +25,8 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.diagnostics.SimpleDiagnosticFactory;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
@@ -340,12 +340,13 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor();
JetType iteratorType = iteratorFunction.getReturnType();
JetType hasNextType = checkConventionForIterator(context, loopRangeExpression, iteratorType, "hasNext",
HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING,
HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, HAS_NEXT_FUNCTION_NONE_APPLICABLE,
LOOP_RANGE_HAS_NEXT_RESOLVED_CALL);
if (hasNextType != null && !isBoolean(hasNextType)) {
context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType));
}
return checkConventionForIterator(context, loopRangeExpression, iteratorType, "next", NEXT_AMBIGUITY, NEXT_MISSING,
return checkConventionForIterator(context, loopRangeExpression, iteratorType, "next",
NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE,
LOOP_RANGE_NEXT_RESOLVED_CALL);
}
else {
@@ -370,19 +371,24 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
@NotNull JetExpression loopRangeExpression,
@NotNull JetType iteratorType,
@NotNull String name,
@NotNull SimpleDiagnosticFactory<JetExpression> ambiguity,
@NotNull SimpleDiagnosticFactory<JetExpression> missing,
@NotNull DiagnosticFactory1<JetExpression, JetType> ambiguity,
@NotNull DiagnosticFactory1<JetExpression, JetType> missing,
@NotNull DiagnosticFactory1<JetExpression, JetType> noneApplicable,
@NotNull WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> resolvedCallKey
) {
OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = resolveFakeCall(
new TransientReceiver(iteratorType), context, Name.identifier(name));
if (nextResolutionResults.isAmbiguity()) {
context.trace.report(ambiguity.on(loopRangeExpression));
context.trace.report(ambiguity.on(loopRangeExpression, iteratorType));
}
else if (nextResolutionResults.isNothing()) {
context.trace.report(missing.on(loopRangeExpression));
context.trace.report(missing.on(loopRangeExpression, iteratorType));
}
else if (!nextResolutionResults.isSuccess()) {
context.trace.report(noneApplicable.on(loopRangeExpression, iteratorType));
}
else {
assert nextResolutionResults.isSuccess();
ResolvedCall<FunctionDescriptor> resolvedCall = nextResolutionResults.getResultingCall();
context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall);
return resolvedCall.getResultingDescriptor().getReturnType();