mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fix parsing of parenthesized JSDoc parameters (#25799)
* Fix parsing of parenthesized JSDoc parameters
Parenthesis can start a jsdoc function parameter since it is just a
type, and parenthesis can start a type:
```js
/** @type {function(((string))): void} */
```
However, this is not legal in other parameter lists:
```ts
function x((((a))): string) { }
```
This change makes jsdoc function parameter lists parse differently than
normal parameter lists by allowing parenthesis as a start character of
jsdoc parameters.
* Parse nested uses of jsdoc function types
* Fix test
This commit is contained in:
+15
-5
@@ -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);
|
||||
case ParsingContext.TypeArguments:
|
||||
case ParsingContext.TupleElementTypes:
|
||||
return token() === SyntaxKind.CommaToken || isStartOfType();
|
||||
@@ -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
|
||||
@@ -1795,6 +1798,7 @@ namespace ts {
|
||||
case ParsingContext.VariableDeclarations:
|
||||
return isReusableVariableDeclaration(node);
|
||||
|
||||
case ParsingContext.JSDocParameters:
|
||||
case ParsingContext.Parameters:
|
||||
return isReusableParameter(node);
|
||||
|
||||
@@ -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;
|
||||
@@ -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 {
|
||||
@@ -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);
|
||||
@@ -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:
|
||||
@@ -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 {
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, --, --))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -0,0 +1,7 @@
|
||||
// @noemit: true
|
||||
// @allowjs: true
|
||||
// @checkjs: true
|
||||
// @strict: true
|
||||
// @Filename: paren.js
|
||||
/** @type {function((string)): string} */
|
||||
var x = s => s.toString()
|
||||
Reference in New Issue
Block a user