From aa36d85329fa1f6ab93aa86e7405027fb8eb20f7 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 19 Mar 2023 10:29:02 -0600 Subject: [PATCH] Add support for TypeScript 5's `@overload` Ref: #2201 --- src/lib/converter/comments/discovery.ts | 17 +++++++++++++++++ src/lib/converter/symbols.ts | 9 ++------- src/lib/utils/options/sources/typedoc.ts | 7 ++++++- src/lib/utils/options/tsdoc-defaults.ts | 2 ++ src/test/behaviorTests.ts | 19 +++++++++++++++++++ src/test/converter2/behavior/overloadTags.js | 18 ++++++++++++++++++ tsdoc.json | 8 ++++++++ 7 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 src/test/converter2/behavior/overloadTags.js diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index 648c55866..0afac4d95 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -3,6 +3,7 @@ import { ReflectionKind } from "../../models"; import { assertNever, Logger } from "../../utils"; import { CommentStyle } from "../../utils/options/declaration"; import { nicePath } from "../../utils/paths"; +import { ok } from "assert"; // Note: This does NOT include JSDoc syntax kinds. This is important! // Comments from @typedef and @callback tags are handled specially by @@ -172,6 +173,22 @@ export function discoverSignatureComment( return; } + if (ts.isJSDocSignature(node)) { + const comment = node.parent.parent; + ok(ts.isJSDoc(comment)); + + return [ + node.getSourceFile(), + [ + { + kind: ts.SyntaxKind.MultiLineCommentTrivia, + pos: comment.pos, + end: comment.end, + }, + ], + ]; + } + const text = node.getSourceFile().text; const comments = collectCommentRanges( diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index f132799b2..4af17148b 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -422,13 +422,8 @@ function convertFunctionOrMethod( // Can't use zip here. We might have less declarations than signatures // or less signatures than declarations. - for (let i = 0; i < signatures.length; i++) { - createSignature( - scope, - ReflectionKind.CallSignature, - signatures[i], - declarations[i] - ); + for (const sig of signatures) { + createSignature(scope, ReflectionKind.CallSignature, sig); } } diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 04b402c49..cda052348 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -301,7 +301,12 @@ export function addTypeDocOptions(options: Pick) { name: "excludeTags", help: "Remove the listed block/modifier tags from doc comments.", type: ParameterType.Array, - defaultValue: ["@override", "@virtual", "@privateRemarks"], + defaultValue: [ + "@override", + "@virtual", + "@privateRemarks", + "@satisfies", + ], validate(value) { if (!Validation.validate([Array, Validation.isTagString], value)) { throw new Error( diff --git a/src/lib/utils/options/tsdoc-defaults.ts b/src/lib/utils/options/tsdoc-defaults.ts index 3cb561b7f..20fa7ea87 100644 --- a/src/lib/utils/options/tsdoc-defaults.ts +++ b/src/lib/utils/options/tsdoc-defaults.ts @@ -25,6 +25,7 @@ export const blockTags = [ "@callback", "@prop", "@property", + "@satisfies", ] as const; export const tsdocInlineTags = ["@link", "@inheritDoc", "@label"] as const; @@ -52,4 +53,5 @@ export const modifierTags = [ "@ignore", "@enum", "@event", + "@overload", ] as const; diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index ffca499d0..9d1c7995c 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -577,6 +577,25 @@ export const behaviorTests: { logger.expectNoOtherMessages(); }, + overloadTags(project) { + const printValue = query(project, "printValue"); + equal(printValue.signatures?.length, 2); + + const [first, second] = printValue.signatures; + + equal(first.parameters?.length, 1); + equal( + Comment.combineDisplayParts(first.parameters[0].comment?.summary), + "first docs" + ); + + equal(second.parameters?.length, 2); + equal( + Comment.combineDisplayParts(second.parameters[0].comment?.summary), + "second docs" + ); + }, + readonlyTag(project) { const title = query(project, "Book.title"); const author = query(project, "Book.author"); diff --git a/src/test/converter2/behavior/overloadTags.js b/src/test/converter2/behavior/overloadTags.js new file mode 100644 index 000000000..b083ca98a --- /dev/null +++ b/src/test/converter2/behavior/overloadTags.js @@ -0,0 +1,18 @@ +/** + * @overload + * @param {string} value first docs + * @return {void} + */ + +/** + * @overload + * @param {number} value second docs + * @param {number} [maximumFractionDigits] second docs + * @return {void} + */ + +/** + * @param {string | number} value impl docs + * @param {number} [maximumFractionDigits] impl docs + */ +export function printValue(value, maximumFractionDigits) {} diff --git a/tsdoc.json b/tsdoc.json index a189eb652..bad03fe52 100644 --- a/tsdoc.json +++ b/tsdoc.json @@ -74,6 +74,14 @@ { "tagName": "@protected", "syntaxKind": "modifier" + }, + { + "tagName": "@satisfies", + "syntaxKind": "block" + }, + { + "tagName": "@overload", + "syntaxKind": "modifier" } ] }