| Index: lib/src/checker/resolver.dart
|
| diff --git a/lib/src/checker/resolver.dart b/lib/src/checker/resolver.dart
|
| index d4bcd799bbdafce9aad95e1f6c67b5091e2ef485..8a35e0d153243515af63a9bc370e5b866547f738 100644
|
| --- a/lib/src/checker/resolver.dart
|
| +++ b/lib/src/checker/resolver.dart
|
| @@ -620,6 +620,50 @@ class RestrictedStaticTypeAnalyzer extends StaticTypeAnalyzer {
|
| }
|
| }
|
|
|
| + // TODO(vsm): Use leafp's matchType here?
|
| + DartType _findIteratedType(InterfaceType type) {
|
| + if (type.element == _typeProvider.iterableType.element) {
|
| + var typeArguments = type.typeArguments;
|
| + assert(typeArguments.length == 1);
|
| + return typeArguments[0];
|
| + }
|
| +
|
| + if (type == _typeProvider.objectType) return null;
|
| +
|
| + var result = _findIteratedType(type.superclass);
|
| + if (result != null) return result;
|
| +
|
| + for (final parent in type.interfaces) {
|
| + result = _findIteratedType(parent);
|
| + if (result != null) return result;
|
| + }
|
| +
|
| + for (final parent in type.mixins) {
|
| + result = _findIteratedType(parent);
|
| + if (result != null) return result;
|
| + }
|
| +
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + visitDeclaredIdentifier(DeclaredIdentifier node) {
|
| + super.visitDeclaredIdentifier(node);
|
| + if (node.type != null) return;
|
| +
|
| + var parent = node.parent;
|
| + assert(parent is ForEachStatement);
|
| + var expr = parent.iterable;
|
| + var element = node.element as LocalVariableElementImpl;
|
| + var exprType = expr.staticType;
|
| + if (exprType is InterfaceType) {
|
| + var iteratedType = _findIteratedType(exprType);
|
| + if (iteratedType != null) {
|
| + element.type = iteratedType;
|
| + }
|
| + }
|
| + }
|
| +
|
| @override // to propagate types to identifiers
|
| visitMethodInvocation(MethodInvocation node) {
|
| // TODO(sigmund): follow up with analyzer team - why is this needed?
|
|
|