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();
@@ -66,14 +66,6 @@ fun box() : String {
System.out?.println(sum)
if(sum != 10) return "b failed"
val c7 = MyCollection5()
sum = 0
for (el in c7) {
sum = sum + el!!
}
if(sum != 0) return "c7 failed"
return "OK"
}
@@ -120,14 +112,3 @@ class MyCollection4() {
fun hasNext() = k > 0
}
}
class MyCollection5() {
fun iterator() : MyIterator? = null
class MyIterator() {
var k : Int = 5
fun next() : Int = k--
fun hasNext() = k > 0
}
}
@@ -0,0 +1,12 @@
class Coll {
fun iterator(): It? = null
}
class It {
fun next() = 1
fun hasNext() = false
}
fun test() {
for (x in <!HAS_NEXT_FUNCTION_NONE_APPLICABLE, NEXT_NONE_APPLICABLE!>Coll()<!>) {}
}
@@ -15,15 +15,12 @@
*/
package org.jetbrains.jet.checkers;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
import java.io.File;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.test.TestMetadata;
import org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve;
import java.io.File;
/** This class is generated by {@link org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve}. DO NOT MODIFY MANUALLY */
public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve {
@@ -879,6 +876,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/controlStructures/forLoopWithNullableRange.kt");
}
@TestMetadata("forWithNullableIterator.kt")
public void testForWithNullableIterator() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlStructures/forWithNullableIterator.kt");
}
@TestMetadata("ForWithoutBraces.kt")
public void testForWithoutBraces() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlStructures/ForWithoutBraces.kt");
@@ -312,7 +312,7 @@ public class ClassGenTest extends CodegenTestCase {
}
public void testKt903() throws Exception {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
blackBoxFile("regressions/kt903.jet");
}
@@ -403,7 +403,7 @@ public class ClassGenTest extends CodegenTestCase {
}
public void testKt1980() {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
blackBoxFile("regressions/kt1980.kt");
}
@@ -108,7 +108,7 @@ public class ControlStructuresTest extends CodegenTestCase {
}
public void testFor() throws Exception {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
loadFile();
// System.out.println(generateToText());
final Method main = generateFunction();
@@ -117,7 +117,7 @@ public class ControlStructuresTest extends CodegenTestCase {
}
public void testIfBlock() throws Exception {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
loadFile();
// System.out.println(generateToText());
final Method main = generateFunction();
@@ -22,7 +22,7 @@ public class SafeRefTest extends CodegenTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
}
public void test247 () throws Exception {
@@ -165,7 +165,7 @@ public class LiveTemplatesTest extends LightCodeInsightFixtureTestCase {
public void testIter() {
start();
assertStringItems("args", "collection", "myList", "str", "stream");
assertStringItems("args", "myList", "str", "stream");
type("args");
nextTab(2);
+1 -1
View File
@@ -17,7 +17,7 @@ public var asserter: Asserter
if (_asserter == null) {
val klass = javaClass<Asserter>()
val loader = ServiceLoader.load(klass)!!
for (a in loader) {
for (a in loader.iterator()!!) {
if (a != null) {
_asserter = a
break