knip 2.1.3 → 2.2.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 (116) hide show
  1. package/README.md +10 -8
  2. package/dist/{configuration-chief.js → ConfigurationChief.js} +39 -38
  3. package/dist/{dependency-deputy.d.ts → DependencyDeputy.d.ts} +4 -2
  4. package/dist/{dependency-deputy.js → DependencyDeputy.js} +29 -10
  5. package/dist/{principal-factory.d.ts → PrincipalFactory.d.ts} +1 -1
  6. package/dist/{principal-factory.js → PrincipalFactory.js} +1 -1
  7. package/dist/{project-principal.d.ts → ProjectPrincipal.d.ts} +7 -4
  8. package/dist/{project-principal.js → ProjectPrincipal.js} +6 -4
  9. package/dist/{workspace-worker.d.ts → WorkspaceWorker.d.ts} +1 -1
  10. package/dist/{workspace-worker.js → WorkspaceWorker.js} +0 -2
  11. package/dist/binaries/index.d.ts +2 -2
  12. package/dist/binaries/index.js +12 -16
  13. package/dist/binaries/resolvers/fallback.js +8 -4
  14. package/dist/binaries/resolvers/npx.js +3 -1
  15. package/dist/binaries/types.d.ts +1 -5
  16. package/dist/cli.js +1 -1
  17. package/dist/index.js +57 -47
  18. package/dist/manifest/index.d.ts +1 -3
  19. package/dist/manifest/index.js +11 -25
  20. package/dist/plugins/_template/index.js +1 -1
  21. package/dist/plugins/ava/index.js +4 -6
  22. package/dist/plugins/babel/index.js +1 -1
  23. package/dist/plugins/capacitor/index.js +1 -1
  24. package/dist/plugins/changesets/index.js +1 -1
  25. package/dist/plugins/commitizen/index.js +1 -1
  26. package/dist/plugins/commitlint/index.js +1 -1
  27. package/dist/plugins/cspell/index.js +1 -1
  28. package/dist/plugins/eslint/index.js +1 -1
  29. package/dist/plugins/gatsby/index.js +1 -1
  30. package/dist/plugins/github-actions/index.js +4 -6
  31. package/dist/plugins/husky/index.js +4 -6
  32. package/dist/plugins/jest/index.js +1 -1
  33. package/dist/plugins/lefthook/index.js +4 -6
  34. package/dist/plugins/lint-staged/index.js +7 -7
  35. package/dist/plugins/markdownlint/index.js +1 -1
  36. package/dist/plugins/mocha/index.js +1 -1
  37. package/dist/plugins/npm-package-json-lint/index.js +1 -1
  38. package/dist/plugins/nx/index.js +4 -4
  39. package/dist/plugins/nyc/index.js +1 -1
  40. package/dist/plugins/postcss/index.js +1 -1
  41. package/dist/plugins/prettier/index.js +1 -1
  42. package/dist/plugins/release-it/index.js +4 -4
  43. package/dist/plugins/remark/index.js +1 -1
  44. package/dist/plugins/semantic-release/index.js +1 -1
  45. package/dist/plugins/storybook/index.js +1 -1
  46. package/dist/plugins/stryker/index.js +1 -1
  47. package/dist/plugins/typedoc/index.js +1 -1
  48. package/dist/plugins/typescript/index.js +1 -1
  49. package/dist/plugins/vitest/index.js +1 -1
  50. package/dist/plugins/webpack/index.js +1 -1
  51. package/dist/types/config.d.ts +1 -1
  52. package/dist/types/{ast.d.ts → exports.d.ts} +0 -10
  53. package/dist/types/imports.d.ts +14 -0
  54. package/dist/types/imports.js +1 -0
  55. package/dist/types/plugins.d.ts +1 -2
  56. package/dist/types/workspace.d.ts +1 -0
  57. package/dist/typescript/SourceFile.d.ts +1 -0
  58. package/dist/typescript/getImportsAndExports.d.ts +29 -0
  59. package/dist/typescript/getImportsAndExports.js +158 -0
  60. package/dist/typescript/visitors/exports/exportAssignment.d.ts +3 -0
  61. package/dist/typescript/visitors/exports/exportAssignment.js +8 -0
  62. package/dist/typescript/visitors/exports/exportDeclaration.d.ts +3 -0
  63. package/dist/typescript/visitors/exports/exportDeclaration.js +13 -0
  64. package/dist/typescript/visitors/exports/exportKeyword.d.ts +3 -0
  65. package/dist/typescript/visitors/exports/exportKeyword.js +77 -0
  66. package/dist/typescript/visitors/exports/index.d.ts +3 -0
  67. package/dist/typescript/visitors/exports/index.js +6 -0
  68. package/dist/typescript/visitors/exports/moduleExportsAccessExpression.d.ts +3 -0
  69. package/dist/typescript/visitors/exports/moduleExportsAccessExpression.js +31 -0
  70. package/dist/typescript/visitors/helpers.d.ts +3 -0
  71. package/dist/typescript/visitors/helpers.js +3 -0
  72. package/dist/typescript/visitors/imports/importCall.d.ts +3 -0
  73. package/dist/typescript/visitors/imports/importCall.js +35 -0
  74. package/dist/typescript/visitors/imports/importDeclaration.d.ts +3 -0
  75. package/dist/typescript/visitors/imports/importDeclaration.js +32 -0
  76. package/dist/typescript/visitors/imports/importEqualsDeclaration.d.ts +3 -0
  77. package/dist/typescript/visitors/imports/importEqualsDeclaration.js +11 -0
  78. package/dist/typescript/visitors/imports/index.d.ts +3 -0
  79. package/dist/typescript/visitors/imports/index.js +17 -0
  80. package/dist/typescript/visitors/imports/jsDocType.d.ts +3 -0
  81. package/dist/typescript/visitors/imports/jsDocType.js +11 -0
  82. package/dist/typescript/visitors/imports/reExportDeclaration.d.ts +3 -0
  83. package/dist/typescript/visitors/imports/reExportDeclaration.js +21 -0
  84. package/dist/typescript/visitors/imports/requireCall.d.ts +3 -0
  85. package/dist/typescript/visitors/imports/requireCall.js +46 -0
  86. package/dist/typescript/visitors/imports/requireResolveCall.d.ts +3 -0
  87. package/dist/typescript/visitors/imports/requireResolveCall.js +14 -0
  88. package/dist/typescript/visitors/index.d.ts +10 -0
  89. package/dist/typescript/visitors/index.js +15 -0
  90. package/dist/typescript/visitors/scripts/index.d.ts +3 -0
  91. package/dist/typescript/visitors/scripts/index.js +3 -0
  92. package/dist/typescript/visitors/scripts/zx.d.ts +3 -0
  93. package/dist/typescript/visitors/scripts/zx.js +8 -0
  94. package/dist/util/array.d.ts +0 -1
  95. package/dist/util/array.js +0 -7
  96. package/dist/util/compilers.d.ts +5 -4
  97. package/dist/util/compilers.js +1 -3
  98. package/dist/util/glob.js +1 -1
  99. package/dist/util/loader.js +1 -1
  100. package/dist/util/plugin.js +1 -1
  101. package/dist/util/require.js +1 -1
  102. package/dist/version.d.ts +1 -1
  103. package/dist/version.js +1 -1
  104. package/package.json +1 -1
  105. package/dist/typescript/ast-walker.d.ts +0 -16
  106. package/dist/typescript/ast-walker.js +0 -364
  107. package/dist/{configuration-chief.d.ts → ConfigurationChief.d.ts} +0 -0
  108. package/dist/{configuration-validator.d.ts → ConfigurationValidator.d.ts} +6 -6
  109. /package/dist/{configuration-validator.js → ConfigurationValidator.js} +0 -0
  110. /package/dist/{console-streamer.d.ts → ConsoleStreamer.d.ts} +0 -0
  111. /package/dist/{console-streamer.js → ConsoleStreamer.js} +0 -0
  112. /package/dist/{issue-collector.d.ts → IssueCollector.d.ts} +0 -0
  113. /package/dist/{issue-collector.js → IssueCollector.js} +0 -0
  114. /package/dist/types/{ast.js → exports.js} +0 -0
  115. /package/dist/util/{performance.d.ts → Performance.d.ts} +0 -0
  116. /package/dist/util/{performance.js → Performance.js} +0 -0
@@ -0,0 +1,46 @@
1
+ import ts from 'typescript';
2
+ import { isRequireCall, findAncestor, findDescendants } from '../../ast-helpers.js';
3
+ import { isJS } from '../helpers.js';
4
+ import { importVisitor as visit } from '../index.js';
5
+ export default visit(isJS, node => {
6
+ if (isRequireCall(node)) {
7
+ if (ts.isStringLiteralLike(node.arguments[0])) {
8
+ const specifier = node.arguments[0].text;
9
+ if (specifier) {
10
+ const propertyAccessExpression = findAncestor(node, _node => {
11
+ if (ts.isExpressionStatement(_node) || ts.isCallExpression(_node))
12
+ return 'STOP';
13
+ return ts.isPropertyAccessExpression(_node);
14
+ });
15
+ if (propertyAccessExpression) {
16
+ const identifier = String(propertyAccessExpression.name.escapedText);
17
+ return { identifier, specifier };
18
+ }
19
+ else {
20
+ const variableDeclaration = node.parent;
21
+ if (ts.isVariableDeclaration(variableDeclaration) &&
22
+ ts.isVariableDeclarationList(variableDeclaration.parent)) {
23
+ if (ts.isIdentifier(variableDeclaration.name)) {
24
+ return { identifier: 'default', specifier };
25
+ }
26
+ else {
27
+ const bindings = findDescendants(variableDeclaration, ts.isBindingElement);
28
+ if (bindings.length > 0) {
29
+ return bindings.map(element => {
30
+ const identifier = (element.propertyName ?? element.name).getText();
31
+ return { identifier, specifier };
32
+ });
33
+ }
34
+ else {
35
+ return { identifier: 'default', specifier };
36
+ }
37
+ }
38
+ }
39
+ else {
40
+ return { identifier: 'default', specifier };
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ });
@@ -0,0 +1,3 @@
1
+ import ts from 'typescript';
2
+ declare const _default: (sourceFile: ts.SourceFile) => ((node: ts.Node, options: import("../../getImportsAndExports.js").GetImportsAndExportsOptions) => import("../../getImportsAndExports.js").AddImportOptions | import("../../getImportsAndExports.js").AddImportOptions[] | undefined) | undefined;
3
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import ts from 'typescript';
2
+ import { isRequireResolveCall } from '../../ast-helpers.js';
3
+ import { isJS } from '../helpers.js';
4
+ import { importVisitor as visit } from '../index.js';
5
+ export default visit(isJS, node => {
6
+ if (isRequireResolveCall(node)) {
7
+ if (node.arguments[0] && ts.isStringLiteralLike(node.arguments[0])) {
8
+ const specifier = node.arguments[0].text;
9
+ if (specifier) {
10
+ return { specifier };
11
+ }
12
+ }
13
+ }
14
+ });
@@ -0,0 +1,10 @@
1
+ import ts from 'typescript';
2
+ import type { GetImportsAndExportsOptions, AddExportOptions, AddImportOptions } from '../getImportsAndExports.js';
3
+ type FileCondition = (sourceFile: ts.SourceFile) => boolean;
4
+ type VisitorFactory<T> = (fileCondition: FileCondition, fn: Visitor<T>) => VisitorCondition<T>;
5
+ type VisitorCondition<T> = (sourceFile: ts.SourceFile) => undefined | Visitor<T>;
6
+ type Visitor<T> = (node: ts.Node, options: GetImportsAndExportsOptions) => undefined | T | T[];
7
+ export declare const importVisitor: VisitorFactory<AddImportOptions>;
8
+ export declare const exportVisitor: VisitorFactory<AddExportOptions>;
9
+ export declare const scriptVisitor: VisitorFactory<string>;
10
+ export {};
@@ -0,0 +1,15 @@
1
+ export const importVisitor = (fileCondition, visitorFn) => sourceFile => {
2
+ if (fileCondition(sourceFile)) {
3
+ return (node, options) => visitorFn(node, options);
4
+ }
5
+ };
6
+ export const exportVisitor = (fileCondition, visitorFn) => sourceFile => {
7
+ if (fileCondition(sourceFile)) {
8
+ return (node, options) => visitorFn(node, options);
9
+ }
10
+ };
11
+ export const scriptVisitor = (fileCondition, visitorFn) => sourceFile => {
12
+ if (fileCondition(sourceFile)) {
13
+ return (node, options) => visitorFn(node, options);
14
+ }
15
+ };
@@ -0,0 +1,3 @@
1
+ import ts from 'typescript';
2
+ declare const _default: (sourceFile: ts.SourceFile) => (((node: ts.Node, options: import("../../getImportsAndExports.js").GetImportsAndExportsOptions) => string | string[] | undefined) | undefined)[];
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import zx from './zx.js';
2
+ const visitors = [zx];
3
+ export default (sourceFile) => visitors.map(v => v(sourceFile)).filter(v => v);
@@ -0,0 +1,3 @@
1
+ import ts from 'typescript';
2
+ declare const _default: (sourceFile: ts.SourceFile) => ((node: ts.Node, options: import("../../getImportsAndExports.js").GetImportsAndExportsOptions) => string | string[] | undefined) | undefined;
3
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import ts from 'typescript';
2
+ import { stripQuotes } from '../../ast-helpers.js';
3
+ import { scriptVisitor as visit } from '../index.js';
4
+ export default visit(sourceFile => ts.getShebang(sourceFile.text) === '#!/usr/bin/env zx', node => {
5
+ if (ts.isTaggedTemplateExpression(node) && node.tag.getText() === '$') {
6
+ return stripQuotes(node.template.getText());
7
+ }
8
+ });
@@ -1,3 +1,2 @@
1
1
  export declare const compact: <T>(collection: (T | undefined)[]) => T[];
2
2
  export declare const arrayify: (value?: string[] | string) => string[];
3
- export declare const partition: <T>(values: Set<T> | T[], predicate: (value: T) => boolean) => [T[], T[]];
@@ -1,9 +1,2 @@
1
1
  export const compact = (collection) => Array.from(new Set(collection)).filter((value) => Boolean(value));
2
2
  export const arrayify = (value) => Array.isArray(value) ? value : typeof value === 'string' ? [value] : [];
3
- export const partition = (values, predicate) => {
4
- const results = [[], []];
5
- values.forEach(value => {
6
- results[predicate(value) ? 0 : 1].push(value);
7
- });
8
- return results;
9
- };
@@ -1,7 +1,8 @@
1
+ import { AsyncCompilerFn, SyncCompilerFn } from '../types/compilers.js';
1
2
  import { RawConfiguration } from '../types/config.js';
2
3
  export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
3
- exclude?: string[] | undefined;
4
- include?: string[] | undefined;
4
+ syncCompilers: Record<string, SyncCompilerFn>;
5
+ asyncCompilers: Record<string, AsyncCompilerFn>;
5
6
  entry?: string | string[] | undefined;
6
7
  project?: string | string[] | undefined;
7
8
  paths?: Record<string, string[]> | undefined;
@@ -10,8 +11,8 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
10
11
  ignoreDependencies?: string[] | undefined;
11
12
  ignoreWorkspaces?: string[] | undefined;
12
13
  compilers?: Record<string, ((args_0: string, ...args_1: unknown[]) => string) | ((args_0: string, ...args_1: unknown[]) => Promise<string>)> | undefined;
13
- syncCompilers?: Record<string, (args_0: string, ...args_1: unknown[]) => string> | undefined;
14
- asyncCompilers?: Record<string, (args_0: string, ...args_1: unknown[]) => Promise<string>> | undefined;
14
+ include?: string[] | undefined;
15
+ exclude?: string[] | undefined;
15
16
  workspaces?: Record<string, {
16
17
  entry?: string | string[] | undefined;
17
18
  project?: string | string[] | undefined;
@@ -16,7 +16,5 @@ export const partitionCompilers = (rawLocalConfig) => {
16
16
  const ext = normalizeExt(extension);
17
17
  asyncCompilers[ext] = rawLocalConfig.asyncCompilers[extension];
18
18
  }
19
- rawLocalConfig.syncCompilers = syncCompilers;
20
- rawLocalConfig.asyncCompilers = asyncCompilers;
21
- return rawLocalConfig;
19
+ return { ...rawLocalConfig, syncCompilers, asyncCompilers };
22
20
  };
package/dist/util/glob.js CHANGED
@@ -4,7 +4,7 @@ import { ROOT_WORKSPACE_NAME } from '../constants.js';
4
4
  import { compact } from './array.js';
5
5
  import { debugLogObject } from './debug.js';
6
6
  import { join, relative } from './path.js';
7
- import { timerify } from './performance.js';
7
+ import { timerify } from './Performance.js';
8
8
  export const prependDirToPattern = (workingDir, pattern) => {
9
9
  if (pattern.startsWith('!'))
10
10
  return '!' + join(workingDir, pattern.slice(1));
@@ -2,7 +2,7 @@ import { pathToFileURL } from 'node:url';
2
2
  import { LoaderError } from './errors.js';
3
3
  import { loadJSON, loadYAML, loadFile, parseJSON, parseYAML } from './fs.js';
4
4
  import { extname } from './path.js';
5
- import { timerify } from './performance.js';
5
+ import { timerify } from './Performance.js';
6
6
  import { jiti } from './register.js';
7
7
  const load = async (filePath) => {
8
8
  try {
@@ -1,5 +1,5 @@
1
1
  import { _load } from './loader.js';
2
- import { timerify } from './performance.js';
2
+ import { timerify } from './Performance.js';
3
3
  export const toCamelCase = (name) => name.toLowerCase().replace(/(-[a-z])/g, group => group.toUpperCase().replace('-', ''));
4
4
  export const hasDependency = (dependencies, values) => values.some(value => {
5
5
  if (typeof value === 'string') {
@@ -3,7 +3,7 @@ import { pathToFileURL } from 'node:url';
3
3
  import { debugLog } from './debug.js';
4
4
  import { getPackageNameFromModuleSpecifier } from './modules.js';
5
5
  import { cwd, toPosix, join } from './path.js';
6
- import { timerify } from './performance.js';
6
+ import { timerify } from './Performance.js';
7
7
  const createRequire = (path) => nodeCreateRequire(pathToFileURL(path ?? cwd));
8
8
  const require = createRequire();
9
9
  const resolve = (specifier) => toPosix(require.resolve(specifier));
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.1.3";
1
+ export declare const version = "2.2.1";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.1.3';
1
+ export const version = '2.2.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "2.1.3",
3
+ "version": "2.2.1",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://github.com/webpro/knip",
6
6
  "repository": "github:webpro/knip",
@@ -1,16 +0,0 @@
1
- import type { BoundSourceFile } from './SourceFile.js';
2
- import type { Imports, ExportItems } from '../types/ast.js';
3
- type Options = {
4
- skipTypeOnly: boolean;
5
- skipExports: boolean;
6
- };
7
- export declare const getImportsAndExports: (sourceFile: BoundSourceFile, options: Options) => {
8
- imports: {
9
- internal: Imports;
10
- external: Set<string>;
11
- unresolved: Set<string>;
12
- };
13
- exports: ExportItems;
14
- duplicateExports: string[][];
15
- };
16
- export {};
@@ -1,364 +0,0 @@
1
- import { isBuiltin } from 'node:module';
2
- import ts from 'typescript';
3
- import { SymbolType } from '../types/issues.js';
4
- import { isInNodeModules } from '../util/path.js';
5
- import * as ast from './ast-helpers.js';
6
- export const getImportsAndExports = (sourceFile, options) => {
7
- const internalImports = new Map();
8
- const externalImports = new Set();
9
- const unresolvedImports = new Set();
10
- const exports = new Map();
11
- const aliasedExports = {};
12
- const importedInternalSymbols = new Map();
13
- const addInternalImport = ({ identifier = '__anonymous', specifier, symbol, filePath, }) => {
14
- const isStar = identifier === '*';
15
- const isReExported = Boolean(isStar && !symbol);
16
- if (!internalImports.has(filePath)) {
17
- internalImports.set(filePath, {
18
- specifier,
19
- isStar,
20
- isReExported,
21
- isReExportedBy: new Set(),
22
- symbols: new Set(),
23
- });
24
- }
25
- const internalImport = internalImports.get(filePath);
26
- if (isReExported) {
27
- internalImport.isReExported = isReExported;
28
- internalImport.isReExportedBy.add(sourceFile.fileName);
29
- }
30
- if (isStar) {
31
- internalImport.isStar = isStar;
32
- }
33
- if (!isStar) {
34
- internalImport.symbols.add(identifier);
35
- }
36
- if (isStar && symbol) {
37
- importedInternalSymbols.set(symbol, filePath);
38
- }
39
- };
40
- const addImport = ({ specifier, symbol, identifier = '__anonymous' }) => {
41
- if (isBuiltin(specifier))
42
- return;
43
- const module = sourceFile.resolvedModules?.get(specifier, undefined);
44
- if (module?.resolvedModule) {
45
- const filePath = module.resolvedModule.resolvedFileName;
46
- if (filePath) {
47
- if (module.resolvedModule.isExternalLibraryImport) {
48
- if (!isInNodeModules(filePath)) {
49
- addInternalImport({ identifier, specifier, symbol, filePath });
50
- }
51
- else if (ast.isDeclarationFileExtension(module.resolvedModule.extension)) {
52
- externalImports.add(specifier);
53
- }
54
- else {
55
- externalImports.add(module.resolvedModule.packageId?.name ?? specifier);
56
- }
57
- }
58
- else {
59
- addInternalImport({ identifier, specifier, symbol, filePath });
60
- }
61
- }
62
- }
63
- else {
64
- unresolvedImports.add(specifier);
65
- }
66
- };
67
- const maybeAddNamespaceAccessAsImport = ({ namespace, member }) => {
68
- const symbol = sourceFile.locals?.get(namespace);
69
- if (symbol) {
70
- const importedSymbolFilePath = importedInternalSymbols.get(symbol);
71
- if (importedSymbolFilePath) {
72
- const internalImport = internalImports.get(importedSymbolFilePath);
73
- internalImport?.symbols.add(member);
74
- }
75
- }
76
- };
77
- const addExport = ({ node, identifier, type, pos, members }) => {
78
- if (options.skipExports)
79
- return;
80
- if (exports.has(identifier)) {
81
- const item = exports.get(identifier);
82
- exports.set(identifier, { ...item, node, type, pos, members });
83
- }
84
- else {
85
- exports.set(identifier, { node, type, pos, members });
86
- }
87
- };
88
- const addAliasedExport = (symbol, alias) => {
89
- aliasedExports[symbol] = aliasedExports[symbol] ?? [symbol];
90
- aliasedExports[symbol].push(alias);
91
- };
92
- const maybeAddAliasedExport = (node, alias) => {
93
- if (node && ts.isIdentifier(node) && sourceFile.symbol?.exports?.has(node.getText())) {
94
- addAliasedExport(node.getText(), alias);
95
- }
96
- };
97
- const visit = (node) => {
98
- if (ts.isImportDeclaration(node) && ts.isStringLiteralLike(node.moduleSpecifier)) {
99
- const specifier = node.moduleSpecifier.text;
100
- if (!node.importClause) {
101
- addImport({ specifier });
102
- }
103
- else {
104
- if (node.importClause.isTypeOnly && options.skipTypeOnly)
105
- return;
106
- if (ast.isDefaultImport(node)) {
107
- addImport({ specifier, identifier: 'default' });
108
- }
109
- if (node.importClause?.namedBindings) {
110
- if (ts.isNamespaceImport(node.importClause.namedBindings)) {
111
- const symbol = node.importClause.namedBindings.symbol;
112
- addImport({ symbol, specifier, identifier: '*' });
113
- }
114
- if (ts.isNamedImports(node.importClause.namedBindings)) {
115
- node.importClause.namedBindings.elements.forEach(element => {
116
- const identifier = (element.propertyName ?? element.name).getText();
117
- addImport({ symbol: element.symbol, specifier, identifier });
118
- });
119
- }
120
- }
121
- }
122
- }
123
- if (ast.isImportCall(node)) {
124
- if (node.arguments[0] && ts.isStringLiteralLike(node.arguments[0])) {
125
- const specifier = node.arguments[0].text;
126
- let _node = node.parent;
127
- while (_node) {
128
- if (ts.isExpressionStatement(_node)) {
129
- addImport({ specifier });
130
- break;
131
- }
132
- if (_node.parent && ts.isCallExpression(_node.parent)) {
133
- addImport({ specifier, identifier: 'default' });
134
- break;
135
- }
136
- if (ast.isAccessExpression(_node)) {
137
- const identifier = ast.getAccessExpressionName(_node);
138
- const isPromiseLike = identifier === 'then';
139
- const symbol = isPromiseLike ? 'default' : identifier;
140
- addImport({ identifier: symbol, specifier });
141
- break;
142
- }
143
- if (ast.isVariableDeclarationList(_node)) {
144
- const variableDeclarations = ast.findDescendants(_node, _node => ts.isVariableDeclaration(_node));
145
- variableDeclarations.forEach(variableDeclaration => {
146
- if (ts.isIdentifier(variableDeclaration.name)) {
147
- addImport({ identifier: 'default', specifier });
148
- }
149
- else {
150
- const binds = ast.findDescendants(variableDeclaration, _node => ts.isBindingElement(_node));
151
- binds.forEach(element => {
152
- const symbol = element.propertyName?.getText() || element.name.getText();
153
- addImport({ identifier: symbol, specifier });
154
- });
155
- }
156
- });
157
- break;
158
- }
159
- _node = _node.parent;
160
- }
161
- }
162
- }
163
- if (ts.isImportEqualsDeclaration(node) &&
164
- ts.isExternalModuleReference(node.moduleReference) &&
165
- ts.isStringLiteralLike(node.moduleReference.expression)) {
166
- const specifier = node.moduleReference.expression.text;
167
- addImport({ specifier, identifier: 'default' });
168
- }
169
- if (ast.isRequireCall(node)) {
170
- if (ts.isStringLiteralLike(node.arguments[0])) {
171
- const specifier = node.arguments[0].text;
172
- if (specifier) {
173
- const propertyAccessExpression = ast.findAncestor(node, _node => {
174
- if (ts.isExpressionStatement(_node) || ts.isCallExpression(_node))
175
- return 'STOP';
176
- return ts.isPropertyAccessExpression(_node);
177
- });
178
- if (propertyAccessExpression) {
179
- const identifier = String(propertyAccessExpression.name.escapedText);
180
- addImport({ identifier, specifier });
181
- }
182
- else {
183
- const variableDeclaration = node.parent;
184
- if (ts.isVariableDeclaration(variableDeclaration) &&
185
- ts.isVariableDeclarationList(variableDeclaration.parent)) {
186
- if (ts.isIdentifier(variableDeclaration.name)) {
187
- addImport({ identifier: 'default', specifier });
188
- }
189
- else {
190
- const bindings = ast.findDescendants(variableDeclaration, ts.isBindingElement);
191
- if (bindings.length > 0) {
192
- bindings.forEach(element => {
193
- const identifier = (element.propertyName ?? element.name).getText();
194
- addImport({ identifier, specifier });
195
- });
196
- }
197
- else {
198
- addImport({ identifier: 'default', specifier });
199
- }
200
- }
201
- }
202
- else {
203
- addImport({ identifier: 'default', specifier });
204
- }
205
- }
206
- }
207
- }
208
- }
209
- if (ast.isRequireResolveCall(node)) {
210
- if (node.arguments[0] && ts.isStringLiteralLike(node.arguments[0])) {
211
- const specifier = node.arguments[0].text;
212
- if (specifier) {
213
- addImport({ specifier });
214
- }
215
- }
216
- }
217
- const modifierKinds = node.modifiers?.map(modifier => modifier.kind) ?? [];
218
- if (ts.isExportAssignment(node)) {
219
- addExport({ node, identifier: 'default', type: SymbolType.UNKNOWN, pos: node.expression.getStart() });
220
- maybeAddAliasedExport(node.expression, 'default');
221
- }
222
- if (modifierKinds.includes(ts.SyntaxKind.ExportKeyword)) {
223
- if (ts.isVariableStatement(node)) {
224
- node.declarationList.declarations.forEach(declaration => {
225
- if (ts.isObjectBindingPattern(declaration.name)) {
226
- declaration.name.elements.forEach(element => {
227
- if (ts.isIdentifier(element.name)) {
228
- addExport({
229
- node: element,
230
- identifier: element.name.escapedText.toString(),
231
- type: SymbolType.UNKNOWN,
232
- pos: element.name.getStart(),
233
- });
234
- }
235
- });
236
- }
237
- else if (ts.isArrayBindingPattern(declaration.name)) {
238
- declaration.name.elements.forEach(element => {
239
- if (ts.isBindingElement(element)) {
240
- addExport({
241
- node: element,
242
- identifier: element.getText(),
243
- type: SymbolType.UNKNOWN,
244
- pos: element.getStart(),
245
- });
246
- }
247
- });
248
- }
249
- else {
250
- const identifier = declaration.name.getText();
251
- addExport({ node: declaration, identifier, type: SymbolType.UNKNOWN, pos: declaration.name.getStart() });
252
- maybeAddAliasedExport(declaration.initializer, identifier);
253
- }
254
- });
255
- }
256
- if (ts.isFunctionDeclaration(node) && node.name) {
257
- const identifier = modifierKinds.includes(ts.SyntaxKind.DefaultKeyword) ? 'default' : node.name.getText();
258
- const pos = (node.name ?? node.body ?? node).getStart();
259
- addExport({ node, identifier, pos, type: SymbolType.FUNCTION });
260
- }
261
- if (ts.isClassDeclaration(node) && node.name) {
262
- const identifier = modifierKinds.includes(ts.SyntaxKind.DefaultKeyword) ? 'default' : node.name.getText();
263
- const pos = (node.name ?? node).getStart();
264
- const members = node.members
265
- .filter((member) => (ts.isPropertyDeclaration(member) || ts.isMethodDeclaration(member)) && !ast.isPrivateMember(member))
266
- .map(member => ({
267
- node: member,
268
- identifier: member.name.getText(),
269
- pos: member.name.getStart(),
270
- type: SymbolType.MEMBER,
271
- }));
272
- addExport({ node, identifier, type: SymbolType.CLASS, pos, members });
273
- }
274
- if (ts.isTypeAliasDeclaration(node)) {
275
- addExport({ node, identifier: node.name.getText(), type: SymbolType.TYPE, pos: node.name.getStart() });
276
- }
277
- if (ts.isInterfaceDeclaration(node)) {
278
- addExport({ node, identifier: node.name.getText(), type: SymbolType.INTERFACE, pos: node.name.getStart() });
279
- }
280
- if (ts.isEnumDeclaration(node)) {
281
- const identifier = modifierKinds.includes(ts.SyntaxKind.DefaultKeyword) ? 'default' : node.name.getText();
282
- const pos = node.name.getStart();
283
- const members = node.members.map(member => ({
284
- node: member,
285
- identifier: ast.stripQuotes(member.name.getText()),
286
- pos: member.name.getStart(),
287
- type: SymbolType.MEMBER,
288
- }));
289
- addExport({ node, identifier, type: SymbolType.ENUM, pos, members });
290
- }
291
- }
292
- if (ts.isExportDeclaration(node)) {
293
- if (node.moduleSpecifier && ts.isStringLiteralLike(node.moduleSpecifier)) {
294
- if (!node.exportClause) {
295
- addImport({ identifier: '*', specifier: node.moduleSpecifier.text });
296
- }
297
- else if (node.exportClause.kind === ts.SyntaxKind.NamespaceExport) {
298
- addImport({ identifier: '*', specifier: node.moduleSpecifier.text });
299
- }
300
- else {
301
- const specifier = node.moduleSpecifier;
302
- node.exportClause.elements.forEach(element => {
303
- const identifier = (element.propertyName ?? element.name).getText();
304
- addImport({ identifier, specifier: specifier.text });
305
- });
306
- }
307
- }
308
- else if (node.exportClause && ts.isNamedExports(node.exportClause)) {
309
- const type = node.isTypeOnly ? SymbolType.TYPE : SymbolType.UNKNOWN;
310
- node.exportClause.elements.forEach(element => {
311
- addExport({ node: element, identifier: element.name.getText(), type, pos: element.name.pos });
312
- });
313
- }
314
- }
315
- if (ast.isModuleExportsAccessExpression(node)) {
316
- const parent = node.parent;
317
- if (ts.isPropertyAccessExpression(parent)) {
318
- const identifier = parent.name.getText();
319
- const pos = parent.name.getStart();
320
- addExport({ node, identifier, type: SymbolType.UNKNOWN, pos });
321
- }
322
- else if (ts.isElementAccessExpression(parent)) {
323
- const identifier = ast.stripQuotes(parent.argumentExpression.getText());
324
- const pos = parent.argumentExpression.getStart();
325
- addExport({ node, identifier, type: SymbolType.UNKNOWN, pos });
326
- }
327
- else if (ts.isBinaryExpression(parent)) {
328
- const expr = parent.right;
329
- if (ts.isObjectLiteralExpression(expr) && expr.properties.every(ts.isShorthandPropertyAssignment)) {
330
- expr.properties.forEach(node => {
331
- addExport({ node, identifier: node.getText(), type: SymbolType.UNKNOWN, pos: node.pos });
332
- });
333
- }
334
- else {
335
- addExport({ node, identifier: 'default', type: SymbolType.UNKNOWN, pos: node.getStart() });
336
- }
337
- }
338
- }
339
- if ('jsDoc' in node) {
340
- const type = ts.getJSDocType(node);
341
- if (type && ast.isValidImportTypeNode(type)) {
342
- addImport({ specifier: type.argument.literal.text });
343
- }
344
- }
345
- if (ast.isAccessExpression(node)) {
346
- maybeAddNamespaceAccessAsImport({
347
- namespace: node.expression.getText(),
348
- member: ast.getAccessExpressionName(node),
349
- });
350
- }
351
- ts.forEachChild(node, visit);
352
- };
353
- visit(sourceFile);
354
- const duplicateExports = Object.values(aliasedExports);
355
- return {
356
- imports: {
357
- internal: internalImports,
358
- external: externalImports,
359
- unresolved: unresolvedImports,
360
- },
361
- exports,
362
- duplicateExports,
363
- };
364
- };