diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index da13fcb4391..7c5f2108c1e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2116,6 +2116,10 @@ namespace ts { result = addRange(result, getJSDocParameterTags(node as ParameterDeclaration)); break; } + if (node.kind === SyntaxKind.TypeParameter) { + result = addRange(result, getJSDocTypeParameterTags(node as TypeParameterDeclaration)); + break; + } node = getNextJSDocCommentLocation(node); } return result || emptyArray; @@ -4994,15 +4998,14 @@ namespace ts { /** * Gets the JSDoc parameter tags for the node if present. * - * @remarks Returns any JSDoc param tag that matches the provided + * @remarks Returns any JSDoc param tag whose name matches the provided * parameter, whether a param tag on a containing function * expression, or a param tag on a variable declaration whose * initializer is the containing function. The tags closest to the * node are returned first, so in the previous example, the param * tag on the containing function expression would be first. * - * Does not return tags for binding patterns, because JSDoc matches - * parameters by name and binding patterns do not have a name. + * For binding patterns, parameter tags are matched by position. */ export function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray { if (param.name) { @@ -5023,6 +5026,22 @@ namespace ts { return emptyArray; } + /** + * Gets the JSDoc type parameter tags for the node if present. + * + * @remarks Returns any JSDoc template tag whose names match the provided + * parameter, whether a template tag on a containing function + * expression, or a template tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the template + * tag on the containing function expression would be first. + */ + export function getJSDocTypeParameterTags(param: TypeParameterDeclaration): ReadonlyArray { + const name = param.name.escapedText; + return getJSDocTags(param.parent).filter((tag): tag is JSDocTemplateTag => + isJSDocTemplateTag(tag) && tag.typeParameters.some(tp => tp.name.escapedText === name)); + } + /** * Return true if the node has JSDoc parameter tags. * diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 5211b244e21..b6174be75e0 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -591,6 +591,6 @@ namespace ts.SignatureHelp { const param = checker.typeParameterToDeclaration(typeParameter, enclosingDeclaration)!; printer.writeNode(EmitHint.Unspecified, param, sourceFile, writer); }); - return { name: typeParameter.symbol.name, documentation: emptyArray, displayParts, isOptional: false }; + return { name: typeParameter.symbol.name, documentation: typeParameter.symbol.getDocumentationComment(checker), displayParts, isOptional: false }; } } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index fd291c5387f..d34298c59d5 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3208,17 +3208,27 @@ declare namespace ts { /** * Gets the JSDoc parameter tags for the node if present. * - * @remarks Returns any JSDoc param tag that matches the provided + * @remarks Returns any JSDoc param tag whose name matches the provided * parameter, whether a param tag on a containing function * expression, or a param tag on a variable declaration whose * initializer is the containing function. The tags closest to the * node are returned first, so in the previous example, the param * tag on the containing function expression would be first. * - * Does not return tags for binding patterns, because JSDoc matches - * parameters by name and binding patterns do not have a name. + * For binding patterns, parameter tags are matched by position. */ function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray; + /** + * Gets the JSDoc type parameter tags for the node if present. + * + * @remarks Returns any JSDoc template tag whose names match the provided + * parameter, whether a template tag on a containing function + * expression, or a template tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the template + * tag on the containing function expression would be first. + */ + function getJSDocTypeParameterTags(param: TypeParameterDeclaration): ReadonlyArray; /** * Return true if the node has JSDoc parameter tags. * diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 852ca173b33..2a1a44d54f2 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3208,17 +3208,27 @@ declare namespace ts { /** * Gets the JSDoc parameter tags for the node if present. * - * @remarks Returns any JSDoc param tag that matches the provided + * @remarks Returns any JSDoc param tag whose name matches the provided * parameter, whether a param tag on a containing function * expression, or a param tag on a variable declaration whose * initializer is the containing function. The tags closest to the * node are returned first, so in the previous example, the param * tag on the containing function expression would be first. * - * Does not return tags for binding patterns, because JSDoc matches - * parameters by name and binding patterns do not have a name. + * For binding patterns, parameter tags are matched by position. */ function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray; + /** + * Gets the JSDoc type parameter tags for the node if present. + * + * @remarks Returns any JSDoc template tag whose names match the provided + * parameter, whether a template tag on a containing function + * expression, or a template tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the template + * tag on the containing function expression would be first. + */ + function getJSDocTypeParameterTags(param: TypeParameterDeclaration): ReadonlyArray; /** * Return true if the node has JSDoc parameter tags. * diff --git a/tests/cases/fourslash/signatureHelpTypeArguments2.ts b/tests/cases/fourslash/signatureHelpTypeArguments2.ts new file mode 100644 index 00000000000..6d39e6e8870 --- /dev/null +++ b/tests/cases/fourslash/signatureHelpTypeArguments2.ts @@ -0,0 +1,37 @@ +/// + +/////** some documentation +//// * @template T some documentation 2 +//// * @template W +//// * @template U,V others +//// * @param a ok +//// * @param b not ok +//// */ +////function f(a: number, b: string, c: boolean): void { } +////f(a: number, b: string, c: boolean): void", + parameterName, + parameterSpan: parameterName, + docComment: "some documentation", + parameterDocComment, + tags: [{ name: "template", text: "T some documentation 2" }, + { name: "template", text: "W" }, + { name: "template", text: "U, V others" }, + { name: "param", text: "a ok" }, + { name: "param", text: "b not ok" }] + } +} + +verify.signatureHelp( + build("f0", "T", "some documentation 2"), + build("f1", "U", "others"), + build("f2", "V", "others"), + build("f3", "W", ""), +);