mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 12:51:30 -05:00
Fix 8262: allow unparenthesized parameter in async arrow-function (#8444)
* Allow unparenthesize of parameter in async arrow-function * Add tests and baselines * Address PR * Address PR: refactor to use "parseSimpleArrowFunctionExpression" * Address PR: add comment * Address PR
This commit is contained in:
@@ -2685,7 +2685,8 @@ namespace ts {
|
||||
// 2) LeftHandSideExpression = AssignmentExpression[?in,?yield]
|
||||
// 3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield]
|
||||
// 4) ArrowFunctionExpression[?in,?yield]
|
||||
// 5) [+Yield] YieldExpression[?In]
|
||||
// 5) AsyncArrowFunctionExpression[in,yield,await]
|
||||
// 6) [+Yield] YieldExpression[?In]
|
||||
//
|
||||
// Note: for ease of implementation we treat productions '2' and '3' as the same thing.
|
||||
// (i.e. they're both BinaryExpressions with an assignment operator in it).
|
||||
@@ -2695,11 +2696,18 @@ namespace ts {
|
||||
return parseYieldExpression();
|
||||
}
|
||||
|
||||
// Then, check if we have an arrow function (production '4') that starts with a parenthesized
|
||||
// parameter list. If we do, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
|
||||
// Then, check if we have an arrow function (production '4' and '5') that starts with a parenthesized
|
||||
// parameter list or is an async arrow function.
|
||||
// AsyncArrowFunctionExpression:
|
||||
// 1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In]
|
||||
// 2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In]
|
||||
// Production (1) of AsyncArrowFunctionExpression is parsed in "tryParseAsyncSimpleArrowFunctionExpression".
|
||||
// And production (2) is parsed in "tryParseParenthesizedArrowFunctionExpression".
|
||||
//
|
||||
// If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
|
||||
// not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done
|
||||
// with AssignmentExpression if we see one.
|
||||
const arrowExpression = tryParseParenthesizedArrowFunctionExpression();
|
||||
const arrowExpression = tryParseParenthesizedArrowFunctionExpression() || tryParseAsyncSimpleArrowFunctionExpression();
|
||||
if (arrowExpression) {
|
||||
return arrowExpression;
|
||||
}
|
||||
@@ -2791,10 +2799,17 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function parseSimpleArrowFunctionExpression(identifier: Identifier): Expression {
|
||||
function parseSimpleArrowFunctionExpression(identifier: Identifier, asyncModifier?: ModifiersArray): ArrowFunction {
|
||||
Debug.assert(token === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
|
||||
|
||||
const node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction, identifier.pos);
|
||||
let node: ArrowFunction;
|
||||
if (asyncModifier) {
|
||||
node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction, asyncModifier.pos);
|
||||
setModifiers(node, asyncModifier);
|
||||
}
|
||||
else {
|
||||
node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction, identifier.pos);
|
||||
}
|
||||
|
||||
const parameter = <ParameterDeclaration>createNode(SyntaxKind.Parameter, identifier.pos);
|
||||
parameter.name = identifier;
|
||||
@@ -2805,7 +2820,7 @@ namespace ts {
|
||||
node.parameters.end = parameter.end;
|
||||
|
||||
node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, "=>");
|
||||
node.body = parseArrowFunctionExpressionBody(/*isAsync*/ false);
|
||||
node.body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier);
|
||||
|
||||
return finishNode(node);
|
||||
}
|
||||
@@ -2973,6 +2988,32 @@ namespace ts {
|
||||
return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false);
|
||||
}
|
||||
|
||||
function tryParseAsyncSimpleArrowFunctionExpression(): ArrowFunction {
|
||||
const isUnParenthesizedAsyncArrowFunction = lookAhead(isUnParenthesizedAsyncArrowFunctionWorker);
|
||||
if (isUnParenthesizedAsyncArrowFunction === Tristate.True) {
|
||||
const asyncModifier = parseModifiersForArrowFunction();
|
||||
const expr = parseBinaryExpressionOrHigher(/*precedence*/ 0);
|
||||
return parseSimpleArrowFunctionExpression(<Identifier>expr, asyncModifier);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isUnParenthesizedAsyncArrowFunctionWorker(): Tristate {
|
||||
if (token === SyntaxKind.AsyncKeyword) {
|
||||
nextToken();
|
||||
if (scanner.hasPrecedingLineBreak()) {
|
||||
return Tristate.False;
|
||||
}
|
||||
// Check for un-parenthesized AsyncArrowFunction
|
||||
const expr = parseBinaryExpressionOrHigher(/*precedence*/ 0);
|
||||
if (!scanner.hasPrecedingLineBreak() && expr.kind === SyntaxKind.Identifier && token === SyntaxKind.EqualsGreaterThanToken) {
|
||||
return Tristate.True;
|
||||
}
|
||||
}
|
||||
|
||||
return Tristate.False;
|
||||
}
|
||||
|
||||
function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction {
|
||||
const node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction);
|
||||
setModifiers(node, parseModifiersForArrowFunction());
|
||||
|
||||
Reference in New Issue
Block a user