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);
|
DiagnosticFactory1<JetSimpleNameExpression, ClassifierDescriptor> NO_CLASS_OBJECT = DiagnosticFactory1.create(ERROR);
|
||||||
SimpleDiagnosticFactory<PsiElement> NO_GENERICS_IN_SUPERTYPE_SPECIFIER = SimpleDiagnosticFactory.create(ERROR);
|
SimpleDiagnosticFactory<PsiElement> NO_GENERICS_IN_SUPERTYPE_SPECIFIER = SimpleDiagnosticFactory.create(ERROR);
|
||||||
|
|
||||||
SimpleDiagnosticFactory<JetExpression> HAS_NEXT_MISSING = SimpleDiagnosticFactory.create(ERROR);
|
DiagnosticFactory1<JetExpression, JetType> HAS_NEXT_MISSING = DiagnosticFactory1.create(ERROR);
|
||||||
SimpleDiagnosticFactory<JetExpression> HAS_NEXT_FUNCTION_AMBIGUITY = SimpleDiagnosticFactory.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);
|
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);
|
SimpleDiagnosticFactory<JetExpression> ITERATOR_MISSING = SimpleDiagnosticFactory.create(ERROR);
|
||||||
AmbiguousDescriptorDiagnosticFactory ITERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create();
|
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_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(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_MISSING, "hasNext() cannot be called on iterator() of type ''{0}''", RENDER_TYPE);
|
||||||
MAP.put(HAS_NEXT_FUNCTION_AMBIGUITY, "Function 'iterator().hasNext()' is ambiguous for this expression");
|
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}",
|
MAP.put(HAS_NEXT_FUNCTION_TYPE_MISMATCH, "The ''iterator().hasNext()'' function of the loop range must return jet.Boolean, but returns {0}",
|
||||||
RENDER_TYPE);
|
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_MISSING, "For-loop range must have an iterator() method");
|
||||||
MAP.put(ITERATOR_AMBIGUITY, "Method ''iterator()'' is ambiguous for this expression: {0}", AMBIGUOUS_CALLS);
|
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.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
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.Errors;
|
||||||
import org.jetbrains.jet.lang.diagnostics.SimpleDiagnosticFactory;
|
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
@@ -340,12 +340,13 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor();
|
FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor();
|
||||||
JetType iteratorType = iteratorFunction.getReturnType();
|
JetType iteratorType = iteratorFunction.getReturnType();
|
||||||
JetType hasNextType = checkConventionForIterator(context, loopRangeExpression, iteratorType, "hasNext",
|
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);
|
LOOP_RANGE_HAS_NEXT_RESOLVED_CALL);
|
||||||
if (hasNextType != null && !isBoolean(hasNextType)) {
|
if (hasNextType != null && !isBoolean(hasNextType)) {
|
||||||
context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, 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);
|
LOOP_RANGE_NEXT_RESOLVED_CALL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -370,19 +371,24 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
@NotNull JetExpression loopRangeExpression,
|
@NotNull JetExpression loopRangeExpression,
|
||||||
@NotNull JetType iteratorType,
|
@NotNull JetType iteratorType,
|
||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
@NotNull SimpleDiagnosticFactory<JetExpression> ambiguity,
|
@NotNull DiagnosticFactory1<JetExpression, JetType> ambiguity,
|
||||||
@NotNull SimpleDiagnosticFactory<JetExpression> missing,
|
@NotNull DiagnosticFactory1<JetExpression, JetType> missing,
|
||||||
|
@NotNull DiagnosticFactory1<JetExpression, JetType> noneApplicable,
|
||||||
@NotNull WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> resolvedCallKey
|
@NotNull WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> resolvedCallKey
|
||||||
) {
|
) {
|
||||||
OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = resolveFakeCall(
|
OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = resolveFakeCall(
|
||||||
new TransientReceiver(iteratorType), context, Name.identifier(name));
|
new TransientReceiver(iteratorType), context, Name.identifier(name));
|
||||||
if (nextResolutionResults.isAmbiguity()) {
|
if (nextResolutionResults.isAmbiguity()) {
|
||||||
context.trace.report(ambiguity.on(loopRangeExpression));
|
context.trace.report(ambiguity.on(loopRangeExpression, iteratorType));
|
||||||
}
|
}
|
||||||
else if (nextResolutionResults.isNothing()) {
|
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 {
|
else {
|
||||||
|
assert nextResolutionResults.isSuccess();
|
||||||
ResolvedCall<FunctionDescriptor> resolvedCall = nextResolutionResults.getResultingCall();
|
ResolvedCall<FunctionDescriptor> resolvedCall = nextResolutionResults.getResultingCall();
|
||||||
context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall);
|
context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall);
|
||||||
return resolvedCall.getResultingDescriptor().getReturnType();
|
return resolvedCall.getResultingDescriptor().getReturnType();
|
||||||
|
|||||||
@@ -66,14 +66,6 @@ fun box() : String {
|
|||||||
System.out?.println(sum)
|
System.out?.println(sum)
|
||||||
if(sum != 10) return "b failed"
|
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"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,14 +112,3 @@ class MyCollection4() {
|
|||||||
fun hasNext() = k > 0
|
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;
|
package org.jetbrains.jet.checkers;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
import org.jetbrains.jet.test.TestMetadata;
|
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 */
|
/** This class is generated by {@link org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve}. DO NOT MODIFY MANUALLY */
|
||||||
public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve {
|
public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
@@ -879,6 +876,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
doTest("compiler/testData/diagnostics/tests/controlStructures/forLoopWithNullableRange.kt");
|
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")
|
@TestMetadata("ForWithoutBraces.kt")
|
||||||
public void testForWithoutBraces() throws Exception {
|
public void testForWithoutBraces() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/controlStructures/ForWithoutBraces.kt");
|
doTest("compiler/testData/diagnostics/tests/controlStructures/ForWithoutBraces.kt");
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ public class ClassGenTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testKt903() throws Exception {
|
public void testKt903() throws Exception {
|
||||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
|
||||||
blackBoxFile("regressions/kt903.jet");
|
blackBoxFile("regressions/kt903.jet");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,7 +403,7 @@ public class ClassGenTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testKt1980() {
|
public void testKt1980() {
|
||||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
|
||||||
blackBoxFile("regressions/kt1980.kt");
|
blackBoxFile("regressions/kt1980.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testFor() throws Exception {
|
public void testFor() throws Exception {
|
||||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
|
||||||
loadFile();
|
loadFile();
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
@@ -117,7 +117,7 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testIfBlock() throws Exception {
|
public void testIfBlock() throws Exception {
|
||||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
|
||||||
loadFile();
|
loadFile();
|
||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class SafeRefTest extends CodegenTestCase {
|
|||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void test247 () throws Exception {
|
public void test247 () throws Exception {
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ public class LiveTemplatesTest extends LightCodeInsightFixtureTestCase {
|
|||||||
public void testIter() {
|
public void testIter() {
|
||||||
start();
|
start();
|
||||||
|
|
||||||
assertStringItems("args", "collection", "myList", "str", "stream");
|
assertStringItems("args", "myList", "str", "stream");
|
||||||
type("args");
|
type("args");
|
||||||
nextTab(2);
|
nextTab(2);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public var asserter: Asserter
|
|||||||
if (_asserter == null) {
|
if (_asserter == null) {
|
||||||
val klass = javaClass<Asserter>()
|
val klass = javaClass<Asserter>()
|
||||||
val loader = ServiceLoader.load(klass)!!
|
val loader = ServiceLoader.load(klass)!!
|
||||||
for (a in loader) {
|
for (a in loader.iterator()!!) {
|
||||||
if (a != null) {
|
if (a != null) {
|
||||||
_asserter = a
|
_asserter = a
|
||||||
break
|
break
|
||||||
|
|||||||
Reference in New Issue
Block a user