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
17 changes: 15 additions & 2 deletions internal/parser/reparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,23 @@ func (p *Parser) reparseJSDocSignature(jsSignature *ast.Node, fun *ast.Node, jsD
}
} else {
jsparam := param.AsJSDocParameterOrPropertyTag()
parameter = p.factory.NewParameterDeclaration(nil, nil, p.factory.DeepCloneReparse(jsparam.Name()), p.makeQuestionIfOptional(jsparam), nil, nil)
var dotDotDotToken *ast.Node
var paramType *ast.TypeNode

if jsparam.TypeExpression != nil {
parameter.AsParameterDeclaration().Type = p.reparseJSDocTypeLiteral(jsparam.TypeExpression.Type())
if jsparam.TypeExpression.Type().Kind == ast.KindJSDocVariadicType {
dotDotDotToken = p.factory.NewToken(ast.KindDotDotDotToken)
dotDotDotToken.Loc = jsparam.Loc
dotDotDotToken.Flags = p.contextFlags | ast.NodeFlagsReparsed

variadicType := jsparam.TypeExpression.Type().AsJSDocVariadicType()
paramType = p.reparseJSDocTypeLiteral(variadicType.Type)
} else {
paramType = p.reparseJSDocTypeLiteral(jsparam.TypeExpression.Type())
}
}

parameter = p.factory.NewParameterDeclaration(nil, dotDotDotToken, p.factory.DeepCloneReparse(jsparam.Name()), p.makeQuestionIfOptional(jsparam), paramType, nil)
}
p.finishReparsedNode(parameter, param)
parameters = append(parameters, parameter)
Expand Down
158 changes: 158 additions & 0 deletions testdata/baselines/reference/conformance/jsdocVariadicInOverload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
//// [tests/cases/conformance/jsdoc/jsdocVariadicInOverload.ts] ////

//// [typeTagForMultipleVariableDeclarations.js]
// based on code from unifiedjs/unified
class Node {}
/**
* @template {Node | undefined} [ParseTree=undefined]
* Output of `parse` (optional).
* @template {Node | undefined} [HeadTree=undefined]
* Input for `run` (optional).
* @template {Node | undefined} [TailTree=undefined]
* Output for `run` (optional).
* @template {Node | undefined} [CompileTree=undefined]
* Input of `stringify` (optional).
* @template {string | undefined} [CompileResult=undefined]
* Output of `stringify` (optional).
*/
export class Processor {
/**
* @overload
* @param {string | null | undefined} [preset]
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
*
* @template {Array<unknown>} [Parameters=[]]
* @template {Node | string | undefined} [Input=undefined]
* @template [Output=Input]
* @overload
* @param {number} plugin
* @param {...(Parameters | [boolean])} parameters
* @returns {Processor}
*
* @param {string | number | boolean | null | undefined} value
* Usable value.
* @param {...unknown} parameters
* Parameters, when a plugin is given as a usable value.
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
* Current processor.
*/
use(value, ...parameters) {
return this;
}
}
var p = new Processor();
var x = 1, y = 2, z = 3;
p.use(x, y, z);


//// [typeTagForMultipleVariableDeclarations.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Processor = void 0;
// based on code from unifiedjs/unified
class Node {
}
/**
* @template {Node | undefined} [ParseTree=undefined]
* Output of `parse` (optional).
* @template {Node | undefined} [HeadTree=undefined]
* Input for `run` (optional).
* @template {Node | undefined} [TailTree=undefined]
* Output for `run` (optional).
* @template {Node | undefined} [CompileTree=undefined]
* Input of `stringify` (optional).
* @template {string | undefined} [CompileResult=undefined]
* Output of `stringify` (optional).
*/
class Processor {
/**
* @overload
* @param {string | null | undefined} [preset]
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
*
* @template {Array<unknown>} [Parameters=[]]
* @template {Node | string | undefined} [Input=undefined]
* @template [Output=Input]
* @overload
* @param {number} plugin
* @param {...(Parameters | [boolean])} parameters
* @returns {Processor}
*
* @param {string | number | boolean | null | undefined} value
* Usable value.
* @param {...unknown} parameters
* Parameters, when a plugin is given as a usable value.
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
* Current processor.
*/
use(value, ...parameters) {
return this;
}
}
exports.Processor = Processor;
var p = new Processor();
var x = 1, y = 2, z = 3;
p.use(x, y, z);


//// [typeTagForMultipleVariableDeclarations.d.ts]
// based on code from unifiedjs/unified
declare class Node {
}
/**
* @template {Node | undefined} [ParseTree=undefined]
* Output of `parse` (optional).
* @template {Node | undefined} [HeadTree=undefined]
* Input for `run` (optional).
* @template {Node | undefined} [TailTree=undefined]
* Output for `run` (optional).
* @template {Node | undefined} [CompileTree=undefined]
* Input of `stringify` (optional).
* @template {string | undefined} [CompileResult=undefined]
* Output of `stringify` (optional).
*/
export declare class Processor<ParseTree extends Node | undefined = undefined, HeadTree extends Node | undefined = undefined, TailTree extends Node | undefined = undefined, CompileTree extends Node | undefined = undefined, CompileResult extends string | undefined = undefined> {
/**
* @overload
* @param {string | null | undefined} [preset]
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
*
* @template {Array<unknown>} [Parameters=[]]
* @template {Node | string | undefined} [Input=undefined]
* @template [Output=Input]
* @overload
* @param {number} plugin
* @param {...(Parameters | [boolean])} parameters
* @returns {Processor}
*
* @param {string | number | boolean | null | undefined} value
* Usable value.
* @param {...unknown} parameters
* Parameters, when a plugin is given as a usable value.
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
* Current processor.
*/
use(preset?: string | null | undefined): Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>;
/**
* @overload
* @param {string | null | undefined} [preset]
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
*
* @template {Array<unknown>} [Parameters=[]]
* @template {Node | string | undefined} [Input=undefined]
* @template [Output=Input]
* @overload
* @param {number} plugin
* @param {...(Parameters | [boolean])} parameters
* @returns {Processor}
*
* @param {string | number | boolean | null | undefined} value
* Usable value.
* @param {...unknown} parameters
* Parameters, when a plugin is given as a usable value.
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
* Current processor.
*/
use<Parameters extends Array<unknown> = [], Input extends Node | string | undefined = undefined, Output = Input>(plugin: number, ...parameters: (Parameters | [boolean])): Processor;
}
export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//// [tests/cases/conformance/jsdoc/jsdocVariadicInOverload.ts] ////

=== typeTagForMultipleVariableDeclarations.js ===
// based on code from unifiedjs/unified
class Node {}
>Node : Symbol(Node, Decl(typeTagForMultipleVariableDeclarations.js, 0, 0))

/**
* @template {Node | undefined} [ParseTree=undefined]
* Output of `parse` (optional).
* @template {Node | undefined} [HeadTree=undefined]
* Input for `run` (optional).
* @template {Node | undefined} [TailTree=undefined]
* Output for `run` (optional).
* @template {Node | undefined} [CompileTree=undefined]
* Input of `stringify` (optional).
* @template {string | undefined} [CompileResult=undefined]
* Output of `stringify` (optional).
*/
export class Processor {
>Processor : Symbol(Processor, Decl(typeTagForMultipleVariableDeclarations.js, 1, 13))

/**
* @overload
* @param {string | null | undefined} [preset]
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
*
* @template {Array<unknown>} [Parameters=[]]
* @template {Node | string | undefined} [Input=undefined]
* @template [Output=Input]
* @overload
* @param {number} plugin
* @param {...(Parameters | [boolean])} parameters
* @returns {Processor}
*
* @param {string | number | boolean | null | undefined} value
* Usable value.
* @param {...unknown} parameters
* Parameters, when a plugin is given as a usable value.
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
* Current processor.
*/
use(value, ...parameters) {
>use : Symbol(use, Decl(typeTagForMultipleVariableDeclarations.js, 16, 6), Decl(typeTagForMultipleVariableDeclarations.js, 23, 6), Decl(typeTagForMultipleVariableDeclarations.js, 14, 24))
>value : Symbol(value, Decl(typeTagForMultipleVariableDeclarations.js, 35, 6))
>parameters : Symbol(parameters, Decl(typeTagForMultipleVariableDeclarations.js, 35, 12))

return this;
>this : Symbol(Processor, Decl(typeTagForMultipleVariableDeclarations.js, 1, 13))
}
}
var p = new Processor();
>p : Symbol(p, Decl(typeTagForMultipleVariableDeclarations.js, 39, 3))
>Processor : Symbol(Processor, Decl(typeTagForMultipleVariableDeclarations.js, 1, 13))

var x = 1, y = 2, z = 3;
>x : Symbol(x, Decl(typeTagForMultipleVariableDeclarations.js, 40, 3))
>y : Symbol(y, Decl(typeTagForMultipleVariableDeclarations.js, 40, 10))
>z : Symbol(z, Decl(typeTagForMultipleVariableDeclarations.js, 40, 17))

p.use(x, y, z);
>p.use : Symbol(use, Decl(typeTagForMultipleVariableDeclarations.js, 16, 6), Decl(typeTagForMultipleVariableDeclarations.js, 23, 6), Decl(typeTagForMultipleVariableDeclarations.js, 14, 24))
>p : Symbol(p, Decl(typeTagForMultipleVariableDeclarations.js, 39, 3))
>use : Symbol(use, Decl(typeTagForMultipleVariableDeclarations.js, 16, 6), Decl(typeTagForMultipleVariableDeclarations.js, 23, 6), Decl(typeTagForMultipleVariableDeclarations.js, 14, 24))
>x : Symbol(x, Decl(typeTagForMultipleVariableDeclarations.js, 40, 3))
>y : Symbol(y, Decl(typeTagForMultipleVariableDeclarations.js, 40, 10))
>z : Symbol(z, Decl(typeTagForMultipleVariableDeclarations.js, 40, 17))

Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//// [tests/cases/conformance/jsdoc/jsdocVariadicInOverload.ts] ////

=== typeTagForMultipleVariableDeclarations.js ===
// based on code from unifiedjs/unified
class Node {}
>Node : Node

/**
* @template {Node | undefined} [ParseTree=undefined]
* Output of `parse` (optional).
* @template {Node | undefined} [HeadTree=undefined]
* Input for `run` (optional).
* @template {Node | undefined} [TailTree=undefined]
* Output for `run` (optional).
* @template {Node | undefined} [CompileTree=undefined]
* Input of `stringify` (optional).
* @template {string | undefined} [CompileResult=undefined]
* Output of `stringify` (optional).
*/
export class Processor {
>Processor : Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>

/**
* @overload
* @param {string | null | undefined} [preset]
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
*
* @template {Array<unknown>} [Parameters=[]]
* @template {Node | string | undefined} [Input=undefined]
* @template [Output=Input]
* @overload
* @param {number} plugin
* @param {...(Parameters | [boolean])} parameters
* @returns {Processor}
*
* @param {string | number | boolean | null | undefined} value
* Usable value.
* @param {...unknown} parameters
* Parameters, when a plugin is given as a usable value.
* @returns {Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>}
* Current processor.
*/
use(value, ...parameters) {
>use : { (preset?: string): Processor<ParseTree, HeadTree, TailTree, CompileTree, CompileResult>; <Parameters extends unknown[] = [], Input extends string | Node = undefined, Output = Input>(plugin: number, ...parameters: Parameters | [boolean]): Processor<undefined, undefined, undefined, undefined, undefined>; }
>value : string | number | boolean
>parameters : unknown[]

return this;
>this : this
}
}
var p = new Processor();
>p : Processor<undefined, undefined, undefined, undefined, undefined>
>new Processor() : Processor<undefined, undefined, undefined, undefined, undefined>
>Processor : typeof Processor

var x = 1, y = 2, z = 3;
>x : number
>1 : 1
>y : number
>2 : 2
>z : number
>3 : 3

p.use(x, y, z);
>p.use(x, y, z) : Processor<undefined, undefined, undefined, undefined, undefined>
>p.use : { (preset?: string): Processor<undefined, undefined, undefined, undefined, undefined>; <Parameters extends unknown[] = [], Input extends string | Node = undefined, Output = Input>(plugin: number, ...parameters: Parameters | [boolean]): Processor<undefined, undefined, undefined, undefined, undefined>; }
>p : Processor<undefined, undefined, undefined, undefined, undefined>
>use : { (preset?: string): Processor<undefined, undefined, undefined, undefined, undefined>; <Parameters extends unknown[] = [], Input extends string | Node = undefined, Output = Input>(plugin: number, ...parameters: Parameters | [boolean]): Processor<undefined, undefined, undefined, undefined, undefined>; }
>x : number
>y : number
>z : number

Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
callbackTagVariadicType.js(9,18): error TS2554: Expected 1 arguments, but got 2.
callbackTagVariadicType.js(3,4): error TS2370: A rest parameter must be of an array type.
callbackTagVariadicType.js(9,13): error TS2345: Argument of type '["a", "b"]' is not assignable to parameter of type 'string'.


==== callbackTagVariadicType.js (1 errors) ====
==== callbackTagVariadicType.js (2 errors) ====
/**
* @callback Foo
* @param {...string} args
~~~~~~~~~~~~~~~~~~~~~~~
Copy link
Member Author

Choose a reason for hiding this comment

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

this shows the old, still unsupported semantics where the parameter args becomes a rest parameter and the type string becomes string[]. Only the first happens now, based on seeing how a real person (Titus Woormer) wrote overloads.

* @returns {number}
~~~
!!! error TS2370: A rest parameter must be of an array type.
*/

/** @type {Foo} */
export const x = () => 1
var res = x('a', 'b')
~~~
!!! error TS2554: Expected 1 arguments, but got 2.
~~~~~~~~
!!! error TS2345: Argument of type '["a", "b"]' is not assignable to parameter of type 'string'.

Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var res = (0, exports.x)('a', 'b');


//// [callbackTagVariadicType.d.ts]
export type Foo = (args: string[]) => number;
export type Foo = (...args: string) => number;
/**
* @callback Foo
* @param {...string} args
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@


//// [callbackTagVariadicType.d.ts]
+export type Foo = (args: string[]) => number;
+export type Foo = (...args: string) => number;
/**
* @callback Foo
* @param {...string} args
Expand Down
Loading
Loading