From d248684bf941c4fc26ce16569e23a2f21f278a6d Mon Sep 17 00:00:00 2001 From: Bodil Stokke <17880+bodil@users.noreply.github.com> Date: Tue, 26 Jul 2022 13:26:41 +0100 Subject: [PATCH 1/2] Decide a ReferenceType's package name by looking for a package.json. --- src/lib/models/types.ts | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/lib/models/types.ts b/src/lib/models/types.ts index ce4fc8db4..98da1764f 100644 --- a/src/lib/models/types.ts +++ b/src/lib/models/types.ts @@ -1,3 +1,6 @@ +import * as fs from "fs"; +import * as path from "path"; + import type * as ts from "typescript"; import type { Context } from "../converter"; import { Reflection } from "./reflections/abstract"; @@ -847,18 +850,28 @@ export class ReferenceType extends Type { .fileName.replace(/\\/g, "/"); if (!symbolPath) return ref; - let startIndex = symbolPath.indexOf("node_modules/"); - if (startIndex === -1) return ref; - startIndex += "node_modules/".length; - let stopIndex = symbolPath.indexOf("/", startIndex); - // Scoped package, e.g. `@types/node` - if (symbolPath[startIndex] === "@") { - stopIndex = symbolPath.indexOf("/", stopIndex + 1); + function findPackageForPath(sourcePath: string): string | undefined { + let basePath = sourcePath; + for (;;) { + const nextPath = path.dirname(basePath); + if (nextPath === basePath) { + return; + } + basePath = nextPath; + const projectPath = path.join(basePath, "package.json"); + try { + const packageJsonData = fs.readFileSync(projectPath, { + encoding: "utf8", + }); + const packageJson = JSON.parse(packageJsonData); + return packageJson.name; + } catch (err) { + continue; + } + } } - const packageName = symbolPath.substring(startIndex, stopIndex); - ref.package = packageName; - + ref.package = findPackageForPath(symbolPath); return ref; } From 65dfba35dbd1cba268bda4b8a03acc3abcf8fa39 Mon Sep 17 00:00:00 2001 From: Bodil Stokke <17880+bodil@users.noreply.github.com> Date: Wed, 27 Jul 2022 15:41:33 +0100 Subject: [PATCH 2/2] Try looking for a node_modules path first, and cache expensive lookups. --- src/lib/models/types.ts | 59 ++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/src/lib/models/types.ts b/src/lib/models/types.ts index 98da1764f..178e48e46 100644 --- a/src/lib/models/types.ts +++ b/src/lib/models/types.ts @@ -850,27 +850,21 @@ export class ReferenceType extends Type { .fileName.replace(/\\/g, "/"); if (!symbolPath) return ref; - function findPackageForPath(sourcePath: string): string | undefined { - let basePath = sourcePath; - for (;;) { - const nextPath = path.dirname(basePath); - if (nextPath === basePath) { - return; - } - basePath = nextPath; - const projectPath = path.join(basePath, "package.json"); - try { - const packageJsonData = fs.readFileSync(projectPath, { - encoding: "utf8", - }); - const packageJson = JSON.parse(packageJsonData); - return packageJson.name; - } catch (err) { - continue; - } + // Attempt to decide package name from path if it contains "node_modules" + let startIndex = symbolPath.lastIndexOf("node_modules/"); + if (startIndex !== -1) { + startIndex += "node_modules/".length; + let stopIndex = symbolPath.indexOf("/", startIndex); + // Scoped package, e.g. `@types/node` + if (symbolPath[startIndex] === "@") { + stopIndex = symbolPath.indexOf("/", stopIndex + 1); } + const packageName = symbolPath.substring(startIndex, stopIndex); + ref.package = packageName; + return ref; } + // Otherwise, look for a "package.json" file in a parent path ref.package = findPackageForPath(symbolPath); return ref; } @@ -1300,3 +1294,32 @@ export class UnknownType extends Type { }; } } + +const packageJsonLookupCache: Record = {}; + +function findPackageForPath(sourcePath: string): string | undefined { + if (packageJsonLookupCache[sourcePath] !== undefined) { + return packageJsonLookupCache[sourcePath]; + } + let basePath = sourcePath; + for (;;) { + const nextPath = path.dirname(basePath); + if (nextPath === basePath) { + return; + } + basePath = nextPath; + const projectPath = path.join(basePath, "package.json"); + try { + const packageJsonData = fs.readFileSync(projectPath, { + encoding: "utf8", + }); + const packageJson = JSON.parse(packageJsonData); + if (packageJson.name !== undefined) { + packageJsonLookupCache[sourcePath] = packageJson.name; + } + return packageJson.name; + } catch (err) { + continue; + } + } +}