Skip to content

Commit 6c3da9c

Browse files
committed
Handle nested @param comments with unions
Closes #1876
1 parent 1e0e38c commit 6c3da9c

File tree

5 files changed

+78
-17
lines changed

5 files changed

+78
-17
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Unreleased
22

3+
### Features
4+
5+
- Support copying `@param` comments for nested members that target union and intersection types, #1876.
6+
37
## v0.22.12 (2022-02-20)
48

59
### Features

src/lib/converter/plugins/CommentPlugin.ts

+26-15
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
} from "../factories/comment";
1919
import { Converter } from "../converter";
2020
import type { Context } from "../context";
21-
import { ReflectionType, SourceReference } from "../../models";
21+
import { ReflectionType, SourceReference, TypeVisitor } from "../../models";
2222
import {
2323
BindOption,
2424
filterMap,
@@ -455,21 +455,32 @@ export class CommentPlugin extends ConverterComponent {
455455

456456
// Moves tags like `@param foo.bar docs for bar` into the `bar` property of the `foo` parameter.
457457
function moveNestedParamTags(comment: Comment, parameter: ParameterReflection) {
458-
if (parameter.type instanceof ReflectionType) {
459-
const tags = comment.tags.filter(
460-
(t) =>
461-
t.tagName === "param" &&
462-
t.paramName.startsWith(`${parameter.name}.`)
463-
);
458+
const visitor: Partial<TypeVisitor> = {
459+
reflection(target) {
460+
const tags = comment.tags.filter(
461+
(t) =>
462+
t.tagName === "param" &&
463+
t.paramName.startsWith(`${parameter.name}.`)
464+
);
464465

465-
for (const tag of tags) {
466-
const path = tag.paramName.split(".");
467-
path.shift();
468-
const child = parameter.type.declaration.getChildByName(path);
466+
for (const tag of tags) {
467+
const path = tag.paramName.split(".");
468+
path.shift();
469+
const child = target.declaration.getChildByName(path);
469470

470-
if (child && !child.comment) {
471-
child.comment = new Comment(tag.text);
471+
if (child && !child.comment) {
472+
child.comment = new Comment(tag.text);
473+
}
472474
}
473-
}
474-
}
475+
},
476+
// #1876, also do this for unions/intersections.
477+
union(u) {
478+
u.types.forEach((t) => t.visit(visitor));
479+
},
480+
intersection(i) {
481+
i.types.forEach((t) => t.visit(visitor));
482+
},
483+
};
484+
485+
parameter.type?.visit(visitor);
475486
}

src/lib/models/types.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ export abstract class Type {
2121
/**
2222
* Visit this type, returning the value returned by the visitor.
2323
*/
24-
visit<T>(visitor: TypeVisitor<T>): T {
25-
return visitor[this.type](this as never);
24+
visit<T>(visitor: TypeVisitor<T>): T;
25+
visit<T>(visitor: Partial<TypeVisitor<T>>): T | undefined;
26+
visit(visitor: Partial<TypeVisitor<unknown>>): unknown {
27+
return visitor[this.type]?.(this as never);
2628
}
2729
}
2830

src/test/converter2/issues/gh1876.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* @param options.min Nested
3+
*/
4+
export function foo(options?: number | { min?: number }): number {
5+
return 0;
6+
}
7+
8+
/**
9+
* @param options.min Nested
10+
*/
11+
export function bar(options: { min: number; max: number } | { min: string }) {
12+
return 0;
13+
}

src/test/issueTests.ts

+31
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ReflectionType,
99
Comment,
1010
CommentTag,
11+
UnionType,
1112
} from "../lib/models";
1213

1314
function query(project: ProjectReflection, name: string) {
@@ -290,4 +291,34 @@ export const issueTests: {
290291
ok(project.children![0].kind === ReflectionKind.Reference);
291292
ok(project.children![1].kind !== ReflectionKind.Reference);
292293
},
294+
295+
gh1876(project) {
296+
const foo = query(project, "foo");
297+
const fooSig = foo.signatures?.[0].parameters?.[0];
298+
ok(fooSig);
299+
ok(fooSig.type instanceof UnionType);
300+
ok(fooSig.type.types[1] instanceof ReflectionType);
301+
equal(
302+
fooSig.type.types[1].declaration.getChildByName("min")?.comment
303+
?.shortText,
304+
"Nested\n"
305+
);
306+
307+
const bar = query(project, "bar");
308+
const barSig = bar.signatures?.[0].parameters?.[0];
309+
ok(barSig);
310+
ok(barSig.type instanceof UnionType);
311+
ok(barSig.type.types[0] instanceof ReflectionType);
312+
ok(barSig.type.types[1] instanceof ReflectionType);
313+
equal(
314+
barSig.type.types[0].declaration.getChildByName("min")?.comment
315+
?.shortText,
316+
"Nested\n"
317+
);
318+
equal(
319+
barSig.type.types[1].declaration.getChildByName("min")?.comment
320+
?.shortText,
321+
"Nested\n"
322+
);
323+
},
293324
};

0 commit comments

Comments
 (0)