| 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 |