Index: lib/src/checker/checker.dart |
diff --git a/lib/src/checker/checker.dart b/lib/src/checker/checker.dart |
index 36d85178606638450536c73ddb9602b347271453..96c2d1d401915ce6e851247061e667418c0f2b10 100644 |
--- a/lib/src/checker/checker.dart |
+++ b/lib/src/checker/checker.dart |
@@ -406,7 +406,9 @@ class CodeChecker extends RecursiveAstVisitor { |
void visitForEachStatement(ForEachStatement node) { |
// Check that the expression is an Iterable. |
var expr = node.iterable; |
- var iterableType = rules.provider.iterableType; |
+ var iterableType = node.awaitKeyword != null |
+ ? rules.provider.streamType |
+ : rules.provider.iterableType; |
var loopVariable = node.identifier != null |
? node.identifier |
: node.loopVariable.identifier; |
@@ -578,69 +580,10 @@ class CodeChecker extends RecursiveAstVisitor { |
node.visitChildren(this); |
} |
- DartType _getExpectedReturnType(FunctionBody body, bool yieldStar) { |
- FunctionType functionType; |
- var parent = body.parent; |
- if (parent is Declaration) { |
- functionType = rules.elementType(parent.element); |
- } else { |
- assert(parent is FunctionExpression); |
- functionType = rules.getStaticType(parent); |
- } |
- |
- var type = functionType.returnType; |
- var provider = rules.provider; |
- |
- InterfaceType expectedType = null; |
- if (body.isAsynchronous) { |
- if (body.isGenerator) { |
- // Stream<T> -> T |
- expectedType = provider.streamType; |
- } else { |
- // Future<T> -> T |
- // TODO(vsm): Revisit with issue #228. |
- expectedType = provider.futureType; |
- } |
- } else { |
- if (body.isGenerator) { |
- // Iterable<T> -> T |
- expectedType = provider.iterableType; |
- } else { |
- // T -> T |
- return type; |
- } |
- } |
- if (yieldStar) { |
- if (type.isDynamic) { |
- // Ensure it's at least a Stream / Iterable. |
- return expectedType.substitute4([provider.dynamicType]); |
- } else { |
- // Analyzer will provide a separate error if expected type |
- // is not compatible with type. |
- return type; |
- } |
- } |
- if (type.isDynamic) { |
- return type; |
- } else if (type is InterfaceType && type.element == expectedType.element) { |
- return type.typeArguments[0]; |
- } else { |
- // Malformed type - fallback on analyzer error. |
- return null; |
- } |
- } |
- |
- FunctionBody _getFunctionBody(AstNode node) { |
- while (node is! FunctionBody) { |
- node = node.parent; |
- } |
- return node as FunctionBody; |
- } |
- |
void _checkReturnOrYield(Expression expression, AstNode node, |
- [bool yieldStar = false]) { |
- var body = _getFunctionBody(node); |
- var type = _getExpectedReturnType(body, yieldStar); |
+ {bool yieldStar: false}) { |
+ var body = node.getAncestor((n) => n is FunctionBody); |
+ var type = rules.getExpectedReturnType(body, yieldStar: yieldStar); |
if (type == null) { |
// We have a type mismatch: the async/async*/sync* modifier does |
// not match the return or yield type. We should have already gotten an |
@@ -665,7 +608,7 @@ class CodeChecker extends RecursiveAstVisitor { |
@override |
void visitYieldStatement(YieldStatement node) { |
- _checkReturnOrYield(node.expression, node, node.star != null); |
+ _checkReturnOrYield(node.expression, node, yieldStar: node.star != null); |
node.visitChildren(this); |
} |