diff --git a/CHANGELOG.md b/CHANGELOG.md index f3e554f22..f50c88131 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,11 @@ ### Currently Broken - Comment rendering +- Inline `@inheritDoc` tags ### Breaking Changes -- TODO: The behavior of `@inheritDoc` has changed... describe how. +- TODO: The behavior of `@inheritDoc` has changed... describe how - `reflection.decorates`, `reflection.decorators`, and their corresponding interfaces have been removed as no code in TypeDoc used them. - The shape of the `Comment` class has changed significantly to support multiple tag kinds. - Listeners to `Converter.EVENT_CREATE_TYPE_PARAMETER` and `Converter.EVENT_CREATE_DECLARATION` will now never be passed a `ts.Node` as their third argument. diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index 86fc813ff..2c5a7dcc1 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -22,19 +22,19 @@ const wantedKinds: Record = { ts.SyntaxKind.PropertyAssignment, ], [ReflectionKind.Variable]: [ts.SyntaxKind.VariableDeclaration], - // Intentionally nothing here, comments will be placed on signatures. - [ReflectionKind.Function]: [], + [ReflectionKind.Function]: [ts.SyntaxKind.FunctionDeclaration], [ReflectionKind.Class]: [ts.SyntaxKind.ClassDeclaration], [ReflectionKind.Interface]: [ts.SyntaxKind.InterfaceDeclaration], - // Intentionally nothing here, comments will be placed on signatures. - [ReflectionKind.Constructor]: [], + [ReflectionKind.Constructor]: [ts.SyntaxKind.Constructor], [ReflectionKind.Property]: [ ts.SyntaxKind.PropertyDeclaration, ts.SyntaxKind.PropertySignature, ts.SyntaxKind.BinaryExpression, ], - // Intentionally nothing here, comments will be placed on signatures. - [ReflectionKind.Method]: [], + [ReflectionKind.Method]: [ + ts.SyntaxKind.FunctionDeclaration, + ts.SyntaxKind.MethodDeclaration, + ], [ReflectionKind.CallSignature]: [ ts.SyntaxKind.FunctionDeclaration, ts.SyntaxKind.VariableDeclaration, @@ -80,6 +80,16 @@ export function discoverComment( continue; } + // Special behavior here! We temporarily put the implementation comment + // on the reflection which contains all the signatures. This lets us pull + // the comment on the implementation if some signature does not have a comment. + if ( + kind & ReflectionKind.ContainsCallSignatures && + !(node as ts.FunctionDeclaration).body + ) { + continue; + } + const comments = ts.getLeadingCommentRanges(text, node.pos); if (reverse) { diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index fc20e2c47..7d014bb74 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -177,7 +177,7 @@ export class Context { "@module", "@inheritDoc", ]), - inlineTags: new Set(["@link", "@inheritDoc"]), + inlineTags: new Set(["@link", "@inheritDoc", "@label"]), modifierTags: new Set([ // TSDoc standard "@public", diff --git a/src/lib/converter/plugins/CategoryPlugin.ts b/src/lib/converter/plugins/CategoryPlugin.ts index f469ccb09..59f1ea0c0 100644 --- a/src/lib/converter/plugins/CategoryPlugin.ts +++ b/src/lib/converter/plugins/CategoryPlugin.ts @@ -2,14 +2,13 @@ import { Reflection, ContainerReflection, DeclarationReflection, - CommentTag, Comment, } from "../../models"; import { ReflectionCategory } from "../../models/ReflectionCategory"; import { Component, ConverterComponent } from "../components"; import { Converter } from "../converter"; import type { Context } from "../context"; -import { BindOption } from "../../utils"; +import { BindOption, removeIf } from "../../utils"; /** * A handler that sorts and categorizes the found reflections in the resolving phase. @@ -178,46 +177,34 @@ export class CategoryPlugin extends ConverterComponent { * @returns The category the reflection belongs to */ static getCategories(reflection: DeclarationReflection) { - function extractCategoryTag(comment: Comment | undefined) { - const categories = new Set(); - if (!comment) return categories; - - const tags = comment.blockTags; - const commentTags: CommentTag[] = []; - tags.forEach((tag) => { - if (tag.tag !== "@category") { - commentTags.push(tag); - return; - } - const text = Comment.combineDisplayParts(tag.content).trim(); - if (!text) { - return; + const categories = new Set(); + function extractCategoryTags(comment: Comment | undefined) { + if (!comment) return; + removeIf(comment.blockTags, (tag) => { + if (tag.tag === "@category") { + categories.add( + Comment.combineDisplayParts(tag.content).trim() + ); + + return true; } - categories.add(text); + return false; }); - comment.blockTags = commentTags; - return categories; } - let categories = new Set(); - - if (reflection.comment) { - categories = extractCategoryTag(reflection.comment); - } else if (reflection.signatures) { - for (const sig of reflection.signatures) { - for (const cat of extractCategoryTag(sig.comment)) { - categories.add(cat); - } - } + extractCategoryTags(reflection.comment); + for (const sig of reflection.getNonIndexSignatures()) { + extractCategoryTags(sig.comment); } if (reflection.type?.type === "reflection") { - reflection.type.declaration.comment?.removeTags("@category"); - reflection.type.declaration.signatures?.forEach((s) => - s.comment?.removeTags("@category") - ); + extractCategoryTags(reflection.type.declaration.comment); + for (const sig of reflection.type.declaration.getNonIndexSignatures()) { + extractCategoryTags(sig.comment); + } } + categories.delete(""); return categories; } diff --git a/src/lib/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index 7ae4c536a..5904c46d9 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -83,8 +83,6 @@ export class SourcePlugin extends ConverterComponent { return; } - if (reflection.name === "constructor") debugger; - let declarations: ts.Declaration[] = []; if (reflection.kind === ReflectionKind.Constructor) { for (const decl of symbol.declarations || []) { diff --git a/src/lib/models/reflections/kind.ts b/src/lib/models/reflections/kind.ts index 660ba0294..1a7077664 100644 --- a/src/lib/models/reflections/kind.ts +++ b/src/lib/models/reflections/kind.ts @@ -69,4 +69,10 @@ export namespace ReflectionKind { ReflectionKind.Property | ReflectionKind.Method | ReflectionKind.Constructor; + + /** @internal */ + export const ContainsCallSignatures = + ReflectionKind.Constructor | + ReflectionKind.Function | + ReflectionKind.Method; } diff --git a/src/lib/output/themes/default/partials/navigation.tsx b/src/lib/output/themes/default/partials/navigation.tsx index 9a32ac6b2..63379a707 100644 --- a/src/lib/output/themes/default/partials/navigation.tsx +++ b/src/lib/output/themes/default/partials/navigation.tsx @@ -80,13 +80,6 @@ function secondaryNavigation(context: DefaultThemeRenderContext, props: PageEven return; } - // TODO: TypeDoc 0.21 did special things here. If there were more than 40 - // children of this page's parent, it only displayed this page's children. - // Otherwise, it displayed *everything*. For now, only display page children. - // It seems weird to do this according to a random hardcoded number. At the very - // least this should be added as a configurable flag, but maybe even the whole - // behavior should be configurable globally... - const pageNavigation = (
    {children diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index 74f33bfdd..b6efb82de 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -56,28 +56,22 @@ export const behaviorTests: Record< ]); }, // Disabled for now, pending https://github.com/TypeStrong/typedoc/issues/1809 - overloads_skip(project) { + overloads(project) { const foo = query(project, "foo"); - equal(foo.signatures?.length, 2); - - equal( - Comment.combineDisplayParts(foo.signatures[0].comment?.summary), - "Implementation comment" + const fooComments = foo.signatures?.map((sig) => + Comment.combineDisplayParts(sig.comment?.summary) ); - equal(foo.signatures[0].comment?.blockTags, []); + equal(fooComments, [ + "No arg comment\n{@label NO_ARGS}", + "{@inheritDoc (foo:NO_ARGS)}\n{@label WITH_X}", + ]); + equal(foo.comment, undefined); - equal( - Comment.combineDisplayParts(foo.signatures[1].comment?.summary), - "Overrides summary" + const bar = query(project, "bar"); + const barComments = bar.signatures?.map((sig) => + Comment.combineDisplayParts(sig.comment?.summary) ); - equal(foo.signatures[1].comment?.blockTags, []); - equal( - Comment.combineDisplayParts( - foo.signatures[1].parameters?.[0].comment?.summary - ), - "docs for x" - ); - - equal(foo.comment, undefined); + equal(barComments, ["Implementation comment", "Custom comment"]); + equal(bar.comment, undefined); }, }; diff --git a/src/test/converter2/behavior/overloads.ts b/src/test/converter2/behavior/overloads.ts index e55f2e73f..79c4aeb2e 100644 --- a/src/test/converter2/behavior/overloads.ts +++ b/src/test/converter2/behavior/overloads.ts @@ -12,3 +12,15 @@ export function foo(x: string): number; export function foo(x?: string): string | number { return x == null ? "" : x.length; } + +export function bar(): string; +/** + * Custom comment + */ +export function bar(x: string): string; +/** + * Implementation comment + */ +export function bar(x?: string) { + return x || ""; +}