Allow `async` as an identifier everywhere.

Fixes #37063

Bug: http://dartbug.com/37063
Change-Id: I2253c3088fbe33eca1072f2480cf0cf3cc363362
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103524
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Leaf Petersen <leafp@google.com>
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8dbdc24..4bb5e3d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,9 @@
 
 ### Language
 
+* The identifier `async` can now be used in asynchronous and generator 
+  functions.
+
 ### Core library
 
 #### `dart:io`
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 5110557..11be8e1 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -51,8 +51,8 @@
   static const ParserErrorCode ASYNC_KEYWORD_USED_AS_IDENTIFIER =
       const ParserErrorCode(
           'ASYNC_KEYWORD_USED_AS_IDENTIFIER',
-          "The keywords 'async', 'await', and 'yield' can't be used as "
-          "identifiers in an asynchronous or generator function.");
+          "The keywords 'await' and 'yield' can't be used as "
+              "identifiers in an asynchronous or generator function.");
 
   static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = _BREAK_OUTSIDE_OF_LOOP;
 
@@ -340,7 +340,7 @@
   static const ParserErrorCode INVALID_COMMENT_REFERENCE = const ParserErrorCode(
       'INVALID_COMMENT_REFERENCE',
       "Comment references should contain a possibly prefixed identifier and "
-      "can start with 'new', but shouldn't contain anything else.");
+          "can start with 'new', but shouldn't contain anything else.");
 
   static const ParserErrorCode INVALID_CONSTRUCTOR_NAME = const ParserErrorCode(
       'INVALID_CONSTRUCTOR_NAME',
@@ -564,7 +564,7 @@
       const ParserErrorCode(
           'MULTIPLE_VARIABLES_IN_FOR_EACH',
           "A single loop variable must be declared in a for-each loop before "
-          "the 'in', but {0} were found.",
+              "the 'in', but {0} were found.",
           correction:
               "Try moving all but one of the declarations inside the loop body.");
 
@@ -588,14 +588,14 @@
       const ParserErrorCode(
           'NATIVE_CLAUSE_IN_NON_SDK_CODE',
           "Native clause can only be used in the SDK and code that is loaded "
-          "through native extensions.",
+              "through native extensions.",
           correction: "Try removing the native clause.");
 
   static const ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE =
       const ParserErrorCode(
           'NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE',
           "Native functions can only be declared in the SDK and code that is "
-          "loaded through native extensions.",
+              "loaded through native extensions.",
           correction: "Try removing the word 'native'.");
 
   static const ParserErrorCode NATIVE_CLAUSE_SHOULD_BE_ANNOTATION =
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 21a62ae..d494c4e 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -6976,8 +6976,7 @@
   SimpleIdentifier _parseSimpleIdentifierUnchecked(
       {bool isDeclaration: false}) {
     String lexeme = _currentToken.lexeme;
-    if ((_inAsync || _inGenerator) &&
-        (lexeme == ASYNC || lexeme == _AWAIT || lexeme == _YIELD)) {
+    if ((_inAsync || _inGenerator) && (lexeme == _AWAIT || lexeme == _YIELD)) {
       _reportErrorForCurrentToken(
           ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
     }
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index e11ba55..01c9695 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -2726,7 +2726,6 @@
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 32, 5),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
index 28ab163..f773a8c 100644
--- a/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
@@ -16,278 +16,6 @@
 
 @reflectiveTest
 class AsyncKeywordUsedAsIdentifierTest extends DriverResolutionTest {
-  test_async_annotation() async {
-    await assertErrorsInCode('''
-const int async = 0;
-f() async {
-  g(@async x) {}
-  g(0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
-    ]);
-  }
-
-  test_async_argumentLabel() async {
-    await assertErrorsInCode('''
-f(c) async {
-  c.g(async: 0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 19, 5),
-    ]);
-  }
-
-  test_async_async() async {
-    await assertErrorsInCode('''
-f() async {
-  var async = 1;
-  print(async);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
-    ]);
-  }
-
-  test_async_asyncStar() async {
-    await assertErrorsInCode('''
-f() async* {
-  var async = 1;
-  print(async);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 19, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
-    ]);
-  }
-
-  test_async_break() async {
-    await assertErrorsInCode('''
-f() async {
-  while (true) {
-    break async;
-  }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 39, 5),
-      error(CompileTimeErrorCode.LABEL_UNDEFINED, 39, 5),
-    ]);
-  }
-
-  test_async_catchException() async {
-    await assertErrorsInCode('''
-g() {}
-f() async {
-  try {
-    g();
-  } catch (async) { }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 47, 5),
-    ]);
-  }
-
-  test_async_catchStacktrace() async {
-    await assertErrorsInCode('''
-g() {}
-f() async {
-  try {
-    g();
-  } catch (e, async) { }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 50, 5),
-      error(HintCode.UNUSED_CATCH_STACK, 50, 5),
-    ]);
-  }
-
-  test_async_continue() async {
-    await assertErrorsInCode('''
-f() async {
-  while (true) {
-    continue async;
-  }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 42, 5),
-      error(CompileTimeErrorCode.LABEL_UNDEFINED, 42, 5),
-    ]);
-  }
-
-  test_async_for() async {
-    await assertErrorsInCode('''
-var async;
-f() async {
-  for (async in []) {}
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 30, 5),
-    ]);
-  }
-
-  test_async_formalParameter() async {
-    await assertErrorsInCode('''
-f() async {
-  g(int async) {}
-  g(0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 20, 5),
-    ]);
-  }
-
-  test_async_getter() async {
-    await assertErrorsInCode('''
-class C {
-  int get async => 1;
-}
-f() async {
-  return new C().async;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 63, 5),
-    ]);
-  }
-
-  test_async_invocation() async {
-    await assertErrorsInCode('''
-class C {
-  int async() => 1;
-}
-f() async {
-  return new C().async();
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 61, 5),
-    ]);
-  }
-
-  test_async_invocation_cascaded() async {
-    await assertErrorsInCode('''
-class C {
-  int async() => 1;
-}
-f() async {
-  return new C()..async();
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 62, 5),
-    ]);
-  }
-
-  test_async_label() async {
-    await assertErrorsInCode('''
-f() async {
-  async: g();
-}
-g() {}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 14, 5),
-      error(HintCode.UNUSED_LABEL, 14, 6),
-    ]);
-  }
-
-  test_async_localFunction() async {
-    await assertErrorsInCode('''
-f() async {
-  int async() => null;
-  async();
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
-    ]);
-  }
-
-  test_async_prefix() async {
-    await assertErrorsInCode('''
-import 'dart:async' as async;
-f() async {
-  return new async.Future.value(0);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 55, 5),
-    ]);
-  }
-
-  test_async_setter() async {
-    await assertErrorsInCode('''
-class C {
-  void set async(int i) {}
-}
-f() async {
-  new C().async = 1;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 61, 5),
-    ]);
-  }
-
-  test_async_setter_cascaded() async {
-    await assertErrorsInCode('''
-class C {
-  void set async(int i) {}
-}
-f() async {
-  return new C()..async = 1;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 69, 5),
-    ]);
-  }
-
-  test_async_stringInterpolation() async {
-    await assertErrorsInCode(r'''
-int async = 1;
-f() async {
-  return "$async";
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
-    ]);
-  }
-
-  test_async_suffix() async {
-    newFile("/test/lib/lib1.dart", content: r'''
-library lib1;
-int async;
-''');
-    await assertErrorsInCode('''
-import 'lib1.dart' as l;
-f() async {
-  return l.async;
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 48, 5),
-    ]);
-  }
-
-  test_async_switchLabel() async {
-    await assertErrorsInCode('''
-f() async {
-  switch (0) {
-    async: case 0: break;
-  }
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 31, 5),
-      error(HintCode.UNUSED_LABEL, 31, 6),
-    ]);
-  }
-
-  test_async_syncStar() async {
-    await assertErrorsInCode('''
-f() sync* {
-  var async = 1;
-  print(async);
-}
-''', [
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
-      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
-    ]);
-  }
-
   test_await_async() async {
     await assertErrorsInCode('''
 f() async {
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 991c13b..24ab44d 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -233,16 +233,6 @@
     message: r"""`assert` can't have more than two arguments.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAsyncAsIdentifier = messageAsyncAsIdentifier;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAsyncAsIdentifier = const MessageCode(
-    "AsyncAsIdentifier",
-    analyzerCodes: <String>["ASYNC_KEYWORD_USED_AS_IDENTIFIER"],
-    message:
-        r"""'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeAwaitAsIdentifier = messageAwaitAsIdentifier;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index db81019..0d0fccb 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -940,8 +940,6 @@
       parser.reportRecoverableError(identifier, fasta.messageAwaitAsIdentifier);
     } else if (optional('yield', identifier)) {
       parser.reportRecoverableError(identifier, fasta.messageYieldAsIdentifier);
-    } else if (optional('async', identifier)) {
-      parser.reportRecoverableError(identifier, fasta.messageAsyncAsIdentifier);
     }
   }
 }
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 42b24b6..4abb6b2 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1165,10 +1165,6 @@
   template: "Abstract methods can't use 'async', 'async*', or 'sync*'."
   analyzerCode: NON_SYNC_ABSTRACT_METHOD
 
-AsyncAsIdentifier:
-  analyzerCode: ASYNC_KEYWORD_USED_AS_IDENTIFIER
-  template: "'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
-
 AwaitAsIdentifier:
   template: "'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
   analyzerCode: ASYNC_KEYWORD_USED_AS_IDENTIFIER
diff --git a/tests/language_2/async_identifier_test.dart b/tests/language_2/async_identifier_test.dart
new file mode 100644
index 0000000..5af2722
--- /dev/null
+++ b/tests/language_2/async_identifier_test.dart
@@ -0,0 +1,209 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// 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 'dart:async' as async;
+import 'async_lib.dart' as l; // Minimal library containing "int async;".
+
+// Adapted from Analyzer test testing where `async` was not previously allowed.
+
+// Helpers
+void ignore(argument) {}
+
+class GNamed {
+  void g({Object async = null}) {}
+}
+
+class AGet {
+  int get async => 1;
+  set async(int i) {}
+}
+
+class ACall {
+  int async() => 1;
+}
+
+main() {
+  // Each test declares a spearate async function, tests that `async`
+  // can occur in it, and makes sure the function is run.
+  {
+    const int async = 0;
+    f() async {
+      g(@async x) {}
+      g(0);
+    }
+
+    f();
+  }
+  {
+    f(c) async {
+      c.g(async: 0);
+    }
+
+    f(GNamed());
+  }
+  {
+    f() async {
+      var async = 1;
+      ignore(async);
+    }
+
+    f();
+  }
+  {
+    f() async* {
+      var async = 1;
+      ignore(async);
+    }
+
+    f().forEach(ignore);
+  }
+  {
+    f() async {
+      async:
+      while (true) {
+        break async;
+      }
+    }
+
+    f();
+  }
+  {
+    g() {}
+    f() async {
+      try {
+        g();
+      } catch (async) {}
+    }
+
+    f();
+  }
+  {
+    g() {}
+    f() async {
+      try {
+        g();
+      } catch (e, async) {}
+    }
+
+    f();
+  }
+  {
+    f() async {
+      async:
+      while (true) {
+        if (false) continue async;
+        break;
+      }
+    }
+
+    f();
+  }
+  {
+    var async;
+    f() async {
+      for (async in []) {}
+    }
+
+    f();
+  }
+  {
+    f() async {
+      g(int async) {}
+      g(0);
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new AGet().async;
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new ACall().async();
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new ACall()..async();
+    }
+
+    f();
+  }
+  {
+    g() {}
+    f() async {
+      async:
+      g();
+    }
+
+    f();
+  }
+  {
+    f() async {
+      int async() => null;
+      async();
+    }
+  }
+  {
+    f() async {
+      return async.Future.value(0);
+    }
+
+    f();
+  }
+  {
+    f() async {
+      new AGet().async = 1;
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return new AGet()..async = 1;
+    }
+
+    f();
+  }
+  {
+    int async = 1;
+    f() async {
+      return "$async";
+    }
+
+    f();
+  }
+  {
+    f() async {
+      return l.async;
+    }
+
+    f();
+  }
+  {
+    f() async {
+      switch (0) {
+        async:
+        case 0:
+          break;
+      }
+    }
+
+    f();
+  }
+  {
+    f() sync* {
+      var async = 1;
+      ignore(async);
+    }
+
+    f();
+  }
+}
diff --git a/tests/language_2/async_lib.dart b/tests/language_2/async_lib.dart
new file mode 100644
index 0000000..a6be037
--- /dev/null
+++ b/tests/language_2/async_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+// Helper library for async_identifier_test.dart
+
+int async;
diff --git a/tests/language_2/known_identifier_usage_error_test.dart b/tests/language_2/known_identifier_usage_error_test.dart
index 9c96dc1..0d56f26 100644
--- a/tests/language_2/known_identifier_usage_error_test.dart
+++ b/tests/language_2/known_identifier_usage_error_test.dart
@@ -21,7 +21,7 @@
 import 'dart:async';
 
 Future<int> f1() async {
-  int async = 1; //# 01: syntax error
+  int async = 1;
   int await = 1; //# 02: syntax error
   int yield = 1; //# 03: syntax error
 
@@ -32,7 +32,7 @@
 }
 
 Stream<int> f2() async* {
-  int async = 1; //# 04: syntax error
+  int async = 1;
   int await = 1; //# 05: syntax error
   int yield = 1; //# 06: syntax error
 
@@ -43,7 +43,7 @@
 }
 
 Iterable<int> f3() sync* {
-  int async = 1; //# 07: syntax error
+  int async = 1;
   int await = 1; //# 08: syntax error
   int yield = 1; //# 09: syntax error
 
diff --git a/tests/language_2/sync_generator2_test.dart b/tests/language_2/sync_generator2_test.dart
index 9e33f0c..feaee63 100644
--- a/tests/language_2/sync_generator2_test.dart
+++ b/tests/language_2/sync_generator2_test.dart
@@ -15,13 +15,10 @@
 test01() sync* {
   var yield = 0; // //# 01: syntax error
   var await = 0; // //# 02: syntax error
-  var async = 0; // //# 03: syntax error
   bool yield() => false; //# 04: syntax error
   bool await() => false; //# 05: syntax error
-  bool async() => false; //# 06: syntax error
 
   var x1 = sync;
-  var x2 = async; // //# 07: syntax error
   var x3 = await; // //# 08: syntax error
   var x4 = await 55; // //# 09: compile-time error
   var x4 = yield; // //# 10: syntax error