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>
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 35f40b1..28ec606 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -1304,16 +1304,39 @@
: 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);
}
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 070694e..86c3bec 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -15470,6 +15470,29 @@
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 @@
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;