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( |