| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be | 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
| 6 // refactored to fit into analyzer. | 6 // refactored to fit into analyzer. |
| 7 library analyzer.src.task.strong.checker; | 7 library analyzer.src.task.strong.checker; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 DartType expectedType = _elementType(element); | 189 DartType expectedType = _elementType(element); |
| 190 if (expectedType == null) expectedType = DynamicTypeImpl.instance; | 190 if (expectedType == null) expectedType = DynamicTypeImpl.instance; |
| 191 checkArgument(arg, expectedType); | 191 checkArgument(arg, expectedType); |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 | 194 |
| 195 void checkAssignment(Expression expr, DartType type) { | 195 void checkAssignment(Expression expr, DartType type) { |
| 196 if (expr is ParenthesizedExpression) { | 196 if (expr is ParenthesizedExpression) { |
| 197 checkAssignment(expr.expression, type); | 197 checkAssignment(expr.expression, type); |
| 198 } else { | 198 } else { |
| 199 if (_checkNonNullAssignment(expr, type)) { | 199 _checkDowncast(expr, type); |
| 200 _checkDowncast(expr, type); | |
| 201 } | |
| 202 } | 200 } |
| 203 } | 201 } |
| 204 | 202 |
| 205 /// Analyzer checks boolean conversions, but we need to check too, because | 203 /// Analyzer checks boolean conversions, but we need to check too, because |
| 206 /// it uses the default assignability rules that allow `dynamic` and `Object` | 204 /// it uses the default assignability rules that allow `dynamic` and `Object` |
| 207 /// to be assigned to bool with no message. | 205 /// to be assigned to bool with no message. |
| 208 void checkBoolean(Expression expr) => | 206 void checkBoolean(Expression expr) => |
| 209 checkAssignment(expr, typeProvider.boolType); | 207 checkAssignment(expr, typeProvider.boolType); |
| 210 | 208 |
| 211 void checkFunctionApplication(InvocationExpression node) { | 209 void checkFunctionApplication(InvocationExpression node) { |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 /// | 734 /// |
| 737 /// If [from] is omitted, uses the static type of [expr]. | 735 /// If [from] is omitted, uses the static type of [expr]. |
| 738 /// | 736 /// |
| 739 /// If [expr] does not require a downcast because it is not related to [to] | 737 /// If [expr] does not require a downcast because it is not related to [to] |
| 740 /// or is already a subtype of it, does nothing. | 738 /// or is already a subtype of it, does nothing. |
| 741 void _checkDowncast(Expression expr, DartType to, {DartType from}) { | 739 void _checkDowncast(Expression expr, DartType to, {DartType from}) { |
| 742 if (from == null) { | 740 if (from == null) { |
| 743 from = _getDefiniteType(expr); | 741 from = _getDefiniteType(expr); |
| 744 } | 742 } |
| 745 | 743 |
| 744 if (!_checkNonNullAssignment(expr, to, from)) return; |
| 745 |
| 746 // We can use anything as void. | 746 // We can use anything as void. |
| 747 if (to.isVoid) return; | 747 if (to.isVoid) return; |
| 748 | 748 |
| 749 // fromT <: toT, no coercion needed. | 749 // fromT <: toT, no coercion needed. |
| 750 if (rules.isSubtypeOf(from, to)) return; | 750 if (rules.isSubtypeOf(from, to)) return; |
| 751 | 751 |
| 752 // Note: a function type is never assignable to a class per the Dart | 752 // Note: a function type is never assignable to a class per the Dart |
| 753 // spec - even if it has a compatible call method. We disallow as | 753 // spec - even if it has a compatible call method. We disallow as |
| 754 // well for consistency. | 754 // well for consistency. |
| 755 if (from is FunctionType && rules.getCallMethodType(to) != null) { | 755 if (from is FunctionType && rules.getCallMethodType(to) != null) { |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 // Variable declaration is inside a function or method, so it's safe. | 870 // Variable declaration is inside a function or method, so it's safe. |
| 871 return; | 871 return; |
| 872 } | 872 } |
| 873 _recordMessage(node, StrongModeCode.UNSAFE_BLOCK_CLOSURE_INFERENCE, | 873 _recordMessage(node, StrongModeCode.UNSAFE_BLOCK_CLOSURE_INFERENCE, |
| 874 [declElement.name]); | 874 [declElement.name]); |
| 875 } | 875 } |
| 876 | 876 |
| 877 /// Checks if the assignment is valid with respect to non-nullable types. | 877 /// Checks if the assignment is valid with respect to non-nullable types. |
| 878 /// Returns `false` if a nullable expression is assigned to a variable of | 878 /// Returns `false` if a nullable expression is assigned to a variable of |
| 879 /// non-nullable type and `true` otherwise. | 879 /// non-nullable type and `true` otherwise. |
| 880 bool _checkNonNullAssignment(Expression expression, DartType type) { | 880 bool _checkNonNullAssignment(Expression expression, DartType to, DartType from
) { |
| 881 var exprType = expression.staticType; | 881 if (rules.isNonNullableType(to) && rules.isNullableType(from)) { |
| 882 if (rules.isNonNullableType(type) && rules.isNullableType(exprType)) { | |
| 883 _recordMessage(expression, StaticTypeWarningCode.INVALID_ASSIGNMENT, | 882 _recordMessage(expression, StaticTypeWarningCode.INVALID_ASSIGNMENT, |
| 884 [exprType, type]); | 883 [from, to]); |
| 885 return false; | 884 return false; |
| 886 } | 885 } |
| 887 return true; | 886 return true; |
| 888 } | 887 } |
| 889 | 888 |
| 890 void _checkReturnOrYield(Expression expression, AstNode node, | 889 void _checkReturnOrYield(Expression expression, AstNode node, |
| 891 {bool yieldStar: false}) { | 890 {bool yieldStar: false}) { |
| 892 FunctionBody body = node.getAncestor((n) => n is FunctionBody); | 891 FunctionBody body = node.getAncestor((n) => n is FunctionBody); |
| 893 var type = _getExpectedReturnType(body, yieldStar: yieldStar); | 892 var type = _getExpectedReturnType(body, yieldStar: yieldStar); |
| 894 if (type == null) { | 893 if (type == null) { |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1477 var visited = new Set<InterfaceType>(); | 1476 var visited = new Set<InterfaceType>(); |
| 1478 do { | 1477 do { |
| 1479 visited.add(current); | 1478 visited.add(current); |
| 1480 current.mixins.reversed.forEach( | 1479 current.mixins.reversed.forEach( |
| 1481 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1480 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); |
| 1482 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1481 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); |
| 1483 current = current.superclass; | 1482 current = current.superclass; |
| 1484 } while (!current.isObject && !visited.contains(current)); | 1483 } while (!current.isObject && !visited.contains(current)); |
| 1485 } | 1484 } |
| 1486 } | 1485 } |
| OLD | NEW |