OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library engine.resolver.static_type_analyzer; | 5 library engine.resolver.static_type_analyzer; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/src/generated/scanner.dart'; | 9 import 'package:analyzer/src/generated/scanner.dart'; |
10 | 10 |
(...skipping 1401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1412 } | 1412 } |
1413 if (body.isAsynchronous) { | 1413 if (body.isAsynchronous) { |
1414 return _typeProvider.futureType | 1414 return _typeProvider.futureType |
1415 .substitute4(<DartType>[flattenFutures(_typeProvider, type)]); | 1415 .substitute4(<DartType>[flattenFutures(_typeProvider, type)]); |
1416 } else { | 1416 } else { |
1417 return type; | 1417 return type; |
1418 } | 1418 } |
1419 } | 1419 } |
1420 | 1420 |
1421 // TODO(vsm): Use leafp's matchType here? | 1421 // TODO(vsm): Use leafp's matchType here? |
1422 DartType _findIteratedType(InterfaceType type, DartType targetType) { | 1422 DartType _findIteratedType(DartType type, DartType targetType) { |
1423 // Set by _find if match is found | 1423 // Set by _find if match is found |
1424 DartType result = null; | 1424 DartType result = null; |
1425 // Elements we've already visited on a given inheritance path. | 1425 // Elements we've already visited on a given inheritance path. |
1426 HashSet<ClassElement> visitedClasses = null; | 1426 HashSet<ClassElement> visitedClasses = null; |
1427 | 1427 |
| 1428 while (type is TypeParameterType) { |
| 1429 TypeParameterElement element = type.element; |
| 1430 type = element.bound; |
| 1431 } |
| 1432 |
1428 bool _find(InterfaceType type) { | 1433 bool _find(InterfaceType type) { |
1429 ClassElement element = type.element; | 1434 ClassElement element = type.element; |
1430 if (type == _typeProvider.objectType || element == null) { | 1435 if (type == _typeProvider.objectType || element == null) { |
1431 return false; | 1436 return false; |
1432 } | 1437 } |
1433 if (element == targetType.element) { | 1438 if (element == targetType.element) { |
1434 List<DartType> typeArguments = type.typeArguments; | 1439 List<DartType> typeArguments = type.typeArguments; |
1435 assert(typeArguments.length == 1); | 1440 assert(typeArguments.length == 1); |
1436 result = typeArguments[0]; | 1441 result = typeArguments[0]; |
1437 return true; | 1442 return true; |
1438 } | 1443 } |
1439 if (visitedClasses == null) { | 1444 if (visitedClasses == null) { |
1440 visitedClasses = new HashSet<ClassElement>(); | 1445 visitedClasses = new HashSet<ClassElement>(); |
1441 } | 1446 } |
1442 // Already visited this class along this path | 1447 // Already visited this class along this path |
1443 if (!visitedClasses.add(element)) { | 1448 if (!visitedClasses.add(element)) { |
1444 return false; | 1449 return false; |
1445 } | 1450 } |
1446 try { | 1451 try { |
1447 return _find(type.superclass) || | 1452 return _find(type.superclass) || |
1448 type.interfaces.any(_find) || | 1453 type.interfaces.any(_find) || |
1449 type.mixins.any(_find); | 1454 type.mixins.any(_find); |
1450 } finally { | 1455 } finally { |
1451 visitedClasses.remove(element); | 1456 visitedClasses.remove(element); |
1452 } | 1457 } |
1453 } | 1458 } |
1454 _find(type); | 1459 if (type is InterfaceType) { |
| 1460 _find(type); |
| 1461 } |
1455 return result; | 1462 return result; |
1456 } | 1463 } |
1457 | 1464 |
1458 /** | 1465 /** |
1459 * Return the best type of the given [expression]. | 1466 * Return the best type of the given [expression]. |
1460 */ | 1467 */ |
1461 DartType _getBestType(Expression expression) { | 1468 DartType _getBestType(Expression expression) { |
1462 return expression.bestType; | 1469 return expression.bestType; |
1463 } | 1470 } |
1464 | 1471 |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1684 */ | 1691 */ |
1685 void _inferForEachLoopVariableType(DeclaredIdentifier loopVariable) { | 1692 void _inferForEachLoopVariableType(DeclaredIdentifier loopVariable) { |
1686 if (loopVariable != null && | 1693 if (loopVariable != null && |
1687 loopVariable.type == null && | 1694 loopVariable.type == null && |
1688 loopVariable.parent is ForEachStatement) { | 1695 loopVariable.parent is ForEachStatement) { |
1689 ForEachStatement loop = loopVariable.parent; | 1696 ForEachStatement loop = loopVariable.parent; |
1690 if (loop.iterable != null) { | 1697 if (loop.iterable != null) { |
1691 Expression expr = loop.iterable; | 1698 Expression expr = loop.iterable; |
1692 LocalVariableElementImpl element = loopVariable.element; | 1699 LocalVariableElementImpl element = loopVariable.element; |
1693 DartType exprType = expr.staticType; | 1700 DartType exprType = expr.staticType; |
1694 if (exprType is InterfaceType) { | 1701 DartType targetType = (loop.awaitKeyword == null) |
1695 DartType targetType = (loop.awaitKeyword == null) | 1702 ? _typeProvider.iterableType |
1696 ? _typeProvider.iterableType | |
1697 : _typeProvider.streamType; | 1703 : _typeProvider.streamType; |
1698 DartType iteratedType = _findIteratedType(exprType, targetType); | 1704 DartType iteratedType = _findIteratedType(exprType, targetType); |
1699 if (element != null && iteratedType != null) { | 1705 if (element != null && iteratedType != null) { |
1700 element.type = iteratedType; | 1706 element.type = iteratedType; |
1701 loopVariable.identifier.staticType = iteratedType; | 1707 loopVariable.identifier.staticType = iteratedType; |
1702 } | |
1703 } | 1708 } |
1704 } | 1709 } |
1705 } | 1710 } |
1706 } | 1711 } |
1707 | 1712 |
1708 /** | 1713 /** |
1709 * Given a method invocation [node], attempt to infer a better | 1714 * Given a method invocation [node], attempt to infer a better |
1710 * type for the result. | 1715 * type for the result. |
1711 */ | 1716 */ |
1712 bool _inferMethodInvocation(MethodInvocation node) { | 1717 bool _inferMethodInvocation(MethodInvocation node) { |
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2289 } | 2294 } |
2290 // merge types | 2295 // merge types |
2291 if (result == null) { | 2296 if (result == null) { |
2292 result = type; | 2297 result = type; |
2293 } else { | 2298 } else { |
2294 result = _typeSystem.getLeastUpperBound(_typeProvider, result, type); | 2299 result = _typeSystem.getLeastUpperBound(_typeProvider, result, type); |
2295 } | 2300 } |
2296 return null; | 2301 return null; |
2297 } | 2302 } |
2298 } | 2303 } |
OLD | NEW |