knip 6.34.0 → 6.35.0

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 (79) hide show
  1. package/dist/CatalogCounselor.d.ts +2 -0
  2. package/dist/CatalogCounselor.js +30 -7
  3. package/dist/ConfigurationChief.d.ts +6 -0
  4. package/dist/ConfigurationChief.js +3 -5
  5. package/dist/ProjectPrincipal.d.ts +9 -10
  6. package/dist/ProjectPrincipal.js +45 -52
  7. package/dist/WorkspaceWorker.d.ts +3 -3
  8. package/dist/WorkspaceWorker.js +6 -6
  9. package/dist/YamlCatalogPeeker.d.ts +4 -0
  10. package/dist/YamlCatalogPeeker.js +17 -0
  11. package/dist/binaries/bash-parser.d.ts +1 -1
  12. package/dist/binaries/bash-parser.js +12 -58
  13. package/dist/binaries/command.d.ts +5 -0
  14. package/dist/binaries/command.js +47 -0
  15. package/dist/binaries/fallback.d.ts +2 -0
  16. package/dist/binaries/fallback.js +2 -0
  17. package/dist/binaries/plugins.d.ts +1 -0
  18. package/dist/binaries/plugins.js +2 -1
  19. package/dist/binaries/resolvers/pnpm.js +1 -0
  20. package/dist/binaries/util.d.ts +1 -0
  21. package/dist/binaries/util.js +12 -0
  22. package/dist/cli.js +8 -26
  23. package/dist/compilers/index.d.ts +3 -1866
  24. package/dist/compilers/index.js +17 -27
  25. package/dist/compilers/types.d.ts +4 -5
  26. package/dist/graph/analyze.js +71 -53
  27. package/dist/graph/build.d.ts +3 -3
  28. package/dist/graph/build.js +63 -31
  29. package/dist/plugins/_vue/auto-import.js +28 -4
  30. package/dist/plugins/index.d.ts +1 -0
  31. package/dist/plugins/index.js +2 -0
  32. package/dist/plugins/mise/index.d.ts +3 -0
  33. package/dist/plugins/mise/index.js +82 -0
  34. package/dist/plugins/mise/scripts.d.ts +7 -0
  35. package/dist/plugins/mise/scripts.js +108 -0
  36. package/dist/plugins/mise/types.d.ts +26 -0
  37. package/dist/plugins/mise/types.js +1 -0
  38. package/dist/plugins/rstest/index.js +3 -2
  39. package/dist/plugins/rstest/types.d.ts +3 -1
  40. package/dist/plugins/vite/helpers.d.ts +2 -2
  41. package/dist/plugins/vite/helpers.js +18 -11
  42. package/dist/plugins/vite/visitors/importMetaGlob.js +12 -0
  43. package/dist/plugins/vitest/index.js +5 -2
  44. package/dist/plugins/vitest/types.d.ts +1 -0
  45. package/dist/schema/configuration.d.ts +20 -4
  46. package/dist/schema/configuration.js +5 -6
  47. package/dist/schema/plugins.d.ts +5 -0
  48. package/dist/schema/plugins.js +1 -0
  49. package/dist/session/index.d.ts +1 -1
  50. package/dist/session/index.js +1 -1
  51. package/dist/session/session.js +22 -4
  52. package/dist/types/PluginNames.d.ts +2 -2
  53. package/dist/types/PluginNames.js +1 -0
  54. package/dist/types/config.d.ts +4 -4
  55. package/dist/types/module-graph.d.ts +2 -0
  56. package/dist/types.d.ts +1 -0
  57. package/dist/typescript/SourceFileManager.d.ts +13 -9
  58. package/dist/typescript/SourceFileManager.js +58 -22
  59. package/dist/typescript/get-imports-and-exports.js +2 -1
  60. package/dist/typescript/visitors/exports.js +8 -4
  61. package/dist/util/catalog.d.ts +5 -0
  62. package/dist/util/catalog.js +37 -17
  63. package/dist/util/create-options.d.ts +17 -3
  64. package/dist/util/create-options.js +14 -3
  65. package/dist/util/errors.d.ts +3 -1
  66. package/dist/util/errors.js +6 -1
  67. package/dist/util/file-entry-cache.js +2 -2
  68. package/dist/util/module-graph.js +1 -0
  69. package/dist/util/package-json.d.ts +1 -0
  70. package/dist/util/preprocessor.d.ts +6 -0
  71. package/dist/util/preprocessor.js +24 -0
  72. package/dist/util/reporter.d.ts +0 -1
  73. package/dist/util/reporter.js +0 -7
  74. package/dist/util/watch.d.ts +1 -1
  75. package/dist/util/watch.js +33 -15
  76. package/dist/version.d.ts +1 -1
  77. package/dist/version.js +1 -1
  78. package/package.json +7 -7
  79. package/schema.json +12 -0
@@ -6,12 +6,14 @@ export type CatalogContainer = {
6
6
  filePath: string;
7
7
  catalog?: Catalog;
8
8
  catalogs?: Catalogs;
9
+ overrides?: Catalog;
9
10
  };
10
11
  export declare class CatalogCounselor {
11
12
  private filePath;
12
13
  private entries;
13
14
  private referencedEntries;
14
15
  private referenceIssues;
16
+ private overrideReferences;
15
17
  private fileContent?;
16
18
  constructor(options: MainOptions);
17
19
  private addReferencedCatalogEntry;
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
2
2
  import { ROOT_WORKSPACE_NAME } from './constants.js';
3
3
  import { JsonCatalogPeeker } from './JsonCatalogPeeker.js';
4
4
  import { PackagePeeker } from './PackagePeeker.js';
5
- import { extractCatalogReferences, parseCatalog } from './util/catalog.js';
5
+ import { extractCatalogReferences, getOverrideCatalogReferences, parseCatalog, } from './util/catalog.js';
6
6
  import { extname } from './util/path.js';
7
7
  import { YamlCatalogPeeker } from './YamlCatalogPeeker.js';
8
8
  export class CatalogCounselor {
@@ -10,10 +10,14 @@ export class CatalogCounselor {
10
10
  entries = new Set();
11
11
  referencedEntries = new Set();
12
12
  referenceIssues = [];
13
+ overrideReferences = [];
13
14
  fileContent;
14
15
  constructor(options) {
15
16
  this.filePath = options.catalog.filePath;
16
17
  this.entries = parseCatalog(options.catalog);
18
+ this.overrideReferences = getOverrideCatalogReferences(options.catalog.overrides);
19
+ for (const reference of this.overrideReferences)
20
+ this.addReference(reference);
17
21
  }
18
22
  addReferencedCatalogEntry(entryName) {
19
23
  this.referencedEntries.add(entryName);
@@ -23,14 +27,18 @@ export class CatalogCounselor {
23
27
  }
24
28
  addWorkspace({ name: workspace, manifest, manifestPath: filePath, manifestStr, }) {
25
29
  const catalogReferences = extractCatalogReferences(manifest);
30
+ if (workspace === ROOT_WORKSPACE_NAME) {
31
+ for (const reference of getOverrideCatalogReferences(manifest.pnpm?.overrides))
32
+ catalogReferences.push(reference);
33
+ }
26
34
  if (catalogReferences.length === 0)
27
35
  return;
28
36
  const peeker = new PackagePeeker(manifestStr);
29
- for (const { catalogName, packageName } of catalogReferences) {
37
+ for (const { catalogName, packageName, selector } of catalogReferences) {
30
38
  const catalogEntryName = `${catalogName}:${packageName}`;
31
39
  this.addReferencedCatalogEntry(catalogEntryName);
32
40
  if (!this.entries.has(catalogEntryName)) {
33
- const pos = peeker.getCatalogReferenceLocation(packageName, catalogName);
41
+ const pos = peeker.getCatalogReferenceLocation(selector ?? packageName, catalogName);
34
42
  this.referenceIssues.push({
35
43
  type: 'catalogReferences',
36
44
  filePath,
@@ -47,11 +55,12 @@ export class CatalogCounselor {
47
55
  const filePath = this.filePath;
48
56
  const workspace = ROOT_WORKSPACE_NAME;
49
57
  const catalogIssues = [];
50
- if (this.entries.size > 0) {
58
+ const overrideReferenceIssues = [];
59
+ if (this.entries.size > 0 || this.overrideReferences.length > 0) {
51
60
  this.fileContent = await readFile(filePath, 'utf-8');
52
61
  const isYaml = ['.yml', '.yaml'].includes(extname(filePath));
53
- const Peeker = isYaml ? YamlCatalogPeeker : JsonCatalogPeeker;
54
- const peeker = new Peeker(this.fileContent);
62
+ const yamlPeeker = isYaml ? new YamlCatalogPeeker(this.fileContent) : undefined;
63
+ const peeker = yamlPeeker ?? new JsonCatalogPeeker(this.fileContent);
55
64
  for (const entry of this.entries.keys()) {
56
65
  if (!this.referencedEntries.has(entry)) {
57
66
  const [parentSymbol, symbol] = entry.split(':');
@@ -62,7 +71,21 @@ export class CatalogCounselor {
62
71
  catalogIssues.push({ type: 'catalog', filePath, workspace, symbol, parentSymbol, fixes, ...pos });
63
72
  }
64
73
  }
74
+ for (const { catalogName, packageName, selector } of this.overrideReferences) {
75
+ if (this.entries.has(`${catalogName}:${packageName}`))
76
+ continue;
77
+ const pos = yamlPeeker?.getOverrideCatalogReferenceLocation(selector);
78
+ overrideReferenceIssues.push({
79
+ type: 'catalogReferences',
80
+ filePath,
81
+ workspace,
82
+ symbol: packageName,
83
+ parentSymbol: catalogName,
84
+ fixes: [],
85
+ ...pos,
86
+ });
87
+ }
65
88
  }
66
- return [...catalogIssues, ...this.referenceIssues];
89
+ return [...catalogIssues, ...this.referenceIssues, ...overrideReferenceIssues];
67
90
  }
68
91
  }
@@ -377,6 +377,11 @@ export declare class ConfigurationChief {
377
377
  entry?: string | string[] | undefined;
378
378
  project?: string | string[] | undefined;
379
379
  } | undefined;
380
+ mise?: string | boolean | string[] | {
381
+ config?: string | string[] | undefined;
382
+ entry?: string | string[] | undefined;
383
+ project?: string | string[] | undefined;
384
+ } | undefined;
380
385
  mocha?: string | boolean | string[] | {
381
386
  config?: string | string[] | undefined;
382
387
  entry?: string | string[] | undefined;
@@ -1058,6 +1063,7 @@ export declare class ConfigurationChief {
1058
1063
  mdx?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1059
1064
  mdxlint?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1060
1065
  metro?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1066
+ mise?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1061
1067
  mocha?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1062
1068
  moonrepo?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1063
1069
  msw?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
@@ -1,4 +1,5 @@
1
1
  import picomatch from 'picomatch';
2
+ import { normalizeCompilers } from './compilers/index.js';
2
3
  import { DEFAULT_EXTENSIONS, ROOT_WORKSPACE_NAME } from './constants.js';
3
4
  import { pluginNames } from './types/PluginNames.js';
4
5
  import { arrayify, compact, partition } from './util/array.js';
@@ -41,8 +42,7 @@ const defaultConfig = {
41
42
  ignoreWorkspaces: [],
42
43
  ignoreExportsUsedInFile: false,
43
44
  isIncludeEntryExports: false,
44
- syncCompilers: new Map(),
45
- asyncCompilers: new Map(),
45
+ compilers: new Map(),
46
46
  rootPluginConfigs: {},
47
47
  };
48
48
  export class ConfigurationChief {
@@ -108,7 +108,6 @@ export class ConfigurationChief {
108
108
  const ignoreIssues = rawConfig.ignoreIssues ?? {};
109
109
  const ignoreWorkspaces = rawConfig.ignoreWorkspaces ?? defaultConfig.ignoreWorkspaces;
110
110
  const isIncludeEntryExports = rawConfig.includeEntryExports ?? this.isIncludeEntryExports;
111
- const { syncCompilers, asyncCompilers } = rawConfig;
112
111
  const rootPluginConfigs = {};
113
112
  for (const [pluginName, pluginConfig] of Object.entries(rawConfig)) {
114
113
  if (isPluginName(pluginName)) {
@@ -127,8 +126,7 @@ export class ConfigurationChief {
127
126
  ignoreIssues,
128
127
  ignoreWorkspaces,
129
128
  isIncludeEntryExports,
130
- syncCompilers: new Map(Object.entries(syncCompilers ?? {})),
131
- asyncCompilers: new Map(Object.entries(asyncCompilers ?? {})),
129
+ compilers: normalizeCompilers(rawConfig),
132
130
  rootPluginConfigs,
133
131
  };
134
132
  }
@@ -1,6 +1,6 @@
1
1
  import type { ParseResult } from 'oxc-parser';
2
2
  import { CacheConsultant } from './CacheConsultant.ts';
3
- import type { AsyncCompilers, Compilers, SyncCompilers } from './compilers/types.ts';
3
+ import type { Compilers } from './compilers/types.ts';
4
4
  import type { GetImportsAndExportsOptions, IgnoreExportsUsedInFile, PluginVisitorContext, PluginVisitorObject } from './types/config.ts';
5
5
  import type { FileNode, ModuleGraph } from './types/module-graph.ts';
6
6
  import type { Paths } from './types/project.ts';
@@ -13,14 +13,13 @@ export declare class ProjectPrincipal {
13
13
  projectPaths: Set<string>;
14
14
  programPaths: Set<string>;
15
15
  skipExportsAnalysis: Set<string>;
16
+ private includeExportsAnalysis;
16
17
  pluginCtx: PluginVisitorContext;
17
18
  pluginVisitorObjects: PluginVisitorObject[];
18
19
  private _visitor;
19
20
  private _localRefsVisitor;
20
- syncCompilers: SyncCompilers;
21
- asyncCompilers: AsyncCompilers;
22
- private scopedSyncCompilers;
23
- private scopedAsyncCompilers;
21
+ compilers: Compilers;
22
+ private scopedCompilers;
24
23
  private paths;
25
24
  private rootDirs;
26
25
  private tsConfigFile;
@@ -29,6 +28,7 @@ export declare class ProjectPrincipal {
29
28
  toSourceFilePath: ToSourceFilePath;
30
29
  private findWorkspacePackageTarget;
31
30
  private findWorkspaceNameByFilePath;
31
+ private isReportExports;
32
32
  fileManager: SourceFileManager;
33
33
  private resolveModule;
34
34
  resolveGlobPattern: ResolveGlobPattern;
@@ -40,7 +40,6 @@ export declare class ProjectPrincipal {
40
40
  addPaths(paths: Paths, basePath: string, scope: string): void;
41
41
  addRootDirs(rootDirs: string[] | undefined, scope: string): void;
42
42
  init(): void;
43
- readFile(filePath: string): string;
44
43
  private hasAcceptedExtension;
45
44
  addEntryPath(filePath: string, options?: {
46
45
  skipExportsAnalysis: boolean;
@@ -51,12 +50,12 @@ export declare class ProjectPrincipal {
51
50
  addProgramPath(filePath: string): void;
52
51
  addProjectPath(filePath: string): void;
53
52
  removeProjectPath(filePath: string): void;
54
- runAsyncCompilers(): Promise<void>;
55
- walkAndAnalyze(analyzeFile: (filePath: string, parseResult: ParseResult | undefined, sourceText: string, cachedFile?: FileNode) => Iterable<string> | undefined): void;
56
- getUsedResolvedFiles(): string[];
53
+ walkAndAnalyze(analyzeFile: (filePath: string, parseResult: ParseResult | undefined, sourceText: string, cachedFile?: FileNode) => Iterable<string> | undefined): Promise<void>;
54
+ getUsedResolvedFiles(): Promise<Set<string>>;
57
55
  private resolveSpecifier;
58
56
  getUnreferencedFiles(): string[];
59
- analyzeSourceFile(filePath: string, options: GetImportsAndExportsOptions, ignoreExportsUsedInFile: IgnoreExportsUsedInFile, parseResult?: ParseResult, sourceText?: string, cachedFile?: FileNode): FileNode;
57
+ private getCachedFile;
58
+ analyzeSourceFile(filePath: string, sourceText: string, options: GetImportsAndExportsOptions, ignoreExportsUsedInFile: IgnoreExportsUsedInFile, parseResult?: ParseResult, cachedFile?: FileNode): FileNode;
60
59
  invalidateFile(filePath: string): void;
61
60
  reconcileCache(graph: ModuleGraph): void;
62
61
  }
@@ -1,7 +1,6 @@
1
1
  import { extractSpecifiers } from './typescript/follow-imports.js';
2
2
  import { _parseFile } from './typescript/ast-nodes.js';
3
3
  import { CacheConsultant } from './CacheConsultant.js';
4
- import { getCompilerExtensions } from './compilers/index.js';
5
4
  import { DEFAULT_EXTENSIONS } from './constants.js';
6
5
  import { _getImportsAndExports } from './typescript/get-imports-and-exports.js';
7
6
  import { createBunShellVisitor } from './typescript/visitors/script-visitors.js';
@@ -16,6 +15,7 @@ export class ProjectPrincipal {
16
15
  projectPaths = new Set();
17
16
  programPaths = new Set();
18
17
  skipExportsAnalysis = new Set();
18
+ includeExportsAnalysis = new Set();
19
19
  pluginCtx = {
20
20
  filePath: '',
21
21
  sourceText: '',
@@ -28,10 +28,8 @@ export class ProjectPrincipal {
28
28
  pluginVisitorObjects = [];
29
29
  _visitor;
30
30
  _localRefsVisitor;
31
- syncCompilers = new Map();
32
- asyncCompilers = new Map();
33
- scopedSyncCompilers = new Map();
34
- scopedAsyncCompilers = new Map();
31
+ compilers = new Map();
32
+ scopedCompilers = new Map();
35
33
  paths = new Map();
36
34
  rootDirs = new Map();
37
35
  tsConfigFile;
@@ -40,6 +38,7 @@ export class ProjectPrincipal {
40
38
  toSourceFilePath;
41
39
  findWorkspacePackageTarget;
42
40
  findWorkspaceNameByFilePath;
41
+ isReportExports;
43
42
  fileManager;
44
43
  resolveModule = () => undefined;
45
44
  resolveGlobPattern = pattern => [pattern];
@@ -51,38 +50,25 @@ export class ProjectPrincipal {
51
50
  this.toSourceFilePath = toSourceFilePath;
52
51
  this.findWorkspacePackageTarget = findWorkspacePackageTarget;
53
52
  this.findWorkspaceNameByFilePath = findWorkspaceNameByFilePath;
53
+ this.isReportExports = options.isReportExports;
54
54
  this.tsConfigFile = options.tsConfigFile ? toAbsolute(options.tsConfigFile, options.cwd) : undefined;
55
55
  this.pluginVisitorObjects.push(createBunShellVisitor(this.pluginCtx));
56
56
  this.fileManager = new SourceFileManager({
57
- compilers: [this.syncCompilers, this.asyncCompilers],
57
+ compilers: this.compilers,
58
+ isSession: options.isSession || options.isWatch,
58
59
  });
59
60
  this.walkAndAnalyze = timerify(this.walkAndAnalyze.bind(this), 'walkAndAnalyze');
60
61
  }
61
62
  addCompilers(workspaceName, compilers) {
62
- for (const [ext, compiler] of compilers[0]) {
63
- const workspaceCompilers = this.scopedSyncCompilers.get(ext);
63
+ for (const [ext, compiler] of compilers) {
64
+ const workspaceCompilers = this.scopedCompilers.get(ext);
64
65
  if (workspaceCompilers) {
65
66
  workspaceCompilers.set(workspaceName, compiler);
66
67
  }
67
68
  else {
68
69
  const workspaceCompilers = new Map([[workspaceName, compiler]]);
69
- this.scopedSyncCompilers.set(ext, workspaceCompilers);
70
- this.syncCompilers.set(ext, (source, filePath) => {
71
- const owner = this.findWorkspaceNameByFilePath(filePath);
72
- return ((owner ? workspaceCompilers.get(owner) : undefined) ?? compiler)(source, filePath);
73
- });
74
- this.extensions.add(ext);
75
- }
76
- }
77
- for (const [ext, compiler] of compilers[1]) {
78
- const workspaceCompilers = this.scopedAsyncCompilers.get(ext);
79
- if (workspaceCompilers) {
80
- workspaceCompilers.set(workspaceName, compiler);
81
- }
82
- else {
83
- const workspaceCompilers = new Map([[workspaceName, compiler]]);
84
- this.scopedAsyncCompilers.set(ext, workspaceCompilers);
85
- this.asyncCompilers.set(ext, (source, filePath) => {
70
+ this.scopedCompilers.set(ext, workspaceCompilers);
71
+ this.compilers.set(ext, (source, filePath) => {
86
72
  const owner = this.findWorkspaceNameByFilePath(filePath);
87
73
  return ((owner ? workspaceCompilers.get(owner) : undefined) ?? compiler)(source, filePath);
88
74
  });
@@ -107,19 +93,11 @@ export class ProjectPrincipal {
107
93
  this.rootDirs.set(scope, compact([...scoped, ...rootDirs]));
108
94
  }
109
95
  init() {
110
- this.extensions = new Set([
111
- ...DEFAULT_EXTENSIONS,
112
- ...getCompilerExtensions([this.syncCompilers, this.asyncCompilers]),
113
- ]);
114
- const customCompilerExtensions = getCompilerExtensions([this.syncCompilers, this.asyncCompilers]);
115
96
  const scopedPaths = this.paths.size > 0 ? Array.from(this.paths, ([scope, paths]) => ({ scope, paths })) : undefined;
116
97
  const scopedRootDirs = this.rootDirs.size > 0 ? Array.from(this.rootDirs, ([scope, rootDirs]) => ({ scope, rootDirs })) : undefined;
117
- this.resolveModule = createCustomModuleResolver({ scopedPaths, scopedRootDirs }, customCompilerExtensions, this.toSourceFilePath, this.findWorkspacePackageTarget, this.tsConfigFile);
98
+ this.resolveModule = createCustomModuleResolver({ scopedPaths, scopedRootDirs }, [...this.compilers.keys()], this.toSourceFilePath, this.findWorkspacePackageTarget, this.tsConfigFile);
118
99
  this.resolveGlobPattern = createGlobAliasResolver(scopedPaths);
119
100
  }
120
- readFile(filePath) {
121
- return this.fileManager.readFile(filePath);
122
- }
123
101
  hasAcceptedExtension(filePath) {
124
102
  return this.extensions.has(extname(filePath));
125
103
  }
@@ -127,8 +105,16 @@ export class ProjectPrincipal {
127
105
  if (!isInNodeModules(filePath) && this.hasAcceptedExtension(filePath)) {
128
106
  this.entryPaths.add(filePath);
129
107
  this.projectPaths.add(filePath);
130
- if (options?.skipExportsAnalysis)
131
- this.skipExportsAnalysis.add(filePath);
108
+ if (options) {
109
+ if (options.skipExportsAnalysis) {
110
+ if (!this.includeExportsAnalysis.has(filePath))
111
+ this.skipExportsAnalysis.add(filePath);
112
+ }
113
+ else {
114
+ this.includeExportsAnalysis.add(filePath);
115
+ this.skipExportsAnalysis.delete(filePath);
116
+ }
117
+ }
132
118
  this.onPathAdded?.(filePath);
133
119
  }
134
120
  }
@@ -151,23 +137,19 @@ export class ProjectPrincipal {
151
137
  removeProjectPath(filePath) {
152
138
  this.entryPaths.delete(filePath);
153
139
  this.projectPaths.delete(filePath);
140
+ this.skipExportsAnalysis.delete(filePath);
141
+ this.includeExportsAnalysis.delete(filePath);
154
142
  this.invalidateFile(filePath);
155
143
  this.deletedFiles.add(filePath);
156
144
  }
157
- async runAsyncCompilers() {
158
- const add = timerify(this.fileManager.compileAndAddSourceFile.bind(this.fileManager));
159
- for (const filePath of this.projectPaths)
160
- if (this.asyncCompilers.has(extname(filePath)))
161
- await add(filePath);
162
- }
163
- walkAndAnalyze(analyzeFile) {
145
+ async walkAndAnalyze(analyzeFile) {
164
146
  this.resolvedFiles.clear();
165
147
  const visited = new Set([...this.entryPaths, ...this.programPaths]);
166
148
  this.onPathAdded = p => visited.add(p);
167
149
  try {
168
150
  for (const filePath of visited) {
169
151
  const isProjectPath = this.projectPaths.has(filePath);
170
- const cachedFile = isProjectPath ? this.cache.getCachedFile(filePath) : undefined;
152
+ const cachedFile = isProjectPath ? this.getCachedFile(filePath) : undefined;
171
153
  if (cachedFile) {
172
154
  const internalPaths = analyzeFile(filePath, undefined, '', cachedFile);
173
155
  if (internalPaths)
@@ -175,7 +157,8 @@ export class ProjectPrincipal {
175
157
  visited.add(p);
176
158
  continue;
177
159
  }
178
- const sourceText = this.fileManager.readFile(filePath);
160
+ const loaded = this.fileManager.loadSourceText(filePath);
161
+ const sourceText = typeof loaded === 'string' ? loaded : await loaded;
179
162
  if (!sourceText) {
180
163
  if (isProjectPath)
181
164
  analyzeFile(filePath, undefined, '');
@@ -207,11 +190,12 @@ export class ProjectPrincipal {
207
190
  }
208
191
  this.resolvedFiles = visited;
209
192
  }
210
- getUsedResolvedFiles() {
193
+ async getUsedResolvedFiles() {
211
194
  this.resolvedFiles.clear();
212
195
  const visited = new Set([...this.entryPaths, ...this.programPaths]);
213
196
  for (const filePath of visited) {
214
- const sourceText = this.fileManager.readFile(filePath);
197
+ const loaded = this.fileManager.loadSourceText(filePath);
198
+ const sourceText = typeof loaded === 'string' ? loaded : await loaded;
215
199
  if (!sourceText)
216
200
  continue;
217
201
  try {
@@ -226,7 +210,11 @@ export class ProjectPrincipal {
226
210
  }
227
211
  }
228
212
  this.resolvedFiles = visited;
229
- return Array.from(this.projectPaths).filter(filePath => visited.has(filePath));
213
+ const usedFiles = new Set();
214
+ for (const filePath of this.projectPaths)
215
+ if (visited.has(filePath))
216
+ usedFiles.add(filePath);
217
+ return usedFiles;
230
218
  }
231
219
  resolveSpecifier(specifier, containingFile) {
232
220
  return this.resolveModule(specifier, containingFile)?.resolvedFileName;
@@ -234,17 +222,21 @@ export class ProjectPrincipal {
234
222
  getUnreferencedFiles() {
235
223
  return Array.from(this.projectPaths).filter(filePath => !this.resolvedFiles.has(filePath));
236
224
  }
237
- analyzeSourceFile(filePath, options, ignoreExportsUsedInFile, parseResult, sourceText, cachedFile) {
225
+ getCachedFile(filePath) {
226
+ const cachedFile = this.cache.getCachedFile(filePath);
227
+ const skipExports = this.skipExportsAnalysis.has(filePath) || !this.isReportExports;
228
+ return cachedFile?.skipExports === skipExports ? cachedFile : undefined;
229
+ }
230
+ analyzeSourceFile(filePath, sourceText, options, ignoreExportsUsedInFile, parseResult, cachedFile) {
238
231
  if (cachedFile)
239
232
  return cachedFile;
240
- const cached = this.cache.getCachedFile(filePath);
233
+ const cached = this.getCachedFile(filePath);
241
234
  if (cached)
242
235
  return cached;
243
- sourceText ??= this.fileManager.readFile(filePath);
244
236
  const skipExports = this.skipExportsAnalysis.has(filePath);
245
237
  if (options.isFixExports || options.isFixTypes) {
246
238
  const ext = extname(filePath);
247
- if (!DEFAULT_EXTENSIONS.has(ext) && (this.syncCompilers.has(ext) || this.asyncCompilers.has(ext))) {
239
+ if (!DEFAULT_EXTENSIONS.has(ext) && this.compilers.has(ext)) {
248
240
  options = { ...options, isFixExports: false, isFixTypes: false };
249
241
  }
250
242
  }
@@ -255,6 +247,7 @@ export class ProjectPrincipal {
255
247
  }
256
248
  invalidateFile(filePath) {
257
249
  this.fileManager.invalidate(filePath);
250
+ this.cache.removeEntry(filePath);
258
251
  }
259
252
  reconcileCache(graph) {
260
253
  for (const [filePath, file] of graph) {
@@ -18,7 +18,7 @@ type WorkspaceManagerOptions = {
18
18
  handleInput: HandleInput;
19
19
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
20
20
  getManifest: (dir: string) => Manifest | undefined;
21
- readFile: (filePath: string) => string;
21
+ readRawFile: (filePath: string) => string;
22
22
  negatedWorkspacePatterns: string[];
23
23
  ignoredWorkspacePatterns: string[];
24
24
  enabledPluginsInAncestors: string[];
@@ -40,7 +40,7 @@ export declare class WorkspaceWorker {
40
40
  handleInput: HandleInput;
41
41
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
42
42
  getManifest: (dir: string) => Manifest | undefined;
43
- readFile: (filePath: string) => string;
43
+ readRawFile: (filePath: string) => string;
44
44
  negatedWorkspacePatterns: string[];
45
45
  ignoredWorkspacePatterns: string[];
46
46
  options: MainOptions;
@@ -49,7 +49,7 @@ export declare class WorkspaceWorker {
49
49
  enabledPluginsInAncestors: string[];
50
50
  cache: CacheConsultant<CacheItem>;
51
51
  configFilesMap: Map<string, Map<PluginName, Set<string>>>;
52
- constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getManifest, readFile, configFilesMap, options, }: WorkspaceManagerOptions);
52
+ constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getManifest, readRawFile, configFilesMap, options, }: WorkspaceManagerOptions);
53
53
  init(): Promise<void>;
54
54
  private determineEnabledPlugins;
55
55
  private getConfigForPlugin;
@@ -31,7 +31,7 @@ export class WorkspaceWorker {
31
31
  handleInput;
32
32
  findWorkspaceByFilePath;
33
33
  getManifest;
34
- readFile;
34
+ readRawFile;
35
35
  negatedWorkspacePatterns = [];
36
36
  ignoredWorkspacePatterns = [];
37
37
  options;
@@ -40,7 +40,7 @@ export class WorkspaceWorker {
40
40
  enabledPluginsInAncestors;
41
41
  cache;
42
42
  configFilesMap;
43
- constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getManifest, readFile, configFilesMap, options, }) {
43
+ constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getManifest, readRawFile, configFilesMap, options, }) {
44
44
  this.name = name;
45
45
  this.dir = dir;
46
46
  this.config = config;
@@ -54,7 +54,7 @@ export class WorkspaceWorker {
54
54
  this.handleInput = handleInput;
55
55
  this.findWorkspaceByFilePath = findWorkspaceByFilePath;
56
56
  this.getManifest = getManifest;
57
- this.readFile = readFile;
57
+ this.readRawFile = readRawFile;
58
58
  this.options = options;
59
59
  this.cache = new CacheConsultant(`plugins-${name}`, options);
60
60
  this.getConfigurationHints = timerify(this.getConfigurationHints.bind(this), 'getConfigurationHints');
@@ -341,7 +341,7 @@ export class WorkspaceWorker {
341
341
  parsed = parsedConfigCache.get(configFilePath);
342
342
  }
343
343
  else {
344
- const sourceText = this.readFile(configFilePath);
344
+ const sourceText = this.readRawFile(configFilePath);
345
345
  parsed = sourceText ? _parseFile(configFilePath, sourceText) : undefined;
346
346
  parsedConfigCache.set(configFilePath, parsed);
347
347
  }
@@ -387,7 +387,7 @@ export class WorkspaceWorker {
387
387
  }
388
388
  }
389
389
  if (plugin.resolveFromAST && parsed) {
390
- const resolveASTOpts = { ...resolveOpts, readFile: this.readFile };
390
+ const resolveASTOpts = { ...resolveOpts, readFile: this.readRawFile };
391
391
  const inputs = plugin.resolveFromAST(parsed.program, resolveASTOpts);
392
392
  for (const input of inputs)
393
393
  addInput(input, configFilePath);
@@ -461,7 +461,7 @@ export class WorkspaceWorker {
461
461
  if (visited.has(filePath))
462
462
  return;
463
463
  visited.add(filePath);
464
- const sourceText = this.readFile(filePath);
464
+ const sourceText = this.readRawFile(filePath);
465
465
  if (!sourceText)
466
466
  return;
467
467
  for (const literal of collectStringLiterals(sourceText, filePath)) {
@@ -9,4 +9,8 @@ export declare class YamlCatalogPeeker {
9
9
  line: number;
10
10
  col: number;
11
11
  } | undefined;
12
+ getOverrideCatalogReferenceLocation(selector: string): {
13
+ line: number;
14
+ col: number;
15
+ } | undefined;
12
16
  }
@@ -22,6 +22,9 @@ export class YamlCatalogPeeker {
22
22
  else if (line.startsWith('catalogs:')) {
23
23
  this.sections.catalogs = i;
24
24
  }
25
+ else if (line.startsWith('overrides:')) {
26
+ this.sections.overrides = i;
27
+ }
25
28
  }
26
29
  this.ready = true;
27
30
  }
@@ -63,4 +66,18 @@ export class YamlCatalogPeeker {
63
66
  }
64
67
  }
65
68
  }
69
+ getOverrideCatalogReferenceLocation(selector) {
70
+ if (!this.ready)
71
+ this.init();
72
+ const startLine = this.sections.overrides;
73
+ if (typeof startLine === 'undefined')
74
+ return;
75
+ for (let i = startLine + 1; i < this.lines.length; i++) {
76
+ const line = this.lines[i];
77
+ if (!line.startsWith(' '))
78
+ break;
79
+ if (matchesKey(line, ' ', selector))
80
+ return { line: i + 1, col: line.indexOf(selector) + 1 };
81
+ }
82
+ }
66
83
  }
@@ -1,3 +1,3 @@
1
1
  import type { GetInputsFromScriptsOptions } from '../types/config.ts';
2
- import { type Input } from '../util/input.ts';
2
+ import type { Input } from '../util/input.ts';
3
3
  export declare const getDependenciesFromScript: (script: string, options: GetInputsFromScriptsOptions) => Input[];
@@ -1,16 +1,11 @@
1
1
  import { parse } from 'unbash';
2
- import { Plugins, pluginArgsMap } from '../plugins.js';
3
2
  import { debugLogObject } from '../util/debug.js';
4
- import { toBinary, toDeferResolve } from '../util/input.js';
5
3
  import { extractBinary, isValidBinary } from '../util/modules.js';
6
4
  import { relative } from '../util/path.js';
7
5
  import { substringBefore, truncate } from '../util/string.js';
8
6
  import { walkCommands } from '../util/scripts.js';
9
- import { resolve as fallbackResolve } from './fallback.js';
10
- import KnownResolvers from './resolvers/index.js';
11
- import { resolve as resolverFromPlugins } from './plugins.js';
12
- import { parseNodeArgs } from './util.js';
13
- const spawningBinaries = ['cross-env', 'retry-cli'];
7
+ import { getDependenciesFromCommand } from './command.js';
8
+ import { toScript } from './util.js';
14
9
  const collectExpansionScripts = (word, out) => {
15
10
  if (!word.parts)
16
11
  return;
@@ -35,21 +30,19 @@ export const getDependenciesFromScript = (script, options) => {
35
30
  const first = typeof args[0] === 'string' ? args[0] : args[0].value;
36
31
  if (!isValidBinary(substringBefore(first, ' ')))
37
32
  return [];
38
- const parts = [];
39
- for (const arg of args) {
40
- if (typeof arg === 'string') {
41
- if (arg !== '--')
42
- parts.push(arg);
43
- }
44
- else if (arg.value !== '--')
45
- parts.push(arg.text);
46
- }
47
- return getDependenciesFromScript(parts.join(' '), {
33
+ return getDependenciesFromScript(toScript(args), {
48
34
  ...options,
49
35
  knownBinsOnly: false,
50
36
  ...opts,
51
37
  });
52
38
  };
39
+ const fromWords = (words, opts) => {
40
+ const script = words
41
+ .filter(word => word.text !== '--')
42
+ .map(word => word.text)
43
+ .join(' ');
44
+ return getDependenciesFromScript(script, opts);
45
+ };
53
46
  const definedFunctions = new Set();
54
47
  const collectFunctionNames = (statements) => {
55
48
  for (const stmt of statements)
@@ -68,8 +61,6 @@ export const getDependenciesFromScript = (script, options) => {
68
61
  return [...mainDeps, ...expansionDeps];
69
62
  };
70
63
  const processCommand = (node, pending) => {
71
- const text = node.name?.value;
72
- const binary = text ? extractBinary(text) : text;
73
64
  if (node.name)
74
65
  collectExpansionScripts(node.name, pending);
75
66
  for (const prefix of node.prefix)
@@ -77,46 +68,9 @@ export const getDependenciesFromScript = (script, options) => {
77
68
  collectExpansionScripts(prefix.value, pending);
78
69
  for (const suffix of node.suffix)
79
70
  collectExpansionScripts(suffix, pending);
80
- if (!binary || binary === '.' || binary === 'source' || binary === '[')
81
- return [];
82
- if (binary.startsWith('-') || binary.startsWith('..'))
83
- return [];
84
- if (definedFunctions.has(binary))
85
- return [];
86
- const words = node.suffix;
87
- if (binary === '!' || binary === 'test')
88
- return fromArgs(words);
89
- const fromNodeOptions = node.prefix
90
- .filter(a => a.name === 'NODE_OPTIONS' && a.value)
91
- .map(a => a.value.value)
92
- .map(arg => parseNodeArgs(arg.split(' ')))
93
- .filter(args => args.require)
94
- .flatMap(arg => arg.require)
95
- .map(id => toDeferResolve(id));
96
- if (binary in KnownResolvers) {
97
- const resolver = KnownResolvers[binary];
98
- return resolver(binary, words, { ...options, fromArgs });
99
- }
100
- if (pluginArgsMap.has(binary)) {
101
- return [...resolverFromPlugins(binary, words, { ...options, fromArgs }), ...fromNodeOptions];
102
- }
103
- if (spawningBinaries.includes(binary)) {
104
- const rest = node.suffix
105
- .filter(w => w.text !== '--')
106
- .map(w => w.text)
107
- .join(' ');
108
- return [toBinary(binary), ...getDependenciesFromScript(rest, options)];
109
- }
110
- if (binary in Plugins) {
111
- const inputs = fallbackResolve(binary, words, { ...options, fromArgs });
112
- if (options.knownBinsOnly)
113
- for (const input of inputs)
114
- input.optional = true;
115
- return [...inputs, ...fromNodeOptions];
116
- }
117
- if (options.knownBinsOnly && !text?.startsWith('.'))
71
+ if (definedFunctions.size && node.name && definedFunctions.has(extractBinary(node.name.value)))
118
72
  return [];
119
- return [...fallbackResolve(binary, words, { ...options, fromArgs }), ...fromNodeOptions];
73
+ return getDependenciesFromCommand(node, { ...options, fromArgs }, fromWords);
120
74
  };
121
75
  try {
122
76
  const parsed = parse(script);