| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library analyzer.src.generated.resolver; | 5 library analyzer.src.generated.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 3481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3492 * expression, or simple infinite loop such as `while(true)`. | 3492 * expression, or simple infinite loop such as `while(true)`. |
| 3493 */ | 3493 */ |
| 3494 class ExitDetector extends GeneralizingAstVisitor<bool> { | 3494 class ExitDetector extends GeneralizingAstVisitor<bool> { |
| 3495 /** | 3495 /** |
| 3496 * Set to `true` when a `break` is encountered, and reset to `false` when a | 3496 * Set to `true` when a `break` is encountered, and reset to `false` when a |
| 3497 * `do`, `while`, `for` or `switch` block is entered. | 3497 * `do`, `while`, `for` or `switch` block is entered. |
| 3498 */ | 3498 */ |
| 3499 bool _enclosingBlockContainsBreak = false; | 3499 bool _enclosingBlockContainsBreak = false; |
| 3500 | 3500 |
| 3501 /** | 3501 /** |
| 3502 * Set to `true` when a `continue` is encountered, and reset to `false` when a |
| 3503 * `do`, `while`, `for` or `switch` block is entered. |
| 3504 */ |
| 3505 bool _enclosingBlockContainsContinue = false; |
| 3506 |
| 3507 /** |
| 3502 * Add node when a labelled `break` is encountered. | 3508 * Add node when a labelled `break` is encountered. |
| 3503 */ | 3509 */ |
| 3504 Set<AstNode> _enclosingBlockBreaksLabel = new Set<AstNode>(); | 3510 Set<AstNode> _enclosingBlockBreaksLabel = new Set<AstNode>(); |
| 3505 | 3511 |
| 3506 @override | 3512 @override |
| 3507 bool visitArgumentList(ArgumentList node) => | 3513 bool visitArgumentList(ArgumentList node) => |
| 3508 _visitExpressions(node.arguments); | 3514 _visitExpressions(node.arguments); |
| 3509 | 3515 |
| 3510 @override | 3516 @override |
| 3511 bool visitAsExpression(AsExpression node) => _nodeExits(node.expression); | 3517 bool visitAsExpression(AsExpression node) => _nodeExits(node.expression); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3599 if (_nodeExits(conditionExpression)) { | 3605 if (_nodeExits(conditionExpression)) { |
| 3600 return true; | 3606 return true; |
| 3601 } | 3607 } |
| 3602 if (thenStatement == null || elseStatement == null) { | 3608 if (thenStatement == null || elseStatement == null) { |
| 3603 return false; | 3609 return false; |
| 3604 } | 3610 } |
| 3605 return thenStatement.accept(this) && elseStatement.accept(this); | 3611 return thenStatement.accept(this) && elseStatement.accept(this); |
| 3606 } | 3612 } |
| 3607 | 3613 |
| 3608 @override | 3614 @override |
| 3609 bool visitContinueStatement(ContinueStatement node) => false; | 3615 bool visitContinueStatement(ContinueStatement node) { |
| 3616 _enclosingBlockContainsContinue = true; |
| 3617 return false; |
| 3618 } |
| 3610 | 3619 |
| 3611 @override | 3620 @override |
| 3612 bool visitDoStatement(DoStatement node) { | 3621 bool visitDoStatement(DoStatement node) { |
| 3613 bool outerBreakValue = _enclosingBlockContainsBreak; | 3622 bool outerBreakValue = _enclosingBlockContainsBreak; |
| 3623 bool outerContinueValue = _enclosingBlockContainsContinue; |
| 3614 _enclosingBlockContainsBreak = false; | 3624 _enclosingBlockContainsBreak = false; |
| 3625 _enclosingBlockContainsContinue = false; |
| 3615 try { | 3626 try { |
| 3616 if (_nodeExits(node.body) && !_enclosingBlockContainsBreak) { | 3627 bool bodyExits = _nodeExits(node.body); |
| 3628 bool containsBreakOrContinue = |
| 3629 _enclosingBlockContainsBreak || _enclosingBlockContainsContinue; |
| 3630 // Even if we determine that the body "exits", there might be break or |
| 3631 // continue statements that actually mean it _doesn't_ always exit. |
| 3632 if (bodyExits && !containsBreakOrContinue) { |
| 3617 return true; | 3633 return true; |
| 3618 } | 3634 } |
| 3619 Expression conditionExpression = node.condition; | 3635 Expression conditionExpression = node.condition; |
| 3620 if (_nodeExits(conditionExpression)) { | 3636 if (_nodeExits(conditionExpression)) { |
| 3621 return true; | 3637 return true; |
| 3622 } | 3638 } |
| 3623 // TODO(jwren) Do we want to take all constant expressions into account? | 3639 // TODO(jwren) Do we want to take all constant expressions into account? |
| 3624 if (conditionExpression is BooleanLiteral) { | 3640 if (conditionExpression is BooleanLiteral) { |
| 3625 // If do {} while (true), and the body doesn't break, then return true. | 3641 // If do {} while (true), and the body doesn't break, then return true. |
| 3626 if (conditionExpression.value && !_enclosingBlockContainsBreak) { | 3642 if (conditionExpression.value && !_enclosingBlockContainsBreak) { |
| 3627 return true; | 3643 return true; |
| 3628 } | 3644 } |
| 3629 } | 3645 } |
| 3630 return false; | 3646 return false; |
| 3631 } finally { | 3647 } finally { |
| 3632 _enclosingBlockContainsBreak = outerBreakValue; | 3648 _enclosingBlockContainsBreak = outerBreakValue; |
| 3649 _enclosingBlockContainsContinue = outerContinueValue; |
| 3633 } | 3650 } |
| 3634 } | 3651 } |
| 3635 | 3652 |
| 3636 @override | 3653 @override |
| 3637 bool visitEmptyStatement(EmptyStatement node) => false; | 3654 bool visitEmptyStatement(EmptyStatement node) => false; |
| 3638 | 3655 |
| 3639 @override | 3656 @override |
| 3640 bool visitExpressionStatement(ExpressionStatement node) => | 3657 bool visitExpressionStatement(ExpressionStatement node) => |
| 3641 _nodeExits(node.expression); | 3658 _nodeExits(node.expression); |
| 3642 | 3659 |
| (...skipping 7397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11040 return null; | 11057 return null; |
| 11041 } | 11058 } |
| 11042 if (identical(node.staticElement, variable)) { | 11059 if (identical(node.staticElement, variable)) { |
| 11043 if (node.inSetterContext()) { | 11060 if (node.inSetterContext()) { |
| 11044 result = true; | 11061 result = true; |
| 11045 } | 11062 } |
| 11046 } | 11063 } |
| 11047 return null; | 11064 return null; |
| 11048 } | 11065 } |
| 11049 } | 11066 } |
| OLD | NEW |