mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 01:04:49 -05:00
Merge pull request #18417 from Microsoft/fail-spec-lambda-parsing-on-parameter-initialiser-missing-=
Fail speculative parsing of arrow functions when their parameter initialisers are missing a =
This commit is contained in:
@@ -2240,7 +2240,7 @@ namespace ts {
|
||||
isStartOfType(/*inStartOfParameter*/ true);
|
||||
}
|
||||
|
||||
function parseParameter(): ParameterDeclaration {
|
||||
function parseParameter(requireEqualsToken?: boolean): ParameterDeclaration {
|
||||
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter);
|
||||
if (token() === SyntaxKind.ThisKeyword) {
|
||||
node.name = createIdentifier(/*isIdentifier*/ true);
|
||||
@@ -2269,19 +2269,11 @@ namespace ts {
|
||||
|
||||
node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
|
||||
node.type = parseParameterType();
|
||||
node.initializer = parseBindingElementInitializer(/*inParameter*/ true);
|
||||
node.initializer = parseInitializer(/*inParameter*/ true, requireEqualsToken);
|
||||
|
||||
return addJSDocComment(finishNode(node));
|
||||
}
|
||||
|
||||
function parseBindingElementInitializer(inParameter: boolean) {
|
||||
return inParameter ? parseParameterInitializer() : parseNonParameterInitializer();
|
||||
}
|
||||
|
||||
function parseParameterInitializer() {
|
||||
return parseInitializer(/*inParameter*/ true);
|
||||
}
|
||||
|
||||
function fillSignature(
|
||||
returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken,
|
||||
flags: SignatureFlags,
|
||||
@@ -2334,7 +2326,8 @@ namespace ts {
|
||||
setYieldContext(!!(flags & SignatureFlags.Yield));
|
||||
setAwaitContext(!!(flags & SignatureFlags.Await));
|
||||
|
||||
const result = parseDelimitedList(ParsingContext.Parameters, flags & SignatureFlags.JSDoc ? parseJSDocParameter : parseParameter);
|
||||
const result = parseDelimitedList(ParsingContext.Parameters,
|
||||
flags & SignatureFlags.JSDoc ? parseJSDocParameter : () => parseParameter(!!(flags & SignatureFlags.RequireCompleteParameterList)));
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
setAwaitContext(savedAwaitContext);
|
||||
@@ -3011,7 +3004,7 @@ namespace ts {
|
||||
return expr;
|
||||
}
|
||||
|
||||
function parseInitializer(inParameter: boolean): Expression {
|
||||
function parseInitializer(inParameter: boolean, requireEqualsToken?: boolean): Expression {
|
||||
if (token() !== SyntaxKind.EqualsToken) {
|
||||
// It's not uncommon during typing for the user to miss writing the '=' token. Check if
|
||||
// there is no newline after the last token and if we're on an expression. If so, parse
|
||||
@@ -3026,11 +3019,17 @@ namespace ts {
|
||||
// do not try to parse initializer
|
||||
return undefined;
|
||||
}
|
||||
if (inParameter && requireEqualsToken) {
|
||||
// = is required when speculatively parsing arrow function parameters,
|
||||
// so return a fake initializer as a signal that the equals token was missing
|
||||
const result = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics._0_expected, "=") as Identifier;
|
||||
result.escapedText = "= not found" as __String;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Initializer[In, Yield] :
|
||||
// = AssignmentExpression[?In, ?Yield]
|
||||
|
||||
parseExpected(SyntaxKind.EqualsToken);
|
||||
return parseAssignmentExpressionOrHigher();
|
||||
}
|
||||
@@ -3345,8 +3344,7 @@ namespace ts {
|
||||
function tryParseAsyncSimpleArrowFunctionExpression(): ArrowFunction | undefined {
|
||||
// We do a check here so that we won't be doing unnecessarily call to "lookAhead"
|
||||
if (token() === SyntaxKind.AsyncKeyword) {
|
||||
const isUnParenthesizedAsyncArrowFunction = lookAhead(isUnParenthesizedAsyncArrowFunctionWorker);
|
||||
if (isUnParenthesizedAsyncArrowFunction === Tristate.True) {
|
||||
if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === Tristate.True) {
|
||||
const asyncModifier = parseModifiersForArrowFunction();
|
||||
const expr = parseBinaryExpressionOrHigher(/*precedence*/ 0);
|
||||
return parseSimpleArrowFunctionExpression(<Identifier>expr, asyncModifier);
|
||||
@@ -3380,7 +3378,6 @@ namespace ts {
|
||||
const node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction);
|
||||
node.modifiers = parseModifiersForArrowFunction();
|
||||
const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None;
|
||||
|
||||
// Arrow functions are never generators.
|
||||
//
|
||||
// If we're speculatively parsing a signature for a parenthesized arrow function, then
|
||||
@@ -3403,7 +3400,8 @@ namespace ts {
|
||||
// - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
|
||||
//
|
||||
// So we need just a bit of lookahead to ensure that it can only be a signature.
|
||||
if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && token() !== SyntaxKind.OpenBraceToken) {
|
||||
if (!allowAmbiguity && ((token() !== SyntaxKind.EqualsGreaterThanToken && token() !== SyntaxKind.OpenBraceToken) ||
|
||||
find(node.parameters, p => p.initializer && ts.isIdentifier(p.initializer) && p.initializer.escapedText === "= not found"))) {
|
||||
// Returning undefined here will cause our caller to rewind to where we started from.
|
||||
return undefined;
|
||||
}
|
||||
@@ -5152,7 +5150,7 @@ namespace ts {
|
||||
const node = <BindingElement>createNode(SyntaxKind.BindingElement);
|
||||
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
node.name = parseIdentifierOrPattern();
|
||||
node.initializer = parseBindingElementInitializer(/*inParameter*/ false);
|
||||
node.initializer = parseInitializer(/*inParameter*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@@ -5169,7 +5167,7 @@ namespace ts {
|
||||
node.propertyName = propertyName;
|
||||
node.name = parseIdentifierOrPattern();
|
||||
}
|
||||
node.initializer = parseBindingElementInitializer(/*inParameter*/ false);
|
||||
node.initializer = parseInitializer(/*inParameter*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@@ -5208,7 +5206,7 @@ namespace ts {
|
||||
node.name = parseIdentifierOrPattern();
|
||||
node.type = parseTypeAnnotation();
|
||||
if (!isInOrOfKeyword(token())) {
|
||||
node.initializer = parseInitializer(/*inParameter*/ false);
|
||||
node.initializer = parseNonParameterInitializer();
|
||||
}
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user