knip 6.13.1 → 6.14.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 (40) hide show
  1. package/dist/CacheConsultant.d.ts +3 -3
  2. package/dist/CacheConsultant.js +13 -16
  3. package/dist/ConfigurationChief.d.ts +1 -0
  4. package/dist/ConfigurationChief.js +11 -2
  5. package/dist/DependencyDeputy.d.ts +3 -0
  6. package/dist/DependencyDeputy.js +28 -8
  7. package/dist/ProjectPrincipal.d.ts +1 -0
  8. package/dist/ProjectPrincipal.js +43 -52
  9. package/dist/WorkspaceWorker.js +3 -3
  10. package/dist/cli.js +1 -1
  11. package/dist/graph/build.js +1 -0
  12. package/dist/plugins/nuxt/helpers.js +3 -3
  13. package/dist/plugins/nx/index.js +1 -3
  14. package/dist/plugins/sst/resolveFromAST.js +2 -2
  15. package/dist/run.js +7 -2
  16. package/dist/typescript/ast-helpers.js +2 -2
  17. package/dist/typescript/ast-nodes.d.ts +1 -1
  18. package/dist/typescript/ast-nodes.js +3 -1
  19. package/dist/typescript/get-imports-and-exports.js +4 -4
  20. package/dist/typescript/visitors/walk.d.ts +2 -1
  21. package/dist/typescript/visitors/walk.js +3 -1
  22. package/dist/util/Performance.d.ts +3 -1
  23. package/dist/util/Performance.js +6 -2
  24. package/dist/util/cli-arguments.d.ts +2 -1
  25. package/dist/util/cli-arguments.js +52 -50
  26. package/dist/util/disk-cache.d.ts +10 -0
  27. package/dist/util/disk-cache.js +62 -0
  28. package/dist/util/file-entry-cache.d.ts +0 -7
  29. package/dist/util/file-entry-cache.js +15 -53
  30. package/dist/util/gitignore-cache.d.ts +12 -0
  31. package/dist/util/gitignore-cache.js +77 -0
  32. package/dist/util/glob-cache.d.ts +2 -2
  33. package/dist/util/glob-cache.js +9 -57
  34. package/dist/util/glob-core.d.ts +4 -0
  35. package/dist/util/glob-core.js +14 -1
  36. package/dist/util/glob.js +12 -6
  37. package/dist/util/module-graph.js +17 -13
  38. package/dist/version.d.ts +1 -1
  39. package/dist/version.js +1 -1
  40. package/package.json +1 -1
@@ -1,9 +1,9 @@
1
1
  import type { MainOptions } from './util/create-options.ts';
2
2
  import { type FileDescriptor } from './util/file-entry-cache.ts';
3
3
  export declare class CacheConsultant<T> {
4
- private isEnabled;
5
4
  private cache;
5
+ getFileDescriptor: (filePath: string) => FileDescriptor<T>;
6
+ reconcile: () => void;
6
7
  constructor(name: string, options: MainOptions);
7
- getFileDescriptor(filePath: string): FileDescriptor<T>;
8
- reconcile(): void;
8
+ getCachedFile(filePath: string): T | undefined;
9
9
  }
@@ -3,24 +3,21 @@ import { timerify } from './util/Performance.js';
3
3
  import { version } from './version.js';
4
4
  const dummyFileDescriptor = { key: '', changed: true, notFound: true };
5
5
  export class CacheConsultant {
6
- isEnabled;
7
6
  cache;
7
+ getFileDescriptor = () => dummyFileDescriptor;
8
+ reconcile = () => { };
8
9
  constructor(name, options) {
9
- this.isEnabled = options.isCache;
10
- if (this.isEnabled) {
11
- const cacheName = `${name.replace(/[^a-z0-9]/g, '-').replace(/-*$/, '')}-${options.isProduction ? '-prod' : ''}-${version}`;
12
- this.cache = new FileEntryCache(cacheName, options.cacheLocation);
13
- this.reconcile = timerify(this.cache.reconcile).bind(this.cache);
14
- this.getFileDescriptor = timerify(this.cache.getFileDescriptor).bind(this.cache);
15
- }
10
+ if (!options.isCache)
11
+ return;
12
+ const cacheName = `${name.replace(/[^a-z0-9]/g, '-').replace(/-*$/, '')}-${options.isProduction ? '-prod' : ''}-${version}`;
13
+ this.cache = new FileEntryCache(cacheName, options.cacheLocation);
14
+ this.getFileDescriptor = timerify(this.cache.getFileDescriptor.bind(this.cache));
15
+ this.reconcile = timerify(this.cache.reconcile.bind(this.cache));
16
16
  }
17
- getFileDescriptor(filePath) {
18
- if (this.isEnabled && this.cache)
19
- return this.cache.getFileDescriptor(filePath);
20
- return dummyFileDescriptor;
21
- }
22
- reconcile() {
23
- if (this.isEnabled && this.cache)
24
- this.cache.reconcile();
17
+ getCachedFile(filePath) {
18
+ if (!this.cache)
19
+ return undefined;
20
+ const fd = this.cache.getFileDescriptor(filePath);
21
+ return !fd.changed ? fd.meta?.data : undefined;
25
22
  }
26
23
  }
@@ -35,6 +35,7 @@ export declare class ConfigurationChief {
35
35
  availableWorkspaceNames: string[];
36
36
  availableWorkspacePkgNames: Set<string>;
37
37
  availableWorkspaceDirs: string[];
38
+ private availableWorkspaceDirsWithSlash;
38
39
  workspaceGraph: WorkspaceGraph;
39
40
  private workspaceByFileCache;
40
41
  constructor(options: MainOptions);
@@ -8,6 +8,7 @@ import { _dirGlob, removeProductionSuffix } from './util/glob.js';
8
8
  import { graphSequencer } from './util/graph-sequencer.js';
9
9
  import mapWorkspaces from './util/map-workspaces.js';
10
10
  import { join, relative } from './util/path.js';
11
+ import { timerify } from './util/Performance.js';
11
12
  import { normalizePluginConfig } from './util/plugin.js';
12
13
  import { toRegexOrString } from './util/regex.js';
13
14
  import { ELLIPSIS } from './util/string.js';
@@ -63,6 +64,7 @@ export class ConfigurationChief {
63
64
  availableWorkspaceNames = [];
64
65
  availableWorkspacePkgNames = new Set();
65
66
  availableWorkspaceDirs = [];
67
+ availableWorkspaceDirsWithSlash = [];
66
68
  workspaceGraph = new Map();
67
69
  workspaceByFileCache = new Map();
68
70
  constructor(options) {
@@ -74,6 +76,7 @@ export class ConfigurationChief {
74
76
  this.workspaces = options.workspaces;
75
77
  this.rawConfig = options.parsedConfig;
76
78
  this.config = this.normalize(options.parsedConfig ?? {});
79
+ this.findWorkspaceByFilePath = timerify(this.findWorkspaceByFilePath.bind(this), 'findWorkspaceByFilePath');
77
80
  }
78
81
  getConfigurationHints() {
79
82
  const hints = [];
@@ -139,6 +142,7 @@ export class ConfigurationChief {
139
142
  .sort(byPathDepth)
140
143
  .reverse()
141
144
  .map(dir => join(this.cwd, dir));
145
+ this.availableWorkspaceDirsWithSlash = this.availableWorkspaceDirs.map(dir => `${dir}/`);
142
146
  this.workspaceGraph = createWorkspaceGraph(this.cwd, this.availableWorkspaceNames, wsPkgNames, packages);
143
147
  this.selectedWorkspaces = this.getSelectedWorkspaces();
144
148
  this.workspaceFilePathFilter = createWorkspaceFilePathFilter(this.cwd, this.selectedWorkspaces, this.availableWorkspaceNames);
@@ -347,8 +351,13 @@ export class ConfigurationChief {
347
351
  findWorkspaceByFilePath(filePath) {
348
352
  if (this.workspaceByFileCache.has(filePath))
349
353
  return this.workspaceByFileCache.get(filePath);
350
- const workspaceDir = this.availableWorkspaceDirs.find(workspaceDir => filePath.startsWith(`${workspaceDir}/`));
351
- const workspace = workspaceDir ? this.workspacesByDir.get(workspaceDir) : undefined;
354
+ let workspace;
355
+ for (let i = 0; i < this.availableWorkspaceDirsWithSlash.length; i++) {
356
+ if (filePath.startsWith(this.availableWorkspaceDirsWithSlash[i])) {
357
+ workspace = this.workspacesByDir.get(this.availableWorkspaceDirs[i]);
358
+ break;
359
+ }
360
+ }
352
361
  this.workspaceByFileCache.set(filePath, workspace);
353
362
  return workspace;
354
363
  }
@@ -8,6 +8,7 @@ export declare class DependencyDeputy {
8
8
  isStrict: boolean;
9
9
  isReportDependencies: boolean;
10
10
  _manifests: WorkspaceManifests;
11
+ workspacePkgNames: Set<string>;
11
12
  referencedDependencies: Map<string, Set<string>>;
12
13
  referencedBinaries: Map<string, Set<string>>;
13
14
  hostDependencies: Map<string, HostDependencies>;
@@ -43,8 +44,10 @@ export declare class DependencyDeputy {
43
44
  unusedIgnoreBinaries: Set<string | RegExp>;
44
45
  unusedIgnoreUnresolved: Set<string | RegExp>;
45
46
  } | undefined;
47
+ setWorkspacePkgNames(pkgNames: Iterable<string>): void;
46
48
  getProductionDependencies(workspaceName: string): DependencyArray;
47
49
  getDevDependencies(workspaceName: string): DependencyArray;
50
+ private dependencyCache;
48
51
  getDependencies(workspaceName: string): DependencySet;
49
52
  setInstalledBinaries(workspaceName: string, installedBinaries: Map<string, Set<string>>): void;
50
53
  getInstalledBinaries(workspaceName: string): InstalledBinaries | undefined;
@@ -10,6 +10,7 @@ export class DependencyDeputy {
10
10
  isStrict;
11
11
  isReportDependencies;
12
12
  _manifests = new Map();
13
+ workspacePkgNames = new Set();
13
14
  referencedDependencies;
14
15
  referencedBinaries;
15
16
  hostDependencies;
@@ -39,11 +40,7 @@ export class DependencyDeputy {
39
40
  const requiredPeerDependencies = peerDependencies.filter(dep => !optionalPeerDependencies.has(dep));
40
41
  const devDependencies = Object.keys(manifest.devDependencies ?? {});
41
42
  const allDependencies = [...dependencies, ...devDependencies, ...peerDependencies, ...optionalDependencies];
42
- const packageNames = [
43
- ...dependencies,
44
- ...(this.isStrict ? peerDependencies : []),
45
- ...(this.isProduction ? [] : devDependencies),
46
- ];
43
+ const packageNames = [...dependencies, ...peerDependencies, ...(this.isProduction ? [] : devDependencies)];
47
44
  if (this.isReportDependencies) {
48
45
  const { hostDependencies, installedBinaries, hasTypesIncluded } = getDependencyMetaData({
49
46
  packageNames,
@@ -79,6 +76,9 @@ export class DependencyDeputy {
79
76
  getWorkspaceManifest(workspaceName) {
80
77
  return this._manifests.get(workspaceName);
81
78
  }
79
+ setWorkspacePkgNames(pkgNames) {
80
+ this.workspacePkgNames = new Set(pkgNames);
81
+ }
82
82
  getProductionDependencies(workspaceName) {
83
83
  const manifest = this._manifests.get(workspaceName);
84
84
  if (!manifest)
@@ -90,11 +90,15 @@ export class DependencyDeputy {
90
90
  getDevDependencies(workspaceName) {
91
91
  return this._manifests.get(workspaceName)?.devDependencies ?? [];
92
92
  }
93
+ dependencyCache = new Map();
93
94
  getDependencies(workspaceName) {
95
+ let deps = this.dependencyCache.get(workspaceName);
96
+ if (deps)
97
+ return deps;
94
98
  const manifest = this._manifests.get(workspaceName);
95
- if (!manifest)
96
- return new Set();
97
- return new Set([...manifest.dependencies, ...manifest.devDependencies]);
99
+ deps = manifest ? new Set([...manifest.dependencies, ...manifest.devDependencies]) : new Set();
100
+ this.dependencyCache.set(workspaceName, deps);
101
+ return deps;
98
102
  }
99
103
  setInstalledBinaries(workspaceName, installedBinaries) {
100
104
  this.installedBinaries.set(workspaceName, installedBinaries);
@@ -153,6 +157,22 @@ export class DependencyDeputy {
153
157
  return true;
154
158
  if (this._manifests.get(workspace.name)?.engines[packageName])
155
159
  return true;
160
+ if (!this.isStrict && this.workspacePkgNames.has(packageName)) {
161
+ this.addReferencedDependency(workspace.name, packageName);
162
+ return true;
163
+ }
164
+ if (!this.isStrict) {
165
+ for (const name of workspaceNames) {
166
+ const hosts = this.getHostDependenciesFor(name, packageName);
167
+ if (hosts.length === 0)
168
+ continue;
169
+ const m = this._manifests.get(name);
170
+ if (m && hosts.some(h => m.allDependencies.has(h.name))) {
171
+ this.addReferencedDependency(name, packageName);
172
+ return true;
173
+ }
174
+ }
175
+ }
156
176
  this.addReferencedDependency(workspace.name, packageName);
157
177
  return false;
158
178
  }
@@ -27,6 +27,7 @@ export declare class ProjectPrincipal {
27
27
  private resolveModule;
28
28
  resolvedFiles: Set<string>;
29
29
  deletedFiles: Set<string>;
30
+ private onPathAdded;
30
31
  constructor(options: MainOptions, toSourceFilePath: ToSourceFilePath, findWorkspaceManifestImports?: WorkspaceManifestHandler);
31
32
  addCompilers(compilers: [SyncCompilers, AsyncCompilers]): void;
32
33
  addPaths(paths: Paths, basePath: string): void;
@@ -1,5 +1,5 @@
1
1
  import { extractSpecifiers } from './typescript/follow-imports.js';
2
- import { parseFile } from './typescript/ast-nodes.js';
2
+ import { _parseFile } from './typescript/ast-nodes.js';
3
3
  import { CacheConsultant } from './CacheConsultant.js';
4
4
  import { getCompilerExtensions } from './compilers/index.js';
5
5
  import { DEFAULT_EXTENSIONS } from './constants.js';
@@ -36,6 +36,7 @@ export class ProjectPrincipal {
36
36
  resolveModule = () => undefined;
37
37
  resolvedFiles = new Set();
38
38
  deletedFiles = new Set();
39
+ onPathAdded;
39
40
  constructor(options, toSourceFilePath, findWorkspaceManifestImports) {
40
41
  this.cache = new CacheConsultant('root', options);
41
42
  this.toSourceFilePath = toSourceFilePath;
@@ -44,6 +45,7 @@ export class ProjectPrincipal {
44
45
  this.fileManager = new SourceFileManager({
45
46
  compilers: [this.syncCompilers, this.asyncCompilers],
46
47
  });
48
+ this.walkAndAnalyze = timerify(this.walkAndAnalyze.bind(this), 'walkAndAnalyze');
47
49
  }
48
50
  addCompilers(compilers) {
49
51
  for (const [ext, compiler] of compilers[0]) {
@@ -100,6 +102,7 @@ export class ProjectPrincipal {
100
102
  this.projectPaths.add(filePath);
101
103
  if (options?.skipExportsAnalysis)
102
104
  this.skipExportsAnalysis.add(filePath);
105
+ this.onPathAdded?.(filePath);
103
106
  }
104
107
  }
105
108
  addEntryPaths(filePaths, options) {
@@ -109,6 +112,7 @@ export class ProjectPrincipal {
109
112
  addProgramPath(filePath) {
110
113
  if (!isInNodeModules(filePath) && this.hasAcceptedExtension(filePath)) {
111
114
  this.programPaths.add(filePath);
115
+ this.onPathAdded?.(filePath);
112
116
  }
113
117
  }
114
118
  addProjectPath(filePath) {
@@ -134,61 +138,48 @@ export class ProjectPrincipal {
134
138
  walkAndAnalyze(analyzeFile) {
135
139
  this.resolvedFiles.clear();
136
140
  const visited = new Set([...this.entryPaths, ...this.programPaths]);
137
- let lastEntrySize = this.entryPaths.size;
138
- let lastProgramSize = this.programPaths.size;
139
- const rescanFrontier = () => {
140
- if (this.entryPaths.size > lastEntrySize || this.programPaths.size > lastProgramSize) {
141
- for (const p of this.entryPaths)
142
- visited.add(p);
143
- for (const p of this.programPaths)
144
- visited.add(p);
145
- lastEntrySize = this.entryPaths.size;
146
- lastProgramSize = this.programPaths.size;
147
- }
148
- };
149
- for (const filePath of visited) {
150
- const isProjectPath = this.projectPaths.has(filePath);
151
- let cachedFile;
152
- if (isProjectPath) {
153
- const fd = this.cache.getFileDescriptor(filePath);
154
- if (!fd.changed && fd.meta?.data)
155
- cachedFile = fd.meta.data;
156
- }
157
- if (cachedFile) {
158
- const internalPaths = analyzeFile(filePath, undefined, '', cachedFile);
159
- if (internalPaths)
160
- for (const p of internalPaths)
161
- visited.add(p);
162
- rescanFrontier();
163
- continue;
164
- }
165
- const sourceText = this.fileManager.readFile(filePath);
166
- if (!sourceText) {
167
- if (isProjectPath)
168
- analyzeFile(filePath, undefined, '');
169
- continue;
170
- }
171
- try {
172
- const result = parseFile(filePath, sourceText);
173
- this.fileManager.sourceTextCache.delete(filePath);
174
- if (isProjectPath) {
175
- const internalPaths = analyzeFile(filePath, result, sourceText);
141
+ this.onPathAdded = p => visited.add(p);
142
+ try {
143
+ for (const filePath of visited) {
144
+ const isProjectPath = this.projectPaths.has(filePath);
145
+ const cachedFile = isProjectPath ? this.cache.getCachedFile(filePath) : undefined;
146
+ if (cachedFile) {
147
+ const internalPaths = analyzeFile(filePath, undefined, '', cachedFile);
176
148
  if (internalPaths)
177
149
  for (const p of internalPaths)
178
150
  visited.add(p);
151
+ continue;
152
+ }
153
+ const sourceText = this.fileManager.readFile(filePath);
154
+ if (!sourceText) {
155
+ if (isProjectPath)
156
+ analyzeFile(filePath, undefined, '');
157
+ continue;
179
158
  }
180
- else {
181
- for (const specifier of extractSpecifiers(result, sourceText, filePath)) {
182
- const resolved = this.resolveSpecifier(specifier, filePath);
183
- if (resolved && !isInNodeModules(resolved))
184
- visited.add(resolved);
159
+ try {
160
+ const result = _parseFile(filePath, sourceText);
161
+ this.fileManager.sourceTextCache.delete(filePath);
162
+ if (isProjectPath) {
163
+ const internalPaths = analyzeFile(filePath, result, sourceText);
164
+ if (internalPaths)
165
+ for (const p of internalPaths)
166
+ visited.add(p);
167
+ }
168
+ else {
169
+ for (const specifier of extractSpecifiers(result, sourceText, filePath)) {
170
+ const resolved = this.resolveSpecifier(specifier, filePath);
171
+ if (resolved && !isInNodeModules(resolved))
172
+ visited.add(resolved);
173
+ }
185
174
  }
186
175
  }
187
- rescanFrontier();
188
- }
189
- catch {
176
+ catch {
177
+ }
190
178
  }
191
179
  }
180
+ finally {
181
+ this.onPathAdded = undefined;
182
+ }
192
183
  this.resolvedFiles = visited;
193
184
  }
194
185
  getUsedResolvedFiles() {
@@ -199,7 +190,7 @@ export class ProjectPrincipal {
199
190
  if (!sourceText)
200
191
  continue;
201
192
  try {
202
- const result = parseFile(filePath, sourceText);
193
+ const result = _parseFile(filePath, sourceText);
203
194
  for (const specifier of extractSpecifiers(result, sourceText, filePath)) {
204
195
  const resolved = this.resolveSpecifier(specifier, filePath);
205
196
  if (resolved && !isInNodeModules(resolved))
@@ -221,9 +212,9 @@ export class ProjectPrincipal {
221
212
  analyzeSourceFile(filePath, options, ignoreExportsUsedInFile, parseResult, sourceText, cachedFile) {
222
213
  if (cachedFile)
223
214
  return cachedFile;
224
- const fd = this.cache.getFileDescriptor(filePath);
225
- if (!fd.changed && fd.meta?.data)
226
- return fd.meta.data;
215
+ const cached = this.cache.getCachedFile(filePath);
216
+ if (cached)
217
+ return cached;
227
218
  sourceText ??= this.fileManager.readFile(filePath);
228
219
  const skipExports = this.skipExportsAnalysis.has(filePath);
229
220
  if (options.isFixExports || options.isFixTypes) {
@@ -7,7 +7,7 @@ import { getFilteredScripts } from './manifest/helpers.js';
7
7
  import { PluginEntries, Plugins } from './plugins.js';
8
8
  import { createManifest } from './util/package-json.js';
9
9
  import { collectStringLiterals, isExternalReExportsOnly } from './typescript/ast-helpers.js';
10
- import { parseFile } from './typescript/ast-nodes.js';
10
+ import { _parseFile } from './typescript/ast-nodes.js';
11
11
  import { compact } from './util/array.js';
12
12
  import { debugLogArray, debugLogObject } from './util/debug.js';
13
13
  import { _glob, hasNoProductionSuffix, hasProductionSuffix, negate } from './util/glob.js';
@@ -57,7 +57,7 @@ export class WorkspaceWorker {
57
57
  this.readFile = readFile;
58
58
  this.options = options;
59
59
  this.cache = new CacheConsultant(`plugins-${name}`, options);
60
- this.getConfigurationHints = timerify(this.getConfigurationHints.bind(this), 'worker.getConfigurationHints');
60
+ this.getConfigurationHints = timerify(this.getConfigurationHints.bind(this), 'getConfigurationHints');
61
61
  }
62
62
  async init() {
63
63
  this.enabledPlugins = await this.determineEnabledPlugins();
@@ -310,7 +310,7 @@ export class WorkspaceWorker {
310
310
  }
311
311
  else {
312
312
  const sourceText = this.readFile(configFilePath);
313
- parsed = sourceText ? parseFile(configFilePath, sourceText) : undefined;
313
+ parsed = sourceText ? _parseFile(configFilePath, sourceText) : undefined;
314
314
  parsedConfigCache.set(configFilePath, parsed);
315
315
  }
316
316
  }
package/dist/cli.js CHANGED
@@ -68,7 +68,7 @@ const main = async () => {
68
68
  console.log(`\n${perfObserver.getTimerifiedFunctionsTable()}`);
69
69
  if (perfObserver.isMemoryUsageEnabled && !args['memory-realtime'])
70
70
  console.log(`\n${perfObserver.getMemoryUsageTable()}`);
71
- if (perfObserver.isEnabled) {
71
+ if (perfObserver.isEnabled || perfObserver.isDurationEnabled) {
72
72
  const duration = perfObserver.getCurrentDurationInMs();
73
73
  console.log('\nTotal running time:', prettyMilliseconds(duration));
74
74
  perfObserver.reset();
@@ -44,6 +44,7 @@ export async function build({ chief, collector, counselor, deputy, principal, is
44
44
  });
45
45
  counselor.addWorkspace(manifest);
46
46
  }
47
+ deputy.setWorkspacePkgNames(chief.availableWorkspacePkgNames);
47
48
  collector.addIgnorePatterns(chief.config.ignore.map(id => ({ pattern: prependDir(options.cwd, id), id })));
48
49
  collector.addIgnoreFilesPatterns(chief.config.ignoreFiles.map(id => ({ pattern: prependDir(options.cwd, id), id })));
49
50
  if (options.configFilePath) {
@@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs';
2
2
  import { createRequire } from 'node:module';
3
3
  import { Visitor } from 'oxc-parser';
4
4
  import { scriptBodies } from '../../compilers/compilers.js';
5
- import { parseFile } from '../../typescript/ast-nodes.js';
5
+ import { _parseFile } from '../../typescript/ast-nodes.js';
6
6
  import { basename, dirname, isInNodeModules, join } from '../../util/path.js';
7
7
  export const getVueSfc = (cwd) => {
8
8
  try {
@@ -23,7 +23,7 @@ const readFile = (filePath) => {
23
23
  return '';
24
24
  }
25
25
  };
26
- export const readAndParseFile = (filePath) => parseFile(filePath, readFile(filePath));
26
+ export const readAndParseFile = (filePath) => _parseFile(filePath, readFile(filePath));
27
27
  export const collectIdentifiers = (source, fileName) => {
28
28
  const identifiers = new Set();
29
29
  const visitor = new Visitor({
@@ -31,7 +31,7 @@ export const collectIdentifiers = (source, fileName) => {
31
31
  identifiers.add(node.name);
32
32
  },
33
33
  });
34
- visitor.visit(parseFile(fileName, source).program);
34
+ visitor.visit(_parseFile(fileName, source).program);
35
35
  return identifiers;
36
36
  };
37
37
  export const collectTemplateInfo = (tree) => {
@@ -35,9 +35,7 @@ const resolveConfig = async (localConfig, options) => {
35
35
  .map(target => target?.executor)
36
36
  .filter(executor => executor && !executor.startsWith('.'))
37
37
  .map(executor => executor?.split(':')[0]);
38
- const expand = (value) => value
39
- .replaceAll('{projectRoot}', options.configFileDir)
40
- .replaceAll('{workspaceRoot}', options.rootCwd);
38
+ const expand = (value) => value.replaceAll('{projectRoot}', options.configFileDir).replaceAll('{workspaceRoot}', options.rootCwd);
41
39
  const resolveTargetCwd = (targetCwd) => {
42
40
  if (!targetCwd)
43
41
  return options.cwd;
@@ -1,6 +1,6 @@
1
1
  import { Visitor } from 'oxc-parser';
2
2
  import { collectPropertyValues, getImportMap } from '../../typescript/ast-helpers.js';
3
- import { parseFile } from '../../typescript/ast-nodes.js';
3
+ import { _parseFile } from '../../typescript/ast-nodes.js';
4
4
  import { toDeferResolveProductionEntry } from '../../util/input.js';
5
5
  import { dirname } from '../../util/path.js';
6
6
  import { _resolveSync } from '../../util/resolve.js';
@@ -27,7 +27,7 @@ export const getInputsFromHandlers = (program, options) => {
27
27
  if (resolvedPath) {
28
28
  const stackText = options.readFile(resolvedPath);
29
29
  if (stackText) {
30
- const stackResult = parseFile('stack.ts', stackText);
30
+ const stackResult = _parseFile('stack.ts', stackText);
31
31
  addHandlers(collectPropertyValues(stackResult.program, 'handler'));
32
32
  }
33
33
  }
package/dist/run.js CHANGED
@@ -9,6 +9,7 @@ import { IssueCollector } from './IssueCollector.js';
9
9
  import { ProjectPrincipal } from './ProjectPrincipal.js';
10
10
  import watchReporter from './reporters/watch.js';
11
11
  import { debugLogObject } from './util/debug.js';
12
+ import { flushGitignoreCache, initGitignoreCache } from './util/gitignore-cache.js';
12
13
  import { flushGlobCache, initGlobCache } from './util/glob-cache.js';
13
14
  import { getGitIgnoredHandler } from './util/glob-core.js';
14
15
  import { getModuleSourcePathHandler, getWorkspaceManifestHandler } from './util/to-source-path.js';
@@ -16,8 +17,10 @@ import { getSessionHandler } from './util/watch.js';
16
17
  export const run = async (options) => {
17
18
  debugLogObject('*', 'Unresolved configuration', options);
18
19
  debugLogObject('*', 'Included issue types', options.includedIssueTypes);
19
- if (options.isCache)
20
+ if (options.isCache) {
20
21
  initGlobCache(options.cacheLocation);
22
+ initGitignoreCache(options.cacheLocation);
23
+ }
21
24
  const chief = new ConfigurationChief(options);
22
25
  const deputy = new DependencyDeputy(options);
23
26
  const streamer = new ConsoleStreamer(options);
@@ -83,8 +86,10 @@ export const run = async (options) => {
83
86
  const { issues, counters, tagHints, configurationHints } = collector.getIssues();
84
87
  if (!options.isWatch)
85
88
  streamer.clear();
86
- if (options.isCache)
89
+ if (options.isCache) {
87
90
  flushGlobCache();
91
+ flushGitignoreCache();
92
+ }
88
93
  return {
89
94
  results: {
90
95
  issues,
@@ -1,7 +1,7 @@
1
1
  import { Visitor } from 'oxc-parser';
2
2
  import stripJsonComments from 'strip-json-comments';
3
3
  import { extname, isInternal } from '../util/path.js';
4
- import { getStringValue, isStringLiteral, parseFile } from './ast-nodes.js';
4
+ import { _parseFile, getStringValue, isStringLiteral } from './ast-nodes.js';
5
5
  export const getPropertyKey = (prop) => prop?.key?.type === 'Identifier' ? prop.key.name : getStringValue(prop?.key);
6
6
  export const getImportMap = (program) => {
7
7
  const importMap = new Map();
@@ -191,7 +191,7 @@ export const collectStringLiterals = (sourceText, filePath) => {
191
191
  collectJsonStringLiterals(JSON.parse(stripJsonComments(sourceText, { trailingCommas: true })), literals);
192
192
  return literals;
193
193
  }
194
- const result = parseFile(filePath, sourceText);
194
+ const result = _parseFile(filePath, sourceText);
195
195
  const visitor = new Visitor({
196
196
  Literal(node) {
197
197
  if (typeof node.value === 'string')
@@ -2,7 +2,7 @@ import { type TSEnumDeclaration, type TSModuleDeclaration } from 'oxc-parser';
2
2
  import type { GetImportsAndExportsOptions, IgnoreExportsUsedInFile } from '../types/config.ts';
3
3
  import type { SymbolType } from '../types/issues.ts';
4
4
  import type { ExportMember } from '../types/module-graph.ts';
5
- export declare const parseFile: (filePath: string, sourceText: string) => import("oxc-parser").ParseResult;
5
+ export declare const _parseFile: (filePath: string, sourceText: string) => import("oxc-parser").ParseResult;
6
6
  export type ResolveModule = (specifier: string, containingFile: string) => ResolvedModule | undefined;
7
7
  export interface ResolvedModule {
8
8
  resolvedFileName: string;
@@ -1,16 +1,18 @@
1
1
  import { parseSync, rawTransferSupported, } from 'oxc-parser';
2
2
  import { DEFAULT_EXTENSIONS, FIX_FLAGS, SYMBOL_TYPE } from '../constants.js';
3
3
  import { extname } from '../util/path.js';
4
+ import { timerify } from '../util/Performance.js';
4
5
  import { EMPTY_TAGS } from './visitors/jsdoc.js';
5
6
  const defaultParseOptions = {
6
7
  sourceType: 'unambiguous',
7
8
  experimentalRawTransfer: rawTransferSupported(),
8
9
  };
9
- export const parseFile = (filePath, sourceText) => {
10
+ const parseFile = (filePath, sourceText) => {
10
11
  const ext = extname(filePath);
11
12
  const parseFileName = DEFAULT_EXTENSIONS.has(ext) ? filePath : `${filePath}.ts`;
12
13
  return parseSync(parseFileName, sourceText, defaultParseOptions);
13
14
  };
15
+ export const _parseFile = timerify(parseFile);
14
16
  export const buildLineStarts = (sourceText) => {
15
17
  const starts = [0];
16
18
  for (let i = 0; i < sourceText.length; i++) {
@@ -6,9 +6,9 @@ import { timerify } from '../util/Performance.js';
6
6
  import { dirname, isInNodeModules, resolve } from '../util/path.js';
7
7
  import { shouldIgnore } from '../util/tag.js';
8
8
  import { extractImportsFromComments } from './comments.js';
9
- import { buildLineStarts, getLineAndCol, parseFile, shouldCountRefs, } from './ast-nodes.js';
9
+ import { _parseFile, buildLineStarts, getLineAndCol, shouldCountRefs, } from './ast-nodes.js';
10
10
  import { buildJSDocTagLookup } from './visitors/jsdoc.js';
11
- import { walkAST } from './visitors/walk.js';
11
+ import { _walkAST } from './visitors/walk.js';
12
12
  const getImportsAndExports = (filePath, sourceText, resolveModule, options, ignoreExportsUsedInFile, skipExportsForFile, visitor, pluginCtx, cachedParseResult) => {
13
13
  const skipExports = skipExportsForFile || !options.isReportExports;
14
14
  const isDts = filePath.endsWith('.d.ts') || filePath.endsWith('.d.cts') || filePath.endsWith('.d.mts');
@@ -159,7 +159,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
159
159
  }
160
160
  }
161
161
  };
162
- const result = cachedParseResult ?? parseFile(filePath, sourceText);
162
+ const result = cachedParseResult ?? _parseFile(filePath, sourceText);
163
163
  const lineStarts = buildLineStarts(sourceText);
164
164
  const getJSDocTags = buildJSDocTagLookup(result.comments, sourceText);
165
165
  let hasNodeModuleImport = false;
@@ -255,7 +255,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
255
255
  pluginCtx.addScript = (s) => scripts.add(s);
256
256
  pluginCtx.addImport = (spec, pos, mod) => addImport(spec, undefined, undefined, undefined, pos, mod);
257
257
  }
258
- const localRefs = walkAST(result.program, sourceText, filePath, {
258
+ const localRefs = _walkAST(result.program, sourceText, filePath, {
259
259
  lineStarts,
260
260
  skipExports,
261
261
  options,
@@ -81,5 +81,6 @@ export interface WalkState extends WalkContext {
81
81
  }
82
82
  export declare const isShadowed: (name: string, pos: number) => boolean;
83
83
  export declare function buildVisitor(pluginVisitorObjects: PluginVisitorObject[], includeLocalRefs?: boolean): Visitor;
84
- export declare function walkAST(program: Program, sourceText: string, filePath: string, ctx: WalkContext): Set<string> | undefined;
84
+ declare function walkAST(program: Program, sourceText: string, filePath: string, ctx: WalkContext): Set<string> | undefined;
85
+ export declare const _walkAST: typeof walkAST;
85
86
  export {};
@@ -2,6 +2,7 @@ import { Visitor, visitorKeys, } from 'oxc-parser';
2
2
  import { FIX_FLAGS, IMPORT_FLAGS, OPAQUE, SYMBOL_TYPE } from '../../constants.js';
3
3
  import { addValue } from '../../util/module-graph.js';
4
4
  import { isInNodeModules } from '../../util/path.js';
5
+ import { timerify } from '../../util/Performance.js';
5
6
  import { getLineAndCol, getStringValue, isStringLiteral } from '../ast-nodes.js';
6
7
  import { EMPTY_TAGS } from './jsdoc.js';
7
8
  import { handleCallExpression, handleNewExpression } from './calls.js';
@@ -673,7 +674,7 @@ export function buildVisitor(pluginVisitorObjects, includeLocalRefs) {
673
674
  }
674
675
  return new Visitor(merged);
675
676
  }
676
- export function walkAST(program, sourceText, filePath, ctx) {
677
+ function walkAST(program, sourceText, filePath, ctx) {
677
678
  const isJS = filePath.endsWith('.js') || filePath.endsWith('.mjs') || filePath.endsWith('.cjs') || filePath.endsWith('.jsx');
678
679
  state = {
679
680
  ...ctx,
@@ -780,3 +781,4 @@ export function walkAST(program, sourceText, filePath, ctx) {
780
781
  state = undefined;
781
782
  return localRefs;
782
783
  }
784
+ export const _walkAST = timerify(walkAST);
@@ -13,6 +13,7 @@ declare class Performance {
13
13
  isEnabled: boolean;
14
14
  isTimerifyFunctions: boolean;
15
15
  isMemoryUsageEnabled: boolean;
16
+ isDurationEnabled: boolean;
16
17
  startTime: number;
17
18
  endTime: number;
18
19
  perfEntries: PerformanceEntry[];
@@ -21,7 +22,8 @@ declare class Performance {
21
22
  memId?: string;
22
23
  fnObserver?: PerformanceObserver;
23
24
  memObserver?: PerformanceObserver;
24
- constructor({ isTimerifyFunctions, isMemoryUsageEnabled }: {
25
+ constructor({ isTimerifyFunctions, isMemoryUsageEnabled, isDurationEnabled }: {
26
+ isDurationEnabled?: boolean | undefined;
25
27
  isMemoryUsageEnabled?: boolean | undefined;
26
28
  isTimerifyFunctions?: boolean | undefined;
27
29
  });