Skip to content

Commit 03426c3

Browse files
committed
Keep type alias comments on the alias
Resolves #2372
1 parent 7715f14 commit 03426c3

File tree

9 files changed

+107
-58
lines changed

9 files changed

+107
-58
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
### Bug Fixes
1515

1616
- Methods which return function types no longer have duplicated comments, #2336.
17+
- Comments on function-like type aliases will now show up under the type alias, rather than nested within the type declaration, #2372.
1718
- Fix crash when converting some complicated union/intersection types, #2451.
1819
- Navigation triangle markers should no longer display on a separate line with some font settings, #2457.
1920
- `@group` and `@category` organization is now applied later to allow inherited comments to create groups/categories, #2459.

src/lib/converter/plugins/CommentPlugin.ts

+21-7
Original file line numberDiff line numberDiff line change
@@ -387,13 +387,6 @@ export class CommentPlugin extends ConverterComponent {
387387
? undefined
388388
: reflection.comment;
389389

390-
// Since this reflection has signatures, remove the comment from the parent
391-
// reflection. This is important so that in type aliases we don't end up with
392-
// a comment rendered twice.
393-
if (!reflection.kindOf(ReflectionKind.ClassOrInterface)) {
394-
delete reflection.comment;
395-
}
396-
397390
for (const signature of signatures) {
398391
const childComment = (signature.comment ||= comment?.clone());
399392
if (!childComment) continue;
@@ -450,6 +443,27 @@ export class CommentPlugin extends ConverterComponent {
450443
childComment?.removeTags("@typeParam");
451444
childComment?.removeTags("@template");
452445
}
446+
447+
// Since this reflection has signatures, we need to remove the comment from the non-primary
448+
// declaration location. For functions, this means removing it from the Function reflection.
449+
// For type aliases, this means removing it from reflection.type.declaration.
450+
// This is important so that in type aliases we don't end up with a comment rendered twice.
451+
if (
452+
reflection.kindOf(
453+
ReflectionKind.FunctionOrMethod | ReflectionKind.Constructor,
454+
)
455+
) {
456+
delete reflection.comment;
457+
}
458+
if (reflection.kindOf(ReflectionKind.TypeAlias)) {
459+
reflection.comment?.removeTags("@param");
460+
reflection.comment?.removeTags("@typeParam");
461+
reflection.comment?.removeTags("@template");
462+
463+
for (const sig of signatures) {
464+
delete sig.comment;
465+
}
466+
}
453467
}
454468

455469
private removeExcludedTags(comment: Comment) {

src/lib/validation/documentation.ts

+24-6
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,35 @@ export function validateDocumentation(
5656
}
5757
}
5858

59+
// Type aliases own their comments, even if they're function-likes.
60+
// So if we're a type literal owned by a type alias, don't do anything.
61+
if (
62+
ref.kindOf(ReflectionKind.TypeLiteral) &&
63+
ref.parent?.kindOf(ReflectionKind.TypeAlias)
64+
) {
65+
toProcess.push(ref.parent);
66+
continue;
67+
}
68+
// Ditto for signatures on type aliases.
69+
if (
70+
ref.kindOf(ReflectionKind.CallSignature) &&
71+
ref.parent?.parent?.kindOf(ReflectionKind.TypeAlias)
72+
) {
73+
toProcess.push(ref.parent.parent);
74+
continue;
75+
}
76+
5977
if (ref instanceof DeclarationReflection) {
6078
const signatures =
6179
ref.type instanceof ReflectionType
6280
? ref.type.declaration.getNonIndexSignatures()
6381
: ref.getNonIndexSignatures();
6482

6583
if (signatures.length) {
66-
// We maybe used to have a comment, but the comment plugin has removed it.
67-
// See CommentPlugin.onResolve. We've been asked to validate this reflection,
68-
// (it's probably a type alias) so we should validate that signatures all have
69-
// comments, but we shouldn't produce a warning here.
84+
// We've been asked to validate this reflection, so we should validate that
85+
// signatures all have comments, but we'll still have a comment here because
86+
// type aliases always have their own comment.
7087
toProcess.push(...signatures);
71-
continue;
7288
}
7389
}
7490

@@ -80,7 +96,9 @@ export function validateDocumentation(
8096
}
8197

8298
logger.warn(
83-
`${ref.getFriendlyFullName()}, defined in ${nicePath(
99+
`${ref.getFriendlyFullName()} (${
100+
ReflectionKind[ref.kind]
101+
}), defined in ${nicePath(
84102
symbolId.fileName,
85103
)}, does not have any documentation.`,
86104
);

src/test/converter/alias/specs.json

+8-8
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@
165165
"variant": "declaration",
166166
"kind": 2097152,
167167
"flags": {},
168+
"comment": {
169+
"summary": [
170+
{
171+
"kind": "text",
172+
"text": "A type that describes a compare function, e.g. for array.sort()."
173+
}
174+
]
175+
},
168176
"sources": [
169177
{
170178
"fileName": "alias.ts",
@@ -205,14 +213,6 @@
205213
"variant": "signature",
206214
"kind": 4096,
207215
"flags": {},
208-
"comment": {
209-
"summary": [
210-
{
211-
"kind": "text",
212-
"text": "A type that describes a compare function, e.g. for array.sort()."
213-
}
214-
]
215-
},
216216
"parameters": [
217217
{
218218
"id": 4,

src/test/converter/js/specs.json

+8-8
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,14 @@
685685
"variant": "declaration",
686686
"kind": 2097152,
687687
"flags": {},
688+
"comment": {
689+
"summary": [
690+
{
691+
"kind": "text",
692+
"text": "even though in the same comment block"
693+
}
694+
]
695+
},
688696
"sources": [
689697
{
690698
"fileName": "index.js",
@@ -716,14 +724,6 @@
716724
"variant": "signature",
717725
"kind": 4096,
718726
"flags": {},
719-
"comment": {
720-
"summary": [
721-
{
722-
"kind": "text",
723-
"text": "even though in the same comment block"
724-
}
725-
]
726-
},
727727
"type": {
728728
"type": "intrinsic",
729729
"name": "any"

src/test/converter/mixin/specs.json

+16-16
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,14 @@
12311231
"variant": "declaration",
12321232
"kind": 2097152,
12331233
"flags": {},
1234+
"comment": {
1235+
"summary": [
1236+
{
1237+
"kind": "text",
1238+
"text": "Any constructor function"
1239+
}
1240+
]
1241+
},
12341242
"sources": [
12351243
{
12361244
"fileName": "mixin.ts",
@@ -1275,14 +1283,6 @@
12751283
"variant": "signature",
12761284
"kind": 16384,
12771285
"flags": {},
1278-
"comment": {
1279-
"summary": [
1280-
{
1281-
"kind": "text",
1282-
"text": "Any constructor function"
1283-
}
1284-
]
1285-
},
12861286
"parameters": [
12871287
{
12881288
"id": 9,
@@ -1318,6 +1318,14 @@
13181318
"variant": "declaration",
13191319
"kind": 2097152,
13201320
"flags": {},
1321+
"comment": {
1322+
"summary": [
1323+
{
1324+
"kind": "text",
1325+
"text": "Any function"
1326+
}
1327+
]
1328+
},
13211329
"sources": [
13221330
{
13231331
"fileName": "mixin.ts",
@@ -1362,14 +1370,6 @@
13621370
"variant": "signature",
13631371
"kind": 4096,
13641372
"flags": {},
1365-
"comment": {
1366-
"summary": [
1367-
{
1368-
"kind": "text",
1369-
"text": "Any function"
1370-
}
1371-
]
1372-
},
13731373
"parameters": [
13741374
{
13751375
"id": 4,

src/test/converter2/issues/gh2372.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* The signature for a function acting as an event handler.
3+
* @param e Param should work
4+
*/
5+
export type EventHandler = (e: Event) => void;

src/test/issues.c2.test.ts

+20-9
Original file line numberDiff line numberDiff line change
@@ -414,16 +414,14 @@ describe("Issue Tests", () => {
414414
it("#1734", () => {
415415
const project = convert();
416416
const alias = query(project, "Foo");
417-
const type = alias.type;
418-
ok(type instanceof ReflectionType);
419417

420418
const expectedComment = new Comment();
421419
expectedComment.blockTags = [
422420
new CommentTag("@asdf", [
423421
{ kind: "text", text: "Some example text" },
424422
]),
425423
];
426-
equal(type.declaration.signatures?.[0].comment, expectedComment);
424+
equal(alias.comment, expectedComment);
427425
});
428426

429427
it("#1745", () => {
@@ -565,12 +563,9 @@ describe("Issue Tests", () => {
565563
equal(Type1.type?.type, "reflection" as const);
566564
equal(Type2.type?.type, "reflection" as const);
567565

566+
equal(Type1.comment, new Comment([{ kind: "text", text: "On Tag" }]));
568567
equal(
569-
Type1.type.declaration.signatures?.[0].comment,
570-
new Comment([{ kind: "text", text: "On Tag" }]),
571-
);
572-
equal(
573-
Type2.type.declaration.signatures?.[0].comment,
568+
Type2.comment,
574569
new Comment([{ kind: "text", text: "Some type 2." }]),
575570
);
576571
});
@@ -579,7 +574,7 @@ describe("Issue Tests", () => {
579574
const project = convert();
580575
app.validate(project);
581576
logger.expectMessage(
582-
"warn: UnDocFn.__type, defined in */gh1898.ts, does not have any documentation.",
577+
"warn: UnDocFn (TypeAlias), defined in */gh1898.ts, does not have any documentation.",
583578
);
584579
});
585580

@@ -1166,6 +1161,22 @@ describe("Issue Tests", () => {
11661161
equal(ns?.children?.map((c) => c.name), ["property"]);
11671162
});
11681163

1164+
it("Puts delegate type alias comments on the type alias #2372", () => {
1165+
const project = convert();
1166+
equal(
1167+
getComment(project, "EventHandler"),
1168+
"The signature for a function acting as an event handler.",
1169+
);
1170+
1171+
const typeSig = query(project, "EventHandler").type?.visit({
1172+
reflection(r) {
1173+
return r.declaration.signatures![0];
1174+
},
1175+
});
1176+
1177+
equal(Comment.combineDisplayParts(typeSig?.comment?.summary), "");
1178+
});
1179+
11691180
it("Handles spaces in JSDoc default parameter names #2384", () => {
11701181
const project = convert();
11711182
const Typed = query(project, "Typed");

src/test/validation.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ describe("validateDocumentation", () => {
172172
validateDocumentation(project, logger, ["Function"]);
173173

174174
logger.expectMessage(
175-
"warn: bar, defined in */function.ts, does not have any documentation.",
175+
"warn: bar (CallSignature), defined in */function.ts, does not have any documentation.",
176176
);
177177
logger.expectNoOtherMessages();
178178
});
@@ -183,7 +183,7 @@ describe("validateDocumentation", () => {
183183
validateDocumentation(project, logger, ["Accessor"]);
184184

185185
logger.expectMessage(
186-
"warn: Foo.foo, defined in */getSignature.ts, does not have any documentation.",
186+
"warn: Foo.foo (GetSignature), defined in */getSignature.ts, does not have any documentation.",
187187
);
188188
logger.expectNoOtherMessages();
189189
});
@@ -194,7 +194,7 @@ describe("validateDocumentation", () => {
194194
validateDocumentation(project, logger, ["Constructor"]);
195195

196196
logger.expectMessage(
197-
"warn: Foo.constructor, defined in */class.ts, does not have any documentation.",
197+
"warn: Foo.constructor (ConstructorSignature), defined in */class.ts, does not have any documentation.",
198198
);
199199
logger.expectNoOtherMessages();
200200
});
@@ -205,7 +205,7 @@ describe("validateDocumentation", () => {
205205
validateDocumentation(project, logger, ["Method"]);
206206

207207
logger.expectMessage(
208-
"warn: Foo.method, defined in */interface.ts, does not have any documentation.",
208+
"warn: Foo.method (CallSignature), defined in */interface.ts, does not have any documentation.",
209209
);
210210
logger.expectNoOtherMessages();
211211
});

0 commit comments

Comments
 (0)