From 1e96a2db0e9e641058834b3a839ae93732ec0126 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 23 Apr 2023 12:29:09 -0600 Subject: [PATCH] Improve error messaging for missing entry points Resolves #2242 --- CHANGELOG.md | 13 +++++++++ src/lib/application.ts | 38 ++++++++++++------------ src/lib/utils/entry-point.ts | 48 ++++++++++++++++++++++++------- src/lib/utils/fs.ts | 5 +++- src/lib/utils/package-manifest.ts | 15 ++++++++++ src/test/utils/fs.test.ts | 24 +++++++++++++++- 6 files changed, 112 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d29934ba3..62956cd81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Unreleased +### Features + +- Improved error messaging if a provided entry point could not be converted into a documented module reflection, #2242. +- API: Added support for `g`, `circle`, `ellipse`, `polygon`, and `polyline` svg elements, #2259. + +### Bug Fixes + +- Fixed an infinite loop if more than one entry point was provided, and all entry points were the same. + +### Thanks! + +- @FlippieCoetser + ## v0.24.5 (2023-04-22) ### Features diff --git a/src/lib/application.ts b/src/lib/application.ts index d3d6e1a04..f5f17ee7b 100644 --- a/src/lib/application.ts +++ b/src/lib/application.ts @@ -5,13 +5,7 @@ import { Converter } from "./converter/index"; import { Renderer } from "./output/renderer"; import { Deserializer, JSONOutput, Serializer } from "./serialization"; import type { ProjectReflection } from "./models/index"; -import { - Logger, - ConsoleLogger, - loadPlugins, - writeFile, - normalizePath, -} from "./utils/index"; +import { Logger, ConsoleLogger, loadPlugins, writeFile } from "./utils/index"; import { AbstractComponent, @@ -591,17 +585,25 @@ export class Application extends ChildableComponent< const start = Date.now(); const rootDir = deriveRootDir(this.entryPoints); - this.logger.verbose( - `Derived root dir is ${rootDir}, will expand ${this.entryPoints - .map(normalizePath) - .join(", ")}` - ); - const entryPoints = this.entryPoints.flatMap((entry) => - glob(entry, rootDir) - ); - this.logger.verbose( - `Merging entry points:\n\t${entryPoints.map(nicePath).join("\n\t")}` - ); + const entryPoints = this.entryPoints.flatMap((entry) => { + const result = glob(entry, rootDir); + + if (result.length === 0) { + this.logger.warn( + `The entrypoint glob ${nicePath( + entry + )} did not match any files.` + ); + } else { + this.logger.verbose( + `Expanded ${nicePath(entry)} to:\n\t${result + .map(nicePath) + .join("\n\t")}` + ); + } + + return result; + }); if (entryPoints.length < 1) { this.logger.error("No entry points provided to merge."); diff --git a/src/lib/utils/entry-point.ts b/src/lib/utils/entry-point.ts index 56fef9134..3520e5d0f 100644 --- a/src/lib/utils/entry-point.ts +++ b/src/lib/utils/entry-point.ts @@ -12,7 +12,7 @@ import { import { createMinimatch, matchesAny, nicePath, normalizePath } from "./paths"; import type { Logger } from "./loggers"; import type { Options } from "./options"; -import { deriveRootDir, glob } from "./fs"; +import { deriveRootDir, glob, isDir } from "./fs"; import { assertNever } from "./general"; /** @@ -64,13 +64,18 @@ export function getEntryPoints( ): DocumentationEntryPoint[] | undefined { const entryPoints = options.getValue("entryPoints"); + if (entryPoints.length === 0) { + logger.error("No entry points were provided."); + return; + } + let result: DocumentationEntryPoint[] | undefined; const strategy = options.getValue("entryPointStrategy"); switch (strategy) { case EntryPointStrategy.Resolve: result = getEntryPointsForPaths( logger, - expandGlobs(entryPoints), + expandGlobs(entryPoints, logger), options ); break; @@ -78,7 +83,7 @@ export function getEntryPoints( case EntryPointStrategy.Expand: result = getExpandedEntryPointsForPaths( logger, - expandGlobs(entryPoints), + expandGlobs(entryPoints, logger), options ); break; @@ -101,9 +106,7 @@ export function getEntryPoints( } if (result && result.length === 0) { - logger.error( - "Unable to find any entry points. Make sure TypeDoc can find your tsconfig" - ); + logger.error("Unable to find any entry points. See previous warnings."); return; } @@ -210,10 +213,14 @@ function getEntryPointsForPaths( } } } + + const suggestion = isDir(fileOrDir) + ? " If you wanted to include files inside this directory, set --entryPointStrategy to expand or specify a glob." + : ""; logger.warn( `The entry point ${nicePath( fileOrDir - )} does not exist or is not included in the program for your provided tsconfig.` + )} is not included in the program for your provided tsconfig.${suggestion}` ); } @@ -234,11 +241,30 @@ export function getExpandedEntryPointsForPaths( ); } -function expandGlobs(inputFiles: string[]) { +function expandGlobs(inputFiles: string[], logger: Logger) { const base = deriveRootDir(inputFiles); - const result = inputFiles.flatMap((entry) => - glob(entry, base, { includeDirectories: true, followSymlinks: true }) - ); + const result = inputFiles.flatMap((entry) => { + const result = glob(entry, base, { + includeDirectories: true, + followSymlinks: true, + }); + + if (result.length === 0) { + logger.warn( + `The entrypoint glob ${nicePath( + entry + )} did not match any files.` + ); + } else { + logger.verbose( + `Expanded ${nicePath(entry)} to:\n\t${result + .map(nicePath) + .join("\n\t")}` + ); + } + + return result; + }); return result; } diff --git a/src/lib/utils/fs.ts b/src/lib/utils/fs.ts index 7508e204f..801716a38 100644 --- a/src/lib/utils/fs.ts +++ b/src/lib/utils/fs.ts @@ -57,7 +57,10 @@ export function getCommonDirectory(files: readonly string[]): string { let i = 0; - while (new Set(roots.map((part) => part[i])).size === 1) { + while ( + i < roots[0].length && + new Set(roots.map((part) => part[i])).size === 1 + ) { i++; } diff --git a/src/lib/utils/package-manifest.ts b/src/lib/utils/package-manifest.ts index 2a253152e..5aeed29b3 100644 --- a/src/lib/utils/package-manifest.ts +++ b/src/lib/utils/package-manifest.ts @@ -132,6 +132,21 @@ export function expandPackages( resolve(packageJsonDir, workspace, "package.json"), resolve(packageJsonDir) ); + + if (globbedPackageJsonPaths.length === 0) { + logger.warn( + `The entrypoint glob ${nicePath( + workspace + )} did not match any directories containing package.json.` + ); + } else { + logger.verbose( + `Expanded ${nicePath( + workspace + )} to:\n\t${globbedPackageJsonPaths.map(nicePath).join("\n\t")}` + ); + } + return globbedPackageJsonPaths.flatMap((packageJsonPath) => { if (matchesAny(exclude, dirname(packageJsonPath))) { return []; diff --git a/src/test/utils/fs.test.ts b/src/test/utils/fs.test.ts index af9104d65..1b2456493 100644 --- a/src/test/utils/fs.test.ts +++ b/src/test/utils/fs.test.ts @@ -3,7 +3,7 @@ import { createServer } from "net"; import { Project, tempdirProject } from "@typestrong/fs-fixture-builder"; import { AssertionError, deepStrictEqual as equal } from "assert"; import { basename, dirname, resolve, normalize } from "path"; -import { glob } from "../../lib/utils/fs"; +import { getCommonDirectory, glob } from "../../lib/utils/fs"; describe("fs.ts", () => { let fix: Project; @@ -15,6 +15,28 @@ describe("fs.ts", () => { fix.rm(); }); + describe("getCommonDirectory", () => { + it("Returns the empty string if no files are provided", () => { + equal(getCommonDirectory([]), ""); + }); + + it("Returns the dirname if only one file is provided", () => { + equal(getCommonDirectory(["a/b/c.ts"]), "a/b"); + }); + + it("Handles duplicates paths appropriately", () => { + const p = "a/b/c"; + equal(getCommonDirectory([p, p]), p); + }); + + it("Gets the path common to all files", () => { + equal( + getCommonDirectory(["/a/b/c", "/a/b/c/d/e", "/a/b/d"]), + "/a/b" + ); + }); + }); + describe("glob", () => { it("handles root match", () => { fix.write();