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>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
dbd70dd214
commit
eca6c8953f
@@ -4,6 +4,9 @@
|
||||
|
||||
### Language
|
||||
|
||||
* The identifier `async` can now be used in asynchronous and generator
|
||||
functions.
|
||||
|
||||
### Core library
|
||||
|
||||
#### `dart:io`
|
||||
|
||||
@@ -51,8 +51,8 @@ class ParserErrorCode extends ErrorCode {
|
||||
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 @@ class ParserErrorCode extends ErrorCode {
|
||||
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 @@ class ParserErrorCode extends ErrorCode {
|
||||
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 @@ class ParserErrorCode extends ErrorCode {
|
||||
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 =
|
||||
|
||||
@@ -6976,8 +6976,7 @@ class Parser {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2726,7 +2726,6 @@ class A {
|
||||
}
|
||||
''', [
|
||||
error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 5),
|
||||
error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 32, 5),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,278 +16,6 @@ main() {
|
||||
|
||||
@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 {
|
||||
|
||||
@@ -232,16 +232,6 @@ const MessageCode messageAssertExtraneousArgument = const MessageCode(
|
||||
"AssertExtraneousArgument",
|
||||
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;
|
||||
|
||||
|
||||
@@ -940,8 +940,6 @@ void checkAsyncAwaitYieldAsIdentifier(Token identifier, Parser parser) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1165,10 +1165,6 @@ AbstractNotSync:
|
||||
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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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 @@ Future<int> f1() async {
|
||||
}
|
||||
|
||||
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 @@ Stream<int> f2() async* {
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -15,13 +15,10 @@ var yield = "topLevelYield";
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user