Patterns parsing: add support for guards.

Bug: https://github.com/dart-lang/sdk/issues/50035
Change-Id: I21db09c9d8c1d359e1b125eea2bae2749cdb72fd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/264101
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index 807a3a6..3ad1953 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -6240,8 +6240,14 @@
     if (allowPatterns && optional('case', next)) {
       Token case_ = token = next;
       token = parsePattern(token);
+      next = token.next!;
+      Token? when;
+      if (optional('when', next)) {
+        when = token = next;
+        token = parseExpression(token);
+      }
       token = ensureCloseParen(token, begin);
-      listener.handleParenthesizedCondition(begin, case_, null);
+      listener.handleParenthesizedCondition(begin, case_, when);
     } else {
       token = ensureCloseParen(token, begin);
       listener.handleParenthesizedCondition(
@@ -8258,9 +8264,15 @@
           } else {
             token = parseExpression(caseKeyword);
           }
+          Token? next = token.next!;
+          Token? when;
+          if (optional('when', next)) {
+            when = token = next;
+            token = parseExpression(token);
+          }
           token = ensureColon(token);
-          listener.endCaseExpression(null, token);
-          listener.handleCaseMatch(caseKeyword, null, token);
+          listener.endCaseExpression(when, token);
+          listener.handleCaseMatch(caseKeyword, when, token);
           expressionCount++;
           peek = peekPastLabels(token.next!);
         } else if (expressionCount > 0) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
index ccbb40f..a3afcf2 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
@@ -327,14 +327,17 @@
   static const Keyword VOID =
       const Keyword(/* index = */ 145, "void", "VOID", KeywordStyle.reserved);
 
+  static const Keyword WHEN =
+      const Keyword(/* index = */ 146, "when", 'WHEN', KeywordStyle.pseudo);
+
   static const Keyword WHILE =
-      const Keyword(/* index = */ 146, "while", "WHILE", KeywordStyle.reserved);
+      const Keyword(/* index = */ 147, "while", "WHILE", KeywordStyle.reserved);
 
   static const Keyword WITH =
-      const Keyword(/* index = */ 147, "with", "WITH", KeywordStyle.reserved);
+      const Keyword(/* index = */ 148, "with", "WITH", KeywordStyle.reserved);
 
   static const Keyword YIELD =
-      const Keyword(/* index = */ 148, "yield", "YIELD", KeywordStyle.pseudo);
+      const Keyword(/* index = */ 149, "yield", "YIELD", KeywordStyle.pseudo);
 
   static const List<Keyword> values = const <Keyword>[
     ABSTRACT,
@@ -404,6 +407,7 @@
     TYPEDEF,
     VAR,
     VOID,
+    WHEN,
     WHILE,
     WITH,
     YIELD,
@@ -1978,6 +1982,7 @@
   Keyword.TYPEDEF,
   Keyword.VAR,
   Keyword.VOID,
+  Keyword.WHEN,
   Keyword.WHILE,
   Keyword.WITH,
   Keyword.YIELD,
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 365fed9..d944173 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -1483,6 +1483,7 @@
     required this.whenClause,
   }) {
     _becomeParentOf(pattern);
+    _becomeParentOf(whenClause);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 7b84143..95467fe 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -3282,12 +3282,17 @@
     debugEvent("CaseMatch");
 
     if (_featureSet.isEnabled(Feature.patterns)) {
+      WhenClauseImpl? whenClause;
+      if (when != null) {
+        var expression = pop() as ExpressionImpl;
+        whenClause = WhenClauseImpl(whenKeyword: when, expression: expression);
+      }
       var pattern = pop() as DartPatternImpl;
       push(SwitchPatternCaseImpl(
           labels: <Label>[],
           keyword: caseKeyword,
           pattern: pattern,
-          whenClause: null,
+          whenClause: whenClause,
           colon: colon,
           statements: <Statement>[]));
     } else {
@@ -4561,10 +4566,14 @@
     ExpressionImpl condition;
     CaseClauseImpl? caseClause;
     if (case_ != null) {
-      // TODO(paulberry): what about a guard?
+      WhenClauseImpl? whenClause;
+      if (when != null) {
+        var expression = pop() as ExpressionImpl;
+        whenClause = WhenClauseImpl(whenKeyword: when, expression: expression);
+      }
       var pattern = pop() as DartPatternImpl;
       caseClause = CaseClauseImpl(
-          caseKeyword: case_, pattern: pattern, whenClause: null);
+          caseKeyword: case_, pattern: pattern, whenClause: whenClause);
     }
     condition = pop() as ExpressionImpl;
     push(_ParenthesizedCondition(leftParenthesis, condition, caseClause));
diff --git a/pkg/analyzer/test/generated/patterns_parser_test.dart b/pkg/analyzer/test/generated/patterns_parser_test.dart
index 0b11317..a5b6123 100644
--- a/pkg/analyzer/test/generated/patterns_parser_test.dart
+++ b/pkg/analyzer/test/generated/patterns_parser_test.dart
@@ -21,6 +21,238 @@
 class PatternsTest extends ParserDiagnosticsTest {
   late FindNode findNode;
 
+  test_caseHead_withClassicPattern_guarded_insideIfStatement() {
+    _parse('''
+void f(x) {
+  if (x case 0 when true) {}
+}
+''');
+    var node = findNode.ifStatement('case');
+    assertParsedNodeText(node, r'''
+IfStatement
+  ifKeyword: if
+  leftParenthesis: (
+  condition: SimpleIdentifier
+    token: x
+  caseClause: CaseClause
+    caseKeyword: case
+    pattern: ConstantPattern
+      expression: IntegerLiteral
+        literal: 0
+    whenClause: WhenClause
+      whenKeyword: when
+      expression: BooleanLiteral
+        literal: true
+  rightParenthesis: )
+  thenStatement: Block
+    leftBracket: {
+    rightBracket: }
+''');
+  }
+
+  test_caseHead_withClassicPattern_guarded_insideSwitchStatement() {
+    _parse('''
+void f(x) {
+  switch (x) {
+    case 0 when true:
+      break;
+  }
+}
+''');
+    var node = findNode.switchPatternCase('case');
+    assertParsedNodeText(node, r'''
+SwitchPatternCase
+  keyword: case
+  pattern: ConstantPattern
+    expression: IntegerLiteral
+      literal: 0
+  whenClause: WhenClause
+    whenKeyword: when
+    expression: BooleanLiteral
+      literal: true
+  colon: :
+  statements
+    BreakStatement
+      breakKeyword: break
+      semicolon: ;
+''');
+  }
+
+  test_caseHead_withClassicPattern_unguarded_insideIfStatement() {
+    _parse('''
+void f(x) {
+  if (x case 0) {}
+}
+''');
+    var node = findNode.ifStatement('case');
+    assertParsedNodeText(node, r'''
+IfStatement
+  ifKeyword: if
+  leftParenthesis: (
+  condition: SimpleIdentifier
+    token: x
+  caseClause: CaseClause
+    caseKeyword: case
+    pattern: ConstantPattern
+      expression: IntegerLiteral
+        literal: 0
+  rightParenthesis: )
+  thenStatement: Block
+    leftBracket: {
+    rightBracket: }
+''');
+  }
+
+  test_caseHead_withClassicPattern_unguarded_insideSwitchStatement() {
+    _parse('''
+void f(x) {
+  switch (x) {
+    case 0:
+      break;
+  }
+}
+''');
+    var node = findNode.switchPatternCase('case');
+    assertParsedNodeText(node, r'''
+SwitchPatternCase
+  keyword: case
+  pattern: ConstantPattern
+    expression: IntegerLiteral
+      literal: 0
+  colon: :
+  statements
+    BreakStatement
+      breakKeyword: break
+      semicolon: ;
+''');
+  }
+
+  test_caseHead_withNewPattern_guarded_insideIfStatement() {
+    _parse('''
+void f(x) {
+  if (x case 0 as int when true) {}
+}
+''');
+    var node = findNode.ifStatement('case');
+    assertParsedNodeText(node, r'''
+IfStatement
+  ifKeyword: if
+  leftParenthesis: (
+  condition: SimpleIdentifier
+    token: x
+  caseClause: CaseClause
+    caseKeyword: case
+    pattern: CastPattern
+      pattern: ConstantPattern
+        expression: IntegerLiteral
+          literal: 0
+      asToken: as
+      type: NamedType
+        name: SimpleIdentifier
+          token: int
+    whenClause: WhenClause
+      whenKeyword: when
+      expression: BooleanLiteral
+        literal: true
+  rightParenthesis: )
+  thenStatement: Block
+    leftBracket: {
+    rightBracket: }
+''');
+  }
+
+  test_caseHead_withNewPattern_guarded_insideSwitchStatement() {
+    _parse('''
+void f(x) {
+  switch (x) {
+    case 0 as int when true:
+      break;
+  }
+}
+''');
+    var node = findNode.switchPatternCase('case');
+    assertParsedNodeText(node, r'''
+SwitchPatternCase
+  keyword: case
+  pattern: CastPattern
+    pattern: ConstantPattern
+      expression: IntegerLiteral
+        literal: 0
+    asToken: as
+    type: NamedType
+      name: SimpleIdentifier
+        token: int
+  whenClause: WhenClause
+    whenKeyword: when
+    expression: BooleanLiteral
+      literal: true
+  colon: :
+  statements
+    BreakStatement
+      breakKeyword: break
+      semicolon: ;
+''');
+  }
+
+  test_caseHead_withNewPattern_unguarded_insideIfStatement() {
+    _parse('''
+void f(x) {
+  if (x case 0 as int) {}
+}
+''');
+    var node = findNode.ifStatement('case');
+    assertParsedNodeText(node, r'''
+IfStatement
+  ifKeyword: if
+  leftParenthesis: (
+  condition: SimpleIdentifier
+    token: x
+  caseClause: CaseClause
+    caseKeyword: case
+    pattern: CastPattern
+      pattern: ConstantPattern
+        expression: IntegerLiteral
+          literal: 0
+      asToken: as
+      type: NamedType
+        name: SimpleIdentifier
+          token: int
+  rightParenthesis: )
+  thenStatement: Block
+    leftBracket: {
+    rightBracket: }
+''');
+  }
+
+  test_caseHead_withNewPattern_unguarded_insideSwitchStatement() {
+    _parse('''
+void f(x) {
+  switch (x) {
+    case 0 as int:
+      break;
+  }
+}
+''');
+    var node = findNode.switchPatternCase('case');
+    assertParsedNodeText(node, r'''
+SwitchPatternCase
+  keyword: case
+  pattern: CastPattern
+    pattern: ConstantPattern
+      expression: IntegerLiteral
+        literal: 0
+    asToken: as
+    type: NamedType
+      name: SimpleIdentifier
+        token: int
+  colon: :
+  statements
+    BreakStatement
+      breakKeyword: break
+      semicolon: ;
+''');
+  }
+
   test_cast_insideCase() {
     _parse('''
 void f(x) {
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index 6e742b2..dbdf688 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -1439,6 +1439,14 @@
   }
 
   @override
+  void visitWhenClause(WhenClause node) {
+    _writeln('WhenClause');
+    _withIndent(() {
+      _writeNamedChildEntities(node);
+    });
+  }
+
+  @override
   void visitWhileStatement(WhileStatement node) {
     _writeln('WhileStatement');
     _withIndent(() {
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index ba99d30..c7fc608 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -2281,6 +2281,28 @@
   @override
   void handleParenthesizedCondition(Token token, Token? case_, Token? when) {
     if (case_ != null) {
+      // ignore: unused_local_variable
+      Expression? guard;
+      if (when != null) {
+        assert(checkState(token, [
+          unionOfKinds([
+            ValueKinds.Expression,
+            ValueKinds.Generator,
+            ValueKinds.ProblemBuilder,
+          ]),
+          unionOfKinds([
+            ValueKinds.Expression,
+            ValueKinds.Matcher,
+            ValueKinds.Binder,
+          ]),
+          unionOfKinds([
+            ValueKinds.Expression,
+            ValueKinds.Generator,
+            ValueKinds.ProblemBuilder,
+          ]),
+        ]));
+        guard = popForValue();
+      }
       assert(checkState(token, [
         unionOfKinds([
           ValueKinds.Expression,
@@ -2508,6 +2530,26 @@
 
   @override
   void endCaseExpression(Token? when, Token colon) {
+    // ignore: unused_local_variable
+    Expression? guard;
+    if (when != null) {
+      assert(checkState(colon, [
+        unionOfKinds([
+          ValueKinds.Expression,
+          ValueKinds.Generator,
+          ValueKinds.ProblemBuilder,
+        ]),
+        unionOfKinds([
+          ValueKinds.Expression,
+          ValueKinds.Generator,
+          ValueKinds.ProblemBuilder,
+          ValueKinds.Matcher,
+          ValueKinds.Binder,
+        ]),
+        ValueKinds.ConstantContext,
+      ]));
+      guard = popForValue();
+    }
     assert(checkState(colon, [
       unionOfKinds([
         ValueKinds.Expression,
@@ -2522,10 +2564,12 @@
     Object? value = pop();
     if (value is Matcher || value is Binder) {
       constantContext = pop() as ConstantContext;
+      // TODO(paulberry): handle guard
       super.push(toMatcher(value));
     } else {
       Expression expression = toValue(value);
       constantContext = pop() as ConstantContext;
+      // TODO(paulberry): handle guard
       super.push(expression);
     }
     assert(checkState(colon, [
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart
new file mode 100644
index 0000000..f1abcf1
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart
@@ -0,0 +1,3 @@
+void f(x) {
+  if (x case 0 when true) {}
+}
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.expect
new file mode 100644
index 0000000..791b439
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.expect
@@ -0,0 +1,37 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(x)
+        endMetadataStar(0)
+        beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+          handleNoType(()
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginIfStatement(if)
+          handleIdentifier(x, expression)
+          handleNoTypeArguments(case)
+          handleNoArguments(case)
+          handleSend(x, case)
+          handleLiteralInt(0)
+          handleConstantPattern(null)
+          handleLiteralBool(true)
+          handleParenthesizedCondition((, case, when)
+          beginThenStatement({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endThenStatement(})
+        endIfStatement(if, null)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.intertwined.expect
new file mode 100644
index 0000000..8930d09
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.intertwined.expect
@@ -0,0 +1,89 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(x)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleNoType(()
+                ensureIdentifier((, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, if)
+          parseStatement({)
+            parseStatementX({)
+              parseIfStatement({)
+                listener: beginIfStatement(if)
+                ensureParenthesizedCondition(if, allowCase: true)
+                  parseExpressionInParenthesisRest((, allowCase: true)
+                    parseExpression(()
+                      parsePrecedenceExpression((, 1, true)
+                        parseUnaryExpression((, true)
+                          parsePrimary((, expression)
+                            parseSendOrFunctionLiteral((, expression)
+                              parseSend((, expression)
+                                isNextIdentifier(()
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(case)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(case)
+                                listener: handleSend(x, case)
+                    parsePattern(case, precedence: 1)
+                      parsePrimaryPattern(case)
+                        parsePrecedenceExpression(case, 18, false)
+                          parseUnaryExpression(case, false)
+                            parsePrimary(case, expression)
+                              parseLiteralInt(case)
+                                listener: handleLiteralInt(0)
+                        listener: handleConstantPattern(null)
+                    parseExpression(when)
+                      parsePrecedenceExpression(when, 1, true)
+                        parseUnaryExpression(when, true)
+                          parsePrimary(when, expression)
+                            parseLiteralBool(when)
+                              listener: handleLiteralBool(true)
+                    ensureCloseParen(true, ()
+                    listener: handleParenthesizedCondition((, case, when)
+                listener: beginThenStatement({)
+                parseStatement())
+                  parseStatementX())
+                    parseBlock(), BlockKind(statement))
+                      ensureBlock(), null, null)
+                      listener: beginBlock({, BlockKind(statement))
+                      notEofOrValue(}, })
+                      listener: endBlock(0, {, }, BlockKind(statement))
+                listener: endThenStatement(})
+                listener: endIfStatement(if, null)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.parser.expect
new file mode 100644
index 0000000..de1f943
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.parser.expect
@@ -0,0 +1,9 @@
+void f(x) {
+if (x case 0 when true) {}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]x[StringToken] case[KeywordToken] 0[StringToken] when[KeywordToken] true[KeywordToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.scanner.expect
new file mode 100644
index 0000000..de1f943
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideIfStatement.dart.scanner.expect
@@ -0,0 +1,9 @@
+void f(x) {
+if (x case 0 when true) {}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]x[StringToken] case[KeywordToken] 0[StringToken] when[KeywordToken] true[KeywordToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart
new file mode 100644
index 0000000..b678211
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart
@@ -0,0 +1,6 @@
+void f(x) {
+  switch (x) {
+    case 0 when true:
+      break;
+  }
+}
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.expect
new file mode 100644
index 0000000..78ebb90
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.expect
@@ -0,0 +1,41 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(x)
+        endMetadataStar(0)
+        beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+          handleNoType(()
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginSwitchStatement(switch)
+          handleIdentifier(x, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(x, ))
+          handleParenthesizedCondition((, null, null)
+          beginSwitchBlock({)
+            beginCaseExpression(case)
+              handleLiteralInt(0)
+              handleConstantPattern(null)
+              handleLiteralBool(true)
+            endCaseExpression(when, :)
+            handleCaseMatch(case, when, :)
+            beginSwitchCase(0, 1, case)
+              handleBreakStatement(false, break, ;)
+            endSwitchCase(0, 1, null, null, 1, case, })
+          endSwitchBlock(1, {, })
+        endSwitchStatement(switch, })
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.intertwined.expect
new file mode 100644
index 0000000..a8dfcbe
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.intertwined.expect
@@ -0,0 +1,102 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(x)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleNoType(()
+                ensureIdentifier((, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, switch)
+          parseStatement({)
+            parseStatementX({)
+              parseSwitchStatement({)
+                listener: beginSwitchStatement(switch)
+                ensureParenthesizedCondition(switch, allowCase: false)
+                  parseExpressionInParenthesisRest((, allowCase: false)
+                    parseExpression(()
+                      parsePrecedenceExpression((, 1, true)
+                        parseUnaryExpression((, true)
+                          parsePrimary((, expression)
+                            parseSendOrFunctionLiteral((, expression)
+                              parseSend((, expression)
+                                isNextIdentifier(()
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments())
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments())
+                                listener: handleSend(x, ))
+                    ensureCloseParen(x, ()
+                    listener: handleParenthesizedCondition((, null, null)
+                parseSwitchBlock())
+                  ensureBlock(), null, switch statement)
+                  listener: beginSwitchBlock({)
+                  notEofOrValue(}, case)
+                  peekPastLabels(case)
+                  listener: beginCaseExpression(case)
+                  parsePattern(case, precedence: 1)
+                    parsePrimaryPattern(case)
+                      parsePrecedenceExpression(case, 18, false)
+                        parseUnaryExpression(case, false)
+                          parsePrimary(case, expression)
+                            parseLiteralInt(case)
+                              listener: handleLiteralInt(0)
+                      listener: handleConstantPattern(null)
+                  parseExpression(when)
+                    parsePrecedenceExpression(when, 1, true)
+                      parseUnaryExpression(when, true)
+                        parsePrimary(when, expression)
+                          parseLiteralBool(when)
+                            listener: handleLiteralBool(true)
+                  ensureColon(true)
+                  listener: endCaseExpression(when, :)
+                  listener: handleCaseMatch(case, when, :)
+                  peekPastLabels(break)
+                  parseStatementsInSwitchCase(:, break, case, 0, 1, null, null)
+                    listener: beginSwitchCase(0, 1, case)
+                    parseStatement(:)
+                      parseStatementX(:)
+                        parseBreakStatement(:)
+                          isBreakAllowed()
+                          ensureSemicolon(break)
+                          listener: handleBreakStatement(false, break, ;)
+                    peekPastLabels(})
+                    listener: endSwitchCase(0, 1, null, null, 1, case, })
+                  notEofOrValue(}, })
+                  listener: endSwitchBlock(1, {, })
+                listener: endSwitchStatement(switch, })
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.parser.expect
new file mode 100644
index 0000000..b8edb2d
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.parser.expect
@@ -0,0 +1,15 @@
+void f(x) {
+switch (x) {
+case 0 when true:
+break;
+}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] 0[StringToken] when[KeywordToken] true[KeywordToken]:[SimpleToken]
+break[KeywordToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.scanner.expect
new file mode 100644
index 0000000..b8edb2d
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_guarded_insideSwitchStatement.dart.scanner.expect
@@ -0,0 +1,15 @@
+void f(x) {
+switch (x) {
+case 0 when true:
+break;
+}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] 0[StringToken] when[KeywordToken] true[KeywordToken]:[SimpleToken]
+break[KeywordToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart
new file mode 100644
index 0000000..d0632c7
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart
@@ -0,0 +1,3 @@
+void f(x) {
+  if (x case 0) {}
+}
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.expect
new file mode 100644
index 0000000..c9e3ad2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.expect
@@ -0,0 +1,36 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(x)
+        endMetadataStar(0)
+        beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+          handleNoType(()
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginIfStatement(if)
+          handleIdentifier(x, expression)
+          handleNoTypeArguments(case)
+          handleNoArguments(case)
+          handleSend(x, case)
+          handleLiteralInt(0)
+          handleConstantPattern(null)
+          handleParenthesizedCondition((, case, null)
+          beginThenStatement({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endThenStatement(})
+        endIfStatement(if, null)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.intertwined.expect
new file mode 100644
index 0000000..975d0ce
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.intertwined.expect
@@ -0,0 +1,83 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(x)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleNoType(()
+                ensureIdentifier((, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, if)
+          parseStatement({)
+            parseStatementX({)
+              parseIfStatement({)
+                listener: beginIfStatement(if)
+                ensureParenthesizedCondition(if, allowCase: true)
+                  parseExpressionInParenthesisRest((, allowCase: true)
+                    parseExpression(()
+                      parsePrecedenceExpression((, 1, true)
+                        parseUnaryExpression((, true)
+                          parsePrimary((, expression)
+                            parseSendOrFunctionLiteral((, expression)
+                              parseSend((, expression)
+                                isNextIdentifier(()
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(case)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(case)
+                                listener: handleSend(x, case)
+                    parsePattern(case, precedence: 1)
+                      parsePrimaryPattern(case)
+                        parsePrecedenceExpression(case, 18, false)
+                          parseUnaryExpression(case, false)
+                            parsePrimary(case, expression)
+                              parseLiteralInt(case)
+                                listener: handleLiteralInt(0)
+                        listener: handleConstantPattern(null)
+                    ensureCloseParen(0, ()
+                    listener: handleParenthesizedCondition((, case, null)
+                listener: beginThenStatement({)
+                parseStatement())
+                  parseStatementX())
+                    parseBlock(), BlockKind(statement))
+                      ensureBlock(), null, null)
+                      listener: beginBlock({, BlockKind(statement))
+                      notEofOrValue(}, })
+                      listener: endBlock(0, {, }, BlockKind(statement))
+                listener: endThenStatement(})
+                listener: endIfStatement(if, null)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.parser.expect
new file mode 100644
index 0000000..4a4c785
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.parser.expect
@@ -0,0 +1,9 @@
+void f(x) {
+if (x case 0) {}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]x[StringToken] case[KeywordToken] 0[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.scanner.expect
new file mode 100644
index 0000000..4a4c785
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideIfStatement.dart.scanner.expect
@@ -0,0 +1,9 @@
+void f(x) {
+if (x case 0) {}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]x[StringToken] case[KeywordToken] 0[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart
new file mode 100644
index 0000000..9d25283
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart
@@ -0,0 +1,6 @@
+void f(x) {
+  switch (x) {
+    case 0:
+      break;
+  }
+}
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.expect
new file mode 100644
index 0000000..ac84fe9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.expect
@@ -0,0 +1,40 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(x)
+        endMetadataStar(0)
+        beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+          handleNoType(()
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginSwitchStatement(switch)
+          handleIdentifier(x, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(x, ))
+          handleParenthesizedCondition((, null, null)
+          beginSwitchBlock({)
+            beginCaseExpression(case)
+              handleLiteralInt(0)
+              handleConstantPattern(null)
+            endCaseExpression(null, :)
+            handleCaseMatch(case, null, :)
+            beginSwitchCase(0, 1, case)
+              handleBreakStatement(false, break, ;)
+            endSwitchCase(0, 1, null, null, 1, case, })
+          endSwitchBlock(1, {, })
+        endSwitchStatement(switch, })
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.intertwined.expect
new file mode 100644
index 0000000..363a210
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.intertwined.expect
@@ -0,0 +1,96 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(x)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleNoType(()
+                ensureIdentifier((, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, switch)
+          parseStatement({)
+            parseStatementX({)
+              parseSwitchStatement({)
+                listener: beginSwitchStatement(switch)
+                ensureParenthesizedCondition(switch, allowCase: false)
+                  parseExpressionInParenthesisRest((, allowCase: false)
+                    parseExpression(()
+                      parsePrecedenceExpression((, 1, true)
+                        parseUnaryExpression((, true)
+                          parsePrimary((, expression)
+                            parseSendOrFunctionLiteral((, expression)
+                              parseSend((, expression)
+                                isNextIdentifier(()
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments())
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments())
+                                listener: handleSend(x, ))
+                    ensureCloseParen(x, ()
+                    listener: handleParenthesizedCondition((, null, null)
+                parseSwitchBlock())
+                  ensureBlock(), null, switch statement)
+                  listener: beginSwitchBlock({)
+                  notEofOrValue(}, case)
+                  peekPastLabels(case)
+                  listener: beginCaseExpression(case)
+                  parsePattern(case, precedence: 1)
+                    parsePrimaryPattern(case)
+                      parsePrecedenceExpression(case, 18, false)
+                        parseUnaryExpression(case, false)
+                          parsePrimary(case, expression)
+                            parseLiteralInt(case)
+                              listener: handleLiteralInt(0)
+                      listener: handleConstantPattern(null)
+                  ensureColon(0)
+                  listener: endCaseExpression(null, :)
+                  listener: handleCaseMatch(case, null, :)
+                  peekPastLabels(break)
+                  parseStatementsInSwitchCase(:, break, case, 0, 1, null, null)
+                    listener: beginSwitchCase(0, 1, case)
+                    parseStatement(:)
+                      parseStatementX(:)
+                        parseBreakStatement(:)
+                          isBreakAllowed()
+                          ensureSemicolon(break)
+                          listener: handleBreakStatement(false, break, ;)
+                    peekPastLabels(})
+                    listener: endSwitchCase(0, 1, null, null, 1, case, })
+                  notEofOrValue(}, })
+                  listener: endSwitchBlock(1, {, })
+                listener: endSwitchStatement(switch, })
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.parser.expect
new file mode 100644
index 0000000..14149d9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.parser.expect
@@ -0,0 +1,15 @@
+void f(x) {
+switch (x) {
+case 0:
+break;
+}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] 0[StringToken]:[SimpleToken]
+break[KeywordToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.scanner.expect
new file mode 100644
index 0000000..14149d9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withClassicPattern_unguarded_insideSwitchStatement.dart.scanner.expect
@@ -0,0 +1,15 @@
+void f(x) {
+switch (x) {
+case 0:
+break;
+}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] 0[StringToken]:[SimpleToken]
+break[KeywordToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart
new file mode 100644
index 0000000..833315c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart
@@ -0,0 +1,3 @@
+void f(x) {
+  if (x case 0 as int when true) {}
+}
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.expect
new file mode 100644
index 0000000..a28520f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.expect
@@ -0,0 +1,43 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(x)
+        endMetadataStar(0)
+        beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+          handleNoType(()
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginIfStatement(if)
+          handleIdentifier(x, expression)
+          handleNoTypeArguments(case)
+          handleNoArguments(case)
+          handleSend(x, case)
+          handleLiteralInt(0)
+          handleConstantPattern(null)
+          beginAsOperatorType(as)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(when)
+            handleType(int, null)
+          endAsOperatorType(as)
+          handleCastPattern(as)
+          handleLiteralBool(true)
+          handleParenthesizedCondition((, case, when)
+          beginThenStatement({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endThenStatement(})
+        endIfStatement(if, null)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.intertwined.expect
new file mode 100644
index 0000000..9797f8b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.intertwined.expect
@@ -0,0 +1,96 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(x)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleNoType(()
+                ensureIdentifier((, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, if)
+          parseStatement({)
+            parseStatementX({)
+              parseIfStatement({)
+                listener: beginIfStatement(if)
+                ensureParenthesizedCondition(if, allowCase: true)
+                  parseExpressionInParenthesisRest((, allowCase: true)
+                    parseExpression(()
+                      parsePrecedenceExpression((, 1, true)
+                        parseUnaryExpression((, true)
+                          parsePrimary((, expression)
+                            parseSendOrFunctionLiteral((, expression)
+                              parseSend((, expression)
+                                isNextIdentifier(()
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(case)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(case)
+                                listener: handleSend(x, case)
+                    parsePattern(case, precedence: 1)
+                      parsePrimaryPattern(case)
+                        parsePrecedenceExpression(case, 18, false)
+                          parseUnaryExpression(case, false)
+                            parsePrimary(case, expression)
+                              parseLiteralInt(case)
+                                listener: handleLiteralInt(0)
+                        listener: handleConstantPattern(null)
+                      listener: beginAsOperatorType(as)
+                      computeTypeAfterIsOrAs(as)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(when)
+                      listener: handleType(int, null)
+                      listener: endAsOperatorType(as)
+                      listener: handleCastPattern(as)
+                    parseExpression(when)
+                      parsePrecedenceExpression(when, 1, true)
+                        parseUnaryExpression(when, true)
+                          parsePrimary(when, expression)
+                            parseLiteralBool(when)
+                              listener: handleLiteralBool(true)
+                    ensureCloseParen(true, ()
+                    listener: handleParenthesizedCondition((, case, when)
+                listener: beginThenStatement({)
+                parseStatement())
+                  parseStatementX())
+                    parseBlock(), BlockKind(statement))
+                      ensureBlock(), null, null)
+                      listener: beginBlock({, BlockKind(statement))
+                      notEofOrValue(}, })
+                      listener: endBlock(0, {, }, BlockKind(statement))
+                listener: endThenStatement(})
+                listener: endIfStatement(if, null)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.parser.expect
new file mode 100644
index 0000000..708b554
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.parser.expect
@@ -0,0 +1,9 @@
+void f(x) {
+if (x case 0 as int when true) {}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]x[StringToken] case[KeywordToken] 0[StringToken] as[KeywordToken] int[StringToken] when[KeywordToken] true[KeywordToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.scanner.expect
new file mode 100644
index 0000000..708b554
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideIfStatement.dart.scanner.expect
@@ -0,0 +1,9 @@
+void f(x) {
+if (x case 0 as int when true) {}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]x[StringToken] case[KeywordToken] 0[StringToken] as[KeywordToken] int[StringToken] when[KeywordToken] true[KeywordToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart
new file mode 100644
index 0000000..7db6d2f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart
@@ -0,0 +1,6 @@
+void f(x) {
+  switch (x) {
+    case 0 as int when true:
+      break;
+  }
+}
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.expect
new file mode 100644
index 0000000..27defd71
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.expect
@@ -0,0 +1,47 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(x)
+        endMetadataStar(0)
+        beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+          handleNoType(()
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginSwitchStatement(switch)
+          handleIdentifier(x, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(x, ))
+          handleParenthesizedCondition((, null, null)
+          beginSwitchBlock({)
+            beginCaseExpression(case)
+              handleLiteralInt(0)
+              handleConstantPattern(null)
+              beginAsOperatorType(as)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(when)
+                handleType(int, null)
+              endAsOperatorType(as)
+              handleCastPattern(as)
+              handleLiteralBool(true)
+            endCaseExpression(when, :)
+            handleCaseMatch(case, when, :)
+            beginSwitchCase(0, 1, case)
+              handleBreakStatement(false, break, ;)
+            endSwitchCase(0, 1, null, null, 1, case, })
+          endSwitchBlock(1, {, })
+        endSwitchStatement(switch, })
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.intertwined.expect
new file mode 100644
index 0000000..aef127f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.intertwined.expect
@@ -0,0 +1,109 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(x)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleNoType(()
+                ensureIdentifier((, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, switch)
+          parseStatement({)
+            parseStatementX({)
+              parseSwitchStatement({)
+                listener: beginSwitchStatement(switch)
+                ensureParenthesizedCondition(switch, allowCase: false)
+                  parseExpressionInParenthesisRest((, allowCase: false)
+                    parseExpression(()
+                      parsePrecedenceExpression((, 1, true)
+                        parseUnaryExpression((, true)
+                          parsePrimary((, expression)
+                            parseSendOrFunctionLiteral((, expression)
+                              parseSend((, expression)
+                                isNextIdentifier(()
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments())
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments())
+                                listener: handleSend(x, ))
+                    ensureCloseParen(x, ()
+                    listener: handleParenthesizedCondition((, null, null)
+                parseSwitchBlock())
+                  ensureBlock(), null, switch statement)
+                  listener: beginSwitchBlock({)
+                  notEofOrValue(}, case)
+                  peekPastLabels(case)
+                  listener: beginCaseExpression(case)
+                  parsePattern(case, precedence: 1)
+                    parsePrimaryPattern(case)
+                      parsePrecedenceExpression(case, 18, false)
+                        parseUnaryExpression(case, false)
+                          parsePrimary(case, expression)
+                            parseLiteralInt(case)
+                              listener: handleLiteralInt(0)
+                      listener: handleConstantPattern(null)
+                    listener: beginAsOperatorType(as)
+                    computeTypeAfterIsOrAs(as)
+                    listener: handleIdentifier(int, typeReference)
+                    listener: handleNoTypeArguments(when)
+                    listener: handleType(int, null)
+                    listener: endAsOperatorType(as)
+                    listener: handleCastPattern(as)
+                  parseExpression(when)
+                    parsePrecedenceExpression(when, 1, true)
+                      parseUnaryExpression(when, true)
+                        parsePrimary(when, expression)
+                          parseLiteralBool(when)
+                            listener: handleLiteralBool(true)
+                  ensureColon(true)
+                  listener: endCaseExpression(when, :)
+                  listener: handleCaseMatch(case, when, :)
+                  peekPastLabels(break)
+                  parseStatementsInSwitchCase(:, break, case, 0, 1, null, null)
+                    listener: beginSwitchCase(0, 1, case)
+                    parseStatement(:)
+                      parseStatementX(:)
+                        parseBreakStatement(:)
+                          isBreakAllowed()
+                          ensureSemicolon(break)
+                          listener: handleBreakStatement(false, break, ;)
+                    peekPastLabels(})
+                    listener: endSwitchCase(0, 1, null, null, 1, case, })
+                  notEofOrValue(}, })
+                  listener: endSwitchBlock(1, {, })
+                listener: endSwitchStatement(switch, })
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.parser.expect
new file mode 100644
index 0000000..90e3346
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.parser.expect
@@ -0,0 +1,15 @@
+void f(x) {
+switch (x) {
+case 0 as int when true:
+break;
+}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] 0[StringToken] as[KeywordToken] int[StringToken] when[KeywordToken] true[KeywordToken]:[SimpleToken]
+break[KeywordToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.scanner.expect
new file mode 100644
index 0000000..90e3346
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_guarded_insideSwitchStatement.dart.scanner.expect
@@ -0,0 +1,15 @@
+void f(x) {
+switch (x) {
+case 0 as int when true:
+break;
+}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] 0[StringToken] as[KeywordToken] int[StringToken] when[KeywordToken] true[KeywordToken]:[SimpleToken]
+break[KeywordToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart
new file mode 100644
index 0000000..199154a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart
@@ -0,0 +1,3 @@
+void f(x) {
+  if (x case 0 as int) {}
+}
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.expect
new file mode 100644
index 0000000..36db817
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.expect
@@ -0,0 +1,42 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(x)
+        endMetadataStar(0)
+        beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+          handleNoType(()
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginIfStatement(if)
+          handleIdentifier(x, expression)
+          handleNoTypeArguments(case)
+          handleNoArguments(case)
+          handleSend(x, case)
+          handleLiteralInt(0)
+          handleConstantPattern(null)
+          beginAsOperatorType(as)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments())
+            handleType(int, null)
+          endAsOperatorType(as)
+          handleCastPattern(as)
+          handleParenthesizedCondition((, case, null)
+          beginThenStatement({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endThenStatement(})
+        endIfStatement(if, null)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.intertwined.expect
new file mode 100644
index 0000000..41bea34
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.intertwined.expect
@@ -0,0 +1,90 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(x)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleNoType(()
+                ensureIdentifier((, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, if)
+          parseStatement({)
+            parseStatementX({)
+              parseIfStatement({)
+                listener: beginIfStatement(if)
+                ensureParenthesizedCondition(if, allowCase: true)
+                  parseExpressionInParenthesisRest((, allowCase: true)
+                    parseExpression(()
+                      parsePrecedenceExpression((, 1, true)
+                        parseUnaryExpression((, true)
+                          parsePrimary((, expression)
+                            parseSendOrFunctionLiteral((, expression)
+                              parseSend((, expression)
+                                isNextIdentifier(()
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(case)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(case)
+                                listener: handleSend(x, case)
+                    parsePattern(case, precedence: 1)
+                      parsePrimaryPattern(case)
+                        parsePrecedenceExpression(case, 18, false)
+                          parseUnaryExpression(case, false)
+                            parsePrimary(case, expression)
+                              parseLiteralInt(case)
+                                listener: handleLiteralInt(0)
+                        listener: handleConstantPattern(null)
+                      listener: beginAsOperatorType(as)
+                      computeTypeAfterIsOrAs(as)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments())
+                      listener: handleType(int, null)
+                      listener: endAsOperatorType(as)
+                      listener: handleCastPattern(as)
+                    ensureCloseParen(int, ()
+                    listener: handleParenthesizedCondition((, case, null)
+                listener: beginThenStatement({)
+                parseStatement())
+                  parseStatementX())
+                    parseBlock(), BlockKind(statement))
+                      ensureBlock(), null, null)
+                      listener: beginBlock({, BlockKind(statement))
+                      notEofOrValue(}, })
+                      listener: endBlock(0, {, }, BlockKind(statement))
+                listener: endThenStatement(})
+                listener: endIfStatement(if, null)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.parser.expect
new file mode 100644
index 0000000..a1fc049
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.parser.expect
@@ -0,0 +1,9 @@
+void f(x) {
+if (x case 0 as int) {}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]x[StringToken] case[KeywordToken] 0[StringToken] as[KeywordToken] int[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.scanner.expect
new file mode 100644
index 0000000..a1fc049
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideIfStatement.dart.scanner.expect
@@ -0,0 +1,9 @@
+void f(x) {
+if (x case 0 as int) {}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]x[StringToken] case[KeywordToken] 0[StringToken] as[KeywordToken] int[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart
new file mode 100644
index 0000000..b3f6864
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart
@@ -0,0 +1,6 @@
+void f(x) {
+  switch (x) {
+    case 0 as int:
+      break;
+  }
+}
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.expect
new file mode 100644
index 0000000..be1a9a6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.expect
@@ -0,0 +1,46 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(x)
+        endMetadataStar(0)
+        beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+          handleNoType(()
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginSwitchStatement(switch)
+          handleIdentifier(x, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(x, ))
+          handleParenthesizedCondition((, null, null)
+          beginSwitchBlock({)
+            beginCaseExpression(case)
+              handleLiteralInt(0)
+              handleConstantPattern(null)
+              beginAsOperatorType(as)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(:)
+                handleType(int, null)
+              endAsOperatorType(as)
+              handleCastPattern(as)
+            endCaseExpression(null, :)
+            handleCaseMatch(case, null, :)
+            beginSwitchCase(0, 1, case)
+              handleBreakStatement(false, break, ;)
+            endSwitchCase(0, 1, null, null, 1, case, })
+          endSwitchBlock(1, {, })
+        endSwitchStatement(switch, })
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.intertwined.expect
new file mode 100644
index 0000000..4b3aab4
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.intertwined.expect
@@ -0,0 +1,103 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, f, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(x)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(x, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleNoType(()
+                ensureIdentifier((, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, null, x, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, switch)
+          parseStatement({)
+            parseStatementX({)
+              parseSwitchStatement({)
+                listener: beginSwitchStatement(switch)
+                ensureParenthesizedCondition(switch, allowCase: false)
+                  parseExpressionInParenthesisRest((, allowCase: false)
+                    parseExpression(()
+                      parsePrecedenceExpression((, 1, true)
+                        parseUnaryExpression((, true)
+                          parsePrimary((, expression)
+                            parseSendOrFunctionLiteral((, expression)
+                              parseSend((, expression)
+                                isNextIdentifier(()
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments())
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments())
+                                listener: handleSend(x, ))
+                    ensureCloseParen(x, ()
+                    listener: handleParenthesizedCondition((, null, null)
+                parseSwitchBlock())
+                  ensureBlock(), null, switch statement)
+                  listener: beginSwitchBlock({)
+                  notEofOrValue(}, case)
+                  peekPastLabels(case)
+                  listener: beginCaseExpression(case)
+                  parsePattern(case, precedence: 1)
+                    parsePrimaryPattern(case)
+                      parsePrecedenceExpression(case, 18, false)
+                        parseUnaryExpression(case, false)
+                          parsePrimary(case, expression)
+                            parseLiteralInt(case)
+                              listener: handleLiteralInt(0)
+                      listener: handleConstantPattern(null)
+                    listener: beginAsOperatorType(as)
+                    computeTypeAfterIsOrAs(as)
+                    listener: handleIdentifier(int, typeReference)
+                    listener: handleNoTypeArguments(:)
+                    listener: handleType(int, null)
+                    listener: endAsOperatorType(as)
+                    listener: handleCastPattern(as)
+                  ensureColon(int)
+                  listener: endCaseExpression(null, :)
+                  listener: handleCaseMatch(case, null, :)
+                  peekPastLabels(break)
+                  parseStatementsInSwitchCase(:, break, case, 0, 1, null, null)
+                    listener: beginSwitchCase(0, 1, case)
+                    parseStatement(:)
+                      parseStatementX(:)
+                        parseBreakStatement(:)
+                          isBreakAllowed()
+                          ensureSemicolon(break)
+                          listener: handleBreakStatement(false, break, ;)
+                    peekPastLabels(})
+                    listener: endSwitchCase(0, 1, null, null, 1, case, })
+                  notEofOrValue(}, })
+                  listener: endSwitchBlock(1, {, })
+                listener: endSwitchStatement(switch, })
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.parser.expect
new file mode 100644
index 0000000..e9cba66
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.parser.expect
@@ -0,0 +1,15 @@
+void f(x) {
+switch (x) {
+case 0 as int:
+break;
+}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] 0[StringToken] as[KeywordToken] int[StringToken]:[SimpleToken]
+break[KeywordToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.scanner.expect
new file mode 100644
index 0000000..e9cba66
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/caseHead_withNewPattern_unguarded_insideSwitchStatement.dart.scanner.expect
@@ -0,0 +1,15 @@
+void f(x) {
+switch (x) {
+case 0 as int:
+break;
+}
+}
+
+
+void[KeywordToken] f[StringToken]([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]x[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] 0[StringToken] as[KeywordToken] int[StringToken]:[SimpleToken]
+break[KeywordToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/test/token_test.dart b/pkg/front_end/test/token_test.dart
index 69f13b4..05c199b 100644
--- a/pkg/front_end/test/token_test.dart
+++ b/pkg/front_end/test/token_test.dart
@@ -182,6 +182,7 @@
       Keyword.SHOW,
       Keyword.SOURCE,
       Keyword.SYNC,
+      Keyword.WHEN,
       Keyword.YIELD,
     ]);
     for (Keyword keyword in Keyword.values) {