Skip to content

Commit

Permalink
Handle nested @param comments with unions
Browse files Browse the repository at this point in the history
Closes #1876
  • Loading branch information
Gerrit0 committed Mar 6, 2022
1 parent 1e0e38c commit 6c3da9c
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 17 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,9 @@
# Unreleased

### Features

- Support copying `@param` comments for nested members that target union and intersection types, #1876.

## v0.22.12 (2022-02-20)

### Features
Expand Down
41 changes: 26 additions & 15 deletions src/lib/converter/plugins/CommentPlugin.ts
Expand Up @@ -18,7 +18,7 @@ import {
} from "../factories/comment";
import { Converter } from "../converter";
import type { Context } from "../context";
import { ReflectionType, SourceReference } from "../../models";
import { ReflectionType, SourceReference, TypeVisitor } from "../../models";
import {
BindOption,
filterMap,
Expand Down Expand Up @@ -455,21 +455,32 @@ export class CommentPlugin extends ConverterComponent {

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

for (const tag of tags) {
const path = tag.paramName.split(".");
path.shift();
const child = parameter.type.declaration.getChildByName(path);
for (const tag of tags) {
const path = tag.paramName.split(".");
path.shift();
const child = target.declaration.getChildByName(path);

if (child && !child.comment) {
child.comment = new Comment(tag.text);
if (child && !child.comment) {
child.comment = new Comment(tag.text);
}
}
}
}
},
// #1876, also do this for unions/intersections.
union(u) {
u.types.forEach((t) => t.visit(visitor));
},
intersection(i) {
i.types.forEach((t) => t.visit(visitor));
},
};

parameter.type?.visit(visitor);
}
6 changes: 4 additions & 2 deletions src/lib/models/types.ts
Expand Up @@ -21,8 +21,10 @@ export abstract class Type {
/**
* Visit this type, returning the value returned by the visitor.
*/
visit<T>(visitor: TypeVisitor<T>): T {
return visitor[this.type](this as never);
visit<T>(visitor: TypeVisitor<T>): T;
visit<T>(visitor: Partial<TypeVisitor<T>>): T | undefined;
visit(visitor: Partial<TypeVisitor<unknown>>): unknown {
return visitor[this.type]?.(this as never);
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/test/converter2/issues/gh1876.ts
@@ -0,0 +1,13 @@
/**
* @param options.min Nested
*/
export function foo(options?: number | { min?: number }): number {
return 0;
}

/**
* @param options.min Nested
*/
export function bar(options: { min: number; max: number } | { min: string }) {
return 0;
}
31 changes: 31 additions & 0 deletions src/test/issueTests.ts
Expand Up @@ -8,6 +8,7 @@ import {
ReflectionType,
Comment,
CommentTag,
UnionType,
} from "../lib/models";

function query(project: ProjectReflection, name: string) {
Expand Down Expand Up @@ -290,4 +291,34 @@ export const issueTests: {
ok(project.children![0].kind === ReflectionKind.Reference);
ok(project.children![1].kind !== ReflectionKind.Reference);
},

gh1876(project) {
const foo = query(project, "foo");
const fooSig = foo.signatures?.[0].parameters?.[0];
ok(fooSig);
ok(fooSig.type instanceof UnionType);
ok(fooSig.type.types[1] instanceof ReflectionType);
equal(
fooSig.type.types[1].declaration.getChildByName("min")?.comment
?.shortText,
"Nested\n"
);

const bar = query(project, "bar");
const barSig = bar.signatures?.[0].parameters?.[0];
ok(barSig);
ok(barSig.type instanceof UnionType);
ok(barSig.type.types[0] instanceof ReflectionType);
ok(barSig.type.types[1] instanceof ReflectionType);
equal(
barSig.type.types[0].declaration.getChildByName("min")?.comment
?.shortText,
"Nested\n"
);
equal(
barSig.type.types[1].declaration.getChildByName("min")?.comment
?.shortText,
"Nested\n"
);
},
};

0 comments on commit 6c3da9c

Please sign in to comment.