allow built-in keywords as identifier in for-in loop

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

Change-Id: I2af3a21e96c5654b12c199fc71d87f088e9d739d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99904
Auto-Submit: Dan Rubel <danrubel@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 90e4ca8..775196e 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -2649,6 +2649,40 @@
     expect(forStatement.body, isNotNull);
   }
 
+  void test_parseForStatement_each_finalRequired() {
+    ForStatement forStatement = parseStatement(
+      'for (final required in list) {}',
+      parseControlFlowCollections: true,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable.identifier.name, 'required');
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_finalExternal() {
+    ForStatement forStatement = parseStatement(
+      'for (final external in list) {}',
+      parseControlFlowCollections: true,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable.identifier.name, 'external');
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
   void test_parseForStatement_each_type2() {
     ForStatement forStatement = parseStatement(
       'for (A element in list) {}',
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
index 605c9e2..0dc8030 100644
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
@@ -2,7 +2,7 @@
 // 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.
 
-import '../../scanner/token.dart' show Token;
+import '../../scanner/token.dart' show Keyword, Token;
 import '../messages.dart' as fasta;
 import 'formal_parameter_kind.dart';
 import 'member_kind.dart' show MemberKind;
@@ -21,22 +21,11 @@
     //   external Foo foo();
     // but is the identifier in this declaration
     //   external() => true;
-    if (!token.next.type.isKeyword && !token.next.isIdentifier) {
-      return false;
-    }
-  } else if (token.type.isPseudo) {
-    // A pseudo keyword can only be a modifier as long as it is
-    // followed by another keyword or two identifiers. Otherwise, it is the
-    // identifier or the type before the identifier.
-    //
-    // For example, `required` is a modifier in this declaration:
-    //   bar({required Foo foo});
-    // but is the type in this declaration
-    //   bar({required foo});
-    // and is the identifier in this declaration
-    //   bar({required});
-    if (!token.next.type.isKeyword &&
-        (!token.next.isIdentifier || !token.next.next.isIdentifier)) {
+    // and in
+    //   for (final external in list) { }
+    Token next = token.next;
+    Keyword keyword = next.keyword;
+    if (keyword == null && !next.isIdentifier || keyword == Keyword.IN) {
       return false;
     }
   }
diff --git a/pkg/front_end/test/token_test.dart b/pkg/front_end/test/token_test.dart
index ddde7df..d733068 100644
--- a/pkg/front_end/test/token_test.dart
+++ b/pkg/front_end/test/token_test.dart
@@ -156,6 +156,14 @@
     }
   }
 
+  void test_noPseudoModifiers() {
+    for (Keyword keyword in Keyword.values) {
+      if (keyword.isModifier) {
+        expect(keyword.isPseudo, isFalse, reason: keyword.lexeme);
+      }
+    }
+  }
+
   void test_pseudo_keywords() {
     var pseudoKeywords = new Set<Keyword>.from([
       Keyword.ASYNC,