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 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 /// needed, and if so records it. | 765 /// needed, and if so records it. |
766 /// | 766 /// |
767 /// If [from] is omitted, uses the static type of [expr]. | 767 /// If [from] is omitted, uses the static type of [expr]. |
768 /// | 768 /// |
769 /// 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 |
770 /// [to] or is already a subtype of it, does nothing. | 770 /// [to] or is already a subtype of it, does nothing. |
771 void _checkImplicitCast(Expression expr, DartType to, | 771 void _checkImplicitCast(Expression expr, DartType to, |
772 {DartType from, bool opAssign: false, bool isDeclarationCast: false}) { | 772 {DartType from, bool opAssign: false, bool isDeclarationCast: false}) { |
773 from ??= _getDefiniteType(expr); | 773 from ??= _getDefiniteType(expr); |
774 | 774 |
| 775 _hintOnFuzzyArrows(expr, to, from); |
| 776 |
775 if (_needsImplicitCast(expr, to, | 777 if (_needsImplicitCast(expr, to, |
776 from: from, isDeclarationCast: isDeclarationCast) == | 778 from: from, isDeclarationCast: isDeclarationCast) == |
777 true) { | 779 true) { |
778 _recordImplicitCast(expr, to, from: from, opAssign: opAssign); | 780 _recordImplicitCast(expr, to, from: from, opAssign: opAssign); |
779 } | 781 } |
780 } | 782 } |
781 | 783 |
782 /// Checks if the assignment is valid with respect to non-nullable types. | 784 /// Checks if the assignment is valid with respect to non-nullable types. |
783 /// Returns `false` if a nullable expression is assigned to a variable of | 785 /// Returns `false` if a nullable expression is assigned to a variable of |
784 /// non-nullable type and `true` otherwise. | 786 /// non-nullable type and `true` otherwise. |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 // Dynamic as the parameter type is treated as bottom. A function with | 1070 // Dynamic as the parameter type is treated as bottom. A function with |
1069 // a dynamic parameter type requires a dynamic call in general. | 1071 // a dynamic parameter type requires a dynamic call in general. |
1070 // However, as an optimization, if we have an original definition, we know | 1072 // However, as an optimization, if we have an original definition, we know |
1071 // dynamic is reified as Object - in this case a regular call is fine. | 1073 // dynamic is reified as Object - in this case a regular call is fine. |
1072 if (hasStrictArrow(call.function)) { | 1074 if (hasStrictArrow(call.function)) { |
1073 return false; | 1075 return false; |
1074 } | 1076 } |
1075 return rules.anyParameterType(ft, (pt) => pt.isDynamic); | 1077 return rules.anyParameterType(ft, (pt) => pt.isDynamic); |
1076 } | 1078 } |
1077 | 1079 |
| 1080 void _hintOnFuzzyArrows(Expression expr, DartType to, DartType from) { |
| 1081 // If it is a subtype with fuzzy arrows on, |
| 1082 // check to see if it still is with them off. |
| 1083 if (rules.isSubtypeOf(from, to)) { |
| 1084 // Remove fuzzy arrows |
| 1085 var cFrom = rules.typeToConcreteType(from); |
| 1086 var cTo = rules.typeToConcreteType(to); |
| 1087 // If still true, no warning needed |
| 1088 if (rules.isSubtypeOf(cFrom, cTo)) return; |
| 1089 _recordMessage(expr, HintCode.USES_DYNAMIC_AS_BOTTOM, [from, to]); |
| 1090 } |
| 1091 } |
| 1092 |
1078 /// Returns true if we need an implicit cast of [expr] from [from] type to | 1093 /// Returns true if we need an implicit cast of [expr] from [from] type to |
1079 /// [to] type, returns false if no cast is needed, and returns null if the | 1094 /// [to] type, returns false if no cast is needed, and returns null if the |
1080 /// types are statically incompatible. | 1095 /// types are statically incompatible. |
1081 /// | 1096 /// |
1082 /// If [from] is omitted, uses the static type of [expr] | 1097 /// If [from] is omitted, uses the static type of [expr] |
1083 bool _needsImplicitCast(Expression expr, DartType to, | 1098 bool _needsImplicitCast(Expression expr, DartType to, |
1084 {DartType from, bool isDeclarationCast: false}) { | 1099 {DartType from, bool isDeclarationCast: false}) { |
1085 from ??= _getDefiniteType(expr); | 1100 from ??= _getDefiniteType(expr); |
1086 | 1101 |
1087 if (!_checkNonNullAssignment(expr, to, from)) return false; | 1102 if (!_checkNonNullAssignment(expr, to, from)) return false; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1217 var severity = | 1232 var severity = |
1218 (processor != null) ? processor.severity : errorCode.errorSeverity; | 1233 (processor != null) ? processor.severity : errorCode.errorSeverity; |
1219 | 1234 |
1220 if (severity == ErrorSeverity.ERROR) { | 1235 if (severity == ErrorSeverity.ERROR) { |
1221 _failure = true; | 1236 _failure = true; |
1222 } | 1237 } |
1223 if (errorCode.type == ErrorType.HINT && | 1238 if (errorCode.type == ErrorType.HINT && |
1224 errorCode.name.startsWith('STRONG_MODE_TOP_LEVEL_')) { | 1239 errorCode.name.startsWith('STRONG_MODE_TOP_LEVEL_')) { |
1225 severity = ErrorSeverity.ERROR; | 1240 severity = ErrorSeverity.ERROR; |
1226 } | 1241 } |
1227 if (severity != ErrorSeverity.INFO || _options.strongModeHints) { | 1242 if (severity != ErrorSeverity.INFO || |
| 1243 _options.strongModeHints || |
| 1244 errorCode == HintCode.USES_DYNAMIC_AS_BOTTOM) { |
1228 int begin = node is AnnotatedNode | 1245 int begin = node is AnnotatedNode |
1229 ? node.firstTokenAfterCommentAndMetadata.offset | 1246 ? node.firstTokenAfterCommentAndMetadata.offset |
1230 : node.offset; | 1247 : node.offset; |
1231 int length = node.end - begin; | 1248 int length = node.end - begin; |
1232 var source = resolutionMap | 1249 var source = resolutionMap |
1233 .elementDeclaredByCompilationUnit(node.root as CompilationUnit) | 1250 .elementDeclaredByCompilationUnit(node.root as CompilationUnit) |
1234 .source; | 1251 .source; |
1235 var error = | 1252 var error = |
1236 new AnalysisError(source, begin, length, errorCode, arguments); | 1253 new AnalysisError(source, begin, length, errorCode, arguments); |
1237 reporter.onError(error); | 1254 reporter.onError(error); |
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1981 } | 1998 } |
1982 | 1999 |
1983 /// If node is a [ClassDeclaration] returns its members, otherwise if node is | 2000 /// If node is a [ClassDeclaration] returns its members, otherwise if node is |
1984 /// a [ClassTypeAlias] this returns an empty list. | 2001 /// a [ClassTypeAlias] this returns an empty list. |
1985 WithClause _withClause(Declaration node) { | 2002 WithClause _withClause(Declaration node) { |
1986 return node is ClassDeclaration | 2003 return node is ClassDeclaration |
1987 ? node.withClause | 2004 ? node.withClause |
1988 : (node as ClassTypeAlias).withClause; | 2005 : (node as ClassTypeAlias).withClause; |
1989 } | 2006 } |
1990 } | 2007 } |
OLD | NEW |