Fix parsing label between 2 switch cases

Fix https://github.com/dart-lang/sdk/issues/34453

Change-Id: Ib2280c4482b6530dab3947a0dfd87490bd379034
Reviewed-on: https://dart-review.googlesource.com/75960
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
This commit is contained in:
danrubel 2018-09-21 19:36:40 +00:00 committed by commit-bot@chromium.org
parent 33f6c8ef35
commit 7cd25705ab
2 changed files with 76 additions and 7 deletions

View file

@ -1304,16 +1304,39 @@ class AstBuilder extends StackListener {
: optional(':', colonAfterDefault));
debugEvent("SwitchCase");
List<Statement> statements = popTypedList(statementCount);
List<SwitchMember> members = popTypedList(expressionCount) ?? [];
List<Label> labels = popTypedList(labelCount);
if (defaultKeyword != null) {
members.add(ast.switchDefault(
<Label>[], defaultKeyword, colonAfterDefault, <Statement>[]));
List<Statement> statements = popTypedList<Statement>(statementCount);
List<SwitchMember> members;
if (labelCount == 0 && defaultKeyword == null) {
// Common situation: case with no default and no labels.
members = popTypedList<SwitchMember>(expressionCount) ?? [];
} else {
// Labels and case statements may be intertwined
if (defaultKeyword != null) {
SwitchDefault member = ast.switchDefault(
<Label>[], defaultKeyword, colonAfterDefault, <Statement>[]);
while (peek() is Label) {
member.labels.insert(0, pop());
--labelCount;
}
members = new List<SwitchMember>(expressionCount + 1);
members[expressionCount] = member;
} else {
members = new List<SwitchMember>(expressionCount);
}
for (int index = expressionCount - 1; index >= 0; --index) {
SwitchMember member;
member = pop();
while (peek() is Label) {
member.labels.insert(0, pop());
--labelCount;
}
members[index] = member;
}
assert(labelCount == 0);
}
if (members.isNotEmpty) {
members.last.statements.addAll(statements);
members.first.labels.addAll(labels);
}
push(members);
}

View file

@ -15470,6 +15470,29 @@ main() {
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_labeledCase2() {
SwitchStatement statement =
parseStatement('switch (a) {l1: case 0: l2: case 1: return;}');
assertNoErrors();
expect(statement.switchKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.leftBracket, isNotNull);
expect(statement.members, hasLength(2));
{
List<Label> labels = statement.members[0].labels;
expect(labels, hasLength(1));
expect(labels[0].label.inDeclarationContext(), isTrue);
}
{
List<Label> labels = statement.members[1].labels;
expect(labels, hasLength(1));
expect(labels[0].label.inDeclarationContext(), isTrue);
}
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_labeledDefault() {
var statement =
parseStatement('switch (a) {l1: l2: l3: default:}') as SwitchStatement;
@ -15490,6 +15513,29 @@ main() {
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_labeledDefault2() {
SwitchStatement statement =
parseStatement('switch (a) {l1: case 0: l2: default: return;}');
assertNoErrors();
expect(statement.switchKeyword, isNotNull);
expect(statement.leftParenthesis, isNotNull);
expect(statement.expression, isNotNull);
expect(statement.rightParenthesis, isNotNull);
expect(statement.leftBracket, isNotNull);
expect(statement.members, hasLength(2));
{
List<Label> labels = statement.members[0].labels;
expect(labels, hasLength(1));
expect(labels[0].label.inDeclarationContext(), isTrue);
}
{
List<Label> labels = statement.members[1].labels;
expect(labels, hasLength(1));
expect(labels[0].label.inDeclarationContext(), isTrue);
}
expect(statement.rightBracket, isNotNull);
}
void test_parseSwitchStatement_labeledStatementInCase() {
var statement = parseStatement('switch (a) {case 0: f(); l1: g(); break;}')
as SwitchStatement;