knip 0.0.0-graph.3 → 0.0.0-node-types.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.
- package/README.md +7 -915
- package/bin/knip.js +2 -0
- package/dist/ConfigurationChief.d.ts +14 -6
- package/dist/ConfigurationChief.js +104 -70
- package/dist/ConfigurationValidator.d.ts +553 -321
- package/dist/ConfigurationValidator.js +7 -1
- package/dist/DependencyDeputy.d.ts +4 -1
- package/dist/DependencyDeputy.js +13 -11
- package/dist/PrincipalFactory.d.ts +5 -2
- package/dist/PrincipalFactory.js +11 -7
- package/dist/ProjectPrincipal.d.ts +18 -15
- package/dist/ProjectPrincipal.js +43 -25
- package/dist/WorkspaceWorker.d.ts +9 -7
- package/dist/WorkspaceWorker.js +45 -63
- package/dist/binaries/bash-parser.js +1 -1
- package/dist/binaries/index.js +12 -3
- package/dist/binaries/resolvers/c8.js +2 -1
- package/dist/binaries/resolvers/dotenv.js +2 -1
- package/dist/binaries/resolvers/fallback.js +4 -2
- package/dist/binaries/resolvers/index.d.ts +1 -0
- package/dist/binaries/resolvers/index.js +1 -0
- package/dist/binaries/resolvers/node.js +1 -1
- package/dist/binaries/resolvers/nodemon.js +2 -1
- package/dist/binaries/resolvers/npx.js +2 -1
- package/dist/binaries/resolvers/nx.js +1 -1
- package/dist/binaries/resolvers/pnpm.js +1 -1
- package/dist/binaries/resolvers/rollup.js +2 -1
- package/dist/binaries/resolvers/tsx.d.ts +2 -0
- package/dist/binaries/resolvers/tsx.js +6 -0
- package/dist/binaries/resolvers/yarn.js +1 -1
- package/dist/binaries/util.d.ts +0 -3
- package/dist/binaries/util.js +1 -3
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +10 -9
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +5 -4
- package/dist/index.js +101 -65
- package/dist/manifest/index.js +8 -4
- package/dist/plugins/_template/index.js +15 -3
- package/dist/plugins/_template/types.d.ts +1 -0
- package/dist/plugins/angular/index.js +11 -11
- package/dist/plugins/astro/index.d.ts +7 -0
- package/dist/plugins/astro/index.js +19 -0
- package/dist/plugins/ava/index.d.ts +1 -1
- package/dist/plugins/ava/index.js +28 -7
- package/dist/plugins/ava/types.d.ts +5 -1
- package/dist/plugins/babel/helpers.d.ts +1 -2
- package/dist/plugins/babel/helpers.js +28 -20
- package/dist/plugins/babel/index.js +17 -14
- package/dist/plugins/capacitor/index.js +7 -3
- package/dist/plugins/changesets/index.js +10 -6
- package/dist/plugins/commitizen/index.d.ts +1 -0
- package/dist/plugins/commitizen/index.js +8 -4
- package/dist/plugins/commitizen/types.d.ts +1 -1
- package/dist/plugins/commitlint/index.js +7 -3
- package/dist/plugins/cspell/index.js +7 -3
- package/dist/plugins/cspell/types.d.ts +1 -1
- package/dist/plugins/cypress/index.d.ts +3 -1
- package/dist/plugins/cypress/index.js +17 -4
- package/dist/plugins/drizzle/index.js +5 -7
- package/dist/plugins/eslint/fallback.js +6 -1
- package/dist/plugins/eslint/helpers.d.ts +4 -11
- package/dist/plugins/eslint/helpers.js +24 -26
- package/dist/plugins/eslint/index.d.ts +1 -1
- package/dist/plugins/eslint/index.js +14 -4
- package/dist/plugins/gatsby/index.js +11 -5
- package/dist/plugins/github-actions/index.d.ts +1 -1
- package/dist/plugins/github-actions/index.js +7 -4
- package/dist/plugins/graphql-codegen/index.d.ts +7 -0
- package/dist/plugins/graphql-codegen/index.js +46 -0
- package/dist/plugins/graphql-codegen/types.d.ts +25 -0
- package/dist/plugins/graphql-codegen/types.js +3 -0
- package/dist/plugins/husky/index.js +9 -4
- package/dist/plugins/index.d.ts +4 -0
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/jest/index.d.ts +1 -1
- package/dist/plugins/jest/index.js +21 -12
- package/dist/plugins/jest/types.d.ts +3 -0
- package/dist/plugins/lefthook/index.js +12 -8
- package/dist/plugins/lint-staged/index.d.ts +1 -0
- package/dist/plugins/lint-staged/index.js +10 -7
- package/dist/plugins/markdownlint/index.js +7 -4
- package/dist/plugins/mocha/index.d.ts +1 -0
- package/dist/plugins/mocha/index.js +12 -7
- package/dist/plugins/mocha/types.d.ts +4 -0
- package/dist/plugins/mocha/types.js +1 -0
- package/dist/plugins/next/index.d.ts +2 -1
- package/dist/plugins/next/index.js +7 -0
- package/dist/plugins/node-test-runner/index.d.ts +6 -0
- package/dist/plugins/node-test-runner/index.js +19 -0
- package/dist/plugins/npm-package-json-lint/index.d.ts +1 -0
- package/dist/plugins/npm-package-json-lint/index.js +8 -4
- package/dist/plugins/nx/index.js +13 -10
- package/dist/plugins/nyc/index.js +6 -3
- package/dist/plugins/nyc/types.d.ts +3 -0
- package/dist/plugins/nyc/types.js +1 -0
- package/dist/plugins/playwright/index.d.ts +5 -1
- package/dist/plugins/playwright/index.js +25 -2
- package/dist/plugins/playwright-ct/index.d.ts +3 -1
- package/dist/plugins/playwright-ct/index.js +18 -2
- package/dist/plugins/postcss/index.js +12 -9
- package/dist/plugins/prettier/index.js +11 -6
- package/dist/plugins/prettier/types.d.ts +8 -0
- package/dist/plugins/prettier/types.js +1 -0
- package/dist/plugins/release-it/index.d.ts +1 -0
- package/dist/plugins/release-it/index.js +14 -10
- package/dist/plugins/remark/index.d.ts +1 -0
- package/dist/plugins/remark/index.js +20 -4
- package/dist/plugins/remark/types.d.ts +3 -0
- package/dist/plugins/remark/types.js +1 -0
- package/dist/plugins/remix/index.d.ts +2 -1
- package/dist/plugins/remix/index.js +9 -0
- package/dist/plugins/rollup/index.d.ts +2 -1
- package/dist/plugins/rollup/index.js +8 -1
- package/dist/plugins/semantic-release/index.d.ts +1 -0
- package/dist/plugins/semantic-release/index.js +10 -4
- package/dist/plugins/semantic-release/types.d.ts +1 -1
- package/dist/plugins/sentry/index.d.ts +2 -1
- package/dist/plugins/sentry/index.js +7 -0
- package/dist/plugins/storybook/index.js +28 -10
- package/dist/plugins/storybook/types.d.ts +7 -0
- package/dist/plugins/stryker/index.js +13 -9
- package/dist/plugins/stylelint/index.js +8 -5
- package/dist/plugins/svelte/index.d.ts +2 -1
- package/dist/plugins/svelte/index.js +6 -0
- package/dist/plugins/tsup/index.d.ts +6 -0
- package/dist/plugins/tsup/index.js +23 -0
- package/dist/plugins/tsup/types.d.ts +7 -0
- package/dist/plugins/tsup/types.js +1 -0
- package/dist/plugins/typedoc/index.d.ts +1 -0
- package/dist/plugins/typedoc/index.js +8 -4
- package/dist/plugins/typedoc/types.d.ts +1 -1
- package/dist/plugins/typescript/index.js +16 -11
- package/dist/plugins/vite/index.js +7 -5
- package/dist/plugins/vitest/helpers.d.ts +2 -2
- package/dist/plugins/vitest/index.d.ts +4 -4
- package/dist/plugins/vitest/index.js +55 -26
- package/dist/plugins/vitest/types.d.ts +23 -2
- package/dist/plugins/webpack/index.js +31 -19
- package/dist/plugins/webpack/types.d.ts +2 -1
- package/dist/reporters/codeowners.js +2 -2
- package/dist/reporters/json.js +14 -9
- package/dist/reporters/symbols.js +3 -2
- package/dist/reporters/util.d.ts +8 -2
- package/dist/reporters/util.js +7 -1
- package/dist/types/cli.d.ts +1 -1
- package/dist/types/config.d.ts +9 -4
- package/dist/types/exports.d.ts +1 -0
- package/dist/types/imports.d.ts +6 -0
- package/dist/types/issues.d.ts +11 -1
- package/dist/types/package-json.d.ts +41 -0
- package/dist/types/package-json.js +1 -0
- package/dist/types/plugins.d.ts +5 -7
- package/dist/types/util.d.ts +16 -0
- package/dist/types/util.js +1 -0
- package/dist/types/workspace.d.ts +4 -1
- package/dist/typescript/SourceFile.d.ts +5 -0
- package/dist/typescript/SourceFileManager.js +3 -3
- package/dist/typescript/ast-helpers.d.ts +7 -14
- package/dist/typescript/ast-helpers.js +11 -9
- package/dist/typescript/createHosts.d.ts +1 -0
- package/dist/typescript/createHosts.js +1 -1
- package/dist/typescript/getImportsAndExports.d.ts +7 -5
- package/dist/typescript/getImportsAndExports.js +35 -18
- package/dist/typescript/resolveModuleNames.d.ts +1 -1
- package/dist/typescript/resolveModuleNames.js +38 -12
- package/dist/typescript/visitors/exports/exportDeclaration.js +14 -1
- package/dist/typescript/visitors/exports/exportKeyword.js +5 -2
- package/dist/typescript/visitors/exports/moduleExportsAccessExpression.js +29 -21
- package/dist/typescript/visitors/imports/importCall.js +1 -1
- package/dist/typescript/visitors/imports/importDeclaration.js +3 -3
- package/dist/typescript/visitors/imports/importEqualsDeclaration.js +1 -1
- package/dist/typescript/visitors/imports/jsDocType.js +37 -5
- package/dist/typescript/visitors/imports/propertyAccessCall.js +1 -1
- package/dist/typescript/visitors/imports/reExportDeclaration.js +8 -3
- package/dist/typescript/visitors/imports/requireCall.js +5 -5
- package/dist/util/array.d.ts +3 -1
- package/dist/util/cli-arguments.d.ts +3 -2
- package/dist/util/cli-arguments.js +6 -6
- package/dist/util/compilers.d.ts +122 -80
- package/dist/util/debug.d.ts +3 -3
- package/dist/util/debug.js +12 -18
- package/dist/util/fs.d.ts +2 -0
- package/dist/util/fs.js +22 -3
- package/dist/util/get-included-issue-types.js +14 -18
- package/dist/util/git.js +1 -1
- package/dist/util/glob.js +1 -1
- package/dist/util/loader.d.ts +2 -0
- package/dist/util/loader.js +23 -3
- package/dist/util/modules.d.ts +7 -1
- package/dist/util/modules.js +20 -10
- package/dist/util/object.d.ts +1 -0
- package/dist/util/object.js +3 -0
- package/dist/util/parse-args.d.ts +3 -0
- package/dist/util/parse-args.js +8 -0
- package/dist/util/path.d.ts +1 -0
- package/dist/util/path.js +5 -3
- package/dist/util/plugin.d.ts +4 -3
- package/dist/util/plugin.js +11 -4
- package/dist/util/protocols.d.ts +9 -0
- package/dist/util/protocols.js +9 -0
- package/dist/util/register.d.ts +2 -1
- package/dist/util/register.js +9 -13
- package/dist/util/require.js +7 -5
- package/dist/util/tsconfig-loader.js +2 -1
- package/dist/util/unwrap-function.d.ts +1 -0
- package/dist/util/unwrap-function.js +13 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +86 -85
- package/schema-jsonc.json +11 -0
- package/schema.json +27 -3
- package/dist/plugins/vite/types.d.ts +0 -4
- /package/dist/plugins/{vite → jest}/types.js +0 -0
|
@@ -3,7 +3,7 @@ import ts from 'typescript';
|
|
|
3
3
|
import { getOrSet } from '../util/map.js';
|
|
4
4
|
import { isMaybePackageName, sanitizeSpecifier } from '../util/modules.js';
|
|
5
5
|
import { isInNodeModules } from '../util/path.js';
|
|
6
|
-
import { isDeclarationFileExtension, isAccessExpression, getAccessExpressionName, getJSDocTags, } from './ast-helpers.js';
|
|
6
|
+
import { isDeclarationFileExtension, isAccessExpression, getAccessExpressionName, getJSDocTags, getLineAndCharacterOfPosition, } from './ast-helpers.js';
|
|
7
7
|
import getExportVisitors from './visitors/exports/index.js';
|
|
8
8
|
import { getJSXImplicitImportBase } from './visitors/helpers.js';
|
|
9
9
|
import getImportVisitors from './visitors/imports/index.js';
|
|
@@ -13,12 +13,12 @@ const getVisitors = (sourceFile) => ({
|
|
|
13
13
|
import: getImportVisitors(sourceFile),
|
|
14
14
|
script: getScriptVisitors(sourceFile),
|
|
15
15
|
});
|
|
16
|
-
export const getImportsAndExports = (sourceFile, options) => {
|
|
16
|
+
export const getImportsAndExports = (sourceFile, getResolvedModule, options) => {
|
|
17
17
|
const internalImports = new Map();
|
|
18
18
|
const externalImports = new Set();
|
|
19
19
|
const unresolvedImports = new Set();
|
|
20
20
|
const exports = new Map();
|
|
21
|
-
const aliasedExports =
|
|
21
|
+
const aliasedExports = new Map();
|
|
22
22
|
const scripts = new Set();
|
|
23
23
|
const importedInternalSymbols = new Map();
|
|
24
24
|
const jsxImport = getJSXImplicitImportBase(sourceFile);
|
|
@@ -47,10 +47,10 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
47
47
|
importedInternalSymbols.set(symbol, filePath);
|
|
48
48
|
};
|
|
49
49
|
const addImport = (options) => {
|
|
50
|
-
const { specifier, symbol, identifier = '__anonymous', isReExport = false } = options;
|
|
50
|
+
const { specifier, symbol, identifier = '__anonymous', isReExport = false, pos } = options;
|
|
51
51
|
if (isBuiltin(specifier))
|
|
52
52
|
return;
|
|
53
|
-
const module =
|
|
53
|
+
const module = getResolvedModule(specifier);
|
|
54
54
|
if (module?.resolvedModule) {
|
|
55
55
|
const filePath = module.resolvedModule.resolvedFileName;
|
|
56
56
|
if (filePath) {
|
|
@@ -74,7 +74,13 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
else {
|
|
77
|
-
|
|
77
|
+
if (typeof pos === 'number') {
|
|
78
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(pos);
|
|
79
|
+
unresolvedImports.add({ specifier, pos, line: line + 1, col: character + 1 });
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
unresolvedImports.add({ specifier });
|
|
83
|
+
}
|
|
78
84
|
}
|
|
79
85
|
};
|
|
80
86
|
const maybeAddNamespaceAccessAsImport = ({ namespace, member }) => {
|
|
@@ -87,7 +93,7 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
87
93
|
}
|
|
88
94
|
}
|
|
89
95
|
};
|
|
90
|
-
const addExport = ({ node, identifier, type, pos, members = [] }) => {
|
|
96
|
+
const addExport = ({ node, identifier, type, pos, posDecl, members = [] }) => {
|
|
91
97
|
if (options.skipExports)
|
|
92
98
|
return;
|
|
93
99
|
const jsDocTags = getJSDocTags(node);
|
|
@@ -95,10 +101,10 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
95
101
|
const item = exports.get(identifier);
|
|
96
102
|
const crew = [...item.members, ...members];
|
|
97
103
|
const tags = new Set([...item.jsDocTags, ...jsDocTags]);
|
|
98
|
-
exports.set(identifier, { ...item,
|
|
104
|
+
exports.set(identifier, { ...item, members: crew, jsDocTags: tags });
|
|
99
105
|
}
|
|
100
106
|
else {
|
|
101
|
-
exports.set(identifier, { node, type,
|
|
107
|
+
exports.set(identifier, { node, type, members, jsDocTags, pos, posDecl: posDecl ?? pos });
|
|
102
108
|
}
|
|
103
109
|
if (!jsDocTags.has('@alias')) {
|
|
104
110
|
if (ts.isExportAssignment(node))
|
|
@@ -109,9 +115,17 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
109
115
|
};
|
|
110
116
|
const maybeAddAliasedExport = (node, alias) => {
|
|
111
117
|
const identifier = node?.getText();
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
118
|
+
if (node && identifier) {
|
|
119
|
+
const exprt = sourceFile.symbol?.exports?.get(identifier);
|
|
120
|
+
if (exprt && exprt.valueDeclaration) {
|
|
121
|
+
if (!aliasedExports.has(identifier)) {
|
|
122
|
+
const pos = getLineAndCharacterOfPosition(exprt.valueDeclaration, exprt.valueDeclaration.pos);
|
|
123
|
+
aliasedExports.set(identifier, [{ symbol: identifier, ...pos }]);
|
|
124
|
+
}
|
|
125
|
+
const i = aliasedExports.get(identifier);
|
|
126
|
+
const pos = getLineAndCharacterOfPosition(node, node.pos);
|
|
127
|
+
i?.push({ symbol: alias, ...pos });
|
|
128
|
+
}
|
|
115
129
|
}
|
|
116
130
|
};
|
|
117
131
|
const visit = (node) => {
|
|
@@ -122,11 +136,14 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
122
136
|
[results].flat().forEach(addImport);
|
|
123
137
|
}
|
|
124
138
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
|
|
139
|
+
const isTopLevel = node.parent === sourceFile || node.parent?.parent === sourceFile;
|
|
140
|
+
if (isTopLevel) {
|
|
141
|
+
for (const visitor of visitors.export) {
|
|
142
|
+
if (visitor) {
|
|
143
|
+
const results = visitor(node, options);
|
|
144
|
+
if (results)
|
|
145
|
+
[results].flat().forEach(addExport);
|
|
146
|
+
}
|
|
130
147
|
}
|
|
131
148
|
}
|
|
132
149
|
for (const visitor of visitors.script) {
|
|
@@ -153,7 +170,7 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
153
170
|
},
|
|
154
171
|
exports: {
|
|
155
172
|
exported: exports,
|
|
156
|
-
duplicate:
|
|
173
|
+
duplicate: [...aliasedExports.values()],
|
|
157
174
|
},
|
|
158
175
|
scripts,
|
|
159
176
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
export declare function createCustomModuleResolver(customSys: typeof ts.sys, compilerOptions: ts.CompilerOptions, virtualFileExtensions: string[]): (moduleNames: string[], containingFile: string) => Array<ts.
|
|
2
|
+
export declare function createCustomModuleResolver(customSys: typeof ts.sys, compilerOptions: ts.CompilerOptions, virtualFileExtensions: string[]): (moduleNames: string[], containingFile: string) => Array<ts.ResolvedModuleFull | undefined>;
|
|
@@ -1,29 +1,55 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
+
import { isBuiltin } from 'node:module';
|
|
2
3
|
import ts from 'typescript';
|
|
3
4
|
import { sanitizeSpecifier } from '../util/modules.js';
|
|
4
|
-
import { dirname, extname, isInternal, join } from '../util/path.js';
|
|
5
|
+
import { dirname, extname, isAbsolute, isInternal, join } from '../util/path.js';
|
|
6
|
+
import { isDeclarationFileExtension } from './ast-helpers.js';
|
|
5
7
|
import { ensureRealFilePath, isVirtualFilePath } from './utils.js';
|
|
8
|
+
const resolutionCache = new Map();
|
|
9
|
+
const fileExists = (name, containingFile) => {
|
|
10
|
+
const resolvedFileName = isAbsolute(name) ? name : join(dirname(containingFile), name);
|
|
11
|
+
if (existsSync(resolvedFileName)) {
|
|
12
|
+
return {
|
|
13
|
+
resolvedFileName,
|
|
14
|
+
extension: extname(name),
|
|
15
|
+
isExternalLibraryImport: false,
|
|
16
|
+
resolvedUsingTsExtension: false,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
};
|
|
6
20
|
export function createCustomModuleResolver(customSys, compilerOptions, virtualFileExtensions) {
|
|
7
21
|
function resolveModuleNames(moduleNames, containingFile) {
|
|
8
|
-
return moduleNames.map(moduleName =>
|
|
22
|
+
return moduleNames.map(moduleName => {
|
|
23
|
+
const key = moduleName.startsWith('.')
|
|
24
|
+
? join(dirname(containingFile), moduleName)
|
|
25
|
+
: `${containingFile}:${moduleName}`;
|
|
26
|
+
if (resolutionCache.has(key))
|
|
27
|
+
return resolutionCache.get(key);
|
|
28
|
+
const resolvedModule = resolveModuleName(moduleName, containingFile);
|
|
29
|
+
resolutionCache.set(key, resolvedModule);
|
|
30
|
+
return resolvedModule;
|
|
31
|
+
});
|
|
9
32
|
}
|
|
10
33
|
function resolveModuleName(name, containingFile) {
|
|
11
34
|
const sanitizedSpecifier = sanitizeSpecifier(name);
|
|
35
|
+
if (isBuiltin(sanitizedSpecifier))
|
|
36
|
+
return undefined;
|
|
12
37
|
const tsResolvedModule = ts.resolveModuleName(sanitizedSpecifier, containingFile, compilerOptions, ts.sys).resolvedModule;
|
|
13
38
|
if (!tsResolvedModule) {
|
|
14
39
|
const extension = extname(sanitizedSpecifier);
|
|
15
|
-
if (extension &&
|
|
16
|
-
const
|
|
17
|
-
if (
|
|
18
|
-
return
|
|
19
|
-
resolvedFileName,
|
|
20
|
-
extension,
|
|
21
|
-
isExternalLibraryImport: false,
|
|
22
|
-
resolvedUsingTsExtension: false,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
40
|
+
if (extension && !virtualFileExtensions.includes(extension)) {
|
|
41
|
+
const module = fileExists(sanitizedSpecifier, containingFile);
|
|
42
|
+
if (module)
|
|
43
|
+
return module;
|
|
25
44
|
}
|
|
26
45
|
}
|
|
46
|
+
if (tsResolvedModule &&
|
|
47
|
+
isDeclarationFileExtension(tsResolvedModule?.extension) &&
|
|
48
|
+
isInternal(tsResolvedModule.resolvedFileName)) {
|
|
49
|
+
const module = fileExists(sanitizedSpecifier, containingFile);
|
|
50
|
+
if (module)
|
|
51
|
+
return module;
|
|
52
|
+
}
|
|
27
53
|
if (virtualFileExtensions.length === 0)
|
|
28
54
|
return tsResolvedModule;
|
|
29
55
|
if (tsResolvedModule && !isVirtualFilePath(tsResolvedModule.resolvedFileName, virtualFileExtensions)) {
|
|
@@ -5,8 +5,21 @@ export default visit(() => true, node => {
|
|
|
5
5
|
if (ts.isExportDeclaration(node)) {
|
|
6
6
|
if (node.exportClause && ts.isNamedExports(node.exportClause)) {
|
|
7
7
|
const type = node.isTypeOnly ? SymbolType.TYPE : SymbolType.UNKNOWN;
|
|
8
|
+
const sourceFile = node.getSourceFile();
|
|
9
|
+
const declarations = sourceFile.getNamedDeclarations?.();
|
|
8
10
|
return node.exportClause.elements.map(element => {
|
|
9
|
-
|
|
11
|
+
const identifier = String(element.name.escapedText);
|
|
12
|
+
const declaration = declarations?.get(identifier)?.find((d) => d !== element);
|
|
13
|
+
const pos = element.name.pos;
|
|
14
|
+
const name = ts.getNameOfDeclaration(declaration);
|
|
15
|
+
const posDecl = name?.pos ?? declaration?.pos ?? pos;
|
|
16
|
+
return {
|
|
17
|
+
node: element,
|
|
18
|
+
identifier,
|
|
19
|
+
type,
|
|
20
|
+
pos,
|
|
21
|
+
posDecl,
|
|
22
|
+
};
|
|
10
23
|
});
|
|
11
24
|
}
|
|
12
25
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { SymbolType } from '../../../types/issues.js';
|
|
3
3
|
import { compact } from '../../../util/array.js';
|
|
4
|
-
import { isPrivateMember, stripQuotes } from '../../ast-helpers.js';
|
|
4
|
+
import { isGetOrSetAccessorDeclaration, isPrivateMember, stripQuotes } from '../../ast-helpers.js';
|
|
5
5
|
import { exportVisitor as visit } from '../index.js';
|
|
6
6
|
export default visit(() => true, node => {
|
|
7
7
|
const modifierKinds = node.modifiers?.map(modifier => modifier.kind) ?? [];
|
|
@@ -47,7 +47,10 @@ export default visit(() => true, node => {
|
|
|
47
47
|
const identifier = modifierKinds.includes(ts.SyntaxKind.DefaultKeyword) ? 'default' : node.name.getText();
|
|
48
48
|
const pos = (node.name ?? node).getStart();
|
|
49
49
|
const members = node.members
|
|
50
|
-
.filter((member) => (ts.isPropertyDeclaration(member) ||
|
|
50
|
+
.filter((member) => (ts.isPropertyDeclaration(member) ||
|
|
51
|
+
ts.isMethodDeclaration(member) ||
|
|
52
|
+
isGetOrSetAccessorDeclaration(member)) &&
|
|
53
|
+
!isPrivateMember(member))
|
|
51
54
|
.map(member => ({
|
|
52
55
|
node: member,
|
|
53
56
|
identifier: member.name.getText(),
|
|
@@ -1,30 +1,38 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { SymbolType } from '../../../types/issues.js';
|
|
3
|
-
import {
|
|
3
|
+
import { stripQuotes } from '../../ast-helpers.js';
|
|
4
4
|
import { isJS } from '../helpers.js';
|
|
5
5
|
import { exportVisitor as visit } from '../index.js';
|
|
6
|
+
const isModuleExportsAccess = (node) => ts.isIdentifier(node.expression) && node.expression.escapedText === 'module' && node.name.escapedText === 'exports';
|
|
6
7
|
export default visit(isJS, node => {
|
|
7
|
-
if (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
8
|
+
if (ts.isExpressionStatement(node)) {
|
|
9
|
+
if (ts.isBinaryExpression(node.expression)) {
|
|
10
|
+
if (ts.isPropertyAccessExpression(node.expression.left)) {
|
|
11
|
+
if (ts.isPropertyAccessExpression(node.expression.left.expression) &&
|
|
12
|
+
isModuleExportsAccess(node.expression.left.expression)) {
|
|
13
|
+
const identifier = node.expression.left.name.getText();
|
|
14
|
+
const pos = node.expression.left.name.pos;
|
|
15
|
+
return { node, identifier, type: SymbolType.UNKNOWN, pos };
|
|
16
|
+
}
|
|
17
|
+
else if (isModuleExportsAccess(node.expression.left)) {
|
|
18
|
+
const expr = node.expression.right;
|
|
19
|
+
if (ts.isObjectLiteralExpression(expr) && expr.properties.every(ts.isShorthandPropertyAssignment)) {
|
|
20
|
+
return expr.properties.map(node => {
|
|
21
|
+
return { node, identifier: node.getText(), type: SymbolType.UNKNOWN, pos: node.pos };
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return { node, identifier: 'default', type: SymbolType.UNKNOWN, pos: expr.pos };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
25
28
|
}
|
|
26
|
-
else
|
|
27
|
-
|
|
29
|
+
else if (ts.isElementAccessExpression(node.expression.left) &&
|
|
30
|
+
ts.isPropertyAccessExpression(node.expression.left.expression) &&
|
|
31
|
+
ts.isIdentifier(node.expression.left.expression.name) &&
|
|
32
|
+
isModuleExportsAccess(node.expression.left.expression)) {
|
|
33
|
+
const identifier = stripQuotes(node.expression.left.argumentExpression.getText());
|
|
34
|
+
const pos = node.expression.left.argumentExpression.pos;
|
|
35
|
+
return { node, identifier, type: SymbolType.UNKNOWN, pos };
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
}
|
|
@@ -5,7 +5,7 @@ export default visit(() => true, node => {
|
|
|
5
5
|
if (isImportCall(node)) {
|
|
6
6
|
if (node.arguments[0] && ts.isStringLiteralLike(node.arguments[0])) {
|
|
7
7
|
const specifier = node.arguments[0].text;
|
|
8
|
-
return { specifier, identifier: 'default' };
|
|
8
|
+
return { specifier, identifier: 'default', pos: node.arguments[0].pos };
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
});
|
|
@@ -12,17 +12,17 @@ export default visit(() => true, (node, options) => {
|
|
|
12
12
|
return;
|
|
13
13
|
const imports = [];
|
|
14
14
|
if (isDefaultImport(node)) {
|
|
15
|
-
imports.push({ specifier, identifier: 'default' });
|
|
15
|
+
imports.push({ specifier, identifier: 'default', pos: node.moduleSpecifier.pos });
|
|
16
16
|
}
|
|
17
17
|
if (node.importClause?.namedBindings) {
|
|
18
18
|
if (ts.isNamespaceImport(node.importClause.namedBindings)) {
|
|
19
19
|
const symbol = node.importClause.namedBindings.symbol;
|
|
20
|
-
imports.push({ symbol, specifier, identifier: '*' });
|
|
20
|
+
imports.push({ symbol, specifier, identifier: '*', pos: symbol?.declarations[0]?.pos ?? node.pos });
|
|
21
21
|
}
|
|
22
22
|
if (ts.isNamedImports(node.importClause.namedBindings)) {
|
|
23
23
|
node.importClause.namedBindings.elements.forEach(element => {
|
|
24
24
|
const identifier = (element.propertyName ?? element.name).getText();
|
|
25
|
-
imports.push({ symbol: element.symbol, specifier, identifier });
|
|
25
|
+
imports.push({ symbol: element.symbol, specifier, identifier, pos: element.pos });
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -6,6 +6,6 @@ export default visit(isNotJS, node => {
|
|
|
6
6
|
ts.isExternalModuleReference(node.moduleReference) &&
|
|
7
7
|
ts.isStringLiteralLike(node.moduleReference.expression)) {
|
|
8
8
|
const specifier = node.moduleReference.expression.text;
|
|
9
|
-
return { specifier, identifier: 'default' };
|
|
9
|
+
return { specifier, identifier: 'default', pos: node.moduleReference.expression.pos };
|
|
10
10
|
}
|
|
11
11
|
});
|
|
@@ -1,11 +1,43 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
import { isValidImportTypeNode } from '../../ast-helpers.js';
|
|
3
2
|
import { importVisitor as visit } from '../index.js';
|
|
3
|
+
const extractImportSpecifiers = (node) => {
|
|
4
|
+
const importSpecifiers = [];
|
|
5
|
+
function visit(node) {
|
|
6
|
+
if (ts.isJSDocTypeExpression(node)) {
|
|
7
|
+
const typeNode = node.type;
|
|
8
|
+
if (ts.isTypeReferenceNode(typeNode) && typeNode.typeArguments) {
|
|
9
|
+
typeNode.typeArguments.forEach(arg => {
|
|
10
|
+
if (ts.isImportTypeNode(arg)) {
|
|
11
|
+
const importClause = arg.argument;
|
|
12
|
+
if (ts.isLiteralTypeNode(importClause) && ts.isStringLiteral(importClause.literal)) {
|
|
13
|
+
importSpecifiers.push(importClause.literal.text);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (ts.isJSDocTypeTag(node)) {
|
|
20
|
+
const typeNode = node.typeExpression?.type;
|
|
21
|
+
if (ts.isImportTypeNode(typeNode)) {
|
|
22
|
+
const importClause = typeNode.argument;
|
|
23
|
+
if (ts.isLiteralTypeNode(importClause) && ts.isStringLiteral(importClause.literal)) {
|
|
24
|
+
importSpecifiers.push(importClause.literal.text);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
ts.forEachChild(node, visit);
|
|
29
|
+
}
|
|
30
|
+
visit(node);
|
|
31
|
+
return importSpecifiers;
|
|
32
|
+
};
|
|
4
33
|
export default visit(() => true, node => {
|
|
5
|
-
if ('jsDoc' in node) {
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
8
|
-
return
|
|
34
|
+
if ('jsDoc' in node && node.jsDoc) {
|
|
35
|
+
const jsDoc = node.jsDoc;
|
|
36
|
+
if (jsDoc.length > 0 && jsDoc[0].parent.parent === node.parent) {
|
|
37
|
+
return jsDoc
|
|
38
|
+
.flatMap(jsDoc => (jsDoc.tags ?? []).flatMap(extractImportSpecifiers))
|
|
39
|
+
.map(specifier => ({ specifier }));
|
|
9
40
|
}
|
|
10
41
|
}
|
|
42
|
+
return [];
|
|
11
43
|
});
|
|
@@ -6,7 +6,7 @@ export default visit(() => true, node => {
|
|
|
6
6
|
if (node.arguments[0] && ts.isStringLiteralLike(node.arguments[0])) {
|
|
7
7
|
const specifier = node.arguments[0].text;
|
|
8
8
|
if (specifier)
|
|
9
|
-
return { specifier };
|
|
9
|
+
return { specifier, pos: node.arguments[0].pos };
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
});
|
|
@@ -4,16 +4,21 @@ export default visit(() => true, node => {
|
|
|
4
4
|
if (ts.isExportDeclaration(node)) {
|
|
5
5
|
if (node.moduleSpecifier && ts.isStringLiteralLike(node.moduleSpecifier)) {
|
|
6
6
|
if (!node.exportClause) {
|
|
7
|
-
return { identifier: '*', specifier: node.moduleSpecifier.text, isReExport: true };
|
|
7
|
+
return { identifier: '*', specifier: node.moduleSpecifier.text, isReExport: true, pos: node.pos };
|
|
8
8
|
}
|
|
9
9
|
else if (node.exportClause.kind === ts.SyntaxKind.NamespaceExport) {
|
|
10
|
-
return {
|
|
10
|
+
return {
|
|
11
|
+
identifier: '*',
|
|
12
|
+
specifier: node.moduleSpecifier.text,
|
|
13
|
+
isReExport: true,
|
|
14
|
+
pos: node.exportClause.name.pos,
|
|
15
|
+
};
|
|
11
16
|
}
|
|
12
17
|
else {
|
|
13
18
|
const specifier = node.moduleSpecifier;
|
|
14
19
|
return node.exportClause.elements.map(element => {
|
|
15
20
|
const identifier = (element.propertyName ?? element.name).getText();
|
|
16
|
-
return { identifier, specifier: specifier.text, isReExport: true };
|
|
21
|
+
return { identifier, specifier: specifier.text, isReExport: true, pos: element.pos };
|
|
17
22
|
});
|
|
18
23
|
}
|
|
19
24
|
}
|
|
@@ -13,30 +13,30 @@ export default visit(() => true, node => {
|
|
|
13
13
|
});
|
|
14
14
|
if (propertyAccessExpression) {
|
|
15
15
|
const identifier = String(propertyAccessExpression.name.escapedText);
|
|
16
|
-
return { identifier, specifier };
|
|
16
|
+
return { identifier, specifier, pos: propertyAccessExpression.name.pos };
|
|
17
17
|
}
|
|
18
18
|
else {
|
|
19
19
|
const variableDeclaration = node.parent;
|
|
20
20
|
if (ts.isVariableDeclaration(variableDeclaration) &&
|
|
21
21
|
ts.isVariableDeclarationList(variableDeclaration.parent)) {
|
|
22
22
|
if (ts.isIdentifier(variableDeclaration.name)) {
|
|
23
|
-
return { identifier: 'default', specifier };
|
|
23
|
+
return { identifier: 'default', specifier, pos: node.arguments[0].pos };
|
|
24
24
|
}
|
|
25
25
|
else {
|
|
26
26
|
const bindings = findDescendants(variableDeclaration, ts.isBindingElement);
|
|
27
27
|
if (bindings.length > 0) {
|
|
28
28
|
return bindings.map(element => {
|
|
29
29
|
const identifier = (element.propertyName ?? element.name).getText();
|
|
30
|
-
return { identifier, specifier };
|
|
30
|
+
return { identifier, specifier, pos: element.pos };
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
|
-
return { identifier: 'default', specifier };
|
|
34
|
+
return { identifier: 'default', specifier, pos: node.arguments[0].pos };
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
|
-
return { identifier: 'default', specifier };
|
|
39
|
+
return { identifier: 'default', specifier, pos: node.arguments[0].pos };
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
}
|
package/dist/util/array.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
type Collection<T> = Array<T> | Set<T>;
|
|
2
|
+
export declare const compact: <T>(collection: Collection<T | undefined>) => T[];
|
|
2
3
|
export declare const arrayify: (value?: string[] | string) => string[];
|
|
4
|
+
export {};
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
export declare const helpText = "\u2702\uFE0F Find unused files, dependencies and exports in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -c, --config [file] Configuration file path (default: [.]knip.json[c], knip.js, knip.ts or package.json#knip)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n --production Analyze only production source files (e.g. no tests, devDependencies, exported types)\n --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n
|
|
1
|
+
export declare const helpText = "\u2702\uFE0F Find unused files, dependencies and exports in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -c, --config [file] Configuration file path (default: [.]knip.json[c], knip.js, knip.ts or package.json#knip)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n --production Analyze only production source files (e.g. no tests, devDependencies, exported types)\n --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n -W, --workspace [dir] Analyze a single workspace (default: analyze all configured workspaces)\n --directory [dir] Run process from a different directory (default: cwd)\n --no-gitignore Don't use .gitignore\n --include Report only provided issue type(s), can be comma-separated or repeated (1)\n --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)\n --dependencies Shortcut for --include dependencies,unlisted,binaries,unresolved\n --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates\n --include-entry-exports Include entry files when reporting unused exports\n --isolate-workspaces Isolated workspaces in monorepo\n -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)\n --preprocessor Preprocess the results before providing it to the reporter(s), can be repeated\n --preprocessor-options Pass extra options to the preprocessor (as JSON string, see --reporter-options example)\n --reporter Select reporter: symbols, compact, codeowners, json, can be repeated (default: symbols)\n --reporter-options Pass extra options to the reporter (as JSON string, see example)\n --no-config-hints Suppress configuration hints\n --no-exit-code Always exit with code zero (0)\n --max-issues Maximum number of issues before non-zero exit code (default: 0)\n -d, --debug Show debug output\n --performance Measure count and running time of expensive functions and display stats table\n -h, --help Print this help text\n -V, --version Print version\n\n(1) Issue types: files, dependencies, unlisted, unresolved, exports, nsExports, classMembers, types, nsTypes, enumMembers, duplicates\n\nExamples:\n\n$ knip\n$ knip --production\n$ knip --workspace packages/client --include files,dependencies\n$ knip -c ./config/knip.json --reporter compact\n$ knip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n\nMore documentation and bug reports: https://github.com/webpro/knip";
|
|
2
2
|
declare const _default: {
|
|
3
3
|
config: string | undefined;
|
|
4
4
|
debug: boolean | undefined;
|
|
5
|
-
'debug-file-filter': string | undefined;
|
|
6
5
|
dependencies: boolean | undefined;
|
|
6
|
+
directory: string | undefined;
|
|
7
7
|
exclude: string[] | undefined;
|
|
8
8
|
exports: boolean | undefined;
|
|
9
9
|
help: boolean | undefined;
|
|
10
10
|
'ignore-internal': boolean | undefined;
|
|
11
11
|
include: string[] | undefined;
|
|
12
12
|
'include-entry-exports': boolean | undefined;
|
|
13
|
+
'isolate-workspaces': boolean | undefined;
|
|
13
14
|
'max-issues': string | undefined;
|
|
14
15
|
'no-config-hints': boolean | undefined;
|
|
15
16
|
'no-exit-code': boolean | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseArgs } from '
|
|
1
|
+
import { parseArgs } from './parse-args.js';
|
|
2
2
|
export const helpText = `✂️ Find unused files, dependencies and exports in your JavaScript and TypeScript projects
|
|
3
3
|
|
|
4
4
|
Usage: knip [options]
|
|
@@ -8,14 +8,15 @@ Options:
|
|
|
8
8
|
-t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)
|
|
9
9
|
--production Analyze only production source files (e.g. no tests, devDependencies, exported types)
|
|
10
10
|
--strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)
|
|
11
|
-
--ignore-internal Ignore exports with tag @internal (JSDoc/TSDoc)
|
|
12
11
|
-W, --workspace [dir] Analyze a single workspace (default: analyze all configured workspaces)
|
|
12
|
+
--directory [dir] Run process from a different directory (default: cwd)
|
|
13
13
|
--no-gitignore Don't use .gitignore
|
|
14
14
|
--include Report only provided issue type(s), can be comma-separated or repeated (1)
|
|
15
15
|
--exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)
|
|
16
|
-
--dependencies Shortcut for --include dependencies,unlisted,unresolved
|
|
16
|
+
--dependencies Shortcut for --include dependencies,unlisted,binaries,unresolved
|
|
17
17
|
--exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates
|
|
18
18
|
--include-entry-exports Include entry files when reporting unused exports
|
|
19
|
+
--isolate-workspaces Isolated workspaces in monorepo
|
|
19
20
|
-n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)
|
|
20
21
|
--preprocessor Preprocess the results before providing it to the reporter(s), can be repeated
|
|
21
22
|
--preprocessor-options Pass extra options to the preprocessor (as JSON string, see --reporter-options example)
|
|
@@ -25,7 +26,6 @@ Options:
|
|
|
25
26
|
--no-exit-code Always exit with code zero (0)
|
|
26
27
|
--max-issues Maximum number of issues before non-zero exit code (default: 0)
|
|
27
28
|
-d, --debug Show debug output
|
|
28
|
-
--debug-file-filter Filter for files in debug output (regex as string)
|
|
29
29
|
--performance Measure count and running time of expensive functions and display stats table
|
|
30
30
|
-h, --help Print this help text
|
|
31
31
|
-V, --version Print version
|
|
@@ -39,7 +39,6 @@ $ knip --production
|
|
|
39
39
|
$ knip --workspace packages/client --include files,dependencies
|
|
40
40
|
$ knip -c ./config/knip.json --reporter compact
|
|
41
41
|
$ knip --reporter codeowners --reporter-options '{"path":".github/CODEOWNERS"}'
|
|
42
|
-
$ knip --debug --debug-file-filter '(specific|particular)-module'
|
|
43
42
|
|
|
44
43
|
More documentation and bug reports: https://github.com/webpro/knip`;
|
|
45
44
|
let parsedArgs;
|
|
@@ -48,14 +47,15 @@ try {
|
|
|
48
47
|
options: {
|
|
49
48
|
config: { type: 'string', short: 'c' },
|
|
50
49
|
debug: { type: 'boolean', short: 'd' },
|
|
51
|
-
'debug-file-filter': { type: 'string' },
|
|
52
50
|
dependencies: { type: 'boolean' },
|
|
51
|
+
directory: { type: 'string' },
|
|
53
52
|
exclude: { type: 'string', multiple: true },
|
|
54
53
|
exports: { type: 'boolean' },
|
|
55
54
|
help: { type: 'boolean', short: 'h' },
|
|
56
55
|
'ignore-internal': { type: 'boolean' },
|
|
57
56
|
include: { type: 'string', multiple: true },
|
|
58
57
|
'include-entry-exports': { type: 'boolean' },
|
|
58
|
+
'isolate-workspaces': { type: 'boolean' },
|
|
59
59
|
'max-issues': { type: 'string' },
|
|
60
60
|
'no-config-hints': { type: 'boolean' },
|
|
61
61
|
'no-exit-code': { type: 'boolean' },
|