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 'dart:collection'; | 9 import 'dart:collection'; |
10 import 'package:analyzer/analyzer.dart'; | 10 import 'package:analyzer/analyzer.dart'; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 if (element == null) { | 190 if (element == null) { |
191 // We found an argument mismatch, the analyzer will report this too, | 191 // We found an argument mismatch, the analyzer will report this too, |
192 // so no need to insert an error for this here. | 192 // so no need to insert an error for this here. |
193 continue; | 193 continue; |
194 } | 194 } |
195 checkArgument(arg, _elementType(element)); | 195 checkArgument(arg, _elementType(element)); |
196 } | 196 } |
197 } | 197 } |
198 | 198 |
199 void checkAssignment(Expression expr, DartType type) { | 199 void checkAssignment(Expression expr, DartType type) { |
| 200 checkForCast(expr, type); |
| 201 } |
| 202 |
| 203 void checkDeclarationCast(Expression expr, DartType type) { |
| 204 checkForCast(expr, type, isDeclarationCast: true); |
| 205 } |
| 206 |
| 207 void checkForCast(Expression expr, DartType type, |
| 208 {bool isDeclarationCast = false}) { |
200 if (expr is ParenthesizedExpression) { | 209 if (expr is ParenthesizedExpression) { |
201 checkAssignment(expr.expression, type); | 210 checkForCast(expr.expression, type); |
202 } else { | 211 } else { |
203 _checkImplicitCast(expr, type); | 212 _checkImplicitCast(expr, type, isDeclarationCast: isDeclarationCast); |
204 } | 213 } |
205 } | 214 } |
206 | 215 |
207 /// Analyzer checks boolean conversions, but we need to check too, because | 216 /// Analyzer checks boolean conversions, but we need to check too, because |
208 /// it uses the default assignability rules that allow `dynamic` and `Object` | 217 /// it uses the default assignability rules that allow `dynamic` and `Object` |
209 /// to be assigned to bool with no message. | 218 /// to be assigned to bool with no message. |
210 void checkBoolean(Expression expr) => | 219 void checkBoolean(Expression expr) => |
211 checkAssignment(expr, typeProvider.boolType); | 220 checkAssignment(expr, typeProvider.boolType); |
212 | 221 |
213 void _checkFunctionApplication(InvocationExpression node) { | 222 void _checkFunctionApplication(InvocationExpression node) { |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 elementType = DynamicTypeImpl.instance; | 434 elementType = DynamicTypeImpl.instance; |
426 } | 435 } |
427 } | 436 } |
428 | 437 |
429 // If the sequence doesn't implement the interface at all, [ErrorVerifier] | 438 // If the sequence doesn't implement the interface at all, [ErrorVerifier] |
430 // will report the error, so ignore it here. | 439 // will report the error, so ignore it here. |
431 if (elementType != null) { | 440 if (elementType != null) { |
432 // Insert a cast from the sequence's element type to the loop variable's | 441 // Insert a cast from the sequence's element type to the loop variable's |
433 // if needed. | 442 // if needed. |
434 _checkImplicitCast(loopVariable, _getDefiniteType(loopVariable), | 443 _checkImplicitCast(loopVariable, _getDefiniteType(loopVariable), |
435 from: elementType); | 444 from: elementType, isDeclarationCast: true); |
436 } | 445 } |
437 } | 446 } |
438 | 447 |
439 node.visitChildren(this); | 448 node.visitChildren(this); |
440 } | 449 } |
441 | 450 |
442 @override | 451 @override |
443 void visitForStatement(ForStatement node) { | 452 void visitForStatement(ForStatement node) { |
444 if (node.condition != null) { | 453 if (node.condition != null) { |
445 checkBoolean(node.condition); | 454 checkBoolean(node.condition); |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 } | 686 } |
678 | 687 |
679 @override | 688 @override |
680 void visitVariableDeclarationList(VariableDeclarationList node) { | 689 void visitVariableDeclarationList(VariableDeclarationList node) { |
681 TypeAnnotation type = node.type; | 690 TypeAnnotation type = node.type; |
682 | 691 |
683 for (VariableDeclaration variable in node.variables) { | 692 for (VariableDeclaration variable in node.variables) { |
684 var initializer = variable.initializer; | 693 var initializer = variable.initializer; |
685 if (initializer != null) { | 694 if (initializer != null) { |
686 if (type != null) { | 695 if (type != null) { |
687 checkAssignment(initializer, type.type); | 696 checkDeclarationCast(initializer, type.type); |
688 } | 697 } |
689 } | 698 } |
690 } | 699 } |
691 | 700 |
692 node.visitChildren(this); | 701 node.visitChildren(this); |
693 } | 702 } |
694 | 703 |
695 @override | 704 @override |
696 void visitWhileStatement(WhileStatement node) { | 705 void visitWhileStatement(WhileStatement node) { |
697 checkBoolean(node.condition); | 706 checkBoolean(node.condition); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
753 } | 762 } |
754 | 763 |
755 /// Checks if an implicit cast of [expr] from [from] type to [to] type is | 764 /// Checks if an implicit cast of [expr] from [from] type to [to] type is |
756 /// needed, and if so records it. | 765 /// needed, and if so records it. |
757 /// | 766 /// |
758 /// If [from] is omitted, uses the static type of [expr]. | 767 /// If [from] is omitted, uses the static type of [expr]. |
759 /// | 768 /// |
760 /// If [expr] does not require an implicit cast because it is not related to | 769 /// If [expr] does not require an implicit cast because it is not related to |
761 /// [to] or is already a subtype of it, does nothing. | 770 /// [to] or is already a subtype of it, does nothing. |
762 void _checkImplicitCast(Expression expr, DartType to, | 771 void _checkImplicitCast(Expression expr, DartType to, |
763 {DartType from, bool opAssign: false}) { | 772 {DartType from, bool opAssign: false, bool isDeclarationCast: false}) { |
764 from ??= _getDefiniteType(expr); | 773 from ??= _getDefiniteType(expr); |
765 | 774 |
766 if (_needsImplicitCast(expr, to, from: from) == true) { | 775 if (_needsImplicitCast(expr, to, |
| 776 from: from, isDeclarationCast: isDeclarationCast) == |
| 777 true) { |
767 _recordImplicitCast(expr, to, from: from, opAssign: opAssign); | 778 _recordImplicitCast(expr, to, from: from, opAssign: opAssign); |
768 } | 779 } |
769 } | 780 } |
770 | 781 |
771 /// Checks if the assignment is valid with respect to non-nullable types. | 782 /// Checks if the assignment is valid with respect to non-nullable types. |
772 /// Returns `false` if a nullable expression is assigned to a variable of | 783 /// Returns `false` if a nullable expression is assigned to a variable of |
773 /// non-nullable type and `true` otherwise. | 784 /// non-nullable type and `true` otherwise. |
774 bool _checkNonNullAssignment( | 785 bool _checkNonNullAssignment( |
775 Expression expression, DartType to, DartType from) { | 786 Expression expression, DartType to, DartType from) { |
776 if (rules.isNonNullableType(to) && rules.isNullableType(from)) { | 787 if (rules.isNonNullableType(to) && rules.isNullableType(from)) { |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 return false; | 1066 return false; |
1056 } | 1067 } |
1057 return rules.anyParameterType(ft, (pt) => pt.isDynamic); | 1068 return rules.anyParameterType(ft, (pt) => pt.isDynamic); |
1058 } | 1069 } |
1059 | 1070 |
1060 /// Returns true if we need an implicit cast of [expr] from [from] type to | 1071 /// Returns true if we need an implicit cast of [expr] from [from] type to |
1061 /// [to] type, returns false if no cast is needed, and returns null if the | 1072 /// [to] type, returns false if no cast is needed, and returns null if the |
1062 /// types are statically incompatible. | 1073 /// types are statically incompatible. |
1063 /// | 1074 /// |
1064 /// If [from] is omitted, uses the static type of [expr] | 1075 /// If [from] is omitted, uses the static type of [expr] |
1065 bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) { | 1076 bool _needsImplicitCast(Expression expr, DartType to, |
| 1077 {DartType from, bool isDeclarationCast: false}) { |
1066 from ??= _getDefiniteType(expr); | 1078 from ??= _getDefiniteType(expr); |
1067 | 1079 |
1068 if (!_checkNonNullAssignment(expr, to, from)) return false; | 1080 if (!_checkNonNullAssignment(expr, to, from)) return false; |
1069 | 1081 |
1070 // We can use anything as void. | 1082 // We can use anything as void. |
1071 if (to.isVoid) return false; | 1083 if (to.isVoid) return false; |
1072 | 1084 |
1073 // fromT <: toT, no coercion needed. | 1085 // fromT <: toT, no coercion needed. |
1074 if (rules.isSubtypeOf(from, to)) return false; | 1086 if (rules.isSubtypeOf(from, to)) return false; |
1075 | 1087 |
1076 // Down cast or legal sideways cast, coercion needed. | 1088 // Down cast or legal sideways cast, coercion needed. |
1077 if (rules.isAssignableTo(from, to)) return true; | 1089 if (rules.isAssignableTo(from, to, isDeclarationCast: isDeclarationCast)) |
| 1090 return true; |
1078 | 1091 |
1079 // Special case for FutureOr to handle returned values from async functions. | 1092 // Special case for FutureOr to handle returned values from async functions. |
1080 // In this case, we're more permissive than assignability. | 1093 // In this case, we're more permissive than assignability. |
1081 if (to.element == typeProvider.futureOrType.element) { | 1094 if (to.element == typeProvider.futureOrType.element) { |
1082 var to1 = (to as InterfaceType).typeArguments[0]; | 1095 var to1 = (to as InterfaceType).typeArguments[0]; |
1083 var to2 = typeProvider.futureType.instantiate([to1]); | 1096 var to2 = typeProvider.futureType.instantiate([to1]); |
1084 return _needsImplicitCast(expr, to1, from: from) == true || | 1097 return _needsImplicitCast(expr, to1, from: from) == true || |
1085 _needsImplicitCast(expr, to2, from: from) == true; | 1098 _needsImplicitCast(expr, to2, from: from) == true; |
1086 } | 1099 } |
1087 | 1100 |
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2001 } | 2014 } |
2002 | 2015 |
2003 /// If node is a [ClassDeclaration] returns its members, otherwise if node is | 2016 /// If node is a [ClassDeclaration] returns its members, otherwise if node is |
2004 /// a [ClassTypeAlias] this returns an empty list. | 2017 /// a [ClassTypeAlias] this returns an empty list. |
2005 WithClause _withClause(Declaration node) { | 2018 WithClause _withClause(Declaration node) { |
2006 return node is ClassDeclaration | 2019 return node is ClassDeclaration |
2007 ? node.withClause | 2020 ? node.withClause |
2008 : (node as ClassTypeAlias).withClause; | 2021 : (node as ClassTypeAlias).withClause; |
2009 } | 2022 } |
2010 } | 2023 } |
OLD | NEW |