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

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

Issue 2176693003: Issue a strong mode warning for type inference that is unsafe with AST-based summaries. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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 '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 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 373
374 @override 374 @override
375 void visitForStatement(ForStatement node) { 375 void visitForStatement(ForStatement node) {
376 if (node.condition != null) { 376 if (node.condition != null) {
377 checkBoolean(node.condition); 377 checkBoolean(node.condition);
378 } 378 }
379 node.visitChildren(this); 379 node.visitChildren(this);
380 } 380 }
381 381
382 @override 382 @override
383 void visitFunctionExpression(FunctionExpression node) {
384 _checkForUnsafeBlockClosureInference(node);
385 super.visitFunctionExpression(node);
386 }
387
388 @override
383 void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 389 void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
384 checkFunctionApplication(node, node.function, node.argumentList); 390 checkFunctionApplication(node, node.function, node.argumentList);
385 node.visitChildren(this); 391 node.visitChildren(this);
386 } 392 }
387 393
388 @override 394 @override
389 void visitIfStatement(IfStatement node) { 395 void visitIfStatement(IfStatement node) {
390 checkBoolean(node.condition); 396 checkBoolean(node.condition);
391 node.visitChildren(this); 397 node.visitChildren(this);
392 } 398 }
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 } 712 }
707 713
708 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) { 714 void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) {
709 if ((_isDynamicTarget(target) || field.staticElement == null) && 715 if ((_isDynamicTarget(target) || field.staticElement == null) &&
710 !_isObjectProperty(target, field)) { 716 !_isObjectProperty(target, field)) {
711 _recordDynamicInvoke(node, target); 717 _recordDynamicInvoke(node, target);
712 } 718 }
713 node.visitChildren(this); 719 node.visitChildren(this);
714 } 720 }
715 721
722 /**
723 * Check if the closure [node] is unsafe due to dartbug.com/26947. If so,
724 * issue a warning.
725 *
726 * TODO(paulberry): eliminate this once dartbug.com/26947 is fixed.
727 */
728 void _checkForUnsafeBlockClosureInference(FunctionExpression node) {
729 if (node.body is! BlockFunctionBody) {
730 return;
731 }
732 if (node.element.returnType.isDynamic) {
733 return;
734 }
735 // Find the enclosing variable declaration whose inferred type might depend
736 // on the inferred return type of the block closure (if any).
737 VariableDeclaration decl = null;
738 AstNode ancestor = node.parent;
739 while (ancestor != null) {
740 if (ancestor is BlockFunctionBody) {
741 // node is inside another block function body; if that block
742 // function body is unsafe, we've already warned about it.
743 return;
744 }
745 if (ancestor is VariableDeclaration) {
Leaf 2016/07/22 23:34:41 Might be a bit clearer just to make this part of t
Paul Berry 2016/07/23 16:18:18 Done.
746 decl = ancestor;
747 break;
748 }
749 if (ancestor is InstanceCreationExpression) {
Leaf 2016/07/22 23:34:41 Presumably this same logic could be applied to Lis
Paul Berry 2016/07/23 16:18:18 Done. PTAL.
750 // node appears inside an instance creation expression; we may be safe
751 // if the type of the instance creation expression requires no
752 // inference.
753 TypeName typeName = ancestor.constructorName.type;
754 DartType type = typeName.type;
755 if (typeName.typeArguments != null) {
756 // Type arguments were explicitly specified. We are safe.
757 return;
758 }
759 if (!(type is ParameterizedType && type.typeParameters.isNotEmpty)) {
760 // Type is not generic. We are safe.
761 return;
762 }
763 }
764 ancestor = ancestor.parent;
765 }
766 if (decl == null) {
767 // node is not inside a variable declaration, so it is safe.
768 return;
769 }
770 VariableElement declElement = decl.element;
771 if (!declElement.hasImplicitType) {
772 // Variable declaration has an explicit type, so it's safe.
773 return;
774 }
775 if (declElement.type.isDynamic) {
776 // No type was successfully inferred for this variable, so it's safe.
777 return;
778 }
779 if (declElement.enclosingElement is ExecutableElement) {
780 // Variable declaration is inside a function or method, so it's safe.
781 return;
782 }
783 _recordMessage(node, StrongModeCode.UNSAFE_BLOCK_CLOSURE_INFERENCE,
784 [declElement.name]);
785 }
786
716 void _checkReturnOrYield(Expression expression, AstNode node, 787 void _checkReturnOrYield(Expression expression, AstNode node,
717 {bool yieldStar: false}) { 788 {bool yieldStar: false}) {
718 FunctionBody body = node.getAncestor((n) => n is FunctionBody); 789 FunctionBody body = node.getAncestor((n) => n is FunctionBody);
719 var type = _getExpectedReturnType(body, yieldStar: yieldStar); 790 var type = _getExpectedReturnType(body, yieldStar: yieldStar);
720 if (type == null) { 791 if (type == null) {
721 // We have a type mismatch: the async/async*/sync* modifier does 792 // We have a type mismatch: the async/async*/sync* modifier does
722 // not match the return or yield type. We should have already gotten an 793 // not match the return or yield type. We should have already gotten an
723 // analyzer error in this case. 794 // analyzer error in this case.
724 return; 795 return;
725 } 796 }
(...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 var visited = new Set<InterfaceType>(); 1441 var visited = new Set<InterfaceType>();
1371 do { 1442 do {
1372 visited.add(current); 1443 visited.add(current);
1373 current.mixins.reversed.forEach( 1444 current.mixins.reversed.forEach(
1374 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); 1445 (m) => _checkIndividualOverridesFromClass(node, m, seen, true));
1375 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); 1446 _checkIndividualOverridesFromClass(node, current.superclass, seen, true);
1376 current = current.superclass; 1447 current = current.superclass;
1377 } while (!current.isObject && !visited.contains(current)); 1448 } while (!current.isObject && !visited.contains(current));
1378 } 1449 }
1379 } 1450 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/error.dart ('k') | pkg/analyzer/test/src/summary/resynthesize_ast_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698