Index: pkg/analyzer/lib/src/generated/error_verifier.dart |
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart |
index 70aa151cd7bd61ecdba7c55b6ccd368b9666745c..7d0c52be00f21130eeef324d522e9d8db516a6a7 100644 |
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart |
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart |
@@ -689,6 +689,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} |
@override |
+ Object visitForEachStatement(ForEachStatement node) { |
+ _checkForInIterable(node); |
+ return super.visitForEachStatement(node); |
+ } |
+ |
+ @override |
Object visitFunctionDeclaration(FunctionDeclaration node) { |
ExecutableElement outerFunction = _enclosingFunction; |
try { |
@@ -5663,16 +5669,65 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} |
/** |
+ * Check for a type mis-match between the iterable expression and the |
+ * assigned variable in a for-in statement. |
+ */ |
+ void _checkForInIterable(ForEachStatement node) { |
+ // Ignore malformed for statements. |
+ if (node.identifier == null && node.loopVariable == null) { |
+ return; |
+ } |
+ |
+ DartType iterableType = getStaticType(node.iterable); |
+ if (iterableType.isDynamic) { |
+ return; |
+ } |
+ |
+ // The type of the loop variable. |
+ SimpleIdentifier variable = node.identifier != null |
Jennifer Messerly
2016/03/08 19:14:11
probably not worth it, but this could be:
nod
|
+ ? node.identifier |
+ : node.loopVariable.identifier; |
+ DartType variableType = getStaticType(variable); |
+ |
+ DartType loopType = node.awaitKeyword != null |
+ ? _typeProvider.streamType |
+ : _typeProvider.iterableType; |
+ |
+ // Use an explicit string instead of [loopType] to remove the "<E>". |
+ String loopTypeName = node.awaitKeyword != null |
Jennifer Messerly
2016/03/08 19:14:11
do you need this? Isn't this just: `loopType.name`
|
+ ? "Stream" |
+ : "Iterable"; |
+ |
+ // The object being iterated has to implement Iterable<T> for some T that |
+ // is assignable to the variable's type. |
+ // TODO(rnystrom): Move this into mostSpecificTypeArgument()? |
Jennifer Messerly
2016/03/08 19:14:11
yeah, I think that makes sense.
|
+ iterableType = iterableType.resolveToBound(_typeProvider.objectType); |
+ DartType bestIterableType = _typeSystem.mostSpecificTypeArgument( |
+ iterableType, loopType); |
+ if (bestIterableType == null) { |
+ _errorReporter.reportTypeErrorForNode( |
+ StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, |
+ node, |
+ [iterableType, loopTypeName]); |
+ } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) { |
+ _errorReporter.reportTypeErrorForNode( |
+ StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, |
+ node, |
+ [iterableType, loopTypeName, variableType]); |
+ } |
+ } |
+ |
+ /** |
* Check for a type mis-match between the yielded type and the declared |
* return type of a generator function. |
* |
* This method should only be called in generator functions. |
*/ |
- bool _checkForYieldOfInvalidType( |
+ void _checkForYieldOfInvalidType( |
Brian Wilkerson
2016/03/08 01:12:12
fyi: I don't know that it matters, but the origina
Bob Nystrom
2016/03/08 19:00:50
I'm not sure about the other methods, but this one
|
Expression yieldExpression, bool isYieldEach) { |
assert(_inGenerator); |
if (_enclosingFunction == null) { |
- return false; |
+ return; |
} |
DartType declaredReturnType = _enclosingFunction.returnType; |
DartType staticYieldedType = getStaticType(yieldExpression); |
@@ -5691,7 +5746,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, |
yieldExpression, |
[impliedReturnType, declaredReturnType]); |
- return true; |
+ return; |
} |
if (isYieldEach) { |
// Since the declared return type might have been "dynamic", we need to |
@@ -5708,10 +5763,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, |
yieldExpression, |
[impliedReturnType, requiredReturnType]); |
- return true; |
+ return; |
} |
} |
- return false; |
} |
/** |