From fb4d169670c889f161506bbea8283cf919368773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sat, 19 Mar 2022 17:10:34 +0000 Subject: [PATCH 01/21] Fix path entry point regex --- src/lib/utils/entry-point.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/utils/entry-point.ts b/src/lib/utils/entry-point.ts index 12ba08995..45886014f 100644 --- a/src/lib/utils/entry-point.ts +++ b/src/lib/utils/entry-point.ts @@ -139,7 +139,7 @@ function getEntryPointsForPaths( entryLoop: for (const fileOrDir of inputFiles.map(normalizePath)) { const toCheck = [fileOrDir]; - if (!/\.[tj]sx?/.test(fileOrDir)) { + if (!/\.[tj]sx?$/.test(fileOrDir)) { toCheck.push( `${fileOrDir}/index.ts`, `${fileOrDir}/index.tsx`, From e5b041d23aa7f4af8873f5fb36fc47d74bd3b179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sat, 19 Mar 2022 17:10:49 +0000 Subject: [PATCH 02/21] Use `Array.prototype.flatMap` No need to hand-roll this anymore. --- src/lib/application.ts | 6 ++++-- src/lib/converter/jsdoc.ts | 5 ++--- src/lib/converter/utils/nodes.ts | 12 ++++++------ src/lib/models/sources/directory.ts | 3 +-- src/lib/utils/array.ts | 18 ------------------ src/lib/utils/package-manifest.ts | 5 ++--- 6 files changed, 15 insertions(+), 34 deletions(-) diff --git a/src/lib/application.ts b/src/lib/application.ts index 4694fb64e..08c9198de 100644 --- a/src/lib/application.ts +++ b/src/lib/application.ts @@ -23,7 +23,7 @@ import { } from "./utils/component"; import { Options, BindOption } from "./utils"; import type { TypeDocOptions } from "./utils/options/declaration"; -import { flatMap, unique } from "./utils/array"; +import { unique } from "./utils/array"; import { ok } from "assert"; import { DocumentationEntryPoint, @@ -225,7 +225,9 @@ export class Application extends ChildableComponent< `Converting with ${programs.length} programs ${entryPoints.length} entry points` ); - const errors = flatMap([...programs], ts.getPreEmitDiagnostics); + const errors = programs.flatMap((program) => + ts.getPreEmitDiagnostics(program) + ); if (errors.length) { this.logger.diagnostics(errors); return; diff --git a/src/lib/converter/jsdoc.ts b/src/lib/converter/jsdoc.ts index 0b87d59dc..b36d2c581 100644 --- a/src/lib/converter/jsdoc.ts +++ b/src/lib/converter/jsdoc.ts @@ -11,7 +11,6 @@ import { ReflectionType, SignatureReflection, } from "../models"; -import { flatMap } from "../utils/array"; import { getJsDocComment } from "./comments"; import type { Context } from "./context"; import { ConverterEvents } from "./converter-events"; @@ -164,8 +163,8 @@ function convertTemplateParameters(context: Context, node: ts.JSDoc) { function convertTemplateParameterNodes( context: Context, - nodes: readonly ts.JSDocTemplateTag[] | undefined + nodes: readonly ts.JSDocTemplateTag[] = [] ) { - const params = flatMap(nodes ?? [], (tag) => tag.typeParameters); + const params = nodes.flatMap((tag) => tag.typeParameters); return convertTypeParameterNodes(context, params); } diff --git a/src/lib/converter/utils/nodes.ts b/src/lib/converter/utils/nodes.ts index 58a33ff62..4825ca9d4 100644 --- a/src/lib/converter/utils/nodes.ts +++ b/src/lib/converter/utils/nodes.ts @@ -1,5 +1,4 @@ import * as ts from "typescript"; -import { flatMap } from "../../utils/array"; export function isNamedNode(node: ts.Node): node is ts.Node & { name: ts.Identifier | ts.PrivateIdentifier | ts.ComputedPropertyName; @@ -16,11 +15,12 @@ export function getHeritageTypes( declarations: readonly (ts.ClassDeclaration | ts.InterfaceDeclaration)[], kind: ts.SyntaxKind.ImplementsKeyword | ts.SyntaxKind.ExtendsKeyword ): ts.ExpressionWithTypeArguments[] { - const exprs = flatMap(declarations, (d) => - flatMap( - d.heritageClauses?.filter((hc) => hc.token === kind) ?? [], - (hc) => hc.types as readonly ts.ExpressionWithTypeArguments[] - ) + const exprs = declarations.flatMap((d) => + (d.heritageClauses ?? []) + .filter((hc) => hc.token === kind) + .flatMap( + (hc) => hc.types as readonly ts.ExpressionWithTypeArguments[] + ) ); const seenTexts = new Set(); diff --git a/src/lib/models/sources/directory.ts b/src/lib/models/sources/directory.ts index 89bed50e1..4775a096e 100644 --- a/src/lib/models/sources/directory.ts +++ b/src/lib/models/sources/directory.ts @@ -1,7 +1,6 @@ import type { ReflectionGroup } from "../ReflectionGroup"; import type { SourceFile } from "./file"; import type { DeclarationReflection } from ".."; -import { flatMap } from "../../utils/array"; /** * Exposes information about a directory containing source files. @@ -84,6 +83,6 @@ export class SourceDirectory { * files of this directory. */ getAllReflections(): DeclarationReflection[] { - return flatMap(this.files, (file) => file.reflections); + return this.files.flatMap((file) => file.reflections); } } diff --git a/src/lib/utils/array.ts b/src/lib/utils/array.ts index d95ceefdc..fcfd034bd 100644 --- a/src/lib/utils/array.ts +++ b/src/lib/utils/array.ts @@ -156,21 +156,3 @@ export function filterMap( return result; } - -export function flatMap( - arr: readonly T[], - fn: (item: T) => U | readonly U[] | undefined -): U[] { - const result: U[] = []; - - for (const item of arr) { - const newItem = fn(item); - if (newItem instanceof Array) { - result.push(...newItem); - } else if (newItem != null) { - result.push(newItem); - } - } - - return result; -} diff --git a/src/lib/utils/package-manifest.ts b/src/lib/utils/package-manifest.ts index d6dc34ff2..7ea47be57 100644 --- a/src/lib/utils/package-manifest.ts +++ b/src/lib/utils/package-manifest.ts @@ -2,7 +2,6 @@ import { dirname, join, resolve } from "path"; import { existsSync } from "fs"; -import { flatMap } from "./array"; import { readFile, glob } from "./fs"; import type { Logger } from "./loggers"; @@ -79,12 +78,12 @@ export function expandPackages( // to the root of a workspace tree in our params and so we could here // be dealing with either a root or a leaf. So let's do this recursively, // as it actually is simpler from an implementation perspective anyway. - return flatMap(workspaces, (workspace) => { + return workspaces.flatMap((workspace) => { const globbedPackageJsonPaths = glob( resolve(packageJsonDir, workspace, "package.json"), resolve(packageJsonDir) ); - return flatMap(globbedPackageJsonPaths, (packageJsonPath) => { + return globbedPackageJsonPaths.flatMap((packageJsonPath) => { const packageJson = loadPackageManifest(logger, packageJsonPath); if (packageJson === undefined) { logger.error(`Failed to load ${packageJsonPath}`); From ca4d89eb56b1de5eefb4b7798ce3418ffc7ecf39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sat, 19 Mar 2022 17:15:14 +0000 Subject: [PATCH 03/21] Simplify `removeIf` --- src/lib/utils/array.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/utils/array.ts b/src/lib/utils/array.ts index fcfd034bd..14c513508 100644 --- a/src/lib/utils/array.ts +++ b/src/lib/utils/array.ts @@ -82,11 +82,11 @@ export function removeIfPresent(arr: T[] | undefined, item: T) { * @param predicate */ export function removeIf(arr: T[], predicate: (item: T) => boolean) { - const indices = filterMap(arr, (item, index) => - predicate(item) ? index : void 0 - ); - for (const index of indices.reverse()) { - arr.splice(index, 1); + for (let i = 0; i < arr.length; i++) { + if (predicate(arr[i])) { + arr.splice(i, 1); + i--; + } } } From 1c985d4183d36ad3f7a262f0790e2733de1b5f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sat, 19 Mar 2022 17:40:25 +0000 Subject: [PATCH 04/21] Remove unused `toArray` --- src/lib/utils/array.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/lib/utils/array.ts b/src/lib/utils/array.ts index 14c513508..a7a8ebbb2 100644 --- a/src/lib/utils/array.ts +++ b/src/lib/utils/array.ts @@ -116,17 +116,6 @@ export function partition( return [left, right]; } -/** - * Ensures the given item is an array. - * @param item - */ -export function toArray(item: T | readonly T[] | undefined): T[] { - if (item === void 0) { - return []; - } - return Array.isArray(item) ? [...item] : [item]; -} - export function* zip[]>( ...args: T ): Iterable<{ [K in keyof T]: T[K] extends Iterable ? U : T[K] }> { From 3187990bd4d2f485b4ca416731888d97c53ec84c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sat, 19 Mar 2022 22:51:06 +0000 Subject: [PATCH 05/21] Simplify regex --- src/lib/models/reflections/abstract.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/models/reflections/abstract.ts b/src/lib/models/reflections/abstract.ts index d0df3c23a..d144589bc 100644 --- a/src/lib/models/reflections/abstract.ts +++ b/src/lib/models/reflections/abstract.ts @@ -362,7 +362,7 @@ export abstract class Reflection { */ getAlias(): string { if (!this._alias) { - let alias = this.name.replace(/[^a-z0-9]/gi, "_"); + let alias = this.name.replace(/\W/g, "_"); if (alias === "") { alias = "reflection-" + this.id; } From 78882b07b9dcf86e234a68386d967bd76704bb31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sat, 19 Mar 2022 22:51:17 +0000 Subject: [PATCH 06/21] Simplify binary logic --- src/lib/utils/enum.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/utils/enum.ts b/src/lib/utils/enum.ts index 836c7b864..f11462380 100644 --- a/src/lib/utils/enum.ts +++ b/src/lib/utils/enum.ts @@ -1,6 +1,6 @@ export function getEnumFlags(flags: T): T[] { const result: T[] = []; - for (let i = 1; i <= flags; i *= 2) { + for (let i = 1; i <= flags; i <<= 1) { if (flags & i) { result.push(i as T); } @@ -11,7 +11,7 @@ export function getEnumFlags(flags: T): T[] { // T & {} reduces inference priority export function removeFlag(flag: T, remove: T & {}): T { - return ((flag ^ remove) & flag) as T; + return (flag & ~remove) as T; } export function hasAllFlags(flags: number, check: number): boolean { From cf71f63bc8cd825014101d73f90bc3522da5c7b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sat, 19 Mar 2022 23:36:16 +0000 Subject: [PATCH 07/21] Simplify `LegendBuilder` --- src/lib/output/plugins/LegendPlugin.ts | 35 ++++++++------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/lib/output/plugins/LegendPlugin.ts b/src/lib/output/plugins/LegendPlugin.ts index e3c651576..1f131771e 100644 --- a/src/lib/output/plugins/LegendPlugin.ts +++ b/src/lib/output/plugins/LegendPlugin.ts @@ -214,31 +214,23 @@ export class LegendBuilder { build(): LegendItem[][] { const filteredLegend = completeLegend - .map((list) => { - return list.filter((item) => { - for (const classes of this._classesList) { - if (this.isArrayEqualToSet(item.classes, classes)) { - return true; - } - } - return false; - }); - }) + .map((list) => + list.filter((item) => + this._classesList.some((classes) => + this.isArrayEqualToSet(item.classes, classes) + ) + ) + ) .filter((list) => list.length); return filteredLegend; } registerCssClasses(classArray: string[]) { - let exists = false; const items = classArray.filter((cls) => !ignoredClasses.has(cls)); - - for (const classes of this._classesList) { - if (this.isArrayEqualToSet(items, classes)) { - exists = true; - break; - } - } + const exists = this._classesList.some((classes) => + this.isArrayEqualToSet(items, classes) + ); if (!exists) { this._classesList.push(new Set(items)); @@ -250,12 +242,7 @@ export class LegendBuilder { return false; } - for (const value of a) { - if (!b.has(value)) { - return false; - } - } - return true; + return a.every((item) => b.has(item)); } } From 6c4fcac6bf4ca1f2c1442290dcdd0a2aa1f6fb1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 00:18:45 +0000 Subject: [PATCH 08/21] Use `map` instead of `forEach`/`pop` --- src/lib/converter/plugins/SourcePlugin.ts | 7 +++---- src/lib/models/comments/comment.ts | 14 ++++---------- src/lib/models/reflections/declaration.ts | 7 +++---- src/lib/models/reflections/signature.ts | 5 ++--- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/lib/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index 5904c46d9..6ed36c5e1 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -176,10 +176,9 @@ export class SourcePlugin extends ConverterComponent { const project = context.project; const home = project.directory; project.files.forEach((file) => { - const reflections: DeclarationReflection[] = []; - file.reflections.forEach((reflection) => { - reflections.push(reflection); - }); + const reflections: DeclarationReflection[] = file.reflections.map( + (reflection) => reflection + ); let directory = home; const path = Path.dirname(file.fileName); diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 22839d943..eb55801e1 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -73,23 +73,17 @@ export class Comment { static combineDisplayParts( parts: readonly CommentDisplayPart[] | undefined ): string { - const result: string[] = []; - - for (const item of parts || []) { + const result: string[] = (parts || []).map((item) => { switch (item.kind) { case "text": - result.push(item.text); - break; case "code": - result.push(item.text); - break; + return item.text; case "inline-tag": - result.push("{", item.tag, " ", item.text, "}"); - break; + return `{${item.tag} ${item.text}}`; default: assertNever(item); } - } + }); return result.join(""); } diff --git a/src/lib/models/reflections/declaration.ts b/src/lib/models/reflections/declaration.ts index e16647cba..1381dc32e 100644 --- a/src/lib/models/reflections/declaration.ts +++ b/src/lib/models/reflections/declaration.ts @@ -232,10 +232,9 @@ export class DeclarationReflection extends ContainerReflection { let result = super.toString(); if (this.typeParameters) { - const parameters: string[] = []; - this.typeParameters.forEach((parameter) => { - parameters.push(parameter.name); - }); + const parameters: string[] = this.typeParameters.map( + (parameter) => parameter.name + ); result += "<" + parameters.join(", ") + ">"; } diff --git a/src/lib/models/reflections/signature.ts b/src/lib/models/reflections/signature.ts index 87a8a7aea..baf83b798 100644 --- a/src/lib/models/reflections/signature.ts +++ b/src/lib/models/reflections/signature.ts @@ -92,9 +92,8 @@ export class SignatureReflection extends Reflection { let result = super.toString(); if (this.typeParameters) { - const parameters: string[] = []; - this.typeParameters.forEach((parameter) => - parameters.push(parameter.name) + const parameters: string[] = this.typeParameters.map( + (parameter) => parameter.name ); result += "<" + parameters.join(", ") + ">"; } From c2aa591008b406b87d8aafa758d01179d18bb17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 00:29:13 +0000 Subject: [PATCH 09/21] Remove condition that will never match `reflection.name === ""` won't match if `!reflection.name` is checked above. --- src/lib/output/plugins/JavascriptIndexPlugin.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/output/plugins/JavascriptIndexPlugin.ts b/src/lib/output/plugins/JavascriptIndexPlugin.ts index 9775b9d23..15d7193c3 100644 --- a/src/lib/output/plugins/JavascriptIndexPlugin.ts +++ b/src/lib/output/plugins/JavascriptIndexPlugin.ts @@ -52,8 +52,7 @@ export class JavascriptIndexPlugin extends RendererComponent { if ( !reflection.url || !reflection.name || - reflection.flags.isExternal || - reflection.name === "" + reflection.flags.isExternal ) { continue; } From 5ce91ec26ebab56d4ee17a3d0e22ad5631a80a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 00:29:35 +0000 Subject: [PATCH 10/21] Use ||= --- src/lib/utils/events.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/utils/events.ts b/src/lib/utils/events.ts index 55a84c603..da4f39f46 100644 --- a/src/lib/utils/events.ts +++ b/src/lib/utils/events.ts @@ -142,7 +142,7 @@ function onApi( options: OnApiOptions ): EventHandlers { if (callback) { - const handlers = events[name] || (events[name] = []); + const handlers = (events[name] ||= []); const context = options.context, ctx = options.ctx, listening = options.listening, From 03db21b6bb1fac150d217d09f9be59708f9eab91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 11:28:07 +0000 Subject: [PATCH 11/21] Use `flatMap` instead of `reduce`/`concat` --- src/lib/converter/plugins/CommentPlugin.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index 0b905b7fc..23ce07644 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -223,9 +223,8 @@ export class CommentPlugin extends ConverterComponent { ); someRemoved.forEach((reflection) => { reflection.sources = unique( - reflection.signatures!.reduce( - (c, s) => c.concat(s.sources || []), - [] + reflection.signatures!.flatMap( + (s) => s.sources ?? [] ) ); }); From ab09cd0db99899121133ef0b250843fa85a520fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 12:01:24 +0000 Subject: [PATCH 12/21] Simplift `isExcluded`/`isExternal` --- src/lib/converter/converter.ts | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts index d78668378..bba2c83c5 100644 --- a/src/lib/converter/converter.ts +++ b/src/lib/converter/converter.ts @@ -389,34 +389,24 @@ export class Converter extends ChildableComponent< } private isExcluded(symbol: ts.Symbol) { - this.excludeCache ??= createMinimatch( + const cache = (this.excludeCache ??= createMinimatch( this.application.options.getValue("exclude") - ); + )); - for (const node of symbol.getDeclarations() ?? []) { - if (matchesAny(this.excludeCache, node.getSourceFile().fileName)) { - return true; - } - } - - return false; + return (symbol.getDeclarations() ?? []).some((node) => + matchesAny(cache, node.getSourceFile().fileName) + ); } /** @internal */ isExternal(symbol: ts.Symbol) { - this.externalPatternCache ??= createMinimatch(this.externalPattern); - for (const node of symbol.getDeclarations() ?? []) { - if ( - matchesAny( - this.externalPatternCache, - node.getSourceFile().fileName - ) - ) { - return true; - } - } + const cache = (this.externalPatternCache ??= createMinimatch( + this.externalPattern + )); - return false; + return (symbol.getDeclarations() ?? []).some((node) => + matchesAny(cache, node.getSourceFile().fileName) + ); } } From 46730fe59fa98eadd158d42ac8ef5fb5c5a02675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 11:36:55 +0000 Subject: [PATCH 13/21] Don't use `getSymbolFromReflection` for sort --- src/lib/utils/sort.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/lib/utils/sort.ts b/src/lib/utils/sort.ts index 0fb40a6a1..187616536 100644 --- a/src/lib/utils/sort.ts +++ b/src/lib/utils/sort.ts @@ -26,21 +26,18 @@ const sorts: Record< (a: DeclarationReflection, b: DeclarationReflection) => boolean > = { "source-order"(a, b) { - const aSymbol = a.project.getSymbolFromReflection(a); - const bSymbol = b.project.getSymbolFromReflection(b); - // This is going to be somewhat ambiguous. No way around that. Treat the first // declaration of a symbol as its ordering declaration. - const aDecl = aSymbol?.getDeclarations()?.[0]; - const bDecl = bSymbol?.getDeclarations()?.[0]; + const aSource = a.sources?.[0]; + const bSource = b.sources?.[0]; - if (aDecl && bDecl) { - const aFile = aDecl.getSourceFile().fileName; - const bFile = bDecl.getSourceFile().fileName; + if (aSource && bSource) { + const aFile = aSource.fileName; + const bFile = bSource.fileName; if (aFile < bFile) { return true; } - if (aFile == bFile && aDecl.pos < bDecl.pos) { + if (aFile == bFile && aSource.character < bSource.character) { return true; } From 7fe1e9e901733ef7b28e56ad08ea1cf9673a87a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 11:41:49 +0000 Subject: [PATCH 14/21] Use reflection source for validateDocumentation --- src/lib/validation/documentation.ts | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/lib/validation/documentation.ts b/src/lib/validation/documentation.ts index 57426989f..ec1cb454c 100644 --- a/src/lib/validation/documentation.ts +++ b/src/lib/validation/documentation.ts @@ -1,7 +1,5 @@ -import * as path from "path"; -import * as ts from "typescript"; import { ProjectReflection, ReflectionKind } from "../models"; -import { Logger, normalizePath } from "../utils"; +import type { Logger } from "../utils"; export function validateDocumentation( project: ProjectReflection, @@ -14,23 +12,15 @@ export function validateDocumentation( ); for (const ref of project.getReflectionsByKind(kinds)) { - const symbol = project.getSymbolFromReflection(ref); - if (!ref.comment && symbol?.declarations) { - const decl = symbol.declarations[0]; - const sourceFile = decl.getSourceFile(); - const { line } = ts.getLineAndCharacterOfPosition( - sourceFile, - decl.getStart() - ); - const file = normalizePath( - path.relative(process.cwd(), sourceFile.fileName) - ); + const decl = ref.sources?.[0]; + if (!ref.comment && decl) { + const { line, fileName } = decl; - if (file.includes("node_modules")) { + if (fileName.includes("node_modules")) { continue; } - const loc = `${file}:${line + 1}`; + const loc = `${fileName}:${line + 1}`; logger.warn( `${ref.name}, defined at ${loc}, does not have any documentation.` ); From 4d5ddb81a5bffee5317acaf1020353d925b573f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 12:31:42 +0000 Subject: [PATCH 15/21] Remove unused `node` from context trigger --- src/lib/converter/context.ts | 5 ++--- src/lib/converter/factories/index-signature.ts | 6 +----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 7bce96a33..2bf29634b 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -287,10 +287,9 @@ export class Context { * * @param name The name of the event that should be triggered. * @param reflection The triggering reflection. - * @param node The triggering TypeScript node if available. */ - trigger(name: string, reflection: Reflection, node?: ts.Node) { - this.converter.trigger(name, this, reflection, node); + trigger(name: string, reflection: Reflection) { + this.converter.trigger(name, this, reflection); } /** @internal */ diff --git a/src/lib/converter/factories/index-signature.ts b/src/lib/converter/factories/index-signature.ts index 96f170010..e8536c589 100644 --- a/src/lib/converter/factories/index-signature.ts +++ b/src/lib/converter/factories/index-signature.ts @@ -46,10 +46,6 @@ export function convertIndexSignature(context: Context, symbol: ts.Symbol) { context.registerReflection(index, indexSymbol); context.scope.indexSignature = index; - context.trigger( - ConverterEvents.CREATE_SIGNATURE, - index, - indexDeclaration - ); + context.trigger(ConverterEvents.CREATE_SIGNATURE, index); } } From 5d4c2049ee7a4f64f51b8d927d98379589019fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 12:50:12 +0000 Subject: [PATCH 16/21] Final changes --- src/lib/converter/plugins/ImplementsPlugin.ts | 5 +---- src/lib/models/comments/comment.ts | 14 +++++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/lib/converter/plugins/ImplementsPlugin.ts b/src/lib/converter/plugins/ImplementsPlugin.ts index e8ce3984d..c458b734a 100644 --- a/src/lib/converter/plugins/ImplementsPlugin.ts +++ b/src/lib/converter/plugins/ImplementsPlugin.ts @@ -266,10 +266,7 @@ export class ImplementsPlugin extends ConverterComponent { } // Need this because we re-use reflections for type literals. - if ( - !reflection.parent || - !reflection.parent.kindOf(ReflectionKind.ClassOrInterface) - ) { + if (!reflection.parent?.kindOf(ReflectionKind.ClassOrInterface)) { return; } diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index eb55801e1..bd17c0798 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -73,19 +73,23 @@ export class Comment { static combineDisplayParts( parts: readonly CommentDisplayPart[] | undefined ): string { - const result: string[] = (parts || []).map((item) => { + let result = ""; + + for (const item of parts || []) { switch (item.kind) { case "text": case "code": - return item.text; + result += item.text; + break; case "inline-tag": - return `{${item.tag} ${item.text}}`; + result += `{${item.tag} ${item.text}}`; + break; default: assertNever(item); } - }); + } - return result.join(""); + return result; } /** From 77cf85489839a76cfa6283c64d12c3441b3c03b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 18:23:11 +0000 Subject: [PATCH 17/21] Revert "Remove unused `node` from context trigger" This reverts commit 4d5ddb81a5bffee5317acaf1020353d925b573f3. --- src/lib/converter/context.ts | 5 +++-- src/lib/converter/factories/index-signature.ts | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 2bf29634b..7bce96a33 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -287,9 +287,10 @@ export class Context { * * @param name The name of the event that should be triggered. * @param reflection The triggering reflection. + * @param node The triggering TypeScript node if available. */ - trigger(name: string, reflection: Reflection) { - this.converter.trigger(name, this, reflection); + trigger(name: string, reflection: Reflection, node?: ts.Node) { + this.converter.trigger(name, this, reflection, node); } /** @internal */ diff --git a/src/lib/converter/factories/index-signature.ts b/src/lib/converter/factories/index-signature.ts index e8536c589..96f170010 100644 --- a/src/lib/converter/factories/index-signature.ts +++ b/src/lib/converter/factories/index-signature.ts @@ -46,6 +46,10 @@ export function convertIndexSignature(context: Context, symbol: ts.Symbol) { context.registerReflection(index, indexSymbol); context.scope.indexSignature = index; - context.trigger(ConverterEvents.CREATE_SIGNATURE, index); + context.trigger( + ConverterEvents.CREATE_SIGNATURE, + index, + indexDeclaration + ); } } From 37a65671b33dae9d16e27d425281bf2d61c99371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 18:23:13 +0000 Subject: [PATCH 18/21] Revert "Use reflection source for validateDocumentation" This reverts commit 7fe1e9e901733ef7b28e56ad08ea1cf9673a87a8. --- src/lib/validation/documentation.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/lib/validation/documentation.ts b/src/lib/validation/documentation.ts index ec1cb454c..57426989f 100644 --- a/src/lib/validation/documentation.ts +++ b/src/lib/validation/documentation.ts @@ -1,5 +1,7 @@ +import * as path from "path"; +import * as ts from "typescript"; import { ProjectReflection, ReflectionKind } from "../models"; -import type { Logger } from "../utils"; +import { Logger, normalizePath } from "../utils"; export function validateDocumentation( project: ProjectReflection, @@ -12,15 +14,23 @@ export function validateDocumentation( ); for (const ref of project.getReflectionsByKind(kinds)) { - const decl = ref.sources?.[0]; - if (!ref.comment && decl) { - const { line, fileName } = decl; + const symbol = project.getSymbolFromReflection(ref); + if (!ref.comment && symbol?.declarations) { + const decl = symbol.declarations[0]; + const sourceFile = decl.getSourceFile(); + const { line } = ts.getLineAndCharacterOfPosition( + sourceFile, + decl.getStart() + ); + const file = normalizePath( + path.relative(process.cwd(), sourceFile.fileName) + ); - if (fileName.includes("node_modules")) { + if (file.includes("node_modules")) { continue; } - const loc = `${fileName}:${line + 1}`; + const loc = `${file}:${line + 1}`; logger.warn( `${ref.name}, defined at ${loc}, does not have any documentation.` ); From e26d04be19fb3738f8d493bea8263164112b2a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 18:23:15 +0000 Subject: [PATCH 19/21] Revert "Don't use `getSymbolFromReflection` for sort" This reverts commit 46730fe59fa98eadd158d42ac8ef5fb5c5a02675. --- src/lib/utils/sort.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/lib/utils/sort.ts b/src/lib/utils/sort.ts index 187616536..0fb40a6a1 100644 --- a/src/lib/utils/sort.ts +++ b/src/lib/utils/sort.ts @@ -26,18 +26,21 @@ const sorts: Record< (a: DeclarationReflection, b: DeclarationReflection) => boolean > = { "source-order"(a, b) { + const aSymbol = a.project.getSymbolFromReflection(a); + const bSymbol = b.project.getSymbolFromReflection(b); + // This is going to be somewhat ambiguous. No way around that. Treat the first // declaration of a symbol as its ordering declaration. - const aSource = a.sources?.[0]; - const bSource = b.sources?.[0]; + const aDecl = aSymbol?.getDeclarations()?.[0]; + const bDecl = bSymbol?.getDeclarations()?.[0]; - if (aSource && bSource) { - const aFile = aSource.fileName; - const bFile = bSource.fileName; + if (aDecl && bDecl) { + const aFile = aDecl.getSourceFile().fileName; + const bFile = bDecl.getSourceFile().fileName; if (aFile < bFile) { return true; } - if (aFile == bFile && aSource.character < bSource.character) { + if (aFile == bFile && aDecl.pos < bDecl.pos) { return true; } From 62ddb4c183e12ce5929193e368498c4cce8b6482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 18:26:02 +0000 Subject: [PATCH 20/21] Changes for review --- src/lib/converter/jsdoc.ts | 4 ++-- src/lib/converter/plugins/SourcePlugin.ts | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/lib/converter/jsdoc.ts b/src/lib/converter/jsdoc.ts index b36d2c581..7284161c6 100644 --- a/src/lib/converter/jsdoc.ts +++ b/src/lib/converter/jsdoc.ts @@ -163,8 +163,8 @@ function convertTemplateParameters(context: Context, node: ts.JSDoc) { function convertTemplateParameterNodes( context: Context, - nodes: readonly ts.JSDocTemplateTag[] = [] + nodes: readonly ts.JSDocTemplateTag[] | undefined ) { - const params = nodes.flatMap((tag) => tag.typeParameters); + const params = (nodes ?? []).flatMap((tag) => tag.typeParameters); return convertTypeParameterNodes(context, params); } diff --git a/src/lib/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index 6ed36c5e1..87b234937 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -176,9 +176,8 @@ export class SourcePlugin extends ConverterComponent { const project = context.project; const home = project.directory; project.files.forEach((file) => { - const reflections: DeclarationReflection[] = file.reflections.map( - (reflection) => reflection - ); + const reflections: DeclarationReflection[] = + file.reflections.slice(); let directory = home; const path = Path.dirname(file.fileName); From 3e1f77f24365abe5b8187798ea964dc13ce5ffcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 20 Mar 2022 18:30:19 +0000 Subject: [PATCH 21/21] Add `cache` variables to separate line --- src/lib/converter/converter.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts index bba2c83c5..d59b8dccb 100644 --- a/src/lib/converter/converter.ts +++ b/src/lib/converter/converter.ts @@ -389,9 +389,10 @@ export class Converter extends ChildableComponent< } private isExcluded(symbol: ts.Symbol) { - const cache = (this.excludeCache ??= createMinimatch( + this.excludeCache ??= createMinimatch( this.application.options.getValue("exclude") - )); + ); + const cache = this.excludeCache; return (symbol.getDeclarations() ?? []).some((node) => matchesAny(cache, node.getSourceFile().fileName) @@ -400,9 +401,8 @@ export class Converter extends ChildableComponent< /** @internal */ isExternal(symbol: ts.Symbol) { - const cache = (this.externalPatternCache ??= createMinimatch( - this.externalPattern - )); + this.externalPatternCache ??= createMinimatch(this.externalPattern); + const cache = this.externalPatternCache; return (symbol.getDeclarations() ?? []).some((node) => matchesAny(cache, node.getSourceFile().fileName)