Report errors when iterator() returns a nullable type
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
+8
-4
@@ -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);
|
||||
|
||||
|
||||
+13
-7
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user