kw_NS_ENUM = &IdentTable.get("NS_ENUM");
kw_NS_OPTIONS = &IdentTable.get("NS_OPTIONS");
+ kw_async = &IdentTable.get("async");
+ kw_await = &IdentTable.get("await");
kw_finally = &IdentTable.get("finally");
- kw_function = &IdentTable.get("function");
kw_from = &IdentTable.get("from");
+ kw_function = &IdentTable.get("function");
kw_import = &IdentTable.get("import");
kw_is = &IdentTable.get("is");
kw_let = &IdentTable.get("let");
kw_var = &IdentTable.get("var");
+ kw_yield = &IdentTable.get("yield");
kw_abstract = &IdentTable.get("abstract");
kw_assert = &IdentTable.get("assert");
IdentifierInfo *kw___except;
// JavaScript keywords.
+ IdentifierInfo *kw_async;
+ IdentifierInfo *kw_await;
IdentifierInfo *kw_finally;
- IdentifierInfo *kw_function;
IdentifierInfo *kw_from;
+ IdentifierInfo *kw_function;
IdentifierInfo *kw_import;
IdentifierInfo *kw_is;
IdentifierInfo *kw_let;
IdentifierInfo *kw_var;
+ IdentifierInfo *kw_yield;
// Java keywords.
IdentifierInfo *kw_abstract;
// FIXME: This returns true for C/C++ keywords like 'struct'.
return FormatTok->is(tok::identifier) &&
(FormatTok->Tok.getIdentifierInfo() == nullptr ||
- !FormatTok->isOneOf(Keywords.kw_in, Keywords.kw_of,
+ !FormatTok->isOneOf(Keywords.kw_in, Keywords.kw_of, Keywords.kw_async,
+ Keywords.kw_await, Keywords.kw_yield,
Keywords.kw_finally, Keywords.kw_function,
Keywords.kw_import, Keywords.kw_is,
Keywords.kw_let, Keywords.kw_var,
static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords,
const FormatToken *FormatTok) {
return FormatTok->isOneOf(
- tok::kw_return,
+ tok::kw_return, Keywords.kw_yield,
// conditionals
tok::kw_if, tok::kw_else,
// loops
tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.kw_finally,
// declaration
tok::kw_const, tok::kw_class, Keywords.kw_var, Keywords.kw_let,
- Keywords.kw_function);
+ Keywords.kw_async, Keywords.kw_function,
+ // import/export
+ Keywords.kw_import, tok::kw_export);
}
// readTokenWithJavaScriptASI reads the next token and terminates the current
// Parse function literal unless 'function' is the first token in a line
// in which case this should be treated as a free-standing function.
if (Style.Language == FormatStyle::LK_JavaScript &&
- FormatTok->is(Keywords.kw_function) && Line->Tokens.size() > 0) {
+ FormatTok->isOneOf(Keywords.kw_async, Keywords.kw_function) &&
+ Line->Tokens.size() > 0) {
tryToParseJSFunction();
break;
}
}
void UnwrappedLineParser::tryToParseJSFunction() {
+ assert(FormatTok->isOneOf(Keywords.kw_async, Keywords.kw_function));
+ if (FormatTok->is(Keywords.kw_async))
+ nextToken();
+ // Consume "function".
nextToken();
+ // Consume * (generator function).
+ if (FormatTok->is(tok::star))
+ nextToken();
+
// Consume function name.
if (FormatTok->is(tok::identifier))
nextToken();
// replace this by using parseAssigmentExpression() inside.
do {
if (Style.Language == FormatStyle::LK_JavaScript) {
- if (FormatTok->is(Keywords.kw_function)) {
+ if (FormatTok->isOneOf(Keywords.kw_async, Keywords.kw_function)) {
tryToParseJSFunction();
continue;
}
break;
case tok::identifier:
if (Style.Language == FormatStyle::LK_JavaScript &&
- FormatTok->is(Keywords.kw_function))
+ FormatTok->isOneOf(Keywords.kw_async, Keywords.kw_function))
tryToParseJSFunction();
else
nextToken();
if (FormatTok->is(tok::kw_default))
nextToken();
- // Consume "function" and "default function", so that these get parsed as
- // free-standing JS functions, i.e. do not require a trailing semicolon.
+ // Consume "async function", "function" and "default function", so that these
+ // get parsed as free-standing JS functions, i.e. do not require a trailing
+ // semicolon.
+ if (FormatTok->is(Keywords.kw_async))
+ nextToken();
if (FormatTok->is(Keywords.kw_function)) {
nextToken();
return;
verifyFormat("function f() {}");
}
+TEST_F(FormatTestJS, GeneratorFunctions) {
+ verifyFormat("function* f() {\n"
+ " let x = 1;\n"
+ " yield x;\n"
+ " yield* something();\n"
+ "}");
+ verifyFormat("function*\n"
+ " f() {\n"
+ "}",
+ getGoogleJSStyleWithColumns(8));
+ verifyFormat("export function* f() {\n"
+ " yield 1;\n"
+ "}\n");
+ verifyFormat("class X {\n"
+ " * generatorMethod() { yield x; }\n"
+ "}");
+}
+
+TEST_F(FormatTestJS, AsyncFunctions) {
+ verifyFormat("async function f() {\n"
+ " let x = 1;\n"
+ " return fetch(x);\n"
+ "}");
+ verifyFormat("async function* f() {\n"
+ " yield fetch(x);\n"
+ "}");
+ verifyFormat("export async function f() {\n"
+ " return fetch(x);\n"
+ "}");
+ verifyFormat("class X {\n"
+ " async asyncMethod() { return fetch(1); }\n"
+ "}");
+}
+
TEST_F(FormatTestJS, ArrayLiterals) {
verifyFormat("var aaaaa: List<SomeThing> =\n"
" [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");