typedoc 0.25.3 → 0.25.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/lib/converter/comments/declarationReference.js +14 -14
  2. package/dist/lib/converter/comments/discovery.js +4 -2
  3. package/dist/lib/converter/comments/parser.js +56 -13
  4. package/dist/lib/converter/context.d.ts +0 -3
  5. package/dist/lib/converter/context.js +0 -3
  6. package/dist/lib/converter/converter.d.ts +0 -1
  7. package/dist/lib/converter/converter.js +0 -1
  8. package/dist/lib/converter/factories/signature.js +29 -3
  9. package/dist/lib/converter/plugins/CategoryPlugin.d.ts +0 -7
  10. package/dist/lib/converter/plugins/CategoryPlugin.js +6 -12
  11. package/dist/lib/converter/plugins/CommentPlugin.d.ts +1 -0
  12. package/dist/lib/converter/plugins/CommentPlugin.js +59 -29
  13. package/dist/lib/converter/plugins/GroupPlugin.d.ts +0 -7
  14. package/dist/lib/converter/plugins/GroupPlugin.js +7 -13
  15. package/dist/lib/converter/plugins/SourcePlugin.js +23 -0
  16. package/dist/lib/converter/plugins/TypePlugin.js +4 -1
  17. package/dist/lib/converter/symbols.js +56 -28
  18. package/dist/lib/converter/types.js +14 -10
  19. package/dist/lib/converter/utils/repository.js +4 -4
  20. package/dist/lib/converter/utils/symbols.js +5 -0
  21. package/dist/lib/models/comments/comment.d.ts +0 -1
  22. package/dist/lib/models/comments/comment.js +0 -1
  23. package/dist/lib/models/reflections/ReflectionSymbolId.d.ts +8 -0
  24. package/dist/lib/models/reflections/ReflectionSymbolId.js +13 -3
  25. package/dist/lib/models/reflections/abstract.d.ts +3 -1
  26. package/dist/lib/models/reflections/abstract.js +4 -2
  27. package/dist/lib/models/reflections/declaration.js +1 -1
  28. package/dist/lib/models/reflections/kind.d.ts +6 -0
  29. package/dist/lib/models/reflections/kind.js +17 -0
  30. package/dist/lib/models/reflections/parameter.js +1 -1
  31. package/dist/lib/models/reflections/project.d.ts +3 -0
  32. package/dist/lib/models/reflections/project.js +59 -6
  33. package/dist/lib/models/reflections/signature.js +1 -1
  34. package/dist/lib/models/sources/file.d.ts +1 -1
  35. package/dist/lib/models/types.d.ts +5 -0
  36. package/dist/lib/models/types.js +42 -31
  37. package/dist/lib/output/themes/default/DefaultTheme.d.ts +1 -1
  38. package/dist/lib/output/themes/default/DefaultTheme.js +82 -11
  39. package/dist/lib/output/themes/default/DefaultThemeRenderContext.d.ts +15 -3
  40. package/dist/lib/output/themes/default/DefaultThemeRenderContext.js +12 -0
  41. package/dist/lib/output/themes/default/partials/comment.js +8 -3
  42. package/dist/lib/output/themes/default/partials/hierarchy.js +18 -1
  43. package/dist/lib/output/themes/default/partials/icon.js +2 -2
  44. package/dist/lib/output/themes/default/partials/member.getterSetter.js +2 -2
  45. package/dist/lib/output/themes/default/partials/member.signature.title.js +2 -2
  46. package/dist/lib/output/themes/default/partials/member.signatures.js +2 -1
  47. package/dist/lib/output/themes/default/partials/parameter.js +2 -2
  48. package/dist/lib/output/themes/default/partials/reflectionPreview.d.ts +4 -0
  49. package/dist/lib/output/themes/default/partials/reflectionPreview.js +21 -0
  50. package/dist/lib/output/themes/default/partials/type.d.ts +3 -1
  51. package/dist/lib/output/themes/default/partials/type.js +29 -27
  52. package/dist/lib/output/themes/default/partials/typeParameters.js +6 -3
  53. package/dist/lib/output/themes/default/templates/hierarchy.d.ts +5 -0
  54. package/dist/lib/output/themes/default/templates/hierarchy.js +32 -0
  55. package/dist/lib/output/themes/default/templates/reflection.js +2 -1
  56. package/dist/lib/output/themes/lib.js +3 -3
  57. package/dist/lib/serialization/components.d.ts +1 -1
  58. package/dist/lib/serialization/schema.d.ts +1 -0
  59. package/dist/lib/serialization/serializer.d.ts +0 -1
  60. package/dist/lib/serialization/serializer.js +0 -1
  61. package/dist/lib/utils/enum.d.ts +1 -0
  62. package/dist/lib/utils/enum.js +5 -1
  63. package/dist/lib/utils/loggers.d.ts +0 -3
  64. package/dist/lib/utils/loggers.js +0 -1
  65. package/dist/lib/utils/options/declaration.d.ts +1 -0
  66. package/dist/lib/utils/options/declaration.js +2 -2
  67. package/dist/lib/utils/options/options.js +6 -5
  68. package/dist/lib/utils/options/readers/tsconfig.js +4 -1
  69. package/dist/lib/utils/options/sources/typedoc.js +1 -0
  70. package/dist/lib/utils/tsconfig.d.ts +1 -0
  71. package/dist/lib/utils/tsconfig.js +33 -1
  72. package/dist/lib/validation/documentation.js +23 -16
  73. package/package.json +13 -10
  74. package/static/main.js +2 -2
  75. package/static/style.css +46 -15
@@ -9,20 +9,20 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.parseDeclarationReference = exports.parseMeaning = exports.parseComponentPath = exports.parseComponent = exports.parseSymbolReference = exports.parseModuleSource = exports.parseString = exports.MeaningKeywords = void 0;
11
11
  exports.MeaningKeywords = [
12
- "class",
13
- "interface",
14
- "type",
15
- "enum",
16
- "namespace",
17
- "function",
18
- "var",
19
- "constructor",
20
- "member",
21
- "event",
22
- "call",
23
- "new",
24
- "index",
25
- "complex",
12
+ "class", // SymbolFlags.Class
13
+ "interface", // SymbolFlags.Interface
14
+ "type", // SymbolFlags.TypeAlias
15
+ "enum", // SymbolFlags.Enum
16
+ "namespace", // SymbolFlags.Module
17
+ "function", // SymbolFlags.Function
18
+ "var", // SymbolFlags.Variable
19
+ "constructor", // SymbolFlags.Constructor
20
+ "member", // SymbolFlags.ClassMember | SymbolFlags.EnumMember
21
+ "event", //
22
+ "call", // SymbolFlags.Signature (for __call)
23
+ "new", // SymbolFlags.Signature (for __new)
24
+ "index", // SymbolFlags.Signature (for __index)
25
+ "complex", // Any complex type
26
26
  // TypeDoc specific
27
27
  "getter",
28
28
  "setter",
@@ -121,13 +121,15 @@ function discoverComment(symbol, kind, logger, commentStyle) {
121
121
  // not the last one, since that will apply to the import or declaration.
122
122
  const reverse = !symbol.declarations?.some(typescript_1.default.isSourceFile);
123
123
  const discovered = [];
124
+ const seen = new Set();
124
125
  for (const decl of symbol.declarations || []) {
125
126
  const text = decl.getSourceFile().text;
126
127
  if (wantedKinds[kind].includes(decl.kind)) {
127
128
  const node = declarationToCommentNode(decl);
128
- if (!node) {
129
+ if (!node || seen.has(node)) {
129
130
  continue;
130
131
  }
132
+ seen.add(node);
131
133
  // Special behavior here! We temporarily put the implementation comment
132
134
  // on the reflection which contains all the signatures. This lets us pull
133
135
  // the comment on the implementation if some signature does not have a comment.
@@ -292,7 +294,7 @@ function declarationToCommentNode(node) {
292
294
  if (node.kind === typescript_1.default.SyntaxKind.ExportSpecifier) {
293
295
  return node.parent.parent;
294
296
  }
295
- if ([typescript_1.default.SyntaxKind.NamespaceExport, typescript_1.default.SyntaxKind.FunctionType].includes(node.kind)) {
297
+ if (typescript_1.default.SyntaxKind.NamespaceExport === node.kind) {
296
298
  return node.parent;
297
299
  }
298
300
  return node;
@@ -126,8 +126,8 @@ function blockTag(comment, lexer, config, warning) {
126
126
  (0, assert_1.ok)(blockTag.kind === lexer_1.TokenSyntaxKind.Tag, "blockTag called not at the start of a block tag."); // blockContent is broken if this fails.
127
127
  const tagName = aliasedTags.get(blockTag.text) || blockTag.text;
128
128
  let content;
129
- if (tagName === "@example" && config.jsDocCompatibility.exampleTag) {
130
- content = exampleBlockContent(comment, lexer, config, warning);
129
+ if (tagName === "@example") {
130
+ return exampleBlock(comment, lexer, config, warning);
131
131
  }
132
132
  else if (["@default", "@defaultValue"].includes(tagName) &&
133
133
  config.jsDocCompatibility.defaultTag) {
@@ -168,14 +168,59 @@ function defaultBlockContent(comment, lexer, config, warning) {
168
168
  /**
169
169
  * The `@example` tag gets a special case because otherwise we will produce many warnings
170
170
  * about unescaped/mismatched/missing braces in legacy JSDoc comments.
171
+ *
172
+ * In TSDoc, we also want to treat the first line of the block as the example name.
171
173
  */
172
- function exampleBlockContent(comment, lexer, config, warning) {
174
+ function exampleBlock(comment, lexer, config, warning) {
173
175
  lexer.mark();
174
176
  const content = blockContent(comment, lexer, config, () => { });
175
177
  const end = lexer.done() || lexer.peek();
176
178
  lexer.release();
177
- if (content.some((part) => part.kind === "code" && part.text.startsWith("```"))) {
178
- return blockContent(comment, lexer, config, warning);
179
+ if (!config.jsDocCompatibility.exampleTag ||
180
+ content.some((part) => part.kind === "code" && part.text.startsWith("```"))) {
181
+ let exampleName = "";
182
+ // First line of @example block is the example name.
183
+ let warnedAboutRichNameContent = false;
184
+ outer: while ((lexer.done() || lexer.peek()) !== end) {
185
+ const next = lexer.peek();
186
+ switch (next.kind) {
187
+ case lexer_1.TokenSyntaxKind.NewLine:
188
+ lexer.take();
189
+ break outer;
190
+ case lexer_1.TokenSyntaxKind.Text: {
191
+ const newline = next.text.indexOf("\n");
192
+ if (newline !== -1) {
193
+ exampleName += next.text.substring(0, newline);
194
+ next.pos += newline + 1;
195
+ break outer;
196
+ }
197
+ else {
198
+ exampleName += lexer.take().text;
199
+ }
200
+ break;
201
+ }
202
+ case lexer_1.TokenSyntaxKind.Code:
203
+ case lexer_1.TokenSyntaxKind.Tag:
204
+ case lexer_1.TokenSyntaxKind.TypeAnnotation:
205
+ case lexer_1.TokenSyntaxKind.CloseBrace:
206
+ case lexer_1.TokenSyntaxKind.OpenBrace:
207
+ if (!warnedAboutRichNameContent) {
208
+ warning("The first line of an example tag will be taken literally as" +
209
+ " the example name, and should only contain text.", lexer.peek());
210
+ warnedAboutRichNameContent = true;
211
+ }
212
+ exampleName += lexer.take().text;
213
+ break;
214
+ default:
215
+ (0, utils_1.assertNever)(next.kind);
216
+ }
217
+ }
218
+ const content = blockContent(comment, lexer, config, warning);
219
+ const tag = new models_1.CommentTag("@example", content);
220
+ if (exampleName.trim()) {
221
+ tag.name = exampleName.trim();
222
+ }
223
+ return tag;
179
224
  }
180
225
  const tokens = [];
181
226
  while ((lexer.done() || lexer.peek()) !== end) {
@@ -187,24 +232,22 @@ function exampleBlockContent(comment, lexer, config, warning) {
187
232
  .trim();
188
233
  const caption = blockText.match(/^\s*<caption>(.*?)<\/caption>\s*(\n|$)/);
189
234
  if (caption) {
190
- return [
191
- {
192
- kind: "text",
193
- text: caption[1] + "\n",
194
- },
235
+ const tag = new models_1.CommentTag("@example", [
195
236
  {
196
237
  kind: "code",
197
238
  text: makeCodeBlock(blockText.slice(caption[0].length)),
198
239
  },
199
- ];
240
+ ]);
241
+ tag.name = caption[1];
242
+ return tag;
200
243
  }
201
244
  else {
202
- return [
245
+ return new models_1.CommentTag("@example", [
203
246
  {
204
247
  kind: "code",
205
248
  text: makeCodeBlock(blockText),
206
249
  },
207
- ];
250
+ ]);
208
251
  }
209
252
  }
210
253
  function blockContent(comment, lexer, config, warning) {
@@ -82,8 +82,5 @@ export declare class Context {
82
82
  getFileComment(node: ts.SourceFile): import("../models/index").Comment | undefined;
83
83
  getJsDocComment(declaration: ts.JSDocPropertyLikeTag | ts.JSDocCallbackTag | ts.JSDocTypedefTag | ts.JSDocTemplateTag | ts.JSDocEnumTag): import("../models/index").Comment | undefined;
84
84
  getSignatureComment(declaration: ts.SignatureDeclaration | ts.JSDocSignature): import("../models/index").Comment | undefined;
85
- /**
86
- * @param callback The callback function that should be executed with the changed context.
87
- */
88
85
  withScope(scope: Reflection): Context;
89
86
  }
@@ -184,9 +184,6 @@ class Context {
184
184
  getSignatureComment(declaration) {
185
185
  return (0, comments_1.getSignatureComment)(declaration, this.converter.config, this.logger, this.converter.commentStyle, this.converter.useTsLinkResolution ? this.checker : undefined);
186
186
  }
187
- /**
188
- * @param callback The callback function that should be executed with the changed context.
189
- */
190
187
  withScope(scope) {
191
188
  const context = new Context(this.converter, this.programs, this.project, scope);
192
189
  context.convertingTypeNode = this.convertingTypeNode;
@@ -117,7 +117,6 @@ export declare class Converter extends ChildableComponent<Application, Converter
117
117
  * Convert the given TypeScript type into its TypeDoc type reflection.
118
118
  *
119
119
  * @param context The context object describing the current state the converter is in.
120
- * @param referenceTarget The target to be used to attempt to resolve reference types
121
120
  * @returns The TypeDoc type reflection representing the given node and type.
122
121
  * @internal
123
122
  */
@@ -203,7 +203,6 @@ let Converter = (() => {
203
203
  * Convert the given TypeScript type into its TypeDoc type reflection.
204
204
  *
205
205
  * @param context The context object describing the current state the converter is in.
206
- * @param referenceTarget The target to be used to attempt to resolve reference types
207
206
  * @returns The TypeDoc type reflection representing the given node and type.
208
207
  * @internal
209
208
  */
@@ -47,6 +47,9 @@ function createSignature(context, kind, signature, symbol, declaration) {
47
47
  else if (kind == models_1.ReflectionKind.SetSignature) {
48
48
  sigRef.type = new models_1.IntrinsicType("void");
49
49
  }
50
+ else if (declaration?.type?.kind === typescript_1.default.SyntaxKind.ThisType) {
51
+ sigRef.type = new models_1.IntrinsicType("this");
52
+ }
50
53
  else {
51
54
  sigRef.type = context.converter.convertType(sigRefCtx, (declaration?.kind === typescript_1.default.SyntaxKind.FunctionDeclaration &&
52
55
  declaration.type) ||
@@ -89,7 +92,14 @@ function convertParameters(context, sigRef, parameters, parameterNodes) {
89
92
  else {
90
93
  type = param.type;
91
94
  }
92
- paramRefl.type = context.converter.convertType(context.withScope(paramRefl), type);
95
+ if (declaration &&
96
+ typescript_1.default.isParameter(declaration) &&
97
+ declaration.type?.kind === typescript_1.default.SyntaxKind.ThisType) {
98
+ paramRefl.type = new models_1.IntrinsicType("this");
99
+ }
100
+ else {
101
+ paramRefl.type = context.converter.convertType(context.withScope(paramRefl), type);
102
+ }
93
103
  let isOptional = false;
94
104
  if (declaration) {
95
105
  isOptional = typescript_1.default.isParameter(declaration)
@@ -114,6 +124,7 @@ function convertParameters(context, sigRef, parameters, parameterNodes) {
114
124
  typescript_1.default.isJSDocVariadicType(declaration.typeExpression.type);
115
125
  }
116
126
  paramRefl.setFlag(models_1.ReflectionFlag.Rest, isRest);
127
+ checkForDestructuredParameterDefaults(paramRefl, parameterNodes?.[i]);
117
128
  return paramRefl;
118
129
  });
119
130
  }
@@ -140,10 +151,27 @@ function convertParameterNodes(context, sigRef, parameters) {
140
151
  ? !!param.dotDotDotToken
141
152
  : !!param.typeExpression &&
142
153
  typescript_1.default.isJSDocVariadicType(param.typeExpression.type));
154
+ checkForDestructuredParameterDefaults(paramRefl, param);
143
155
  return paramRefl;
144
156
  });
145
157
  }
146
158
  exports.convertParameterNodes = convertParameterNodes;
159
+ function checkForDestructuredParameterDefaults(param, decl) {
160
+ if (!decl || !typescript_1.default.isParameter(decl))
161
+ return;
162
+ if (param.name !== "__namedParameters")
163
+ return;
164
+ if (!typescript_1.default.isObjectBindingPattern(decl.name))
165
+ return;
166
+ if (param.type?.type !== "reflection")
167
+ return;
168
+ for (const child of param.type.declaration.children || []) {
169
+ const tsChild = decl.name.elements.find((el) => (el.propertyName || el.name).getText() === child.name);
170
+ if (tsChild) {
171
+ child.defaultValue = (0, convert_expression_1.convertDefaultValue)(tsChild);
172
+ }
173
+ }
174
+ }
147
175
  function convertTypeParameters(context, parent, parameters) {
148
176
  return parameters?.map((param) => {
149
177
  const constraintT = param.getConstraint();
@@ -218,8 +246,6 @@ function convertTemplateParameterNodes(context, nodes) {
218
246
  return paramRefl;
219
247
  });
220
248
  });
221
- const params = (nodes ?? []).flatMap((tag) => tag.typeParameters);
222
- return convertTypeParameterNodes(context, params);
223
249
  }
224
250
  exports.convertTemplateParameterNodes = convertTemplateParameterNodes;
225
251
  function getVariance(modifiers) {
@@ -22,13 +22,6 @@ export declare class CategoryPlugin extends ConverterComponent {
22
22
  * Triggered when the converter begins converting a project.
23
23
  */
24
24
  private onBegin;
25
- /**
26
- * Triggered when the converter resolves a reflection.
27
- *
28
- * @param context The context object describing the current state the converter is in.
29
- * @param reflection The reflection that is currently resolved.
30
- */
31
- private onResolve;
32
25
  /**
33
26
  * Triggered when the converter has finished resolving a project.
34
27
  *
@@ -100,7 +100,6 @@ let CategoryPlugin = (() => {
100
100
  initialize() {
101
101
  this.listenTo(this.owner, {
102
102
  [converter_1.Converter.EVENT_BEGIN]: this.onBegin,
103
- [converter_1.Converter.EVENT_RESOLVE]: this.onResolve,
104
103
  [converter_1.Converter.EVENT_RESOLVE_END]: this.onEndResolve,
105
104
  }, undefined, -200);
106
105
  }
@@ -117,17 +116,6 @@ let CategoryPlugin = (() => {
117
116
  CategoryPlugin.WEIGHTS = this.categoryOrder;
118
117
  }
119
118
  }
120
- /**
121
- * Triggered when the converter resolves a reflection.
122
- *
123
- * @param context The context object describing the current state the converter is in.
124
- * @param reflection The reflection that is currently resolved.
125
- */
126
- onResolve(_context, reflection) {
127
- if (reflection instanceof models_1.ContainerReflection) {
128
- this.categorize(reflection);
129
- }
130
- }
131
119
  /**
132
120
  * Triggered when the converter has finished resolving a project.
133
121
  *
@@ -136,6 +124,12 @@ let CategoryPlugin = (() => {
136
124
  onEndResolve(context) {
137
125
  const project = context.project;
138
126
  this.categorize(project);
127
+ for (const id in project.reflections) {
128
+ const reflection = project.reflections[id];
129
+ if (reflection instanceof models_1.ContainerReflection) {
130
+ this.categorize(reflection);
131
+ }
132
+ }
139
133
  const unusedBoosts = new Set(Object.keys(this.boosts));
140
134
  for (const boost of this.usedBoosts) {
141
135
  unusedBoosts.delete(boost);
@@ -121,4 +121,5 @@ export declare class CommentPlugin extends ConverterComponent {
121
121
  */
122
122
  private isHidden;
123
123
  private excludedByCategory;
124
+ private validateParamTags;
124
125
  }
@@ -382,13 +382,8 @@ let CommentPlugin = (() => {
382
382
  const comment = reflection.kindOf(models_1.ReflectionKind.ClassOrInterface)
383
383
  ? undefined
384
384
  : reflection.comment;
385
- // Since this reflection has signatures, remove the comment from the parent
386
- // reflection. This is important so that in type aliases we don't end up with
387
- // a comment rendered twice.
388
- if (!reflection.kindOf(models_1.ReflectionKind.ClassOrInterface)) {
389
- delete reflection.comment;
390
- }
391
385
  for (const signature of signatures) {
386
+ const signatureHadOwnComment = !!signature.comment;
392
387
  const childComment = (signature.comment ||= comment?.clone());
393
388
  if (!childComment)
394
389
  continue;
@@ -400,7 +395,6 @@ let CommentPlugin = (() => {
400
395
  parameter.name = commentParams[index].name;
401
396
  }
402
397
  }
403
- moveNestedParamTags(childComment, parameter);
404
398
  const tag = childComment.getIdentifiedTag(parameter.name, "@param");
405
399
  if (tag) {
406
400
  parameter.comment = new models_1.Comment(models_1.Comment.cloneDisplayParts(tag.content));
@@ -414,10 +408,26 @@ let CommentPlugin = (() => {
414
408
  parameter.comment = new models_1.Comment(models_1.Comment.cloneDisplayParts(tag.content));
415
409
  }
416
410
  }
411
+ this.validateParamTags(signature, childComment, signature.parameters || [], signatureHadOwnComment);
417
412
  childComment?.removeTags("@param");
418
413
  childComment?.removeTags("@typeParam");
419
414
  childComment?.removeTags("@template");
420
415
  }
416
+ // Since this reflection has signatures, we need to remove the comment from the non-primary
417
+ // declaration location. For functions, this means removing it from the Function reflection.
418
+ // For type aliases, this means removing it from reflection.type.declaration.
419
+ // This is important so that in type aliases we don't end up with a comment rendered twice.
420
+ if (reflection.kindOf(models_1.ReflectionKind.FunctionOrMethod | models_1.ReflectionKind.Constructor)) {
421
+ delete reflection.comment;
422
+ }
423
+ if (reflection.kindOf(models_1.ReflectionKind.TypeAlias)) {
424
+ reflection.comment?.removeTags("@param");
425
+ reflection.comment?.removeTags("@typeParam");
426
+ reflection.comment?.removeTags("@template");
427
+ for (const sig of signatures) {
428
+ delete sig.comment;
429
+ }
430
+ }
421
431
  }
422
432
  removeExcludedTags(comment) {
423
433
  for (const tag of NEVER_RENDERED) {
@@ -512,6 +522,16 @@ let CommentPlugin = (() => {
512
522
  }
513
523
  return excludeCategories.some((cat) => categories.has(cat));
514
524
  }
525
+ validateParamTags(signature, comment, params, signatureHadOwnComment) {
526
+ const paramTags = comment.blockTags.filter((tag) => tag.tag === "@param");
527
+ (0, utils_1.removeIf)(paramTags, (tag) => params.some((param) => param.name === tag.name));
528
+ moveNestedParamTags(/* in-out */ paramTags, params);
529
+ if (signatureHadOwnComment && paramTags.length) {
530
+ for (const tag of paramTags) {
531
+ this.application.logger.warn(`The signature ${signature.getFriendlyFullName()} has an @param with name "${tag.name}", which was not used.`);
532
+ }
533
+ }
534
+ }
515
535
  };
516
536
  _CommentPlugin_excludeTags_accessor_storage = new WeakMap();
517
537
  _CommentPlugin_excludeInternal_accessor_storage = new WeakMap();
@@ -555,29 +575,39 @@ function inTypeLiteral(refl) {
555
575
  return false;
556
576
  }
557
577
  // Moves tags like `@param foo.bar docs for bar` into the `bar` property of the `foo` parameter.
558
- function moveNestedParamTags(comment, parameter) {
559
- const visitor = {
560
- reflection(target) {
561
- const tags = comment.blockTags.filter((t) => t.tag === "@param" &&
562
- t.name?.startsWith(`${parameter.name}.`));
563
- for (const tag of tags) {
564
- const path = tag.name.split(".");
565
- path.shift();
566
- const child = target.declaration.getChildByName(path);
567
- if (child && !child.comment) {
568
- child.comment = new models_1.Comment(models_1.Comment.cloneDisplayParts(tag.content));
578
+ function moveNestedParamTags(
579
+ /* in-out */ paramTags, parameters) {
580
+ const used = new Set();
581
+ for (const param of parameters) {
582
+ const visitor = {
583
+ reflection(target) {
584
+ const tags = paramTags.filter((t) => t.name?.startsWith(`${param.name}.`));
585
+ for (const tag of tags) {
586
+ const path = tag.name.split(".");
587
+ path.shift();
588
+ const child = target.declaration.getChildByName(path);
589
+ if (child && !child.comment) {
590
+ child.comment = new models_1.Comment(models_1.Comment.cloneDisplayParts(tag.content));
591
+ used.add(paramTags.indexOf(tag));
592
+ }
569
593
  }
570
- }
571
- },
572
- // #1876, also do this for unions/intersections.
573
- union(u) {
574
- u.types.forEach((t) => t.visit(visitor));
575
- },
576
- intersection(i) {
577
- i.types.forEach((t) => t.visit(visitor));
578
- },
579
- };
580
- parameter.type?.visit(visitor);
594
+ },
595
+ // #1876, also do this for unions/intersections.
596
+ union(u) {
597
+ u.types.forEach((t) => t.visit(visitor));
598
+ },
599
+ intersection(i) {
600
+ i.types.forEach((t) => t.visit(visitor));
601
+ },
602
+ };
603
+ param.type?.visit(visitor);
604
+ }
605
+ const toRemove = Array.from(used)
606
+ .sort((a, b) => a - b)
607
+ .reverse();
608
+ for (const index of toRemove) {
609
+ paramTags.splice(index, 1);
610
+ }
581
611
  }
582
612
  function movePropertyTags(comment, container) {
583
613
  const propTags = comment.blockTags.filter((tag) => tag.tag === "@prop" || tag.tag === "@property");
@@ -17,13 +17,6 @@ export declare class GroupPlugin extends ConverterComponent {
17
17
  * Create a new GroupPlugin instance.
18
18
  */
19
19
  initialize(): void;
20
- /**
21
- * Triggered when the converter resolves a reflection.
22
- *
23
- * @param context The context object describing the current state the converter is in.
24
- * @param reflection The reflection that is currently resolved.
25
- */
26
- private onResolve;
27
20
  /**
28
21
  * Triggered when the converter has finished resolving a project.
29
22
  *
@@ -100,20 +100,8 @@ let GroupPlugin = (() => {
100
100
  this.sortFunction = (0, sort_1.getSortFunction)(this.application.options);
101
101
  GroupPlugin.WEIGHTS = this.groupOrder;
102
102
  },
103
- [converter_1.Converter.EVENT_RESOLVE]: this.onResolve,
104
103
  [converter_1.Converter.EVENT_RESOLVE_END]: this.onEndResolve,
105
- });
106
- }
107
- /**
108
- * Triggered when the converter resolves a reflection.
109
- *
110
- * @param context The context object describing the current state the converter is in.
111
- * @param reflection The reflection that is currently resolved.
112
- */
113
- onResolve(_context, reflection) {
114
- if (reflection instanceof index_1.ContainerReflection) {
115
- this.group(reflection);
116
- }
104
+ }, undefined, -100);
117
105
  }
118
106
  /**
119
107
  * Triggered when the converter has finished resolving a project.
@@ -122,6 +110,12 @@ let GroupPlugin = (() => {
122
110
  */
123
111
  onEndResolve(context) {
124
112
  this.group(context.project);
113
+ for (const id in context.project.reflections) {
114
+ const reflection = context.project.reflections[id];
115
+ if (reflection instanceof index_1.ContainerReflection) {
116
+ this.group(reflection);
117
+ }
118
+ }
125
119
  const unusedBoosts = new Set(Object.keys(this.boosts));
126
120
  for (const boost of this.usedBoosts) {
127
121
  unusedBoosts.delete(boost);
@@ -196,6 +196,9 @@ let SourcePlugin = (() => {
196
196
  refl instanceof index_1.SignatureReflection)) {
197
197
  continue;
198
198
  }
199
+ if (replaceSourcesWithParentSources(refl)) {
200
+ refl.sources = refl.parent.sources;
201
+ }
199
202
  for (const source of refl.sources || []) {
200
203
  if (this.disableGit || (0, repository_1.gitIsInstalled)()) {
201
204
  const repo = this.getRepository(basePath, source.fullFileName);
@@ -273,3 +276,23 @@ function getLocationNode(node) {
273
276
  return node.name;
274
277
  return node;
275
278
  }
279
+ function replaceSourcesWithParentSources(refl) {
280
+ if (refl instanceof index_1.DeclarationReflection || !refl.sources) {
281
+ return false;
282
+ }
283
+ const symbol = refl.project.getSymbolFromReflection(refl.parent);
284
+ if (!symbol?.declarations) {
285
+ return false;
286
+ }
287
+ for (const decl of symbol.declarations) {
288
+ const file = decl.getSourceFile();
289
+ const pos = file.getLineAndCharacterOfPosition(decl.pos);
290
+ const end = file.getLineAndCharacterOfPosition(decl.end);
291
+ if (refl.sources.some((src) => src.fullFileName === file.fileName &&
292
+ pos.line <= src.line - 1 &&
293
+ src.line - 1 <= end.line)) {
294
+ return false;
295
+ }
296
+ }
297
+ return true;
298
+ }
@@ -156,7 +156,10 @@ let TypePlugin = (() => {
156
156
  if (reflection.extendedBy) {
157
157
  push(reflection.extendedBy);
158
158
  }
159
- reflection.typeHierarchy = root;
159
+ // No point setting up a hierarchy if there is no hierarchy to display
160
+ if (root.next) {
161
+ reflection.typeHierarchy = root;
162
+ }
160
163
  });
161
164
  }
162
165
  };