Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1509,7 +1509,9 @@ namespace ts {
case ParsingContext.ArgumentExpressions:
return token() === SyntaxKind.DotDotDotToken || isStartOfExpression();
case ParsingContext.Parameters:
return isStartOfParameter();
return isStartOfParameter(/*isJSDocParameter*/ false);
case ParsingContext.JSDocParameters:
return isStartOfParameter(/*isJSDocParameter*/ true);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does anything bad happen if we just always treat ( as the start of a parameter? It's a parse error anyway, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me try it ...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It disrupts parsing quite a bit. I'm not sure why, but it appears to cause type parameter lists to be parsed as parameter lists in arrow functions, and it also breaks function expressions inside object literal property assignments.

case ParsingContext.TypeArguments:
case ParsingContext.TupleElementTypes:
return token() === SyntaxKind.CommaToken || isStartOfType();
Expand Down Expand Up @@ -1612,6 +1614,7 @@ namespace ts {
case ParsingContext.TupleElementTypes:
case ParsingContext.ArrayBindingElements:
return token() === SyntaxKind.CloseBracketToken;
case ParsingContext.JSDocParameters:
case ParsingContext.Parameters:
case ParsingContext.RestProperties:
// Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
Expand Down Expand Up @@ -1795,6 +1798,7 @@ namespace ts {
case ParsingContext.VariableDeclarations:
return isReusableVariableDeclaration(node);

case ParsingContext.JSDocParameters:
case ParsingContext.Parameters:
return isReusableParameter(node);

Expand Down Expand Up @@ -2009,6 +2013,7 @@ namespace ts {
case ParsingContext.ArgumentExpressions: return Diagnostics.Argument_expression_expected;
case ParsingContext.ObjectLiteralMembers: return Diagnostics.Property_assignment_expected;
case ParsingContext.ArrayLiteralMembers: return Diagnostics.Expression_or_comma_expected;
case ParsingContext.JSDocParameters: return Diagnostics.Parameter_declaration_expected;
case ParsingContext.Parameters: return Diagnostics.Parameter_declaration_expected;
case ParsingContext.TypeParameters: return Diagnostics.Type_parameter_declaration_expected;
case ParsingContext.TypeArguments: return Diagnostics.Type_argument_expected;
Expand Down Expand Up @@ -2430,12 +2435,12 @@ namespace ts {
return undefined;
}

function isStartOfParameter(): boolean {
function isStartOfParameter(isJSDocParameter: boolean): boolean {
return token() === SyntaxKind.DotDotDotToken ||
isIdentifierOrPattern() ||
isModifierKind(token()) ||
token() === SyntaxKind.AtToken ||
isStartOfType(/*inStartOfParameter*/ true);
isStartOfType(/*inStartOfParameter*/ !isJSDocParameter);
}

function parseParameter(): ParameterDeclaration {
Expand Down Expand Up @@ -2534,7 +2539,9 @@ namespace ts {
setYieldContext(!!(flags & SignatureFlags.Yield));
setAwaitContext(!!(flags & SignatureFlags.Await));

signature.parameters = parseDelimitedList(ParsingContext.Parameters, flags & SignatureFlags.JSDoc ? parseJSDocParameter : parseParameter);
signature.parameters = flags & SignatureFlags.JSDoc ?
parseDelimitedList(ParsingContext.JSDocParameters, parseJSDocParameter) :
parseDelimitedList(ParsingContext.Parameters, parseParameter);

setYieldContext(savedYieldContext);
setAwaitContext(savedAwaitContext);
Expand Down Expand Up @@ -2960,6 +2967,8 @@ namespace ts {
case SyntaxKind.InferKeyword:
case SyntaxKind.ImportKeyword:
return true;
case SyntaxKind.FunctionKeyword:
return !inStartOfParameter;
case SyntaxKind.MinusToken:
return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
case SyntaxKind.OpenParenToken:
Expand All @@ -2973,7 +2982,7 @@ namespace ts {

function isStartOfParenthesizedOrFunctionType() {
nextToken();
return token() === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType();
return token() === SyntaxKind.CloseParenToken || isStartOfParameter(/*isJSDocParameter*/ false) || isStartOfType();
}

function parsePostfixTypeOrHigher(): TypeNode {
Expand Down Expand Up @@ -6255,6 +6264,7 @@ namespace ts {
JsxChildren, // Things between opening and closing JSX tags
ArrayLiteralMembers, // Members in array literal
Parameters, // Parameters in parameter list
JSDocParameters, // JSDoc parameters in parameter list of JSDoc function type
RestProperties, // Property names in a rest type list
TypeParameters, // Type parameters in type parameter list
TypeArguments, // Type arguments in type argument list
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
=== tests/cases/conformance/jsdoc/paren.js ===
/** @type {function((string), function((string)): string): string} */
var x = (s, id) => id(s)
>x : Symbol(x, Decl(paren.js, 1, 3))
>s : Symbol(s, Decl(paren.js, 1, 9))
>id : Symbol(id, Decl(paren.js, 1, 11))
>id : Symbol(id, Decl(paren.js, 1, 11))
>s : Symbol(s, Decl(paren.js, 1, 9))

11 changes: 11 additions & 0 deletions tests/baselines/reference/jsdocParseHigherOrderFunction.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
=== tests/cases/conformance/jsdoc/paren.js ===
/** @type {function((string), function((string)): string): string} */
var x = (s, id) => id(s)
>x : (arg0: string, arg1: (arg0: string) => string) => string
>(s, id) => id(s) : (s: string, id: (arg0: string) => string) => string
>s : string
>id : (arg0: string) => string
>id(s) : string
>id : (arg0: string) => string
>s : string

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
=== tests/cases/conformance/jsdoc/paren.js ===
/** @type {function((string)): string} */
var x = s => s.toString()
>x : Symbol(x, Decl(paren.js, 1, 3))
>s : Symbol(s, Decl(paren.js, 1, 7))
>s.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --))
>s : Symbol(s, Decl(paren.js, 1, 7))
>toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --))

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
=== tests/cases/conformance/jsdoc/paren.js ===
/** @type {function((string)): string} */
var x = s => s.toString()
>x : (arg0: string) => string
>s => s.toString() : (s: string) => string
>s : string
>s.toString() : string
>s.toString : () => string
>s : string
>toString : () => string

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// @noemit: true
// @allowjs: true
// @checkjs: true
// @strict: true
// @Filename: paren.js
/** @type {function((string), function((string)): string): string} */
var x = (s, id) => id(s)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// @noemit: true
// @allowjs: true
// @checkjs: true
// @strict: true
// @Filename: paren.js
/** @type {function((string)): string} */
var x = s => s.toString()