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;