Version 2.12.0-212.0.dev

Merge commit '318babd5ac8799c7251cfe5270e3623ddbc49b58' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart b/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
index 51adec3..7c367b8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
@@ -23,6 +23,11 @@
   /// open parenthesis. If [insertIdentifier] is true, then a synthetic
   /// identifier is included between the open and close parenthesis.
   Token insertParens(Token token, bool includeIdentifier) {
+    // Assert that the token is not eof, though allow an eof-token if the offset
+    // is negative. The last part is because [syntheticPreviousToken] sometimes
+    // creates eof tokens that aren't the real eof-token that has a negative
+    // offset (which wouldn't be valid for the real eof).
+    assert(!token.isEof || token.offset < 0);
     Token next = token.next!;
     int offset = next.charOffset;
     BeginToken leftParen =
@@ -45,6 +50,11 @@
 
   /// Insert [newToken] after [token] and return [newToken].
   Token insertToken(Token token, Token newToken) {
+    // Assert that the token is not eof, though allow an eof-token if the offset
+    // is negative. The last part is because [syntheticPreviousToken] sometimes
+    // creates eof tokens that aren't the real eof-token that has a negative
+    // offset (which wouldn't be valid for the real eof).
+    assert(!token.isEof || token.offset < 0);
     _setNext(newToken, token.next!);
 
     // A no-op rewriter could skip this step.
@@ -56,6 +66,11 @@
   /// Move [endGroup] (a synthetic `)`, `]`, or `}` token) and associated
   /// error token after [token] in the token stream and return [endGroup].
   Token moveSynthetic(Token token, Token endGroup) {
+    // Assert that the token is not eof, though allow an eof-token if the offset
+    // is negative. The last part is because [syntheticPreviousToken] sometimes
+    // creates eof tokens that aren't the real eof-token that has a negative
+    // offset (which wouldn't be valid for the real eof).
+    assert(!token.isEof || token.offset < 0);
     // ignore:unnecessary_null_comparison
     assert(endGroup.beforeSynthetic != null);
     if (token == endGroup) return endGroup;
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart b/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
index c865e0a..6f10b8a 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
@@ -293,11 +293,11 @@
       // identifier `?` Function `(`
       return new ComplexTypeInfo(token, noTypeParamOrArg)
           .computeIdentifierQuestionGFT(required);
-    } else if (required || looksLikeName(next)) {
+    } else if (required || looksLikeNameSimpleType(next)) {
       // identifier `?`
       return simpleNullableType;
     }
-  } else if (required || looksLikeName(next)) {
+  } else if (required || looksLikeNameSimpleType(next)) {
     // identifier identifier
     return simpleType;
   }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
index 5df6fee..73bcfb1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
@@ -412,14 +412,23 @@
   }
 }
 
-bool looksLikeName(Token token) =>
-    token.kind == IDENTIFIER_TOKEN ||
-    optional('this', token) ||
-    (token.isIdentifier &&
-        // Although `typedef` is a legal identifier,
-        // type `typedef` identifier is not legal and in this situation
-        // `typedef` is probably a separate declaration.
-        (!optional('typedef', token) || !token.next!.isIdentifier));
+bool looksLikeName(Token token) {
+  // End-of-file isn't a name, but this is called in a situation where
+  // if there had been a name it would have used the type-info it had
+  // collected --- this being eof probably mean the user is currently
+  // typing and will probably write a name in a moment.
+  return looksLikeNameSimpleType(token) || token.isEof;
+}
+
+bool looksLikeNameSimpleType(Token token) {
+  return token.kind == IDENTIFIER_TOKEN ||
+      optional('this', token) ||
+      (token.isIdentifier &&
+          // Although `typedef` is a legal identifier,
+          // type `typedef` identifier is not legal and in this situation
+          // `typedef` is probably a separate declaration.
+          (!optional('typedef', token) || !token.next!.isIdentifier));
+}
 
 /// When missing a comma, determine if the given token looks like it should
 /// be part of a collection of type parameters or arguments.
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
index 37497f3..fc07690 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
@@ -427,6 +427,7 @@
       errorReporter.reportErrorForNode(
         CompileTimeErrorCode.UNDEFINED_CLASS_BOOLEAN,
         errorNode,
+        [identifier.name],
       );
       return;
     }
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 108a361..84018fc 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -9971,12 +9971,17 @@
 
   /**
    * Same as [CompileTimeErrorCode.UNDEFINED_CLASS], but to catch using
-   * "boolean" instead of "bool".
+   * "boolean" instead of "bool" in order to improve the correction message.
+   *
+   * Parameters:
+   * 0: the name of the undefined class
    */
   static const CompileTimeErrorCode UNDEFINED_CLASS_BOOLEAN =
-      CompileTimeErrorCode(
-          'UNDEFINED_CLASS_BOOLEAN', "Undefined class 'boolean'.",
-          correction: "Try using the type 'bool'.");
+      CompileTimeErrorCode('UNDEFINED_CLASS', "Undefined class '{0}'.",
+          correction: "Try using the type 'bool'.",
+          hasPublishedDocs: true,
+          isUnresolvedIdentifier: true,
+          uniqueName: 'UNDEFINED_CLASS_BOOLEAN');
 
   /**
    * Parameters:
diff --git a/pkg/analyzer/test/generated/statement_parser_test.dart b/pkg/analyzer/test/generated/statement_parser_test.dart
index 1907c1b..189d673 100644
--- a/pkg/analyzer/test/generated/statement_parser_test.dart
+++ b/pkg/analyzer/test/generated/statement_parser_test.dart
@@ -1735,8 +1735,9 @@
     var unit = parseCompilationUnit('<bar<', errors: [
       expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
       expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 0),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 1, 3),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 5, 0),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 0),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 0),
     ]);
     // Validate that recovery has properly updated the token stream.
     analyzer.Token token = unit.beginToken;
@@ -1750,9 +1751,10 @@
 
   void test_partial_typeArg2_34850() {
     var unit = parseCompilationUnit('foo <bar<', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 3),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 3),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 9, 0),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 0),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 0),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 0),
     ]);
     // Validate that recovery has properly updated the token stream.
     analyzer.Token token = unit.beginToken;
diff --git a/pkg/analyzer/test/generated/top_level_parser_test.dart b/pkg/analyzer/test/generated/top_level_parser_test.dart
index 5e36c1c3..140b38a 100644
--- a/pkg/analyzer/test/generated/top_level_parser_test.dart
+++ b/pkg/analyzer/test/generated/top_level_parser_test.dart
@@ -72,6 +72,40 @@
     expectCommentText(importDirective.documentationComment, '/// Doc');
   }
 
+  void test_parse_missing_type_in_list_at_eof() {
+    createParser('Future<List<>>');
+
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 2),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 0),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 0),
+    ]);
+
+    expect(member, isTopLevelVariableDeclaration);
+    TopLevelVariableDeclaration declaration = member;
+    expect(declaration.semicolon, isNotNull);
+    expect(declaration.variables, isNotNull);
+
+    // Ensure type parsed as "Future<List<[empty name]>>".
+    expect(declaration.variables.type, isNotNull);
+    expect(declaration.variables.type.question, isNull);
+    expect(declaration.variables.type, TypeMatcher<TypeName>());
+    TypeName type = declaration.variables.type;
+    expect(type.name.name, "Future");
+    expect(type.typeArguments.arguments.length, 1);
+    expect(type.typeArguments.arguments.single, TypeMatcher<TypeName>());
+    TypeName subType = type.typeArguments.arguments.single;
+    expect(subType.name.name, "List");
+    expect(subType.typeArguments.arguments.length, 1);
+    expect(subType.typeArguments.arguments.single, TypeMatcher<TypeName>());
+    TypeName subSubType = subType.typeArguments.arguments.single;
+    expect(subSubType.name.name, "");
+    expect(subSubType.typeArguments, isNull);
+  }
+
   void test_parseClassDeclaration_abstract() {
     createParser('abstract class A {}');
     CompilationUnitMember member = parseFullCompilationUnitMember();
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
index 6e8b00d..177e4b3 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
@@ -4,10 +4,14 @@
 f() { m(T<R(<Z
               ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_38415.crash:1:15: Expected ';' after this.
 f() { m(T<R(<Z
               ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_38415.crash:1:12: Can't find ')' to match '('.
 f() { m(T<R(<Z
            ^
@@ -53,6 +57,7 @@
                 handleType(Z, null)
               endTypeArguments(1, <, >)
               handleRecoverableError(Message[ExpectedButGot, Expected '[' before this., null, {string: [}], , )
+              // WARNING: Reporting at eof for .
               handleLiteralList(0, [, null, ])
             endArguments(1, (, ))
             handleSend(R, })
@@ -60,6 +65,7 @@
         endArguments(1, (, ))
         handleSend(m, })
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+        // WARNING: Reporting at eof for .
         handleExpressionStatement(;)
       endBlockFunctionBody(1, {, })
     endTopLevelMethod(f, null, })
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.intertwined.expect
index 846b118..76915c7 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.intertwined.expect
@@ -84,6 +84,7 @@
                                                                   listener: endTypeArguments(1, <, >)
                                                                   reportRecoverableError(), Message[ExpectedButGot, Expected '[' before this., null, {string: [}])
                                                                     listener: handleRecoverableError(Message[ExpectedButGot, Expected '[' before this., null, {string: [}], , )
+                                                                    listener: // WARNING: Reporting at eof for .
                                                                   rewriter()
                                                                   parseLiteralListSuffix(>, null)
                                                                     rewriteSquareBrackets(>)
@@ -100,6 +101,7 @@
                   ensureSemicolon())
                     reportRecoverableError([, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
                       listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+                      listener: // WARNING: Reporting at eof for .
                     rewriter()
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, })
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
index 6b57708..c392105 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
@@ -8,14 +8,20 @@
 n<S e(
       ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39024.crash:1:7: A function declaration needs an explicit list of parameters.
 n<S e(
       ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39024.crash:1:7: Expected a function body, but got ''.
 n<S e(
       ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39024.crash:1:6: Can't find ')' to match '('.
 n<S e(
      ^
@@ -38,13 +44,16 @@
       endTypeArguments(1, <, >)
       handleType(n, null)
       handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+      // WARNING: Reporting at eof for .
       handleIdentifier(, topLevelFunctionDeclaration)
       handleNoTypeVariables()
       handleRecoverableError(MissingFunctionParameters, , )
+      // WARNING: Reporting at eof for .
       beginFormalParameters((, MemberKind.TopLevelMethod)
       endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
       handleAsyncModifier(null, null)
       handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
+      // WARNING: Reporting at eof for .
       handleInvalidFunctionBody({)
     endTopLevelMethod(n, null, })
   endTopLevelDeclaration()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
index ff3cb76..e84daf8 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
@@ -24,6 +24,7 @@
           insertSyntheticIdentifier(>, topLevelFunctionDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], messageOnToken: null)
             reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
               listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+              listener: // WARNING: Reporting at eof for .
             rewriter()
           listener: handleIdentifier(, topLevelFunctionDeclaration)
         parseMethodTypeVar()
@@ -32,6 +33,7 @@
           missingParameterMessage(MemberKind.TopLevelMethod)
           reportRecoverableError(, MissingFunctionParameters)
             listener: handleRecoverableError(MissingFunctionParameters, , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
           parseFormalParametersRest((, MemberKind.TopLevelMethod)
             listener: beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -43,6 +45,7 @@
           ensureBlock(), Instance of 'Template<(Token) => Message>', null)
             reportRecoverableError(, Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }])
               listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
+              listener: // WARNING: Reporting at eof for .
             insertBlock())
               rewriter()
               rewriter()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
index 5eccfef..d27aa77 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
@@ -8,10 +8,14 @@
 typedef F<Glib.=
                 ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39033.crash:1:17: Expected ';' after this.
 typedef F<Glib.=
                 ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 beginCompilationUnit(typedef)
   beginMetadataStar(typedef)
   endMetadataStar(0)
@@ -29,10 +33,12 @@
         handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], Glib, Glib)
       endTypeVariables(<, >)
       handleRecoverableError(Message[ExpectedType, Expected a type, but got ''., null, {token: }], , )
+      // WARNING: Reporting at eof for .
       handleIdentifier(, typeReference)
       handleNoTypeArguments()
       handleType(, null)
       handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
     endFunctionTypeAlias(typedef, =, ;)
   endTopLevelDeclaration()
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.intertwined.expect
index 311343c..f0295b4 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.intertwined.expect
@@ -28,6 +28,7 @@
         listener: endTypeVariables(<, >)
         reportRecoverableErrorWithToken(, Instance of 'Template<(Token) => Message>')
           listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got ''., null, {token: }], , )
+          listener: // WARNING: Reporting at eof for .
         rewriter()
         listener: handleIdentifier(, typeReference)
         listener: handleNoTypeArguments()
@@ -35,6 +36,7 @@
         ensureSemicolon()
           reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
             listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
         listener: endFunctionTypeAlias(typedef, =, ;)
   listener: endTopLevelDeclaration()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
index 74d4738..fff362e 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
@@ -24,10 +24,14 @@
 () async => a b < c $? >
                         ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39202.crash:1:25: Expected ';' after this.
 () async => a b < c $? >
                         ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 beginCompilationUnit(()
   beginMetadataStar(()
   endMetadataStar(0)
@@ -73,9 +77,11 @@
       endTypeArguments(1, <, >)
       handleType(b, null)
       handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+      // WARNING: Reporting at eof for .
       handleIdentifier(, topLevelVariableDeclaration)
       handleNoFieldInitializer()
       handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
     endTopLevelFields(null, null, null, null, null, 1, b, ;)
   endTopLevelDeclaration()
 endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
index ee3b3ec..4eab8e2 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
@@ -91,6 +91,7 @@
           insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], messageOnToken: null)
             reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
               listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+              listener: // WARNING: Reporting at eof for .
             rewriter()
           listener: handleIdentifier(, topLevelVariableDeclaration)
         parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
@@ -98,6 +99,7 @@
         ensureSemicolon()
           reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
             listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
         listener: endTopLevelFields(null, null, null, null, null, 1, b, ;)
   listener: endTopLevelDeclaration()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart
index 39aa295..9604d9e 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart
@@ -1 +1 @@
-Stream<List<>>
\ No newline at end of file
+Stream<List<>> /* nothing here */
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.expect
index 9efa6dc..206203b 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.expect
@@ -1,40 +1,52 @@
 Problems reported:
 
-parser/error_recovery/issue_42229.crash:1:8: Expected '>' after this.
-Stream<List<>>
-       ^^^^
+parser/error_recovery/issue_42229.crash:1:34: Expected an identifier, but got ''.
+Stream<List<>> /* nothing here */
+                                 ^...
 
-parser/error_recovery/issue_42229.crash:1:1: A function declaration needs an explicit list of parameters.
-Stream<List<>>
-^^^^^^
+WARNING: Reporting at eof --- see below for details.
 
-parser/error_recovery/issue_42229.crash:1:15: Expected a function body, but got ''.
-Stream<List<>>
-              ^...
+parser/error_recovery/issue_42229.crash:1:13: Expected a type, but got '>>'.
+Stream<List<>> /* nothing here */
+            ^^
+
+parser/error_recovery/issue_42229.crash:1:34: Expected an identifier, but got ''.
+Stream<List<>> /* nothing here */
+                                 ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+parser/error_recovery/issue_42229.crash:1:34: Expected ';' after this.
+Stream<List<>> /* nothing here */
+                                 ^...
+
+WARNING: Reporting at eof --- see below for details.
 
 beginCompilationUnit(Stream)
   beginMetadataStar(Stream)
   endMetadataStar(0)
   beginTopLevelMember(Stream)
-    beginTopLevelMethod(, null)
-      handleNoType()
-      handleIdentifier(Stream, topLevelFunctionDeclaration)
-      beginTypeVariables(<)
-        beginMetadataStar(List)
-        endMetadataStar(0)
-        handleIdentifier(List, typeVariableDeclaration)
-        beginTypeVariable(List)
-          handleTypeVariablesDefined(List, 1)
-          handleNoType(List)
-        endTypeVariable(<, 0, null, null)
-        handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-      endTypeVariables(<, )
-      handleRecoverableError(MissingFunctionParameters, Stream, Stream)
-      beginFormalParameters((, MemberKind.TopLevelMethod)
-      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-      handleAsyncModifier(null, null)
-      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-      handleInvalidFunctionBody({)
-    endTopLevelMethod(Stream, null, })
+    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+    // WARNING: Reporting at eof for .
+    beginFields()
+      handleIdentifier(Stream, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {token: >>}], >>, >>)
+          handleIdentifier(, typeReference)
+          handleNoTypeArguments(>>)
+          handleType(, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Stream, null)
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+      // WARNING: Reporting at eof for .
+      handleIdentifier(, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
+    endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   endTopLevelDeclaration()
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.intertwined.expect
index 099ee94..d645359 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.intertwined.expect
@@ -8,50 +8,44 @@
       listener: endMetadataStar(0)
     parseTopLevelMemberImpl()
       listener: beginTopLevelMember(Stream)
-      isReservedKeyword(<)
-      parseTopLevelMethod(, null, , Instance of 'NoType', null, Stream, false)
-        listener: beginTopLevelMethod(, null)
-        listener: handleNoType()
-        ensureIdentifierPotentiallyRecovered(, topLevelFunctionDeclaration, false)
-          listener: handleIdentifier(Stream, topLevelFunctionDeclaration)
-        parseMethodTypeVar(Stream)
-          listener: beginTypeVariables(<)
-          parseMetadataStar(<)
-            listener: beginMetadataStar(List)
-            listener: endMetadataStar(0)
-          ensureIdentifier(<, typeVariableDeclaration)
-            listener: handleIdentifier(List, typeVariableDeclaration)
-          listener: beginTypeVariable(List)
-          listener: handleTypeVariablesDefined(List, 1)
-          listener: handleNoType(List)
-          listener: endTypeVariable(<, 0, null, null)
-          reportRecoverableError(List, Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}])
-            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-          parseMetadataStar(<)
-          ensureIdentifier(<, typeVariableDeclaration)
-            reportRecoverableErrorWithToken(>>, Instance of 'Template<(Token) => Message>')
+      insertSyntheticIdentifier(>, methodDeclaration, message: null, messageOnToken: null)
+        reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
+          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+          listener: // WARNING: Reporting at eof for .
+        rewriter()
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', , DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Stream, typeReference)
+        listener: beginTypeArguments(<)
+        ensureIdentifier(<, typeReference)
+          listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        reportRecoverableErrorWithToken(>>, Instance of 'Template<(Token) => Message>')
+          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {token: >>}], >>, >>)
+        rewriter()
+        listener: handleIdentifier(, typeReference)
+        listener: handleNoTypeArguments(>>)
+        listener: handleType(, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Stream, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+              listener: // WARNING: Reporting at eof for .
             rewriter()
-          listener: endTypeVariables(<, )
-        parseGetterOrFormalParameters(, Stream, false, MemberKind.TopLevelMethod)
-          missingParameterMessage(MemberKind.TopLevelMethod)
-          reportRecoverableError(Stream, MissingFunctionParameters)
-            listener: handleRecoverableError(MissingFunctionParameters, Stream, Stream)
+          listener: handleIdentifier(, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
-          parseFormalParametersRest((, MemberKind.TopLevelMethod)
-            listener: beginFormalParameters((, MemberKind.TopLevelMethod)
-            listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-        parseAsyncModifierOpt())
-          listener: handleAsyncModifier(null, null)
-          inPlainSync()
-        parseFunctionBody(), false, false)
-          ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(, Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-            insertBlock())
-              rewriter()
-              rewriter()
-          listener: handleInvalidFunctionBody({)
-        listener: endTopLevelMethod(Stream, null, })
+        listener: endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(Stream)
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.parser.expect
index 96c4fba..8f68d8f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.parser.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.parser.expect
@@ -1,11 +1,5 @@
 NOTICE: Stream was rewritten by parser!
 
-Stream<List<>>>(){}
+Stream<List<>> ;
 
-ERROR: Loop in tokens:  (SimpleToken, EOF, 14)) was seen before (linking to (, SyntheticBeginToken, OPEN_PAREN, 14)!
-
-
-
-Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]>>[SimpleToken][SyntheticStringToken]>[SyntheticToken][SimpleToken]([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken]
-
-ERROR: Loop in tokens:  (SimpleToken, EOF, 14)) was seen before (linking to (, SyntheticBeginToken, OPEN_PAREN, 14)!
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken][SyntheticStringToken]>[SimpleToken]>[SimpleToken] [SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.scanner.expect
index 6ca03d9..6b5fffa 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.scanner.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.scanner.expect
@@ -1,3 +1,3 @@
-Stream<List<>>
+Stream<List<>> 
 
-Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]>>[SimpleToken][SimpleToken]
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]>>[SimpleToken] [SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.expect
index 0f7bb9e..20973c0 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.expect
@@ -1,40 +1,44 @@
 Problems reported:
 
-parser/error_recovery/issue_42229_prime.crash:1:8: Expected '>' after this.
-Stream<List<> >
-       ^^^^
-
-parser/error_recovery/issue_42229_prime.crash:1:1: A function declaration needs an explicit list of parameters.
-Stream<List<> >
-^^^^^^
-
-parser/error_recovery/issue_42229_prime.crash:1:16: Expected a function body, but got ''.
+parser/error_recovery/issue_42229_prime.crash:1:16: Expected an identifier, but got ''.
 Stream<List<> >
                ^...
 
+WARNING: Reporting at eof --- see below for details.
+
+parser/error_recovery/issue_42229_prime.crash:1:13: Expected a type, but got '>'.
+Stream<List<> >
+            ^
+
+parser/error_recovery/issue_42229_prime.crash:1:16: Expected ';' after this.
+Stream<List<> >
+               ^...
+
+WARNING: Reporting at eof --- see below for details.
+
 beginCompilationUnit(Stream)
   beginMetadataStar(Stream)
   endMetadataStar(0)
   beginTopLevelMember(Stream)
-    beginTopLevelMethod(, null)
-      handleNoType()
-      handleIdentifier(Stream, topLevelFunctionDeclaration)
-      beginTypeVariables(<)
-        beginMetadataStar(List)
-        endMetadataStar(0)
-        handleIdentifier(List, typeVariableDeclaration)
-        beginTypeVariable(List)
-          handleTypeVariablesDefined(List, 1)
-          handleNoType(List)
-        endTypeVariable(<, 0, null, null)
-        handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-      endTypeVariables(<, >)
-      handleRecoverableError(MissingFunctionParameters, Stream, Stream)
-      beginFormalParameters((, MemberKind.TopLevelMethod)
-      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-      handleAsyncModifier(null, null)
-      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-      handleInvalidFunctionBody({)
-    endTopLevelMethod(Stream, null, })
+    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+    // WARNING: Reporting at eof for .
+    beginFields()
+      handleIdentifier(Stream, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleRecoverableError(Message[ExpectedType, Expected a type, but got '>'., null, {token: >}], >, >)
+          handleIdentifier(, typeReference)
+          handleNoTypeArguments(>)
+          handleType(, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Stream, null)
+      handleIdentifier(, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
+    endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   endTopLevelDeclaration()
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.intertwined.expect
index a66f17e..f21362a 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.intertwined.expect
@@ -8,50 +8,39 @@
       listener: endMetadataStar(0)
     parseTopLevelMemberImpl()
       listener: beginTopLevelMember(Stream)
-      isReservedKeyword(<)
-      parseTopLevelMethod(, null, , Instance of 'NoType', null, Stream, false)
-        listener: beginTopLevelMethod(, null)
-        listener: handleNoType()
-        ensureIdentifierPotentiallyRecovered(, topLevelFunctionDeclaration, false)
-          listener: handleIdentifier(Stream, topLevelFunctionDeclaration)
-        parseMethodTypeVar(Stream)
-          listener: beginTypeVariables(<)
-          parseMetadataStar(<)
-            listener: beginMetadataStar(List)
-            listener: endMetadataStar(0)
-          ensureIdentifier(<, typeVariableDeclaration)
-            listener: handleIdentifier(List, typeVariableDeclaration)
-          listener: beginTypeVariable(List)
-          listener: handleTypeVariablesDefined(List, 1)
-          listener: handleNoType(List)
-          listener: endTypeVariable(<, 0, null, null)
-          reportRecoverableError(List, Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}])
-            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-          parseMetadataStar(<)
-          ensureIdentifier(<, typeVariableDeclaration)
-            reportRecoverableErrorWithToken(>, Instance of 'Template<(Token) => Message>')
-            rewriter()
-          listener: endTypeVariables(<, >)
-        parseGetterOrFormalParameters(>, Stream, false, MemberKind.TopLevelMethod)
-          missingParameterMessage(MemberKind.TopLevelMethod)
-          reportRecoverableError(Stream, MissingFunctionParameters)
-            listener: handleRecoverableError(MissingFunctionParameters, Stream, Stream)
+      insertSyntheticIdentifier(>, methodDeclaration, message: null, messageOnToken: null)
+        reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
+          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+          listener: // WARNING: Reporting at eof for .
+        rewriter()
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', , DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Stream, typeReference)
+        listener: beginTypeArguments(<)
+        ensureIdentifier(<, typeReference)
+          listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        reportRecoverableErrorWithToken(>, Instance of 'Template<(Token) => Message>')
+          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '>'., null, {token: >}], >, >)
+        rewriter()
+        listener: handleIdentifier(, typeReference)
+        listener: handleNoTypeArguments(>)
+        listener: handleType(, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Stream, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
-          parseFormalParametersRest((, MemberKind.TopLevelMethod)
-            listener: beginFormalParameters((, MemberKind.TopLevelMethod)
-            listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-        parseAsyncModifierOpt())
-          listener: handleAsyncModifier(null, null)
-          inPlainSync()
-        parseFunctionBody(), false, false)
-          ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(, Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-            insertBlock())
-              rewriter()
-              rewriter()
-          listener: handleInvalidFunctionBody({)
-        listener: endTopLevelMethod(Stream, null, })
+        listener: endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(Stream)
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.parser.expect
index 69e3549..61baa3f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.parser.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.parser.expect
@@ -1,5 +1,5 @@
 NOTICE: Stream was rewritten by parser!
 
-Stream<List<> >(){}
+Stream<List<> >;
 
-Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken][SyntheticStringToken]>[SimpleToken] >[SimpleToken]([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken][SimpleToken]
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken][SyntheticStringToken]>[SimpleToken] >[SimpleToken][SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.expect
index adf4aeb..6f86b60 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.expect
@@ -1,40 +1,47 @@
 Problems reported:
 
-parser/error_recovery/issue_42229_prime_3.crash:1:8: Expected '>' after this.
-Stream<List<x>> 
-       ^^^^
-
-parser/error_recovery/issue_42229_prime_3.crash:1:1: A function declaration needs an explicit list of parameters.
-Stream<List<x>> 
-^^^^^^
-
-parser/error_recovery/issue_42229_prime_3.crash:1:17: Expected a function body, but got ''.
+parser/error_recovery/issue_42229_prime_3.crash:1:17: Expected an identifier, but got ''.
 Stream<List<x>> 
                 ^...
 
+WARNING: Reporting at eof --- see below for details.
+
+parser/error_recovery/issue_42229_prime_3.crash:1:17: Expected an identifier, but got ''.
+Stream<List<x>> 
+                ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+parser/error_recovery/issue_42229_prime_3.crash:1:17: Expected ';' after this.
+Stream<List<x>> 
+                ^...
+
+WARNING: Reporting at eof --- see below for details.
+
 beginCompilationUnit(Stream)
   beginMetadataStar(Stream)
   endMetadataStar(0)
   beginTopLevelMember(Stream)
-    beginTopLevelMethod(, null)
-      handleNoType()
-      handleIdentifier(Stream, topLevelFunctionDeclaration)
-      beginTypeVariables(<)
-        beginMetadataStar(List)
-        endMetadataStar(0)
-        handleIdentifier(List, typeVariableDeclaration)
-        beginTypeVariable(List)
-          handleTypeVariablesDefined(List, 1)
-          handleNoType(List)
-        endTypeVariable(<, 0, null, null)
-        handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-      endTypeVariables(<, >)
-      handleRecoverableError(MissingFunctionParameters, Stream, Stream)
-      beginFormalParameters((, MemberKind.TopLevelMethod)
-      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-      handleAsyncModifier(null, null)
-      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-      handleInvalidFunctionBody({)
-    endTopLevelMethod(Stream, null, })
+    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+    // WARNING: Reporting at eof for .
+    beginFields()
+      handleIdentifier(Stream, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleIdentifier(x, typeReference)
+          handleNoTypeArguments(>)
+          handleType(x, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Stream, null)
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+      // WARNING: Reporting at eof for .
+      handleIdentifier(, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
+    endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   endTopLevelDeclaration()
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.intertwined.expect
index 12b92e9..b0dde00 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.intertwined.expect
@@ -8,46 +8,40 @@
       listener: endMetadataStar(0)
     parseTopLevelMemberImpl()
       listener: beginTopLevelMember(Stream)
-      isReservedKeyword(<)
-      parseTopLevelMethod(, null, , Instance of 'NoType', null, Stream, false)
-        listener: beginTopLevelMethod(, null)
-        listener: handleNoType()
-        ensureIdentifierPotentiallyRecovered(, topLevelFunctionDeclaration, false)
-          listener: handleIdentifier(Stream, topLevelFunctionDeclaration)
-        parseMethodTypeVar(Stream)
-          listener: beginTypeVariables(<)
-          parseMetadataStar(<)
-            listener: beginMetadataStar(List)
-            listener: endMetadataStar(0)
-          ensureIdentifier(<, typeVariableDeclaration)
-            listener: handleIdentifier(List, typeVariableDeclaration)
-          listener: beginTypeVariable(List)
-          listener: handleTypeVariablesDefined(List, 1)
-          listener: handleNoType(List)
-          listener: endTypeVariable(<, 0, null, null)
-          reportRecoverableError(List, Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}])
-            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-          listener: endTypeVariables(<, >)
-        parseGetterOrFormalParameters(>, Stream, false, MemberKind.TopLevelMethod)
-          missingParameterMessage(MemberKind.TopLevelMethod)
-          reportRecoverableError(Stream, MissingFunctionParameters)
-            listener: handleRecoverableError(MissingFunctionParameters, Stream, Stream)
+      insertSyntheticIdentifier(>, methodDeclaration, message: null, messageOnToken: null)
+        reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
+          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+          listener: // WARNING: Reporting at eof for .
+        rewriter()
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', , DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Stream, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(x, typeReference)
+        listener: handleNoTypeArguments(>)
+        listener: handleType(x, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Stream, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+              listener: // WARNING: Reporting at eof for .
+            rewriter()
+          listener: handleIdentifier(, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
-          parseFormalParametersRest((, MemberKind.TopLevelMethod)
-            listener: beginFormalParameters((, MemberKind.TopLevelMethod)
-            listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-        parseAsyncModifierOpt())
-          listener: handleAsyncModifier(null, null)
-          inPlainSync()
-        parseFunctionBody(), false, false)
-          ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(, Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-            insertBlock())
-              rewriter()
-              rewriter()
-          listener: handleInvalidFunctionBody({)
-        listener: endTopLevelMethod(Stream, null, })
+        listener: endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(Stream)
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.parser.expect
index 356a3d2..a3a072f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.parser.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.parser.expect
@@ -1,5 +1,5 @@
 NOTICE: Stream was rewritten by parser!
 
-Stream<List<x>> (){}
+Stream<List<x>> ;
 
-Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]x[StringToken]>[SimpleToken]>[SimpleToken] ([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken][SimpleToken]
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]x[StringToken]>[SimpleToken]>[SimpleToken] [SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart
new file mode 100644
index 0000000..c5b7aa3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart
@@ -0,0 +1 @@
+Stream<List<x>> y;
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.expect
new file mode 100644
index 0000000..c639885
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.expect
@@ -0,0 +1,21 @@
+beginCompilationUnit(Stream)
+  beginMetadataStar(Stream)
+  endMetadataStar(0)
+  beginTopLevelMember(Stream)
+    beginFields()
+      handleIdentifier(Stream, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleIdentifier(x, typeReference)
+          handleNoTypeArguments(>)
+          handleType(x, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Stream, null)
+      handleIdentifier(y, topLevelVariableDeclaration)
+      handleNoFieldInitializer(;)
+    endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.intertwined.expect
new file mode 100644
index 0000000..8d42e4b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.intertwined.expect
@@ -0,0 +1,32 @@
+parseUnit(Stream)
+  skipErrorTokens(Stream)
+  listener: beginCompilationUnit(Stream)
+  syntheticPreviousToken(Stream)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(Stream)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(Stream)
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', y, DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Stream, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(x, typeReference)
+        listener: handleNoTypeArguments(>)
+        listener: handleType(x, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Stream, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(y, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(y, y, null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer(;)
+        listener: endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(Stream)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.parser.expect
new file mode 100644
index 0000000..bfb0cca
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+Stream<List<x>> y;
+
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]x[StringToken]>[SimpleToken]>[SimpleToken] y[StringToken];[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.scanner.expect
new file mode 100644
index 0000000..ece7ab8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.scanner.expect
@@ -0,0 +1,3 @@
+Stream<List<x>> y;
+
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]x[StringToken]>>[SimpleToken] y[StringToken];[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart
new file mode 100644
index 0000000..b6fc4c6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart
@@ -0,0 +1 @@
+hello
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.expect
new file mode 100644
index 0000000..afecf7c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.expect
@@ -0,0 +1,23 @@
+Problems reported:
+
+parser/error_recovery/issue_42229_prime_5:1:1: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+hello
+^^^^^
+
+parser/error_recovery/issue_42229_prime_5:1:1: Expected ';' after this.
+hello
+^^^^^
+
+beginCompilationUnit(hello)
+  beginMetadataStar(hello)
+  endMetadataStar(0)
+  beginTopLevelMember(hello)
+    beginFields()
+      handleRecoverableError(MissingConstFinalVarOrType, hello, hello)
+      handleNoType()
+      handleIdentifier(hello, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], hello, hello)
+    endTopLevelFields(null, null, null, null, null, 1, hello, ;)
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.intertwined.expect
new file mode 100644
index 0000000..ed05b5e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.intertwined.expect
@@ -0,0 +1,28 @@
+parseUnit(hello)
+  skipErrorTokens(hello)
+  listener: beginCompilationUnit(hello)
+  syntheticPreviousToken(hello)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(hello)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(hello)
+      isReservedKeyword()
+      parseFields(, null, null, null, null, null, null, , Instance of 'NoType', hello, DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        reportRecoverableError(hello, MissingConstFinalVarOrType)
+          listener: handleRecoverableError(MissingConstFinalVarOrType, hello, hello)
+        listener: handleNoType()
+        ensureIdentifierPotentiallyRecovered(, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(hello, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(hello, hello, null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon(hello)
+          reportRecoverableError(hello, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], hello, hello)
+          rewriter()
+        listener: endTopLevelFields(null, null, null, null, null, 1, hello, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(hello)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.parser.expect
new file mode 100644
index 0000000..0026649
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+hello;
+
+hello[StringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.scanner.expect
new file mode 100644
index 0000000..d26b1f2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.scanner.expect
@@ -0,0 +1,3 @@
+hello
+
+hello[StringToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart
new file mode 100644
index 0000000..3aa7912
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart
@@ -0,0 +1 @@
+const foo
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.expect
new file mode 100644
index 0000000..bc06b28
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.expect
@@ -0,0 +1,23 @@
+Problems reported:
+
+parser/error_recovery/issue_42229_prime_6:1:7: The const variable 'foo' must be initialized.
+const foo
+      ^^^
+
+parser/error_recovery/issue_42229_prime_6:1:7: Expected ';' after this.
+const foo
+      ^^^
+
+beginCompilationUnit(const)
+  beginMetadataStar(const)
+  endMetadataStar(0)
+  beginTopLevelMember(const)
+    beginFields()
+      handleNoType(const)
+      handleIdentifier(foo, topLevelVariableDeclaration)
+      handleRecoverableError(Message[ConstFieldWithoutInitializer, The const variable 'foo' must be initialized., Try adding an initializer ('= expression') to the declaration., {name: foo}], foo, foo)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], foo, foo)
+    endTopLevelFields(null, null, null, null, const, 1, const, ;)
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.intertwined.expect
new file mode 100644
index 0000000..c70f970
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.intertwined.expect
@@ -0,0 +1,27 @@
+parseUnit(const)
+  skipErrorTokens(const)
+  listener: beginCompilationUnit(const)
+  syntheticPreviousToken(const)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(const)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(const)
+      parseFields(, null, null, null, null, null, const, const, Instance of 'NoType', foo, DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        listener: handleNoType(const)
+        ensureIdentifierPotentiallyRecovered(const, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(foo, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(foo, foo, null, null, null, const, DeclarationKind.TopLevel, null)
+          reportRecoverableError(foo, Message[ConstFieldWithoutInitializer, The const variable 'foo' must be initialized., Try adding an initializer ('= expression') to the declaration., {name: foo}])
+            listener: handleRecoverableError(Message[ConstFieldWithoutInitializer, The const variable 'foo' must be initialized., Try adding an initializer ('= expression') to the declaration., {name: foo}], foo, foo)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon(foo)
+          reportRecoverableError(foo, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], foo, foo)
+          rewriter()
+        listener: endTopLevelFields(null, null, null, null, const, 1, const, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(const)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.parser.expect
new file mode 100644
index 0000000..3b31882
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+const foo;
+
+const[KeywordToken] foo[StringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.scanner.expect
new file mode 100644
index 0000000..35e6c3a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.scanner.expect
@@ -0,0 +1,3 @@
+const foo
+
+const[KeywordToken] foo[StringToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart
new file mode 100644
index 0000000..b2d9af7
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart
@@ -0,0 +1 @@
+Future<List<>>
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.expect
new file mode 100644
index 0000000..5a36aaf
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.expect
@@ -0,0 +1,52 @@
+Problems reported:
+
+parser/nnbd/issue_44477:1:15: Expected an identifier, but got ''.
+Future<List<>>
+              ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+parser/nnbd/issue_44477:1:13: Expected a type, but got '>>'.
+Future<List<>>
+            ^^
+
+parser/nnbd/issue_44477:1:15: Expected an identifier, but got ''.
+Future<List<>>
+              ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+parser/nnbd/issue_44477:1:15: Expected ';' after this.
+Future<List<>>
+              ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+beginCompilationUnit(Future)
+  beginMetadataStar(Future)
+  endMetadataStar(0)
+  beginTopLevelMember(Future)
+    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+    // WARNING: Reporting at eof for .
+    beginFields()
+      handleIdentifier(Future, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {token: >>}], >>, >>)
+          handleIdentifier(, typeReference)
+          handleNoTypeArguments(>>)
+          handleType(, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Future, null)
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+      // WARNING: Reporting at eof for .
+      handleIdentifier(, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
+    endTopLevelFields(null, null, null, null, null, 1, Future, ;)
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.intertwined.expect
new file mode 100644
index 0000000..3bb97c6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.intertwined.expect
@@ -0,0 +1,51 @@
+parseUnit(Future)
+  skipErrorTokens(Future)
+  listener: beginCompilationUnit(Future)
+  syntheticPreviousToken(Future)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(Future)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(Future)
+      insertSyntheticIdentifier(>, methodDeclaration, message: null, messageOnToken: null)
+        reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
+          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+          listener: // WARNING: Reporting at eof for .
+        rewriter()
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', , DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Future, typeReference)
+        listener: beginTypeArguments(<)
+        ensureIdentifier(<, typeReference)
+          listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        reportRecoverableErrorWithToken(>>, Instance of 'Template<(Token) => Message>')
+          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {token: >>}], >>, >>)
+        rewriter()
+        listener: handleIdentifier(, typeReference)
+        listener: handleNoTypeArguments(>>)
+        listener: handleType(, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Future, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+              listener: // WARNING: Reporting at eof for .
+            rewriter()
+          listener: handleIdentifier(, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
+          rewriter()
+        listener: endTopLevelFields(null, null, null, null, null, 1, Future, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(Future)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.parser.expect
new file mode 100644
index 0000000..63970d7
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+Future<List<>>;
+
+Future[StringToken]<[BeginToken]List[StringToken]<[BeginToken][SyntheticStringToken]>[SimpleToken]>[SimpleToken][SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.scanner.expect
new file mode 100644
index 0000000..f023442
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.scanner.expect
@@ -0,0 +1,3 @@
+Future<List<>>
+
+Future[StringToken]<[BeginToken]List[StringToken]<[BeginToken]>>[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 044da66..3536cb4 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -65,7 +65,6 @@
     expectInfo(noType, 'C*', required: false);
     expectInfo(noType, 'C do', required: false);
 
-    expectInfo(noType, 'C.a', required: false);
     expectInfo(noType, 'C.a;', required: false);
     expectInfo(noType, 'C.a(', required: false);
     expectInfo(noType, 'C.a<', required: false);
@@ -73,11 +72,9 @@
     expectInfo(noType, 'C.a*', required: false);
     expectInfo(noType, 'C.a do', required: false);
 
-    expectInfo(noType, 'C<T>', required: false);
     expectInfo(noType, 'C<T>;', required: false);
     expectInfo(noType, 'C<T>(', required: false);
     expectInfo(noType, 'C<T> do', required: false);
-    expectInfo(noType, 'C<void>', required: false);
 
     expectInfo(noType, 'C<T>= foo', required: false);
     expectInfo(noType, 'C<T>= get', required: false);
@@ -97,9 +94,6 @@
     expectInfo(noType, 'C<T>>= operator', required: false);
     expectInfo(noType, 'C<T>>= Function', required: false);
 
-    expectInfo(noType, 'C<S,T>', required: false);
-    expectInfo(noType, 'C<S<T>>', required: false);
-    expectInfo(noType, 'C.a<T>', required: false);
     expectInfo(noType, 'C<S,T>=', required: false);
     expectInfo(noType, 'C<S<T>>=', required: false);
     expectInfo(noType, 'C.a<T>=', required: false);
@@ -235,7 +229,7 @@
 @reflectiveTest
 class PrefixedTypeInfoTest {
   void test_compute() {
-    expectInfo(prefixedType, 'C.a', required: true);
+    expectInfo(prefixedType, 'C.a', required: null /* i.e. both */);
     expectInfo(prefixedType, 'C.a;', required: true);
     expectInfo(prefixedType, 'C.a(', required: true);
     expectInfo(prefixedType, 'C.a<', required: true);
@@ -466,7 +460,7 @@
 @reflectiveTest
 class SimpleTypeWith1ArgumentTest {
   void test_compute_gt() {
-    expectInfo(simpleTypeWith1Argument, 'C<T>', required: true);
+    expectInfo(simpleTypeWith1Argument, 'C<T>', required: null /* i.e. both */);
     expectInfo(simpleTypeWith1Argument, 'C<T>;', required: true);
     expectInfo(simpleTypeWith1Argument, 'C<T>(', required: true);
     expectInfo(simpleTypeWith1Argument, 'C<T> do', required: true);
@@ -949,13 +943,15 @@
   }
 
   void test_computeType_identifierTypeArg() {
-    expectComplexInfo('C<void>', required: true, expectedCalls: [
-      'handleIdentifier C typeReference',
-      'beginTypeArguments <',
-      'handleVoidKeyword void',
-      'endTypeArguments 1 < >',
-      'handleType C null',
-    ]);
+    expectComplexInfo('C<void>',
+        required: null /* i.e. both */,
+        expectedCalls: [
+          'handleIdentifier C typeReference',
+          'beginTypeArguments <',
+          'handleVoidKeyword void',
+          'endTypeArguments 1 < >',
+          'handleType C null',
+        ]);
   }
 
   void test_computeType_identifierTypeArg_questionMark() {
@@ -969,7 +965,7 @@
   }
 
   void test_computeType_identifierTypeArgComplex() {
-    expectComplexInfo('C<S,T>', required: true, expectedCalls: [
+    expectComplexInfo('C<S,T>', required: null /* i.e. both */, expectedCalls: [
       'handleIdentifier C typeReference',
       'beginTypeArguments <',
       'handleIdentifier S typeReference',
@@ -981,19 +977,21 @@
       'endTypeArguments 2 < >',
       'handleType C null',
     ]);
-    expectComplexInfo('C<S<T>>', required: true, expectedCalls: [
-      'handleIdentifier C typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >',
-      'handleType T null',
-      'endTypeArguments 1 < >',
-      'handleType S null',
-      'endTypeArguments 1 < >',
-      'handleType C null',
-    ]);
+    expectComplexInfo('C<S<T>>',
+        required: null /* i.e. both */,
+        expectedCalls: [
+          'handleIdentifier C typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >',
+          'handleType T null',
+          'endTypeArguments 1 < >',
+          'handleType S null',
+          'endTypeArguments 1 < >',
+          'handleType C null',
+        ]);
     expectComplexInfo('C<S,T> f', expectedAfter: 'f', expectedCalls: [
       'handleIdentifier C typeReference',
       'beginTypeArguments <',
@@ -1219,8 +1217,7 @@
           error(codeExpectedButGot, 6, 6)
         ]);
 
-    expectInfo(noType, 'C<>', required: false);
-    expectComplexInfo('C<>', required: true, expectedCalls: [
+    expectComplexInfo('C<>', required: null /* i.e. both */, expectedCalls: [
       'handleIdentifier C typeReference',
       'beginTypeArguments <',
       'handleIdentifier  typeReference',
@@ -1341,7 +1338,7 @@
   }
 
   void test_computeType_prefixedTypeArg() {
-    expectComplexInfo('C.a<T>', required: true, expectedCalls: [
+    expectComplexInfo('C.a<T>', required: null /* i.e. both */, expectedCalls: [
       'handleIdentifier C prefixedTypeReference',
       'handleIdentifier a typeReferenceContinuation',
       'handleQualified .',
@@ -2514,6 +2511,8 @@
   }
 }
 
+/// Note that if [required] is null it is run both with required [true] and
+/// [false] and expect the same in both situations.
 void expectComplexInfo(String source,
     {bool required,
     bool inDeclaration = false,
@@ -2687,7 +2686,7 @@
   while (start is ErrorToken) {
     start = start.next;
   }
-  return new SyntheticToken(TokenType.EOF, 0)..setNext(start);
+  return new SyntheticToken(TokenType.EOF, -1)..setNext(start);
 }
 
 int countGtGtAndNullEnd(Token token) {
diff --git a/pkg/front_end/test/parser_suite.dart b/pkg/front_end/test/parser_suite.dart
index 8ef6ae8..70bbcad 100644
--- a/pkg/front_end/test/parser_suite.dart
+++ b/pkg/front_end/test/parser_suite.dart
@@ -452,6 +452,14 @@
     }
   }
 
+  bool checkEof(Token token) {
+    bool result = super.checkEof(token);
+    if (result) {
+      errors.add("WARNING: Reporting at eof --- see below for details.");
+    }
+    return result;
+  }
+
   void handleRecoverableError(
       Message message, Token startToken, Token endToken) {
     if (source != null) {
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
index 63a1210..fca16c8 100644
--- a/pkg/front_end/test/parser_test_listener.dart
+++ b/pkg/front_end/test/parser_test_listener.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 import 'package:_fe_analyzer_shared/src/parser/assert.dart';
 import 'package:_fe_analyzer_shared/src/parser/block_kind.dart';
 import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart';
@@ -11,6 +13,7 @@
 import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
 import 'package:_fe_analyzer_shared/src/scanner/error_token.dart';
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+// ignore: import_of_legacy_library_into_null_safe
 import 'package:front_end/src/fasta/messages.dart';
 
 // THIS FILE IS AUTO GENERATED BY 'test/parser_test_listener_creator.dart'
@@ -50,9 +53,25 @@
     }
   }
 
-  void seen(Token token) {}
+  bool checkEof(Token token) {
+    if (token.isEof) {
+      doPrint("// WARNING: Reporting at eof for $token.");
+      return true;
+    }
+    Token? next = token.next;
+    while (next != null && next.offset == token.offset && !next.isEof) {
+      next = next.next;
+    }
+    if (next != null && next.offset == token.offset && next.isEof) {
+      doPrint("// WARNING: Reporting at the eof offset for $token.");
+      return true;
+    }
+    return false;
+  }
 
-  Uri get uri => null;
+  void seen(Token? token) {}
+
+  Uri? get uri => null;
 
   void logEvent(String name) {
     doPrint('logEvent(' '$name)');
@@ -71,7 +90,7 @@
     doPrint('endArguments(' '$count, ' '$beginToken, ' '$endToken)');
   }
 
-  void handleAsyncModifier(Token asyncToken, Token starToken) {
+  void handleAsyncModifier(Token? asyncToken, Token? starToken) {
     seen(asyncToken);
     seen(starToken);
     doPrint('handleAsyncModifier(' '$asyncToken, ' '$starToken)');
@@ -167,7 +186,7 @@
     indent++;
   }
 
-  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+  void beginClassDeclaration(Token begin, Token? abstractToken, Token name) {
     seen(begin);
     seen(abstractToken);
     seen(name);
@@ -175,20 +194,20 @@
     indent++;
   }
 
-  void handleClassExtends(Token extendsKeyword, int typeCount) {
+  void handleClassExtends(Token? extendsKeyword, int typeCount) {
     seen(extendsKeyword);
     doPrint('handleClassExtends(' '$extendsKeyword, ' '$typeCount)');
   }
 
   void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
+      Token? implementsKeyword, int interfacesCount) {
     seen(implementsKeyword);
     doPrint('handleClassOrMixinImplements('
         '$implementsKeyword, '
         '$interfacesCount)');
   }
 
-  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
+  void handleClassHeader(Token begin, Token classKeyword, Token? nativeToken) {
     seen(begin);
     seen(classKeyword);
     seen(nativeToken);
@@ -213,7 +232,7 @@
     indent++;
   }
 
-  void handleMixinOn(Token onKeyword, int typeCount) {
+  void handleMixinOn(Token? onKeyword, int typeCount) {
     seen(onKeyword);
     doPrint('handleMixinOn(' '$onKeyword, ' '$typeCount)');
   }
@@ -246,7 +265,7 @@
     indent++;
   }
 
-  void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+  void beginExtensionDeclaration(Token extensionKeyword, Token? name) {
     seen(extensionKeyword);
     seen(name);
     doPrint('beginExtensionDeclaration(' '$extensionKeyword, ' '$name)');
@@ -311,7 +330,7 @@
   }
 
   void endConstructorReference(
-      Token start, Token periodBeforeName, Token endToken) {
+      Token start, Token? periodBeforeName, Token endToken) {
     indent--;
     seen(start);
     seen(periodBeforeName);
@@ -399,7 +418,7 @@
   }
 
   void beginFactoryMethod(
-      Token lastConsumed, Token externalToken, Token constToken) {
+      Token lastConsumed, Token? externalToken, Token? constToken) {
     seen(lastConsumed);
     seen(externalToken);
     seen(constToken);
@@ -446,8 +465,8 @@
         '$endToken)');
   }
 
-  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
-      Token covariantToken, Token varFinalOrConst) {
+  void beginFormalParameter(Token token, MemberKind kind, Token? requiredToken,
+      Token? covariantToken, Token? varFinalOrConst) {
     seen(token);
     seen(requiredToken);
     seen(covariantToken);
@@ -462,11 +481,11 @@
   }
 
   void endFormalParameter(
-      Token thisKeyword,
-      Token periodAfterThis,
+      Token? thisKeyword,
+      Token? periodAfterThis,
       Token nameToken,
-      Token initializerStart,
-      Token initializerEnd,
+      Token? initializerStart,
+      Token? initializerEnd,
       FormalParameterKind kind,
       MemberKind memberKind) {
     indent--;
@@ -509,12 +528,12 @@
   }
 
   void endClassFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -540,12 +559,12 @@
   }
 
   void endMixinFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -571,12 +590,12 @@
   }
 
   void endExtensionFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -653,7 +672,7 @@
     doPrint('endForStatementBody(' '$token)');
   }
 
-  void handleForInLoopParts(Token awaitToken, Token forToken,
+  void handleForInLoopParts(Token? awaitToken, Token forToken,
       Token leftParenthesis, Token inKeyword) {
     seen(awaitToken);
     seen(forToken);
@@ -763,7 +782,7 @@
   }
 
   void endFunctionTypeAlias(
-      Token typedefKeyword, Token equals, Token endToken) {
+      Token typedefKeyword, Token? equals, Token endToken) {
     indent--;
     seen(typedefKeyword);
     seen(equals);
@@ -782,7 +801,7 @@
   }
 
   void beginNamedMixinApplication(
-      Token begin, Token abstractToken, Token name) {
+      Token begin, Token? abstractToken, Token name) {
     seen(begin);
     seen(abstractToken);
     seen(name);
@@ -797,7 +816,7 @@
   }
 
   void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
-      Token implementsKeyword, Token endToken) {
+      Token? implementsKeyword, Token endToken) {
     indent--;
     seen(begin);
     seen(classKeyword);
@@ -845,7 +864,7 @@
     indent++;
   }
 
-  void endIfStatement(Token ifToken, Token elseToken) {
+  void endIfStatement(Token ifToken, Token? elseToken) {
     indent--;
     seen(ifToken);
     seen(elseToken);
@@ -882,20 +901,20 @@
     indent++;
   }
 
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+  void handleImportPrefix(Token? deferredKeyword, Token? asKeyword) {
     seen(deferredKeyword);
     seen(asKeyword);
     doPrint('handleImportPrefix(' '$deferredKeyword, ' '$asKeyword)');
   }
 
-  void endImport(Token importKeyword, Token semicolon) {
+  void endImport(Token importKeyword, Token? semicolon) {
     indent--;
     seen(importKeyword);
     seen(semicolon);
     doPrint('endImport(' '$importKeyword, ' '$semicolon)');
   }
 
-  void handleRecoverImport(Token semicolon) {
+  void handleRecoverImport(Token? semicolon) {
     seen(semicolon);
     doPrint('handleRecoverImport(' '$semicolon)');
   }
@@ -917,7 +936,7 @@
     indent++;
   }
 
-  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token? equalSign) {
     indent--;
     seen(ifKeyword);
     seen(leftParen);
@@ -1074,7 +1093,7 @@
     indent++;
   }
 
-  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {
+  void handleInterpolationExpression(Token leftBracket, Token? rightBracket) {
     seen(leftBracket);
     seen(rightBracket);
     doPrint('handleInterpolationExpression(' '$leftBracket, ' '$rightBracket)');
@@ -1106,8 +1125,13 @@
     doPrint('endMember()');
   }
 
-  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
-      Token varFinalOrConst, Token getOrSet, Token name) {
+  void beginMethod(
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? varFinalOrConst,
+      Token? getOrSet,
+      Token name) {
     seen(externalToken);
     seen(staticToken);
     seen(covariantToken);
@@ -1124,8 +1148,8 @@
     indent++;
   }
 
-  void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endClassMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1140,8 +1164,8 @@
         '$endToken)');
   }
 
-  void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endMixinMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1156,8 +1180,8 @@
         '$endToken)');
   }
 
-  void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endExtensionMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1172,8 +1196,8 @@
         '$endToken)');
   }
 
-  void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endClassConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1188,8 +1212,8 @@
         '$endToken)');
   }
 
-  void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endMixinConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1204,8 +1228,8 @@
         '$endToken)');
   }
 
-  void endExtensionConstructor(Token getOrSet, Token beginToken,
-      Token beginParam, Token beginInitializers, Token endToken) {
+  void endExtensionConstructor(Token? getOrSet, Token beginToken,
+      Token beginParam, Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1237,7 +1261,7 @@
     indent++;
   }
 
-  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+  void endMetadata(Token beginToken, Token? periodBeforeName, Token endToken) {
     indent--;
     seen(beginToken);
     seen(periodBeforeName);
@@ -1334,7 +1358,7 @@
     doPrint('handleEmptyFunctionBody(' '$semicolon)');
   }
 
-  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
+  void handleExpressionFunctionBody(Token arrowToken, Token? endToken) {
     seen(arrowToken);
     seen(endToken);
     doPrint('handleExpressionFunctionBody(' '$arrowToken, ' '$endToken)');
@@ -1448,11 +1472,11 @@
   }
 
   void endTopLevelFields(
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -1475,14 +1499,14 @@
         '$endToken)');
   }
 
-  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {
+  void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {
     seen(lastConsumed);
     seen(externalToken);
     doPrint('beginTopLevelMethod(' '$lastConsumed, ' '$externalToken)');
     indent++;
   }
 
-  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+  void endTopLevelMethod(Token beginToken, Token? getOrSet, Token endToken) {
     indent--;
     seen(beginToken);
     seen(getOrSet);
@@ -1514,7 +1538,7 @@
     doPrint('endCatchClause(' '$token)');
   }
 
-  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
+  void handleCatchBlock(Token? onKeyword, Token? catchKeyword, Token? comma) {
     seen(onKeyword);
     seen(catchKeyword);
     seen(comma);
@@ -1526,7 +1550,8 @@
     doPrint('handleFinallyBlock(' '$finallyKeyword)');
   }
 
-  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+  void endTryStatement(
+      int catchCount, Token tryKeyword, Token? finallyKeyword) {
     indent--;
     seen(tryKeyword);
     seen(finallyKeyword);
@@ -1534,7 +1559,7 @@
         'endTryStatement(' '$catchCount, ' '$tryKeyword, ' '$finallyKeyword)');
   }
 
-  void handleType(Token beginToken, Token questionMark) {
+  void handleType(Token beginToken, Token? questionMark) {
     seen(beginToken);
     seen(questionMark);
     doPrint('handleType(' '$beginToken, ' '$questionMark)');
@@ -1556,7 +1581,7 @@
     indent++;
   }
 
-  void endFunctionType(Token functionToken, Token questionMark) {
+  void endFunctionType(Token functionToken, Token? questionMark) {
     indent--;
     seen(functionToken);
     seen(questionMark);
@@ -1598,7 +1623,7 @@
   }
 
   void endTypeVariable(
-      Token token, int index, Token extendsOrSuper, Token variance) {
+      Token token, int index, Token? extendsOrSuper, Token? variance) {
     indent--;
     seen(token);
     seen(extendsOrSuper);
@@ -1623,7 +1648,7 @@
     doPrint('endTypeVariables(' '$beginToken, ' '$endToken)');
   }
 
-  void reportVarianceModifierNotEnabled(Token variance) {
+  void reportVarianceModifierNotEnabled(Token? variance) {
     seen(variance);
     doPrint('reportVarianceModifierNotEnabled(' '$variance)');
   }
@@ -1642,7 +1667,7 @@
   }
 
   void beginVariablesDeclaration(
-      Token token, Token lateToken, Token varFinalOrConst) {
+      Token token, Token? lateToken, Token? varFinalOrConst) {
     seen(token);
     seen(lateToken);
     seen(varFinalOrConst);
@@ -1653,7 +1678,7 @@
     indent++;
   }
 
-  void endVariablesDeclaration(int count, Token endToken) {
+  void endVariablesDeclaration(int count, Token? endToken) {
     indent--;
     seen(endToken);
     doPrint('endVariablesDeclaration(' '$count, ' '$endToken)');
@@ -1740,7 +1765,7 @@
     doPrint('endConstExpression(' '$token)');
   }
 
-  void beginForControlFlow(Token awaitToken, Token forToken) {
+  void beginForControlFlow(Token? awaitToken, Token forToken) {
     seen(awaitToken);
     seen(forToken);
     doPrint('beginForControlFlow(' '$awaitToken, ' '$forToken)');
@@ -1798,7 +1823,7 @@
     indent++;
   }
 
-  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token? question) {
     indent--;
     seen(nameToken);
     seen(question);
@@ -1811,7 +1836,7 @@
   }
 
   void handleIndexedExpression(
-      Token question, Token openSquareBracket, Token closeSquareBracket) {
+      Token? question, Token openSquareBracket, Token closeSquareBracket) {
     seen(question);
     seen(openSquareBracket);
     seen(closeSquareBracket);
@@ -1833,7 +1858,7 @@
     doPrint('endIsOperatorType(' '$operator)');
   }
 
-  void handleIsOperator(Token isOperator, Token not) {
+  void handleIsOperator(Token isOperator, Token? not) {
     seen(isOperator);
     seen(not);
     doPrint('handleIsOperator(' '$isOperator, ' '$not)');
@@ -1874,7 +1899,7 @@
   }
 
   void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
-      Token commaToken, Token semicolonToken) {
+      Token? commaToken, Token semicolonToken) {
     indent--;
     seen(assertKeyword);
     seen(leftParenthesis);
@@ -1899,7 +1924,7 @@
   }
 
   void handleLiteralList(
-      int count, Token leftBracket, Token constKeyword, Token rightBracket) {
+      int count, Token leftBracket, Token? constKeyword, Token rightBracket) {
     seen(leftBracket);
     seen(constKeyword);
     seen(rightBracket);
@@ -1913,7 +1938,7 @@
   void handleLiteralSetOrMap(
     int count,
     Token leftBrace,
-    Token constKeyword,
+    Token? constKeyword,
     Token rightBrace,
     bool hasSetEntry,
   ) {
@@ -2033,8 +2058,8 @@
   void endSwitchCase(
       int labelCount,
       int expressionCount,
-      Token defaultKeyword,
-      Token colonAfterDefault,
+      Token? defaultKeyword,
+      Token? colonAfterDefault,
       int statementCount,
       Token firstToken,
       Token endToken) {
@@ -2110,7 +2135,7 @@
     indent++;
   }
 
-  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+  void endYieldStatement(Token yieldToken, Token? starToken, Token endToken) {
     indent--;
     seen(yieldToken);
     seen(starToken);
@@ -2118,7 +2143,7 @@
     doPrint('endYieldStatement(' '$yieldToken, ' '$starToken, ' '$endToken)');
   }
 
-  void endInvalidYieldStatement(Token beginToken, Token starToken,
+  void endInvalidYieldStatement(Token beginToken, Token? starToken,
       Token endToken, MessageCode errorCode) {
     indent--;
     seen(beginToken);
@@ -2137,6 +2162,7 @@
     seen(endToken);
     doPrint(
         'handleRecoverableError(' '$message, ' '$startToken, ' '$endToken)');
+    checkEof(endToken);
   }
 
   void handleErrorToken(ErrorToken token) {
@@ -2170,7 +2196,7 @@
   }
 
   void handleCommentReference(
-      Token newKeyword, Token prefix, Token period, Token token) {
+      Token? newKeyword, Token? prefix, Token? period, Token token) {
     seen(newKeyword);
     seen(prefix);
     seen(period);
diff --git a/pkg/front_end/test/parser_test_listener_creator.dart b/pkg/front_end/test/parser_test_listener_creator.dart
index 1acfac3..18c2152 100644
--- a/pkg/front_end/test/parser_test_listener_creator.dart
+++ b/pkg/front_end/test/parser_test_listener_creator.dart
@@ -37,6 +37,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 import 'package:_fe_analyzer_shared/src/parser/assert.dart';
 import 'package:_fe_analyzer_shared/src/parser/block_kind.dart';
 import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart';
@@ -46,6 +48,7 @@
 import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
 import 'package:_fe_analyzer_shared/src/scanner/error_token.dart';
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+// ignore: import_of_legacy_library_into_null_safe
 import 'package:front_end/src/fasta/messages.dart';
 
 // THIS FILE IS AUTO GENERATED BY 'test/parser_test_listener_creator.dart'
@@ -85,7 +88,23 @@
     }
   }
 
-  void seen(Token token) {}
+  bool checkEof(Token token) {
+    if (token.isEof) {
+      doPrint("// WARNING: Reporting at eof for $token.");
+      return true;
+    }
+    Token? next = token.next;
+    while (next != null && next.offset == token.offset && !next.isEof) {
+      next = next.next;
+    }
+    if (next != null && next.offset == token.offset && next.isEof) {
+      doPrint("// WARNING: Reporting at the eof offset for $token.");
+      return true;
+    }
+    return false;
+  }
+
+  void seen(Token? token) {}
 
 """);
 
@@ -178,6 +197,9 @@
           // It redirects to give an error message, so also do that here.
           out.write("  handleRecoverableError("
               "token.assertionMessage, token, token);");
+        } else if (currentMethodName == "handleRecoverableError") {
+          // Check for reporting on eof.
+          out.write("checkEof(endToken);");
         }
 
         out.write("}");
diff --git a/tools/VERSION b/tools/VERSION
index 5222bce..4ba8897 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 211
+PRERELEASE 212
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/build.py b/tools/build.py
index 9062ef5..513bef8 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -29,7 +29,7 @@
 
 def BuildOptions():
     parser = argparse.ArgumentParser(
-        description='Runs GN (if ncecessary) followed by ninja',
+        description='Runs GN (if necessary) followed by ninja',
         formatter_class=argparse.ArgumentDefaultsHelpFormatter)
 
     config_group = parser.add_argument_group('Configuration Related Arguments')