Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: pkg/analyzer/lib/src/task/strong/checker.dart

Issue 2976963002: Add --no-declaration-casts option to analyzer. (Closed)
Patch Set: Fix comment Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/task/options.dart ('k') | pkg/analyzer/test/src/command_line/arguments_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698