knip 5.87.0 → 6.0.0-1

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 (186) hide show
  1. package/dist/DependencyDeputy.d.ts +3 -3
  2. package/dist/IssueCollector.d.ts +1 -1
  3. package/dist/IssueCollector.js +8 -3
  4. package/dist/IssueFixer.js +2 -2
  5. package/dist/ProjectPrincipal.d.ts +20 -29
  6. package/dist/ProjectPrincipal.js +144 -144
  7. package/dist/WorkspaceWorker.d.ts +5 -5
  8. package/dist/WorkspaceWorker.js +30 -23
  9. package/dist/cli.js +0 -3
  10. package/dist/compilers/index.d.ts +4 -4
  11. package/dist/constants.d.ts +5 -10
  12. package/dist/constants.js +5 -10
  13. package/dist/graph/analyze.d.ts +1 -3
  14. package/dist/graph/analyze.js +10 -33
  15. package/dist/graph/build.d.ts +3 -4
  16. package/dist/graph/build.js +47 -77
  17. package/dist/graph-explorer/operations/has-strictly-ns-references.js +7 -2
  18. package/dist/graph-explorer/operations/is-referenced.js +14 -1
  19. package/dist/plugins/astro/index.js +3 -3
  20. package/dist/plugins/astro/resolveFromAST.d.ts +3 -3
  21. package/dist/plugins/astro/resolveFromAST.js +5 -40
  22. package/dist/plugins/eleventy/index.js +1 -1
  23. package/dist/plugins/execa/index.js +3 -3
  24. package/dist/plugins/execa/visitors/execa.d.ts +2 -3
  25. package/dist/plugins/execa/visitors/execa.js +43 -26
  26. package/dist/plugins/next/index.js +2 -2
  27. package/dist/plugins/next/resolveFromAST.d.ts +2 -2
  28. package/dist/plugins/next/resolveFromAST.js +2 -15
  29. package/dist/plugins/next-mdx/index.js +2 -2
  30. package/dist/plugins/next-mdx/resolveFromAST.d.ts +2 -2
  31. package/dist/plugins/next-mdx/resolveFromAST.js +22 -38
  32. package/dist/plugins/nuxt/helpers.d.ts +4 -4
  33. package/dist/plugins/nuxt/helpers.js +54 -55
  34. package/dist/plugins/nuxt/index.js +8 -6
  35. package/dist/plugins/qwik/index.js +3 -3
  36. package/dist/plugins/qwik/resolveFromAST.d.ts +3 -3
  37. package/dist/plugins/qwik/resolveFromAST.js +5 -23
  38. package/dist/plugins/sst/index.js +2 -2
  39. package/dist/plugins/sst/resolveFromAST.js +32 -31
  40. package/dist/plugins/starlight/index.js +2 -2
  41. package/dist/plugins/starlight/resolveFromAST.d.ts +2 -2
  42. package/dist/plugins/starlight/resolveFromAST.js +7 -18
  43. package/dist/plugins/sveltekit/index.js +6 -12
  44. package/dist/plugins/vite/helpers.d.ts +2 -2
  45. package/dist/plugins/vite/helpers.js +34 -69
  46. package/dist/plugins/vite/index.js +6 -6
  47. package/dist/plugins/vite/visitors/importMetaGlob.d.ts +2 -2
  48. package/dist/plugins/vite/visitors/importMetaGlob.js +31 -28
  49. package/dist/plugins/vitest/index.js +1 -1
  50. package/dist/plugins/webpack/index.js +3 -3
  51. package/dist/plugins/webpack/visitors/requireContext.d.ts +2 -2
  52. package/dist/plugins/webpack/visitors/requireContext.js +29 -26
  53. package/dist/plugins/zx/index.js +3 -3
  54. package/dist/plugins/zx/visitors/zx.d.ts +2 -3
  55. package/dist/plugins/zx/visitors/zx.js +14 -8
  56. package/dist/reporters/codeclimate.js +5 -9
  57. package/dist/reporters/codeowners.js +1 -3
  58. package/dist/reporters/compact.js +10 -23
  59. package/dist/reporters/disclosure.js +3 -5
  60. package/dist/reporters/github-actions.js +4 -6
  61. package/dist/reporters/json.js +6 -7
  62. package/dist/reporters/markdown.js +10 -20
  63. package/dist/reporters/symbols.js +3 -5
  64. package/dist/reporters/util/configuration-hints.js +6 -4
  65. package/dist/reporters/util/util.d.ts +3 -2
  66. package/dist/reporters/util/util.js +1 -0
  67. package/dist/reporters/watch.js +3 -5
  68. package/dist/run.js +6 -5
  69. package/dist/schema/configuration.d.ts +4 -4
  70. package/dist/schema/configuration.js +1 -1
  71. package/dist/types/config.d.ts +11 -11
  72. package/dist/types/exports.d.ts +0 -21
  73. package/dist/types/issues.d.ts +3 -6
  74. package/dist/types/module-graph.d.ts +2 -2
  75. package/dist/types/options.d.ts +0 -2
  76. package/dist/types/project.d.ts +30 -12
  77. package/dist/typescript/SourceFileManager.d.ts +4 -11
  78. package/dist/typescript/SourceFileManager.js +28 -47
  79. package/dist/typescript/ast-helpers.d.ts +11 -73
  80. package/dist/typescript/ast-helpers.js +158 -403
  81. package/dist/typescript/follow-imports.d.ts +2 -0
  82. package/dist/typescript/follow-imports.js +65 -0
  83. package/dist/typescript/get-imports-and-exports.d.ts +5 -12
  84. package/dist/typescript/get-imports-and-exports.js +226 -372
  85. package/dist/typescript/resolve-module-names.d.ts +4 -3
  86. package/dist/typescript/resolve-module-names.js +31 -100
  87. package/dist/typescript/visitors/calls.d.ts +4 -0
  88. package/dist/typescript/visitors/calls.js +128 -0
  89. package/dist/typescript/visitors/exports.d.ts +6 -0
  90. package/dist/typescript/visitors/exports.js +386 -0
  91. package/dist/typescript/visitors/helpers.d.ts +21 -6
  92. package/dist/typescript/visitors/helpers.js +127 -11
  93. package/dist/typescript/visitors/imports.d.ts +4 -0
  94. package/dist/typescript/visitors/imports.js +257 -0
  95. package/dist/typescript/visitors/jsdoc.d.ts +3 -0
  96. package/dist/typescript/visitors/jsdoc.js +66 -0
  97. package/dist/typescript/visitors/local-refs.d.ts +7 -0
  98. package/dist/typescript/visitors/local-refs.js +241 -0
  99. package/dist/typescript/visitors/members.d.ts +4 -0
  100. package/dist/typescript/visitors/members.js +181 -0
  101. package/dist/typescript/visitors/script-visitors.d.ts +2 -0
  102. package/dist/typescript/visitors/script-visitors.js +13 -0
  103. package/dist/typescript/visitors/walk.d.ts +61 -0
  104. package/dist/typescript/visitors/walk.js +349 -0
  105. package/dist/util/cli-arguments.d.ts +1 -3
  106. package/dist/util/cli-arguments.js +2 -6
  107. package/dist/util/create-input-handler.js +2 -2
  108. package/dist/util/create-options.d.ts +5 -9
  109. package/dist/util/create-options.js +31 -10
  110. package/dist/util/fs.d.ts +1 -0
  111. package/dist/util/fs.js +8 -1
  112. package/dist/util/get-included-issue-types.js +2 -2
  113. package/dist/util/issue-initializers.js +1 -5
  114. package/dist/util/load-tsconfig.d.ts +2 -2
  115. package/dist/util/load-tsconfig.js +82 -8
  116. package/dist/util/regex.d.ts +0 -1
  117. package/dist/util/regex.js +0 -2
  118. package/dist/util/resolve.d.ts +4 -3
  119. package/dist/util/resolve.js +47 -25
  120. package/dist/util/to-source-path.d.ts +1 -1
  121. package/dist/util/to-source-path.js +8 -6
  122. package/dist/util/watch.d.ts +2 -3
  123. package/dist/util/watch.js +11 -20
  124. package/dist/version.d.ts +1 -1
  125. package/dist/version.js +1 -1
  126. package/package.json +4 -6
  127. package/schema-jsonc.json +1 -1
  128. package/schema.json +7 -7
  129. package/dist/PrincipalFactory.d.ts +0 -14
  130. package/dist/PrincipalFactory.js +0 -66
  131. package/dist/types/imports.d.ts +0 -10
  132. package/dist/types/imports.js +0 -1
  133. package/dist/typescript/SourceFile.d.ts +0 -35
  134. package/dist/typescript/SourceFile.js +0 -1
  135. package/dist/typescript/create-hosts.d.ts +0 -20
  136. package/dist/typescript/create-hosts.js +0 -35
  137. package/dist/typescript/has-refs-in-file.d.ts +0 -3
  138. package/dist/typescript/has-refs-in-file.js +0 -71
  139. package/dist/typescript/pragmas/custom.d.ts +0 -3
  140. package/dist/typescript/pragmas/custom.js +0 -33
  141. package/dist/typescript/pragmas/index.d.ts +0 -3
  142. package/dist/typescript/pragmas/index.js +0 -3
  143. package/dist/typescript/pragmas/typescript.d.ts +0 -3
  144. package/dist/typescript/pragmas/typescript.js +0 -45
  145. package/dist/typescript/visitors/dynamic-imports/importCall.d.ts +0 -3
  146. package/dist/typescript/visitors/dynamic-imports/importCall.js +0 -225
  147. package/dist/typescript/visitors/dynamic-imports/importType.d.ts +0 -3
  148. package/dist/typescript/visitors/dynamic-imports/importType.js +0 -18
  149. package/dist/typescript/visitors/dynamic-imports/index.d.ts +0 -4
  150. package/dist/typescript/visitors/dynamic-imports/index.js +0 -9
  151. package/dist/typescript/visitors/dynamic-imports/jsDocType.d.ts +0 -4
  152. package/dist/typescript/visitors/dynamic-imports/jsDocType.js +0 -67
  153. package/dist/typescript/visitors/dynamic-imports/moduleRegister.d.ts +0 -3
  154. package/dist/typescript/visitors/dynamic-imports/moduleRegister.js +0 -32
  155. package/dist/typescript/visitors/dynamic-imports/requireCall.d.ts +0 -3
  156. package/dist/typescript/visitors/dynamic-imports/requireCall.js +0 -108
  157. package/dist/typescript/visitors/dynamic-imports/resolveCall.d.ts +0 -3
  158. package/dist/typescript/visitors/dynamic-imports/resolveCall.js +0 -21
  159. package/dist/typescript/visitors/dynamic-imports/urlConstructor.d.ts +0 -3
  160. package/dist/typescript/visitors/dynamic-imports/urlConstructor.js +0 -27
  161. package/dist/typescript/visitors/exports/exportAssignment.d.ts +0 -3
  162. package/dist/typescript/visitors/exports/exportAssignment.js +0 -27
  163. package/dist/typescript/visitors/exports/exportDeclaration.d.ts +0 -3
  164. package/dist/typescript/visitors/exports/exportDeclaration.js +0 -24
  165. package/dist/typescript/visitors/exports/exportKeyword.d.ts +0 -3
  166. package/dist/typescript/visitors/exports/exportKeyword.js +0 -125
  167. package/dist/typescript/visitors/exports/exportsAccessExpression.d.ts +0 -3
  168. package/dist/typescript/visitors/exports/exportsAccessExpression.js +0 -23
  169. package/dist/typescript/visitors/exports/index.d.ts +0 -3
  170. package/dist/typescript/visitors/exports/index.js +0 -13
  171. package/dist/typescript/visitors/exports/moduleExportsAccessExpression.d.ts +0 -3
  172. package/dist/typescript/visitors/exports/moduleExportsAccessExpression.js +0 -78
  173. package/dist/typescript/visitors/imports/importDeclaration.d.ts +0 -3
  174. package/dist/typescript/visitors/imports/importDeclaration.js +0 -73
  175. package/dist/typescript/visitors/imports/importEqualsDeclaration.d.ts +0 -3
  176. package/dist/typescript/visitors/imports/importEqualsDeclaration.js +0 -21
  177. package/dist/typescript/visitors/imports/index.d.ts +0 -3
  178. package/dist/typescript/visitors/imports/index.js +0 -5
  179. package/dist/typescript/visitors/imports/reExportDeclaration.d.ts +0 -3
  180. package/dist/typescript/visitors/imports/reExportDeclaration.js +0 -54
  181. package/dist/typescript/visitors/index.d.ts +0 -14
  182. package/dist/typescript/visitors/index.js +0 -19
  183. package/dist/typescript/visitors/scripts/bun.d.ts +0 -3
  184. package/dist/typescript/visitors/scripts/bun.js +0 -9
  185. package/dist/typescript/visitors/scripts/index.d.ts +0 -4
  186. package/dist/typescript/visitors/scripts/index.js +0 -3
@@ -1,5 +1,5 @@
1
1
  import type { Workspace } from './ConfigurationChief.ts';
2
- import type { ConfigurationHint, Counters, Issue, Issues, SymbolIssueType } from './types/issues.ts';
2
+ import type { ConfigurationHint, Counters, Issue, Issues, IssueType } from './types/issues.ts';
3
3
  import type { PackageJson } from './types/package-json.ts';
4
4
  import type { DependencyArray, DependencySet, HostDependencies, InstalledBinaries, WorkspaceManifests } from './types/workspace.ts';
5
5
  import type { MainOptions } from './util/create-options.ts';
@@ -65,8 +65,8 @@ export declare class DependencyDeputy {
65
65
  devDependencyIssues: Issue[];
66
66
  optionalPeerDependencyIssues: Issue[];
67
67
  };
68
- handleIgnoredDependencies(issues: Issues, counters: Counters, type: SymbolIssueType): void;
69
- handleIgnoredBinaries(issues: Issues, counters: Counters, type: SymbolIssueType): void;
68
+ handleIgnoredDependencies(issues: Issues, counters: Counters, type: IssueType): void;
69
+ handleIgnoredBinaries(issues: Issues, counters: Counters, type: IssueType): void;
70
70
  handleIgnoredUnresolved(issues: Issues, counters: Counters): void;
71
71
  removeIgnoredIssues({ issues, counters }: {
72
72
  issues: Issues;
@@ -43,7 +43,7 @@ export declare class IssueCollector {
43
43
  addIssue(issue: Issue): true | undefined;
44
44
  addConfigurationHint(issue: ConfigurationHint): void;
45
45
  addTagHint(issue: TagHint): void;
46
- purge(): import("./types/issues.ts").IssueSet;
46
+ purge(): Set<string>;
47
47
  getIssues(): {
48
48
  issues: import("./types/issues.ts").Issues;
49
49
  counters: import("./types/issues.ts").Counters;
@@ -122,9 +122,10 @@ export class IssueCollector {
122
122
  }
123
123
  if (this.shouldIgnoreIssue(filePath, 'files'))
124
124
  continue;
125
- this.issues.files.add(filePath);
126
125
  const symbol = relative(this.cwd, filePath);
127
- this.issues._files[symbol] = [{ type: 'files', filePath, symbol, severity: this.rules.files }];
126
+ this.issues.files[symbol] = {
127
+ [symbol]: { type: 'files', filePath, symbol, workspace: '', severity: this.rules.files, fixes: [] },
128
+ };
128
129
  this.counters.files++;
129
130
  this.counters.processed++;
130
131
  }
@@ -160,7 +161,11 @@ export class IssueCollector {
160
161
  this.tagHints.add(issue);
161
162
  }
162
163
  purge() {
163
- const unusedFiles = this.issues.files;
164
+ const unusedFiles = new Set();
165
+ for (const issues of Object.values(this.issues.files)) {
166
+ for (const issue of Object.values(issues))
167
+ unusedFiles.add(issue.filePath);
168
+ }
164
169
  this.issues = initIssues();
165
170
  this.counters = initCounters();
166
171
  return unusedFiles;
@@ -46,7 +46,7 @@ class IssueFixer {
46
46
  async removeUnusedFiles(issues) {
47
47
  if (!this.options.isFixFiles)
48
48
  return;
49
- for (const issue of Object.values(issues._files).flatMap(Object.values)) {
49
+ for (const issue of Object.values(issues.files).flatMap(Object.values)) {
50
50
  await rm(issue.filePath);
51
51
  issue.isFixed = true;
52
52
  }
@@ -54,7 +54,7 @@ class IssueFixer {
54
54
  async removeUnusedExports(issues) {
55
55
  const touchedFiles = new Set();
56
56
  const types = [
57
- ...(this.options.isFixUnusedTypes ? ['types', 'nsTypes', 'classMembers', 'enumMembers'] : []),
57
+ ...(this.options.isFixUnusedTypes ? ['types', 'nsTypes', 'enumMembers', 'namespaceMembers'] : []),
58
58
  ...(this.options.isFixUnusedExports ? ['exports', 'nsExports'] : []),
59
59
  ];
60
60
  if (types.length === 0)
@@ -1,10 +1,9 @@
1
- import ts from 'typescript';
1
+ import type { ParseResult } from 'oxc-parser';
2
2
  import { CacheConsultant } from './CacheConsultant.ts';
3
3
  import type { AsyncCompilers, SyncCompilers } from './compilers/types.ts';
4
- import type { GetImportsAndExportsOptions, IgnoreExportsUsedInFile, Visitors } from './types/config.ts';
5
- import type { Export, ExportMember, FileNode, ModuleGraph } from './types/module-graph.ts';
6
- import type { Paths, PrincipalOptions } from './types/project.ts';
7
- import type { ResolveModuleNames } from './typescript/resolve-module-names.ts';
4
+ import type { GetImportsAndExportsOptions, IgnoreExportsUsedInFile, PluginVisitorContext, PluginVisitorObject } from './types/config.ts';
5
+ import type { FileNode, ModuleGraph } from './types/module-graph.ts';
6
+ import type { Paths } from './types/project.ts';
8
7
  import { SourceFileManager } from './typescript/SourceFileManager.ts';
9
8
  import type { MainOptions } from './util/create-options.ts';
10
9
  import type { ToSourceFilePath } from './util/to-source-path.ts';
@@ -13,30 +12,24 @@ export declare class ProjectPrincipal {
13
12
  projectPaths: Set<string>;
14
13
  programPaths: Set<string>;
15
14
  skipExportsAnalysis: Set<string>;
16
- visitors: Visitors;
17
- cwd: string;
18
- compilerOptions: ts.CompilerOptions;
19
- extensions: Set<string>;
15
+ pluginCtx: PluginVisitorContext;
16
+ pluginVisitorObjects: PluginVisitorObject[];
17
+ private _visitor;
20
18
  syncCompilers: SyncCompilers;
21
19
  asyncCompilers: AsyncCompilers;
22
- isWatch: boolean;
20
+ private paths;
21
+ private extensions;
23
22
  cache: CacheConsultant<FileNode>;
24
23
  toSourceFilePath: ToSourceFilePath;
25
- backend: {
26
- fileManager: SourceFileManager;
27
- compilerHost?: ts.CompilerHost;
28
- resolveModuleNames: ResolveModuleNames;
29
- program?: ts.Program;
30
- typeChecker?: ts.TypeChecker;
31
- languageServiceHost: ts.LanguageServiceHost;
32
- };
33
- findReferences?: ts.LanguageService['findReferences'];
34
- getImplementationAtPosition?: ts.LanguageService['getImplementationAtPosition'];
35
- constructor(options: MainOptions, { compilerOptions, compilers, pkgName, toSourceFilePath }: PrincipalOptions);
36
- init(): void;
37
- addPaths(paths: Paths, basePath: string): void;
24
+ fileManager: SourceFileManager;
25
+ private resolveModule;
26
+ resolvedFiles: Set<string>;
27
+ deletedFiles: Set<string>;
28
+ constructor(options: MainOptions, toSourceFilePath: ToSourceFilePath);
38
29
  addCompilers(compilers: [SyncCompilers, AsyncCompilers]): void;
39
- private createProgram;
30
+ addPaths(paths: Paths, basePath: string): void;
31
+ init(): void;
32
+ readFile(filePath: string): string;
40
33
  private hasAcceptedExtension;
41
34
  addEntryPath(filePath: string, options?: {
42
35
  skipExportsAnalysis: boolean;
@@ -46,15 +39,13 @@ export declare class ProjectPrincipal {
46
39
  }): void;
47
40
  addProgramPath(filePath: string): void;
48
41
  addProjectPath(filePath: string): void;
49
- deletedFiles: Set<unknown>;
50
42
  removeProjectPath(filePath: string): void;
51
43
  runAsyncCompilers(): Promise<void>;
44
+ walkAndAnalyze(analyzeFile: (filePath: string, parseResult: ParseResult | undefined, sourceText: string) => Iterable<string> | undefined): void;
52
45
  getUsedResolvedFiles(): string[];
53
- private getProgramSourceFiles;
46
+ private resolveSpecifier;
54
47
  getUnreferencedFiles(): string[];
55
- analyzeSourceFile(filePath: string, options: GetImportsAndExportsOptions, ignoreExportsUsedInFile: IgnoreExportsUsedInFile): FileNode;
48
+ analyzeSourceFile(filePath: string, options: GetImportsAndExportsOptions, ignoreExportsUsedInFile: IgnoreExportsUsedInFile, parseResult?: ParseResult, sourceText?: string): FileNode;
56
49
  invalidateFile(filePath: string): void;
57
- findUnusedMembers(filePath: string, members: ExportMember[]): ExportMember[];
58
- hasExternalReferences(filePath: string, exportedItem: Export): boolean;
59
50
  reconcileCache(graph: ModuleGraph): void;
60
51
  }
@@ -1,104 +1,85 @@
1
- import ts from 'typescript';
1
+ import { extractSpecifiers } from "./typescript/follow-imports.js";
2
+ import { parseFile } from "./typescript/visitors/helpers.js";
2
3
  import { CacheConsultant } from "./CacheConsultant.js";
3
4
  import { getCompilerExtensions } from "./compilers/index.js";
4
- import { ANONYMOUS, DEFAULT_EXTENSIONS, MEMBER_FLAGS, PUBLIC_TAG } from "./constants.js";
5
- import { createHosts } from "./typescript/create-hosts.js";
5
+ import { DEFAULT_EXTENSIONS } from "./constants.js";
6
6
  import { _getImportsAndExports } from "./typescript/get-imports-and-exports.js";
7
+ import { createBunShellVisitor } from "./typescript/visitors/script-visitors.js";
8
+ import { buildVisitor } from "./typescript/visitors/walk.js";
9
+ import { createCustomModuleResolver } from "./typescript/resolve-module-names.js";
7
10
  import { SourceFileManager } from "./typescript/SourceFileManager.js";
8
11
  import { compact } from "./util/array.js";
9
12
  import { timerify } from "./util/Performance.js";
10
13
  import { extname, isInNodeModules, toAbsolute } from "./util/path.js";
11
- const baseCompilerOptions = {
12
- allowJs: true,
13
- allowSyntheticDefaultImports: true,
14
- declaration: false,
15
- declarationMap: false,
16
- esModuleInterop: true,
17
- inlineSourceMap: false,
18
- inlineSources: false,
19
- jsx: ts.JsxEmit.Preserve,
20
- jsxImportSource: undefined,
21
- lib: [],
22
- noEmit: true,
23
- skipDefaultLibCheck: true,
24
- skipLibCheck: true,
25
- sourceMap: false,
26
- types: ['node'],
27
- };
28
- const tsCreateProgram = timerify(ts.createProgram);
29
14
  export class ProjectPrincipal {
30
15
  entryPaths = new Set();
31
16
  projectPaths = new Set();
32
17
  programPaths = new Set();
33
18
  skipExportsAnalysis = new Set();
34
- visitors = { dynamicImport: [], script: [] };
35
- cwd;
36
- compilerOptions;
37
- extensions;
38
- syncCompilers;
39
- asyncCompilers;
40
- isWatch;
19
+ pluginCtx = {
20
+ filePath: '',
21
+ sourceText: '',
22
+ addScript: () => { },
23
+ addImport: () => { },
24
+ };
25
+ pluginVisitorObjects = [];
26
+ _visitor;
27
+ syncCompilers = new Map();
28
+ asyncCompilers = new Map();
29
+ paths = {};
30
+ extensions = new Set(DEFAULT_EXTENSIONS);
41
31
  cache;
42
32
  toSourceFilePath;
43
- backend;
44
- findReferences;
45
- getImplementationAtPosition;
46
- constructor(options, { compilerOptions, compilers, pkgName, toSourceFilePath }) {
47
- this.compilerOptions = {
48
- ...compilerOptions,
49
- ...baseCompilerOptions,
50
- types: compact([...(compilerOptions.types ?? []), ...(baseCompilerOptions.types ?? [])]),
51
- allowNonTsExtensions: true,
52
- };
53
- const [syncCompilers, asyncCompilers] = compilers;
54
- this.extensions = new Set([...DEFAULT_EXTENSIONS, ...getCompilerExtensions(compilers)]);
55
- this.syncCompilers = syncCompilers;
56
- this.asyncCompilers = asyncCompilers;
57
- this.cwd = options.cwd;
58
- this.isWatch = options.isWatch || options.isSession;
59
- this.cache = new CacheConsultant(pkgName || ANONYMOUS, options);
33
+ fileManager;
34
+ resolveModule = () => undefined;
35
+ resolvedFiles = new Set();
36
+ deletedFiles = new Set();
37
+ constructor(options, toSourceFilePath) {
38
+ this.cache = new CacheConsultant('root', options);
60
39
  this.toSourceFilePath = toSourceFilePath;
61
- this.backend = {
62
- fileManager: new SourceFileManager({ compilers, isSkipLibs: options.isSkipLibs }),
63
- };
64
- }
65
- init() {
66
- const { compilerHost, resolveModuleNames, languageServiceHost } = createHosts({
67
- cwd: this.cwd,
68
- compilerOptions: this.compilerOptions,
69
- entryPaths: this.entryPaths,
40
+ this.pluginVisitorObjects.push(createBunShellVisitor(this.pluginCtx));
41
+ this.fileManager = new SourceFileManager({
70
42
  compilers: [this.syncCompilers, this.asyncCompilers],
71
- toSourceFilePath: this.toSourceFilePath,
72
- useResolverCache: !this.isWatch,
73
- fileManager: this.backend.fileManager,
74
43
  });
75
- this.backend.compilerHost = compilerHost;
76
- this.backend.resolveModuleNames = resolveModuleNames;
77
- this.backend.languageServiceHost = languageServiceHost;
44
+ }
45
+ addCompilers(compilers) {
46
+ for (const [ext, compiler] of compilers[0]) {
47
+ if (!this.syncCompilers.has(ext)) {
48
+ this.syncCompilers.set(ext, compiler);
49
+ this.extensions.add(ext);
50
+ }
51
+ }
52
+ for (const [ext, compiler] of compilers[1]) {
53
+ if (!this.asyncCompilers.has(ext)) {
54
+ this.asyncCompilers.set(ext, compiler);
55
+ this.extensions.add(ext);
56
+ }
57
+ }
78
58
  }
79
59
  addPaths(paths, basePath) {
80
60
  if (!paths)
81
61
  return;
82
- this.compilerOptions.paths ??= {};
83
62
  for (const key in paths) {
84
63
  const prefixes = paths[key].map(prefix => toAbsolute(prefix, basePath));
85
- if (key in this.compilerOptions.paths) {
86
- this.compilerOptions.paths[key] = compact([...this.compilerOptions.paths[key], ...prefixes]);
64
+ if (key in this.paths) {
65
+ this.paths[key] = compact([...this.paths[key], ...prefixes]);
87
66
  }
88
67
  else {
89
- this.compilerOptions.paths[key] = prefixes;
68
+ this.paths[key] = prefixes;
90
69
  }
91
70
  }
92
71
  }
93
- addCompilers(compilers) {
94
- this.syncCompilers = new Map([...this.syncCompilers, ...compilers[0]]);
95
- this.asyncCompilers = new Map([...this.asyncCompilers, ...compilers[1]]);
96
- this.extensions = new Set([...this.extensions, ...getCompilerExtensions(compilers)]);
72
+ init() {
73
+ this.extensions = new Set([
74
+ ...DEFAULT_EXTENSIONS,
75
+ ...getCompilerExtensions([this.syncCompilers, this.asyncCompilers]),
76
+ ]);
77
+ const customCompilerExtensions = getCompilerExtensions([this.syncCompilers, this.asyncCompilers]);
78
+ const pathsOrUndefined = Object.keys(this.paths).length > 0 ? this.paths : undefined;
79
+ this.resolveModule = createCustomModuleResolver({ paths: pathsOrUndefined }, customCompilerExtensions, this.toSourceFilePath);
97
80
  }
98
- createProgram() {
99
- this.backend.program = tsCreateProgram([...this.entryPaths, ...this.programPaths], this.compilerOptions, this.backend.compilerHost, this.backend.program);
100
- const typeChecker = timerify(this.backend.program.getTypeChecker);
101
- this.backend.typeChecker = typeChecker();
81
+ readFile(filePath) {
82
+ return this.fileManager.readFile(filePath);
102
83
  }
103
84
  hasAcceptedExtension(filePath) {
104
85
  return this.extensions.has(extname(filePath));
@@ -126,7 +107,6 @@ export class ProjectPrincipal {
126
107
  this.deletedFiles.delete(filePath);
127
108
  }
128
109
  }
129
- deletedFiles = new Set();
130
110
  removeProjectPath(filePath) {
131
111
  this.entryPaths.delete(filePath);
132
112
  this.projectPaths.delete(filePath);
@@ -134,99 +114,119 @@ export class ProjectPrincipal {
134
114
  this.deletedFiles.add(filePath);
135
115
  }
136
116
  async runAsyncCompilers() {
137
- const add = timerify(this.backend.fileManager.compileAndAddSourceFile.bind(this.backend.fileManager));
117
+ const add = timerify(this.fileManager.compileAndAddSourceFile.bind(this.fileManager));
138
118
  const extensions = Array.from(this.asyncCompilers.keys());
139
119
  const files = Array.from(this.projectPaths).filter(filePath => extensions.includes(extname(filePath)));
140
120
  for (const filePath of files) {
141
121
  await add(filePath);
142
122
  }
143
123
  }
124
+ walkAndAnalyze(analyzeFile) {
125
+ this.resolvedFiles.clear();
126
+ const queue = [...this.entryPaths, ...this.programPaths];
127
+ const visited = new Set();
128
+ let lastEntrySize = this.entryPaths.size;
129
+ let lastProgramSize = this.programPaths.size;
130
+ for (let i = 0; i < queue.length; i++) {
131
+ const filePath = queue[i];
132
+ if (visited.has(filePath))
133
+ continue;
134
+ visited.add(filePath);
135
+ const sourceText = this.fileManager.readFile(filePath);
136
+ if (!sourceText) {
137
+ if (this.projectPaths.has(filePath))
138
+ analyzeFile(filePath, undefined, '');
139
+ continue;
140
+ }
141
+ try {
142
+ const result = parseFile(filePath, sourceText);
143
+ this.fileManager.sourceTextCache.delete(filePath);
144
+ if (this.projectPaths.has(filePath)) {
145
+ const internalPaths = analyzeFile(filePath, result, sourceText);
146
+ if (internalPaths) {
147
+ for (const p of internalPaths) {
148
+ if (!visited.has(p))
149
+ queue.push(p);
150
+ }
151
+ }
152
+ }
153
+ else {
154
+ for (const specifier of extractSpecifiers(result, sourceText, filePath)) {
155
+ const resolved = this.resolveSpecifier(specifier, filePath);
156
+ if (resolved && !isInNodeModules(resolved) && !visited.has(resolved)) {
157
+ queue.push(resolved);
158
+ }
159
+ }
160
+ }
161
+ if (this.entryPaths.size > lastEntrySize || this.programPaths.size > lastProgramSize) {
162
+ for (const p of this.entryPaths) {
163
+ if (!visited.has(p))
164
+ queue.push(p);
165
+ }
166
+ for (const p of this.programPaths) {
167
+ if (!visited.has(p))
168
+ queue.push(p);
169
+ }
170
+ lastEntrySize = this.entryPaths.size;
171
+ lastProgramSize = this.programPaths.size;
172
+ }
173
+ }
174
+ catch {
175
+ }
176
+ }
177
+ this.resolvedFiles = visited;
178
+ }
144
179
  getUsedResolvedFiles() {
145
- this.createProgram();
146
- const sourceFiles = this.getProgramSourceFiles();
147
- return Array.from(this.projectPaths).filter(filePath => sourceFiles.has(filePath));
180
+ this.resolvedFiles.clear();
181
+ const queue = [...this.entryPaths, ...this.programPaths];
182
+ const visited = new Set();
183
+ for (let i = 0; i < queue.length; i++) {
184
+ const filePath = queue[i];
185
+ if (visited.has(filePath))
186
+ continue;
187
+ visited.add(filePath);
188
+ const sourceText = this.fileManager.readFile(filePath);
189
+ if (!sourceText)
190
+ continue;
191
+ try {
192
+ const result = parseFile(filePath, sourceText);
193
+ for (const specifier of extractSpecifiers(result, sourceText, filePath)) {
194
+ const resolved = this.resolveSpecifier(specifier, filePath);
195
+ if (resolved && !isInNodeModules(resolved) && !visited.has(resolved)) {
196
+ queue.push(resolved);
197
+ }
198
+ }
199
+ }
200
+ catch {
201
+ }
202
+ }
203
+ this.resolvedFiles = visited;
204
+ return Array.from(this.projectPaths).filter(filePath => visited.has(filePath));
148
205
  }
149
- getProgramSourceFiles() {
150
- const programSourceFiles = this.backend.program?.getSourceFiles().map(sourceFile => sourceFile.fileName);
151
- return new Set(programSourceFiles);
206
+ resolveSpecifier(specifier, containingFile) {
207
+ return this.resolveModule(specifier, containingFile)?.resolvedFileName;
152
208
  }
153
209
  getUnreferencedFiles() {
154
- const sourceFiles = this.getProgramSourceFiles();
155
- return Array.from(this.projectPaths).filter(filePath => !sourceFiles.has(filePath));
210
+ return Array.from(this.projectPaths).filter(filePath => !this.resolvedFiles.has(filePath));
156
211
  }
157
- analyzeSourceFile(filePath, options, ignoreExportsUsedInFile) {
212
+ analyzeSourceFile(filePath, options, ignoreExportsUsedInFile, parseResult, sourceText) {
158
213
  const fd = this.cache.getFileDescriptor(filePath);
159
214
  if (!fd.changed && fd.meta?.data)
160
215
  return fd.meta.data;
161
- const typeChecker = this.backend.typeChecker;
162
- if (!typeChecker)
163
- throw new Error('TypeChecker must be initialized before source file analysis');
164
- const sourceFile = this.backend.fileManager.getSourceFile(filePath);
165
- if (!sourceFile)
166
- throw new Error(`Unable to find ${filePath}`);
216
+ sourceText ??= this.fileManager.readFile(filePath);
167
217
  const skipExports = this.skipExportsAnalysis.has(filePath);
168
218
  if (options.isFixExports || options.isFixTypes) {
169
219
  const ext = extname(filePath);
170
- if (!DEFAULT_EXTENSIONS.includes(ext) && (this.syncCompilers.has(ext) || this.asyncCompilers.has(ext))) {
220
+ if (!DEFAULT_EXTENSIONS.has(ext) && (this.syncCompilers.has(ext) || this.asyncCompilers.has(ext))) {
171
221
  options = { ...options, isFixExports: false, isFixTypes: false };
172
222
  }
173
223
  }
174
- const resolve = (specifier) => this.backend.resolveModuleNames([specifier], sourceFile.fileName)[0];
175
- return _getImportsAndExports(sourceFile, resolve, typeChecker, options, ignoreExportsUsedInFile, skipExports, this.visitors);
224
+ if (!this._visitor)
225
+ this._visitor = buildVisitor(this.pluginVisitorObjects);
226
+ return _getImportsAndExports(filePath, sourceText, this.resolveModule, options, ignoreExportsUsedInFile, skipExports, this._visitor, this.pluginVisitorObjects.length > 0 ? this.pluginCtx : undefined, parseResult);
176
227
  }
177
228
  invalidateFile(filePath) {
178
- this.backend.fileManager.invalidate(filePath);
179
- }
180
- findUnusedMembers(filePath, members) {
181
- if (!this.findReferences || !this.getImplementationAtPosition) {
182
- const languageService = ts.createLanguageService(this.backend.languageServiceHost, ts.createDocumentRegistry());
183
- this.findReferences = timerify(languageService.findReferences);
184
- this.getImplementationAtPosition = timerify(languageService.getImplementationAtPosition);
185
- }
186
- return members.filter(member => {
187
- if (member.jsDocTags.has(PUBLIC_TAG))
188
- return false;
189
- const implementations = this.getImplementationAtPosition(filePath, member.pos)?.filter(impl => impl.fileName !== filePath || impl.textSpan.start !== member.pos) ?? [];
190
- const referencedSymbols = this.findReferences(filePath, member.pos) ?? [];
191
- if (referencedSymbols.length > 1 && referencedSymbols.some(sym => isInNodeModules(sym.definition.fileName))) {
192
- return false;
193
- }
194
- const refs = referencedSymbols
195
- .filter(sym => !implementations.some(impl => impl.fileName === sym.definition.fileName &&
196
- impl.textSpan.start === sym.definition.textSpan.start &&
197
- impl.textSpan.length === sym.definition.textSpan.length))
198
- .flatMap(refs => refs.references)
199
- .filter(ref => !ref.isDefinition);
200
- if (refs.length === 0)
201
- return true;
202
- if (member.flags & MEMBER_FLAGS.SETTER)
203
- return false;
204
- return !refs.some(ref => !ref.isWriteAccess);
205
- });
206
- }
207
- hasExternalReferences(filePath, exportedItem) {
208
- if (exportedItem.jsDocTags.has(PUBLIC_TAG))
209
- return false;
210
- if (!this.findReferences) {
211
- const languageService = ts.createLanguageService(this.backend.languageServiceHost, ts.createDocumentRegistry());
212
- this.findReferences = timerify(languageService.findReferences);
213
- }
214
- const referencedSymbols = this.findReferences(filePath, exportedItem.pos);
215
- if (!referencedSymbols?.length)
216
- return false;
217
- const externalRefs = referencedSymbols
218
- .flatMap(refs => refs.references)
219
- .filter(ref => !ref.isDefinition && ref.fileName !== filePath)
220
- .filter(ref => {
221
- const sourceFile = this.backend.program?.getSourceFile(ref.fileName);
222
- if (!sourceFile)
223
- return true;
224
- const node = ts.getTokenAtPosition(sourceFile, ref.textSpan.start);
225
- if (!node?.parent?.parent?.parent)
226
- return true;
227
- return !(ts.isExportSpecifier(node.parent) && node.parent.parent.parent.moduleSpecifier);
228
- });
229
- return externalRefs.length > 0;
229
+ this.fileManager.invalidate(filePath);
230
230
  }
231
231
  reconcileCache(graph) {
232
232
  for (const [filePath, file] of graph) {
@@ -1,6 +1,6 @@
1
1
  import { CacheConsultant } from './CacheConsultant.ts';
2
2
  import { type Workspace } from './ConfigurationChief.ts';
3
- import type { GetSourceFile, HandleInput, RegisterCompiler, RegisterVisitor, WorkspaceConfiguration } from './types/config.ts';
3
+ import type { HandleInput, RegisterCompiler, RegisterVisitorsOptions, WorkspaceConfiguration } from './types/config.ts';
4
4
  import type { ConfigurationHint } from './types/issues.ts';
5
5
  import type { PluginName } from './types/PluginNames.ts';
6
6
  import type { PackageJson } from './types/package-json.ts';
@@ -16,7 +16,7 @@ type WorkspaceManagerOptions = {
16
16
  rootManifest: PackageJson | undefined;
17
17
  handleInput: HandleInput;
18
18
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
19
- getSourceFile: GetSourceFile;
19
+ readFile: (filePath: string) => string;
20
20
  negatedWorkspacePatterns: string[];
21
21
  ignoredWorkspacePatterns: string[];
22
22
  enabledPluginsInAncestors: string[];
@@ -37,7 +37,7 @@ export declare class WorkspaceWorker {
37
37
  dependencies: DependencySet;
38
38
  handleInput: HandleInput;
39
39
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
40
- getSourceFile: GetSourceFile;
40
+ readFile: (filePath: string) => string;
41
41
  negatedWorkspacePatterns: string[];
42
42
  ignoredWorkspacePatterns: string[];
43
43
  options: MainOptions;
@@ -46,7 +46,7 @@ export declare class WorkspaceWorker {
46
46
  enabledPluginsInAncestors: string[];
47
47
  cache: CacheConsultant<CacheItem>;
48
48
  configFilesMap: Map<string, Map<PluginName, Set<string>>>;
49
- constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getSourceFile, configFilesMap, options, }: WorkspaceManagerOptions);
49
+ constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, readFile, configFilesMap, options, }: WorkspaceManagerOptions);
50
50
  init(): Promise<void>;
51
51
  private determineEnabledPlugins;
52
52
  private getConfigForPlugin;
@@ -60,7 +60,7 @@ export declare class WorkspaceWorker {
60
60
  getProductionProjectFilePatterns(negatedTestFilePatterns: string[]): string[];
61
61
  private getConfigurationFilePatterns;
62
62
  registerCompilers(registerCompiler: RegisterCompiler): Promise<void>;
63
- registerVisitors(registerVisitors: RegisterVisitor): void;
63
+ registerVisitors(options: RegisterVisitorsOptions): void;
64
64
  runPlugins(): Promise<Input[]>;
65
65
  private filterTransitiveDependencies;
66
66
  getConfigurationHints(type: 'entry' | 'project', patterns: string[], filePaths: string[], includedPaths: Set<string>): ConfigurationHint[];