Chromium Code Reviews| Index: pkg/analyzer/lib/src/generated/resolver.dart |
| diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart |
| index 7dbf6e42c99492dbe9054a776fd77d0869c52b5e..89d2fb832b5eff5327ea2cb0fb5f48e273278c6a 100644 |
| --- a/pkg/analyzer/lib/src/generated/resolver.dart |
| +++ b/pkg/analyzer/lib/src/generated/resolver.dart |
| @@ -3470,6 +3470,11 @@ class ExitDetector extends GeneralizingAstVisitor<bool> { |
| */ |
| bool _enclosingBlockContainsBreak = false; |
| + /** |
| + * Add node when a labelled `break` is encountered. |
| + */ |
| + Set<AstNode> _enclosingBlockBreaksLabel = new Set<AstNode>(); |
|
srawlins
2016/05/25 17:26:03
This probably isn't a popular decision, whole AstN
Brian Wilkerson
2016/05/25 18:13:23
As long as the ExitDetector is not long-lived, the
srawlins
2016/05/25 20:45:23
Acknowledged.
|
| + |
| @override |
| bool visitArgumentList(ArgumentList node) => |
| _visitExpressions(node.arguments); |
| @@ -3545,6 +3550,9 @@ class ExitDetector extends GeneralizingAstVisitor<bool> { |
| @override |
| bool visitBreakStatement(BreakStatement node) { |
| _enclosingBlockContainsBreak = true; |
| + if (node.label != null) { |
| + _enclosingBlockBreaksLabel.add(node.target); |
| + } |
| return false; |
| } |
| @@ -3634,13 +3642,13 @@ class ExitDetector extends GeneralizingAstVisitor<bool> { |
| if (_visitExpressions(node.updaters)) { |
| return true; |
| } |
| + bool blockReturns = _nodeExits(node.body); |
| // TODO(jwren) Do we want to take all constant expressions into account? |
| // If for(; true; ) (or for(;;)), and the body doesn't return or the body |
| // doesn't have a break, then return true. |
| bool implicitOrExplictTrue = conditionExpression == null || |
| (conditionExpression is BooleanLiteral && conditionExpression.value); |
| if (implicitOrExplictTrue) { |
| - bool blockReturns = _nodeExits(node.body); |
| if (blockReturns || !_enclosingBlockContainsBreak) { |
| return true; |
| } |
| @@ -3680,18 +3688,18 @@ class ExitDetector extends GeneralizingAstVisitor<bool> { |
| // TODO(jwren) Do we want to take all constant expressions into account? |
| if (conditionExpression is BooleanLiteral) { |
| if (conditionExpression.value) { |
| - // if(true) ... |
| + // if (true) ... |
| return _nodeExits(thenStatement); |
| } else if (elseStatement != null) { |
| // if (false) ... |
| return _nodeExits(elseStatement); |
| } |
| } |
| - if (thenStatement == null || elseStatement == null) { |
| - return false; |
| - } |
| bool thenExits = _nodeExits(thenStatement); |
|
srawlins
2016/05/25 17:26:03
Need to always visit `then` and `else`, to find po
|
| bool elseExits = _nodeExits(elseStatement); |
| + if (thenStatement == null || elseStatement == null) { |
| + return false; |
| + } |
| return thenExits && elseExits; |
| } |
| @@ -3718,8 +3726,16 @@ class ExitDetector extends GeneralizingAstVisitor<bool> { |
| bool visitLabel(Label node) => false; |
| @override |
| - bool visitLabeledStatement(LabeledStatement node) => |
| - node.statement.accept(this); |
| + bool visitLabeledStatement(LabeledStatement node) { |
| + try { |
| + bool statementExits = _nodeExits(node.statement); |
| + bool neverBrokeFromLabel = |
| + !_enclosingBlockBreaksLabel.contains(node.statement); |
| + return statementExits && neverBrokeFromLabel; |
| + } finally { |
| + _enclosingBlockBreaksLabel.remove(node); |
|
Brian Wilkerson
2016/05/25 18:13:23
"node" --> "node.statement"?
srawlins
2016/05/25 20:45:23
Done.
|
| + } |
| + } |
| @override |
| bool visitLiteral(Literal node) => false; |
| @@ -3873,11 +3889,11 @@ class ExitDetector extends GeneralizingAstVisitor<bool> { |
| if (conditionExpression.accept(this)) { |
| return true; |
| } |
| + bool blockReturns = node.body.accept(this); |
| // TODO(jwren) Do we want to take all constant expressions into account? |
| if (conditionExpression is BooleanLiteral) { |
| // If while(true), and the body doesn't return or the body doesn't have |
| // a break, then return true. |
| - bool blockReturns = node.body.accept(this); |
| if (conditionExpression.value && |
| (blockReturns || !_enclosingBlockContainsBreak)) { |
| return true; |
| @@ -3912,12 +3928,13 @@ class ExitDetector extends GeneralizingAstVisitor<bool> { |
| } |
| bool _visitStatements(NodeList<Statement> statements) { |
| + var exits = false; |
| for (int i = statements.length - 1; i >= 0; i--) { |
| if (statements[i].accept(this)) { |
| - return true; |
| + exits = true; |
|
srawlins
2016/05/25 17:26:03
This may also be unpopular. We can't short circuit
Brian Wilkerson
2016/05/25 18:13:23
I don't understand why. If a statement always exit
srawlins
2016/05/25 20:45:23
OK it walks forwards now.
|
| } |
| } |
| - return false; |
| + return exits; |
| } |
| bool _visitVariableDeclarations( |