knip 6.33.0 → 6.34.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/dist/ProjectPrincipal.d.ts +6 -3
- package/dist/ProjectPrincipal.js +28 -6
- package/dist/cli.js +2 -2
- package/dist/graph/analyze.js +3 -3
- package/dist/graph/build.js +1 -1
- package/dist/plugins/node/index.js +5 -0
- package/dist/plugins/node/visitors/fsPromisesGlob.d.ts +2 -0
- package/dist/plugins/node/visitors/fsPromisesGlob.js +89 -0
- package/dist/plugins/nuxt/index.js +13 -10
- package/dist/run.js +1 -1
- package/dist/types/config.d.ts +1 -0
- package/dist/types/module-graph.d.ts +2 -0
- package/dist/typescript/get-imports-and-exports.js +4 -1
- package/dist/typescript/glob-imports.js +8 -3
- package/dist/typescript/visitors/calls.js +1 -1
- package/dist/typescript/visitors/walk.d.ts +3 -1
- package/dist/typescript/visitors/walk.js +78 -13
- package/dist/util/cli-arguments.d.ts +1 -0
- package/dist/util/cli-arguments.js +9 -0
- package/dist/util/create-options.d.ts +2 -1
- package/dist/util/create-options.js +3 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ParseResult } from 'oxc-parser';
|
|
2
2
|
import { CacheConsultant } from './CacheConsultant.ts';
|
|
3
|
-
import type { AsyncCompilers, SyncCompilers } from './compilers/types.ts';
|
|
3
|
+
import type { AsyncCompilers, Compilers, SyncCompilers } from './compilers/types.ts';
|
|
4
4
|
import type { GetImportsAndExportsOptions, IgnoreExportsUsedInFile, PluginVisitorContext, PluginVisitorObject } from './types/config.ts';
|
|
5
5
|
import type { FileNode, ModuleGraph } from './types/module-graph.ts';
|
|
6
6
|
import type { Paths } from './types/project.ts';
|
|
@@ -19,6 +19,8 @@ export declare class ProjectPrincipal {
|
|
|
19
19
|
private _localRefsVisitor;
|
|
20
20
|
syncCompilers: SyncCompilers;
|
|
21
21
|
asyncCompilers: AsyncCompilers;
|
|
22
|
+
private scopedSyncCompilers;
|
|
23
|
+
private scopedAsyncCompilers;
|
|
22
24
|
private paths;
|
|
23
25
|
private rootDirs;
|
|
24
26
|
private tsConfigFile;
|
|
@@ -26,14 +28,15 @@ export declare class ProjectPrincipal {
|
|
|
26
28
|
cache: CacheConsultant<FileNode>;
|
|
27
29
|
toSourceFilePath: ToSourceFilePath;
|
|
28
30
|
private findWorkspacePackageTarget;
|
|
31
|
+
private findWorkspaceNameByFilePath;
|
|
29
32
|
fileManager: SourceFileManager;
|
|
30
33
|
private resolveModule;
|
|
31
34
|
resolveGlobPattern: ResolveGlobPattern;
|
|
32
35
|
resolvedFiles: Set<string>;
|
|
33
36
|
deletedFiles: Set<string>;
|
|
34
37
|
private onPathAdded;
|
|
35
|
-
constructor(options: MainOptions, toSourceFilePath: ToSourceFilePath, findWorkspacePackageTarget
|
|
36
|
-
addCompilers(
|
|
38
|
+
constructor(options: MainOptions, toSourceFilePath: ToSourceFilePath, findWorkspacePackageTarget: WorkspacePackageTargetHandler | undefined, findWorkspaceNameByFilePath: (filePath: string) => string | undefined);
|
|
39
|
+
addCompilers(workspaceName: string, compilers: Compilers): void;
|
|
37
40
|
addPaths(paths: Paths, basePath: string, scope: string): void;
|
|
38
41
|
addRootDirs(rootDirs: string[] | undefined, scope: string): void;
|
|
39
42
|
init(): void;
|
package/dist/ProjectPrincipal.js
CHANGED
|
@@ -30,6 +30,8 @@ export class ProjectPrincipal {
|
|
|
30
30
|
_localRefsVisitor;
|
|
31
31
|
syncCompilers = new Map();
|
|
32
32
|
asyncCompilers = new Map();
|
|
33
|
+
scopedSyncCompilers = new Map();
|
|
34
|
+
scopedAsyncCompilers = new Map();
|
|
33
35
|
paths = new Map();
|
|
34
36
|
rootDirs = new Map();
|
|
35
37
|
tsConfigFile;
|
|
@@ -37,16 +39,18 @@ export class ProjectPrincipal {
|
|
|
37
39
|
cache;
|
|
38
40
|
toSourceFilePath;
|
|
39
41
|
findWorkspacePackageTarget;
|
|
42
|
+
findWorkspaceNameByFilePath;
|
|
40
43
|
fileManager;
|
|
41
44
|
resolveModule = () => undefined;
|
|
42
45
|
resolveGlobPattern = pattern => [pattern];
|
|
43
46
|
resolvedFiles = new Set();
|
|
44
47
|
deletedFiles = new Set();
|
|
45
48
|
onPathAdded;
|
|
46
|
-
constructor(options, toSourceFilePath, findWorkspacePackageTarget) {
|
|
49
|
+
constructor(options, toSourceFilePath, findWorkspacePackageTarget, findWorkspaceNameByFilePath) {
|
|
47
50
|
this.cache = new CacheConsultant('root', options);
|
|
48
51
|
this.toSourceFilePath = toSourceFilePath;
|
|
49
52
|
this.findWorkspacePackageTarget = findWorkspacePackageTarget;
|
|
53
|
+
this.findWorkspaceNameByFilePath = findWorkspaceNameByFilePath;
|
|
50
54
|
this.tsConfigFile = options.tsConfigFile ? toAbsolute(options.tsConfigFile, options.cwd) : undefined;
|
|
51
55
|
this.pluginVisitorObjects.push(createBunShellVisitor(this.pluginCtx));
|
|
52
56
|
this.fileManager = new SourceFileManager({
|
|
@@ -54,16 +58,34 @@ export class ProjectPrincipal {
|
|
|
54
58
|
});
|
|
55
59
|
this.walkAndAnalyze = timerify(this.walkAndAnalyze.bind(this), 'walkAndAnalyze');
|
|
56
60
|
}
|
|
57
|
-
addCompilers(compilers) {
|
|
61
|
+
addCompilers(workspaceName, compilers) {
|
|
58
62
|
for (const [ext, compiler] of compilers[0]) {
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
const workspaceCompilers = this.scopedSyncCompilers.get(ext);
|
|
64
|
+
if (workspaceCompilers) {
|
|
65
|
+
workspaceCompilers.set(workspaceName, compiler);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const workspaceCompilers = new Map([[workspaceName, compiler]]);
|
|
69
|
+
this.scopedSyncCompilers.set(ext, workspaceCompilers);
|
|
70
|
+
this.syncCompilers.set(ext, (source, filePath) => {
|
|
71
|
+
const owner = this.findWorkspaceNameByFilePath(filePath);
|
|
72
|
+
return ((owner ? workspaceCompilers.get(owner) : undefined) ?? compiler)(source, filePath);
|
|
73
|
+
});
|
|
61
74
|
this.extensions.add(ext);
|
|
62
75
|
}
|
|
63
76
|
}
|
|
64
77
|
for (const [ext, compiler] of compilers[1]) {
|
|
65
|
-
|
|
66
|
-
|
|
78
|
+
const workspaceCompilers = this.scopedAsyncCompilers.get(ext);
|
|
79
|
+
if (workspaceCompilers) {
|
|
80
|
+
workspaceCompilers.set(workspaceName, compiler);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
const workspaceCompilers = new Map([[workspaceName, compiler]]);
|
|
84
|
+
this.scopedAsyncCompilers.set(ext, workspaceCompilers);
|
|
85
|
+
this.asyncCompilers.set(ext, (source, filePath) => {
|
|
86
|
+
const owner = this.findWorkspaceNameByFilePath(filePath);
|
|
87
|
+
return ((owner ? workspaceCompilers.get(owner) : undefined) ?? compiler)(source, filePath);
|
|
88
|
+
});
|
|
67
89
|
this.extensions.add(ext);
|
|
68
90
|
}
|
|
69
91
|
}
|
package/dist/cli.js
CHANGED
|
@@ -51,7 +51,7 @@ const main = async () => {
|
|
|
51
51
|
isShowProgress: options.isShowProgress,
|
|
52
52
|
isTreatConfigHintsAsErrors: options.isTreatConfigHintsAsErrors,
|
|
53
53
|
isTreatTagHintsAsErrors: options.isTreatTagHintsAsErrors,
|
|
54
|
-
maxShowIssues:
|
|
54
|
+
maxShowIssues: options.maxShowIssues,
|
|
55
55
|
options: args['reporter-options'] ?? '',
|
|
56
56
|
preprocessorOptions: args['preprocessor-options'] ?? '',
|
|
57
57
|
selectedWorkspaces,
|
|
@@ -75,7 +75,7 @@ const main = async () => {
|
|
|
75
75
|
perfObserver.reset();
|
|
76
76
|
}
|
|
77
77
|
if (!args['no-exit-code'] &&
|
|
78
|
-
(totalErrorCount >
|
|
78
|
+
(totalErrorCount > options.maxIssues ||
|
|
79
79
|
(!options.isDisableConfigHints && options.isTreatConfigHintsAsErrors && configurationHints.length > 0) ||
|
|
80
80
|
(!options.isDisableTagHints && options.isTreatTagHintsAsErrors && tagHints.size > 0))) {
|
|
81
81
|
process.exitCode = 1;
|
package/dist/graph/analyze.js
CHANGED
|
@@ -191,7 +191,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
-
if (file.imports
|
|
194
|
+
if (file.imports.external) {
|
|
195
195
|
for (const extImport of file.imports.external) {
|
|
196
196
|
const packageName = getPackageNameFromModuleSpecifier(extImport.specifier);
|
|
197
197
|
const isHandled = packageName &&
|
|
@@ -200,7 +200,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
200
200
|
isTypeOnly: extImport.isTypeOnly,
|
|
201
201
|
isResolved: extImport.filePath !== undefined,
|
|
202
202
|
});
|
|
203
|
-
if (!isHandled)
|
|
203
|
+
if (!isHandled && !(extImport.jsDocTags?.size && shouldIgnoreTags(extImport.jsDocTags)))
|
|
204
204
|
collector.addIssue({
|
|
205
205
|
type: 'unlisted',
|
|
206
206
|
filePath,
|
|
@@ -214,7 +214,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
214
214
|
});
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
|
-
if (file.imports
|
|
217
|
+
if (file.imports.unresolved) {
|
|
218
218
|
for (const unresolvedImport of file.imports.unresolved) {
|
|
219
219
|
const { specifier, pos, line, col } = unresolvedImport;
|
|
220
220
|
collector.addIssue({
|
package/dist/graph/build.js
CHANGED
|
@@ -90,7 +90,7 @@ export async function build({ chief, collector, counselor, deputy, principal, is
|
|
|
90
90
|
compilers[0].set(ext, compiler);
|
|
91
91
|
};
|
|
92
92
|
await worker.registerCompilers(registerCompiler);
|
|
93
|
-
principal.addCompilers(compilers);
|
|
93
|
+
principal.addCompilers(name, compilers);
|
|
94
94
|
const extensions = getCompilerExtensions(compilers);
|
|
95
95
|
const extensionGlobStr = `.{${[...DEFAULT_EXTENSIONS, ...extensions].map(ext => ext.slice(1)).join(',')}}`;
|
|
96
96
|
const config = chief.getConfigForWorkspace(name, extensions);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { toEntry, toProductionEntry } from '../../util/input.js';
|
|
2
2
|
import { getScriptCommands } from '../../util/scripts.js';
|
|
3
|
+
import { createFsPromisesGlobVisitor } from './visitors/fsPromisesGlob.js';
|
|
3
4
|
const title = 'Node.js';
|
|
4
5
|
const isEnabled = () => true;
|
|
5
6
|
const patterns = [
|
|
@@ -21,6 +22,9 @@ const hasNodeTest = (scripts) => {
|
|
|
21
22
|
return result;
|
|
22
23
|
};
|
|
23
24
|
const entry = ['server.js'];
|
|
25
|
+
const registerVisitors = ({ ctx, registerVisitor }) => {
|
|
26
|
+
registerVisitor(createFsPromisesGlobVisitor(ctx));
|
|
27
|
+
};
|
|
24
28
|
const resolve = options => {
|
|
25
29
|
const entries = entry.map(id => toProductionEntry(id));
|
|
26
30
|
if (hasNodeTest(options.manifest.scripts) || hasNodeTest(options.rootManifest?.scripts)) {
|
|
@@ -53,5 +57,6 @@ const plugin = {
|
|
|
53
57
|
entry,
|
|
54
58
|
resolve,
|
|
55
59
|
args,
|
|
60
|
+
registerVisitors,
|
|
56
61
|
};
|
|
57
62
|
export default plugin;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { findProperty, getPropertyKey } from '../../../typescript/ast-helpers.js';
|
|
2
|
+
import { getStringValue, isStringLiteral } from '../../../typescript/ast-nodes.js';
|
|
3
|
+
const FS_PROMISES = new Set(['node:fs/promises', 'fs/promises']);
|
|
4
|
+
export function createFsPromisesGlobVisitor(ctx) {
|
|
5
|
+
const globNames = new Set();
|
|
6
|
+
const namespaceNames = new Set();
|
|
7
|
+
return {
|
|
8
|
+
Program() {
|
|
9
|
+
globNames.clear();
|
|
10
|
+
namespaceNames.clear();
|
|
11
|
+
},
|
|
12
|
+
ImportDeclaration(node) {
|
|
13
|
+
if (!FS_PROMISES.has(node.source.value))
|
|
14
|
+
return;
|
|
15
|
+
for (const specifier of node.specifiers ?? []) {
|
|
16
|
+
if (specifier.type === 'ImportNamespaceSpecifier') {
|
|
17
|
+
namespaceNames.add(specifier.local.name);
|
|
18
|
+
}
|
|
19
|
+
else if (specifier.type === 'ImportSpecifier' &&
|
|
20
|
+
specifier.imported.type === 'Identifier' &&
|
|
21
|
+
specifier.imported.name === 'glob') {
|
|
22
|
+
globNames.add(specifier.local.name);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
VariableDeclarator(node) {
|
|
27
|
+
if (node.init?.type !== 'CallExpression' ||
|
|
28
|
+
node.init.callee.type !== 'Identifier' ||
|
|
29
|
+
node.init.callee.name !== 'require' ||
|
|
30
|
+
!isStringLiteral(node.init.arguments[0]) ||
|
|
31
|
+
!FS_PROMISES.has(getStringValue(node.init.arguments[0])))
|
|
32
|
+
return;
|
|
33
|
+
if (node.id.type === 'Identifier') {
|
|
34
|
+
namespaceNames.add(node.id.name);
|
|
35
|
+
}
|
|
36
|
+
else if (node.id.type === 'ObjectPattern') {
|
|
37
|
+
for (const property of node.id.properties) {
|
|
38
|
+
if (property.type === 'Property' &&
|
|
39
|
+
getPropertyKey(property) === 'glob' &&
|
|
40
|
+
property.value.type === 'Identifier') {
|
|
41
|
+
globNames.add(property.value.name);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
CallExpression(node) {
|
|
47
|
+
let isGlobCall = node.callee.type === 'Identifier' && globNames.has(node.callee.name);
|
|
48
|
+
if (!isGlobCall &&
|
|
49
|
+
node.callee.type === 'MemberExpression' &&
|
|
50
|
+
!node.callee.computed &&
|
|
51
|
+
node.callee.object.type === 'Identifier' &&
|
|
52
|
+
namespaceNames.has(node.callee.object.name) &&
|
|
53
|
+
node.callee.property.type === 'Identifier' &&
|
|
54
|
+
node.callee.property.name === 'glob') {
|
|
55
|
+
isGlobCall = true;
|
|
56
|
+
}
|
|
57
|
+
if (!isGlobCall)
|
|
58
|
+
return;
|
|
59
|
+
const arg = node.arguments[0];
|
|
60
|
+
if (!arg)
|
|
61
|
+
return;
|
|
62
|
+
let patterns;
|
|
63
|
+
if (isStringLiteral(arg)) {
|
|
64
|
+
patterns = [getStringValue(arg)];
|
|
65
|
+
}
|
|
66
|
+
else if (arg.type === 'ArrayExpression') {
|
|
67
|
+
patterns = [];
|
|
68
|
+
for (const element of arg.elements) {
|
|
69
|
+
if (!element || !isStringLiteral(element))
|
|
70
|
+
return;
|
|
71
|
+
patterns.push(getStringValue(element));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!patterns?.length || patterns.some(pattern => pattern.startsWith('!')))
|
|
75
|
+
return;
|
|
76
|
+
const options = node.arguments[1];
|
|
77
|
+
if (options && options.type !== 'ObjectExpression')
|
|
78
|
+
return;
|
|
79
|
+
if (options &&
|
|
80
|
+
(options.properties.length > 1 ||
|
|
81
|
+
options.properties.some(property => property.type !== 'Property' || property.computed || getPropertyKey(property) !== 'cwd')))
|
|
82
|
+
return;
|
|
83
|
+
const cwdNode = findProperty(options, 'cwd');
|
|
84
|
+
if (cwdNode && !isStringLiteral(cwdNode))
|
|
85
|
+
return;
|
|
86
|
+
ctx.addImportGlob(patterns, { cwd: cwdNode ? getStringValue(cwdNode) : '.' });
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -87,18 +87,18 @@ const addAppEntries = (inputs, srcDir, serverDir, config, dir) => {
|
|
|
87
87
|
inputs.push(toDeferResolveProductionEntry(resolveAlias(id, srcDir, dir)));
|
|
88
88
|
};
|
|
89
89
|
const findLayerConfigs = (cwd) => _syncGlob({ cwd, patterns: [`layers/*/${config.at(0)}`] });
|
|
90
|
+
const definitionFiles = [
|
|
91
|
+
'.nuxt/imports.d.ts',
|
|
92
|
+
'.nuxt/components.d.ts',
|
|
93
|
+
'.nuxt/types/nitro-routes.d.ts',
|
|
94
|
+
'.nuxt/types/nitro-imports.d.ts',
|
|
95
|
+
];
|
|
90
96
|
const registerCompilers = async ({ cwd, hasDependency, registerCompiler }) => {
|
|
91
|
-
if (hasDependency('nuxt') || hasDependency('nuxt-nightly')) {
|
|
97
|
+
if (hasDependency('nuxt') || hasDependency('nuxt-nightly') || isDirectory(cwd, '.nuxt')) {
|
|
98
|
+
const paths = definitionFiles.map(file => join(cwd, file));
|
|
92
99
|
const maps = createAutoImportMaps();
|
|
93
|
-
const
|
|
94
|
-
'.
|
|
95
|
-
'.nuxt/components.d.ts',
|
|
96
|
-
'.nuxt/types/nitro-routes.d.ts',
|
|
97
|
-
'.nuxt/types/nitro-imports.d.ts',
|
|
98
|
-
];
|
|
99
|
-
for (const file of definitionFiles) {
|
|
100
|
-
const path = join(cwd, file);
|
|
101
|
-
buildAutoImportMap(path, readAndParseFile(path), maps, file.endsWith('components.d.ts'));
|
|
100
|
+
for (const path of paths) {
|
|
101
|
+
buildAutoImportMap(path, readAndParseFile(path), maps, path.endsWith('components.d.ts'));
|
|
102
102
|
}
|
|
103
103
|
registerCompiler({ extension: '.vue', compiler: createVueCompiler(maps, cwd) });
|
|
104
104
|
registerCompiler({ extension: '.ts', compiler: createTsCompiler(maps) });
|
|
@@ -121,6 +121,9 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
121
121
|
addModule(id);
|
|
122
122
|
}
|
|
123
123
|
addAppEntries(inputs, srcDir, serverDir, localConfig, cwd);
|
|
124
|
+
const sharedDir = toAbsolute(localConfig.dir?.shared ?? 'shared', cwd);
|
|
125
|
+
inputs.push(toAlias('#shared', sharedDir));
|
|
126
|
+
inputs.push(toAlias('#shared/*', join(sharedDir, '*'), { dir: cwd }));
|
|
124
127
|
const aliases = localConfig.alias;
|
|
125
128
|
if (aliases) {
|
|
126
129
|
for (const key in aliases) {
|
package/dist/run.js
CHANGED
|
@@ -60,7 +60,7 @@ export const run = async (options) => {
|
|
|
60
60
|
const isGitIgnored = await getGitIgnoredHandler(options, new Set(workspaces.map(w => w.dir)));
|
|
61
61
|
const toSourceFilePath = getModuleSourcePathHandler(chief);
|
|
62
62
|
const findWorkspacePackageTarget = getWorkspacePackageTargetHandler(chief);
|
|
63
|
-
const principal = new ProjectPrincipal(options, toSourceFilePath, findWorkspacePackageTarget);
|
|
63
|
+
const principal = new ProjectPrincipal(options, toSourceFilePath, findWorkspacePackageTarget, filePath => chief.findWorkspaceByFilePath(filePath)?.name);
|
|
64
64
|
collector.setWorkspaceFilter(chief.workspaceFilePathFilter);
|
|
65
65
|
collector.setSelectedWorkspaces(chief.selectedWorkspaces);
|
|
66
66
|
collector.setIgnoreIssues(chief.getIgnoreIssues());
|
package/dist/types/config.d.ts
CHANGED
|
@@ -141,6 +141,7 @@ export type PluginVisitorContext = {
|
|
|
141
141
|
markImportExpressionHandled: (pos: number) => void;
|
|
142
142
|
addImportGlob: (patterns: string[], options?: {
|
|
143
143
|
base?: string;
|
|
144
|
+
cwd?: string;
|
|
144
145
|
filter?: RegExp;
|
|
145
146
|
}) => void;
|
|
146
147
|
markExportRegistered: (name: string) => void;
|
|
@@ -30,6 +30,7 @@ export interface Import extends Position {
|
|
|
30
30
|
readonly identifier: string | undefined;
|
|
31
31
|
readonly isTypeOnly: boolean;
|
|
32
32
|
readonly modifiers: number;
|
|
33
|
+
readonly jsDocTags: Tags | undefined;
|
|
33
34
|
}
|
|
34
35
|
export interface ExternalRef {
|
|
35
36
|
readonly specifier: string;
|
|
@@ -76,6 +77,7 @@ export type FileNode = {
|
|
|
76
77
|
export interface ImportGlob {
|
|
77
78
|
patterns: string[];
|
|
78
79
|
base?: string;
|
|
80
|
+
cwd?: string;
|
|
79
81
|
filter?: RegExp;
|
|
80
82
|
}
|
|
81
83
|
export type ModuleGraph = Map<FilePath, FileNode>;
|
|
@@ -62,6 +62,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
62
62
|
col: opts.col,
|
|
63
63
|
isTypeOnly: isDts || !!(modifiers & IMPORT_FLAGS.TYPE_ONLY),
|
|
64
64
|
modifiers,
|
|
65
|
+
jsDocTags: undefined,
|
|
65
66
|
});
|
|
66
67
|
const file = internal.get(importFilePath);
|
|
67
68
|
const importMaps = file ?? createImports();
|
|
@@ -146,6 +147,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
146
147
|
col,
|
|
147
148
|
isTypeOnly: isDts || !!(modifiers & IMPORT_FLAGS.TYPE_ONLY),
|
|
148
149
|
modifiers,
|
|
150
|
+
jsDocTags,
|
|
149
151
|
});
|
|
150
152
|
}
|
|
151
153
|
}
|
|
@@ -171,6 +173,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
171
173
|
col,
|
|
172
174
|
isTypeOnly: isDts || !!(modifiers & IMPORT_FLAGS.TYPE_ONLY),
|
|
173
175
|
modifiers,
|
|
176
|
+
jsDocTags: undefined,
|
|
174
177
|
});
|
|
175
178
|
}
|
|
176
179
|
}
|
|
@@ -280,7 +283,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
280
283
|
pluginCtx.addScript = (s) => scripts.add(s);
|
|
281
284
|
pluginCtx.addImport = (spec, pos, mod) => addImport(spec, undefined, undefined, undefined, pos, mod);
|
|
282
285
|
pluginCtx.markImportExpressionHandled = (pos) => handledImportExpressions.add(pos);
|
|
283
|
-
pluginCtx.addImportGlob = (patterns, opts) => importGlobs.push({ patterns, base: opts?.base, filter: opts?.filter });
|
|
286
|
+
pluginCtx.addImportGlob = (patterns, opts) => importGlobs.push({ patterns, base: opts?.base, cwd: opts?.cwd, filter: opts?.filter });
|
|
284
287
|
pluginCtx.markExportRegistered = (name) => registeredCustomElements.add(name);
|
|
285
288
|
}
|
|
286
289
|
const localRefs = _walkAST(result.program, sourceText, filePath, result.module.hasModuleSyntax, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { _syncGlob } from '../util/glob.js';
|
|
3
|
-
import { dirname, isAbsolute, join, toRelative } from '../util/path.js';
|
|
3
|
+
import { dirname, isAbsolute, join, toAbsolute, toRelative } from '../util/path.js';
|
|
4
4
|
function resolveBaseDir(base, dir, resolveGlobPattern) {
|
|
5
5
|
if (base.startsWith('.'))
|
|
6
6
|
return join(dir, base);
|
|
@@ -15,8 +15,13 @@ function resolveBaseDir(base, dir, resolveGlobPattern) {
|
|
|
15
15
|
export function resolveImportGlobs(items, containingFile, resolveGlobPattern, workspaceRoot) {
|
|
16
16
|
const filePaths = [];
|
|
17
17
|
const dir = dirname(containingFile);
|
|
18
|
-
for (const { patterns, base, filter } of items) {
|
|
19
|
-
if (
|
|
18
|
+
for (const { patterns, base, cwd, filter } of items) {
|
|
19
|
+
if (cwd !== undefined) {
|
|
20
|
+
for (const filePath of _syncGlob({ patterns, cwd: toAbsolute(cwd, workspaceRoot) })) {
|
|
21
|
+
filePaths.push(filePath);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else if (base !== undefined) {
|
|
20
25
|
const cwd = resolveBaseDir(base, dir, resolveGlobPattern);
|
|
21
26
|
if (!cwd)
|
|
22
27
|
continue;
|
|
@@ -256,7 +256,7 @@ export function handleNewExpression(node, s) {
|
|
|
256
256
|
node.arguments[1].property.name === 'url') {
|
|
257
257
|
const specifier = getStringValue(node.arguments[0]);
|
|
258
258
|
if (specifier)
|
|
259
|
-
s.addImport(specifier, undefined, undefined, undefined, node.arguments[0].start, IMPORT_FLAGS.ENTRY | IMPORT_FLAGS.OPTIONAL);
|
|
259
|
+
s.addImport(specifier, undefined, undefined, undefined, node.arguments[0].start, IMPORT_FLAGS.ENTRY | IMPORT_FLAGS.OPTIONAL, undefined, s.getJSDocTags(node.start));
|
|
260
260
|
return;
|
|
261
261
|
}
|
|
262
262
|
if (s.hasWorkerThreadsImport &&
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Visitor, type Class, type Function as FunctionNode, type Program, type Span, type VariableDeclarator } from 'oxc-parser';
|
|
1
|
+
import { Visitor, type Class, type Function as FunctionNode, type Program, type Span, type TSInterfaceDeclaration, type VariableDeclarator } from 'oxc-parser';
|
|
2
2
|
import type { PluginVisitorObject } from '../../types/config.ts';
|
|
3
3
|
import type { GetImportsAndExportsOptions } from '../../types/config.ts';
|
|
4
4
|
import type { Fix } from '../../types/exports.ts';
|
|
@@ -67,10 +67,12 @@ export interface WalkState extends WalkContext {
|
|
|
67
67
|
scopeEnds: number[];
|
|
68
68
|
shadowScopes: Map<string, [number, number][]>;
|
|
69
69
|
localDeclarations: Map<string, FunctionNode | Class | VariableDeclarator>;
|
|
70
|
+
localInterfaces: Map<string, TSInterfaceDeclaration | null>;
|
|
70
71
|
pendingCallRefs: Array<{
|
|
71
72
|
name: string;
|
|
72
73
|
exportName: string;
|
|
73
74
|
seen: Set<string>;
|
|
75
|
+
kind: 'callee' | 'argument';
|
|
74
76
|
}>;
|
|
75
77
|
pendingMemberCallRefs: Array<{
|
|
76
78
|
objectName: string;
|
|
@@ -49,7 +49,7 @@ const _addExport = (identifier, type, pos, members, fix, isReExport, jsDocTags)
|
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
|
-
const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), inBody = false) => {
|
|
52
|
+
const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), inBody = false, thisType) => {
|
|
53
53
|
if (!node)
|
|
54
54
|
return;
|
|
55
55
|
const type = node.type;
|
|
@@ -64,10 +64,14 @@ const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), i
|
|
|
64
64
|
if (node.typeName?.type === 'Identifier')
|
|
65
65
|
_addRefInExport(node.typeName.name, exportName);
|
|
66
66
|
break;
|
|
67
|
+
case 'TSThisType':
|
|
68
|
+
if (thisType)
|
|
69
|
+
_addRefInExport(thisType, exportName);
|
|
70
|
+
return;
|
|
67
71
|
case 'CallExpression': {
|
|
68
72
|
const callee = node.callee;
|
|
69
73
|
if (callee?.type === 'Identifier') {
|
|
70
|
-
state.pendingCallRefs.push({ name: callee.name, exportName, seen });
|
|
74
|
+
state.pendingCallRefs.push({ name: callee.name, exportName, seen, kind: 'callee' });
|
|
71
75
|
}
|
|
72
76
|
else if (callee?.type === 'MemberExpression' &&
|
|
73
77
|
!callee.computed &&
|
|
@@ -84,8 +88,9 @@ const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), i
|
|
|
84
88
|
const args = node.arguments;
|
|
85
89
|
if (args) {
|
|
86
90
|
for (const arg of args) {
|
|
87
|
-
if (arg?.type === 'Identifier')
|
|
88
|
-
state.pendingCallRefs.push({ name: arg.name, exportName, seen });
|
|
91
|
+
if (arg?.type === 'Identifier') {
|
|
92
|
+
state.pendingCallRefs.push({ name: arg.name, exportName, seen, kind: 'argument' });
|
|
93
|
+
}
|
|
89
94
|
}
|
|
90
95
|
}
|
|
91
96
|
}
|
|
@@ -101,14 +106,14 @@ const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), i
|
|
|
101
106
|
case 'TSSatisfiesExpression':
|
|
102
107
|
if (inBody) {
|
|
103
108
|
if (node.expression)
|
|
104
|
-
_collectRefsInType(node.expression, exportName, signatureOnly, seen, inBody);
|
|
109
|
+
_collectRefsInType(node.expression, exportName, signatureOnly, seen, inBody, thisType);
|
|
105
110
|
return;
|
|
106
111
|
}
|
|
107
112
|
break;
|
|
108
113
|
case 'VariableDeclarator':
|
|
109
114
|
if (inBody) {
|
|
110
115
|
if (node.init)
|
|
111
|
-
_collectRefsInType(node.init, exportName, signatureOnly, seen, inBody);
|
|
116
|
+
_collectRefsInType(node.init, exportName, signatureOnly, seen, inBody, thisType);
|
|
112
117
|
return;
|
|
113
118
|
}
|
|
114
119
|
break;
|
|
@@ -124,14 +129,63 @@ const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), i
|
|
|
124
129
|
if (Array.isArray(val)) {
|
|
125
130
|
for (const item of val) {
|
|
126
131
|
if (item)
|
|
127
|
-
_collectRefsInType(item, exportName, signatureOnly, seen, childInBody);
|
|
132
|
+
_collectRefsInType(item, exportName, signatureOnly, seen, childInBody, thisType);
|
|
128
133
|
}
|
|
129
134
|
}
|
|
130
135
|
else {
|
|
131
|
-
_collectRefsInType(val, exportName, signatureOnly, seen, childInBody);
|
|
136
|
+
_collectRefsInType(val, exportName, signatureOnly, seen, childInBody, thisType);
|
|
132
137
|
}
|
|
133
138
|
}
|
|
134
139
|
};
|
|
140
|
+
const _collectRefsInDirectMemberResult = (fn, exportName, seen) => {
|
|
141
|
+
const body = fn.body;
|
|
142
|
+
if (body?.type !== 'MemberExpression' ||
|
|
143
|
+
body.computed ||
|
|
144
|
+
body.object?.type !== 'Identifier' ||
|
|
145
|
+
body.property?.type !== 'Identifier') {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
const params = Array.isArray(fn.params) ? fn.params : (fn.params?.items ?? []);
|
|
149
|
+
const param = params.find((param) => param.type === 'Identifier' && param.name === body.object.name);
|
|
150
|
+
const paramType = param?.typeAnnotation?.typeAnnotation;
|
|
151
|
+
if (paramType?.type !== 'TSTypeReference' || paramType.typeName?.type !== 'Identifier' || paramType.typeArguments) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
const declaration = state.localInterfaces.get(paramType.typeName.name);
|
|
155
|
+
if (!declaration || declaration.typeParameters)
|
|
156
|
+
return false;
|
|
157
|
+
const members = declaration.body.body.filter((member) => member.type === 'TSPropertySignature' &&
|
|
158
|
+
!member.computed &&
|
|
159
|
+
member.key?.type === 'Identifier' &&
|
|
160
|
+
member.key.name === body.property.name &&
|
|
161
|
+
Boolean(member.typeAnnotation));
|
|
162
|
+
if (members.length !== 1)
|
|
163
|
+
return false;
|
|
164
|
+
_collectRefsInType(members[0].typeAnnotation, exportName, true, seen, false, paramType.typeName.name);
|
|
165
|
+
return true;
|
|
166
|
+
};
|
|
167
|
+
const _collectRefsInCallResult = (node, exportName, seen) => {
|
|
168
|
+
const annotatedType = node.type === 'VariableDeclarator' ? node.id.typeAnnotation?.typeAnnotation : undefined;
|
|
169
|
+
if (annotatedType?.type === 'TSFunctionType') {
|
|
170
|
+
_collectRefsInType(annotatedType.typeParameters, exportName, true, seen);
|
|
171
|
+
return _collectRefsInType(annotatedType.returnType, exportName, true, seen);
|
|
172
|
+
}
|
|
173
|
+
if (annotatedType)
|
|
174
|
+
return _collectRefsInType(annotatedType, exportName, true, seen);
|
|
175
|
+
const fn = node.type === 'VariableDeclarator' ? node.init : node;
|
|
176
|
+
if (fn?.type !== 'ArrowFunctionExpression' &&
|
|
177
|
+
fn?.type !== 'FunctionDeclaration' &&
|
|
178
|
+
fn?.type !== 'FunctionExpression') {
|
|
179
|
+
return _collectRefsInType(node, exportName, true, seen);
|
|
180
|
+
}
|
|
181
|
+
if (fn.returnType) {
|
|
182
|
+
_collectRefsInType(fn.typeParameters, exportName, true, seen);
|
|
183
|
+
return _collectRefsInType(fn.returnType, exportName, true, seen);
|
|
184
|
+
}
|
|
185
|
+
if (_collectRefsInDirectMemberResult(fn, exportName, seen))
|
|
186
|
+
return;
|
|
187
|
+
_collectRefsInType(fn, exportName, true, seen);
|
|
188
|
+
};
|
|
135
189
|
const _addRefInExport = (name, exportName) => {
|
|
136
190
|
const refs = state.referencedInExport.get(name);
|
|
137
191
|
if (refs)
|
|
@@ -221,6 +275,12 @@ const coreVisitorObject = {
|
|
|
221
275
|
state.addImport(specifier, name, undefined, undefined, node.id.start, IMPORT_FLAGS.TYPE_ONLY | IMPORT_FLAGS.AUGMENT);
|
|
222
276
|
}
|
|
223
277
|
},
|
|
278
|
+
TSInterfaceDeclaration(node) {
|
|
279
|
+
if (state.scopeDepth > 0 || state.isInNamespace(node))
|
|
280
|
+
return;
|
|
281
|
+
const name = node.id.name;
|
|
282
|
+
state.localInterfaces.set(name, state.localInterfaces.has(name) ? null : node);
|
|
283
|
+
},
|
|
224
284
|
ClassDeclaration(node) {
|
|
225
285
|
state.classNameStack.push(node.id?.name ?? '');
|
|
226
286
|
if (node.id?.name) {
|
|
@@ -740,6 +800,7 @@ function walkAST(program, sourceText, filePath, hasModuleSyntax, ctx) {
|
|
|
740
800
|
scopeEnds: [],
|
|
741
801
|
shadowScopes: new Map(),
|
|
742
802
|
localDeclarations: new Map(),
|
|
803
|
+
localInterfaces: new Map(),
|
|
743
804
|
pendingCallRefs: [],
|
|
744
805
|
pendingMemberCallRefs: [],
|
|
745
806
|
localToExports: new Map(),
|
|
@@ -756,14 +817,18 @@ function walkAST(program, sourceText, filePath, hasModuleSyntax, ctx) {
|
|
|
756
817
|
ctx.visitor.visit(program);
|
|
757
818
|
while (state.pendingCallRefs.length > 0 || state.pendingMemberCallRefs.length > 0) {
|
|
758
819
|
while (state.pendingCallRefs.length > 0) {
|
|
759
|
-
const { name, exportName, seen } = state.pendingCallRefs.pop();
|
|
760
|
-
|
|
820
|
+
const { name, exportName, seen, kind } = state.pendingCallRefs.pop();
|
|
821
|
+
const key = `${kind}:${name}`;
|
|
822
|
+
if (seen.has(key))
|
|
761
823
|
continue;
|
|
762
824
|
const decl = state.localDeclarations.get(name);
|
|
763
825
|
if (!decl)
|
|
764
826
|
continue;
|
|
765
|
-
seen.add(
|
|
766
|
-
|
|
827
|
+
seen.add(key);
|
|
828
|
+
if (kind === 'callee')
|
|
829
|
+
_collectRefsInCallResult(decl, exportName, seen);
|
|
830
|
+
else
|
|
831
|
+
_collectRefsInType(decl, exportName, true, seen);
|
|
767
832
|
}
|
|
768
833
|
while (state.pendingMemberCallRefs.length > 0) {
|
|
769
834
|
const { objectName, propertyName, exportName, seen } = state.pendingMemberCallRefs.pop();
|
|
@@ -780,7 +845,7 @@ function walkAST(program, sourceText, filePath, hasModuleSyntax, ctx) {
|
|
|
780
845
|
if (fn.type !== 'ArrowFunctionExpression' && fn.type !== 'FunctionExpression')
|
|
781
846
|
continue;
|
|
782
847
|
seen.add(key);
|
|
783
|
-
|
|
848
|
+
_collectRefsInCallResult(fn, exportName, seen);
|
|
784
849
|
}
|
|
785
850
|
}
|
|
786
851
|
for (let i = 0; i < state.memberRefsInFile.length; i += 2) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare const helpText = "\u2702\uFE0F Find unused dependencies, exports and files in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -h, --help Print this help text\n -V, --version Print version\n -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)\n -c, --config [file] Configuration file path\n (default: [.]knip.json[c], knip.(js|ts), knip.config.(js|ts) or package.json#knip)\n --use-tsconfig-files Use tsconfig.json to define project files (override `project` patterns)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n\nMode\n --cache Enable caching\n --cache-location Change cache location (default: node_modules/.cache/knip)\n --include-entry-exports Include entry files when reporting unused exports\n --no-gitignore Don't respect .gitignore\n -p, --production Analyze only production source files (e.g. no test files, devDependencies)\n -s, --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n -w, --watch Watch mode\n\nScope\n -W, --workspace [filter] Filter workspaces by name, directory, or glob (can be repeated)\n -D, --directory [dir] Run process from a different directory (default: cwd)\n --include Include 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,catalog,catalogReferences\n --exports Shortcut for --include exports,nsExports,types,nsTypes,enumMembers,namespaceMembers,duplicates\n --files Shortcut for --include files\n --cycles Shortcut for --include cycles (circular dependencies)\n --tags Include or exclude tagged exports\n\nFix\n -f, --fix Fix issues (modifies files in your repo)\n --fix-type Fix only issues of type, can be comma-separated or repeated (2)\n --allow-remove-files Allow Knip to remove files (with --fix)\n -F, --format Format modified files after --fix using the local formatter\n\nOutput\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 (default: symbols), can be repeated (3)\n --reporter-options Pass extra options to the reporter (as JSON string, see example)\n --no-config-hints Suppress configuration hints\n --no-tag-hints Suppress tag hints\n --treat-config-hints-as-errors Exit with non-zero code (1) if there are any configuration hints\n --treat-tag-hints-as-errors Exit with non-zero code (1) if there are any tag hints\n --max-issues Maximum number of total issues before non-zero exit code (default: 0)\n --max-show-issues Maximum number of issues to display per type\n --no-exit-code Always exit with code zero (0)\n\nTroubleshooting\n -d, --debug Show debug output\n --memory Measure memory usage and display data table\n --memory-realtime Log memory usage in realtime\n --performance Measure count and running time of key functions and display stats table\n --performance-fn [name] Measure only function [name]\n -u, --duration Print total running time (zero overhead, no instrumentation)\n --trace Show trace output\n --trace-dependency [name] Show files that import the named dependency\n --trace-export [name] Show trace output for named export(s)\n --trace-file [file] Show trace output for exports in file\n\n(1) Issue types: files, dependencies, unlisted, unresolved, exports, nsExports, types, nsTypes, enumMembers, namespaceMembers, duplicates, catalog, catalogReferences, cycles\n(2) Fixable issue types: dependencies, exports, types, files, catalog\n(3) Built-in reporters: symbols (default), compact, codeowners, cycles, json, codeclimate, markdown, disclosure, github-actions, sarif\n\nExamples:\n\n$ knip\n$ knip --production\n$ knip --workspace packages/client --include files,dependencies\n$ knip --workspace @myorg/* --workspace '!@myorg/legacy'\n$ knip --workspace './apps/*' --workspace '@shared/utils'\n$ knip -c ./config/knip.json --reporter compact\n$ knip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n$ knip --tags=-lintignore\n\nWebsite: https://knip.dev";
|
|
2
2
|
export type ParsedCLIArgs = ReturnType<typeof parseCLIArgs>;
|
|
3
|
+
export declare const parseNumericOption: (value: string | undefined, option: string) => number | undefined;
|
|
3
4
|
export default function parseCLIArgs(): {
|
|
4
5
|
cache?: boolean | undefined;
|
|
5
6
|
'cache-location'?: string | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseArgs } from 'node:util';
|
|
2
|
+
import { ConfigurationError } from './errors.js';
|
|
2
3
|
export const helpText = `✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects
|
|
3
4
|
|
|
4
5
|
Usage: knip [options]
|
|
@@ -79,6 +80,14 @@ $ knip --reporter codeowners --reporter-options '{"path":".github/CODEOWNERS"}'
|
|
|
79
80
|
$ knip --tags=-lintignore
|
|
80
81
|
|
|
81
82
|
Website: https://knip.dev`;
|
|
83
|
+
export const parseNumericOption = (value, option) => {
|
|
84
|
+
if (value === undefined)
|
|
85
|
+
return undefined;
|
|
86
|
+
if (!/^\d+$/.test(value)) {
|
|
87
|
+
throw new ConfigurationError(`Option --${option} expects a non-negative integer, got: ${value}`);
|
|
88
|
+
}
|
|
89
|
+
return Number(value);
|
|
90
|
+
};
|
|
82
91
|
export default function parseCLIArgs() {
|
|
83
92
|
return parseArgs({
|
|
84
93
|
options: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Options } from '../types/options.ts';
|
|
2
|
-
import type
|
|
2
|
+
import { type ParsedCLIArgs } from './cli-arguments.ts';
|
|
3
3
|
interface CreateOptions extends Partial<Options> {
|
|
4
4
|
args?: ParsedCLIArgs;
|
|
5
5
|
}
|
|
@@ -43,6 +43,7 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
|
|
|
43
43
|
isTreatTagHintsAsErrors: boolean;
|
|
44
44
|
isUseTscFiles: boolean | undefined;
|
|
45
45
|
isWatch: boolean;
|
|
46
|
+
maxIssues: number;
|
|
46
47
|
maxShowIssues: number | undefined;
|
|
47
48
|
parsedConfig: {
|
|
48
49
|
angular?: string | boolean | string[] | {
|
|
@@ -2,6 +2,7 @@ import { partitionCompilers } from '../compilers/index.js';
|
|
|
2
2
|
import { ISSUE_TYPES, KNIP_CONFIG_LOCATIONS } from '../constants.js';
|
|
3
3
|
import { knipConfigurationSchema } from '../schema/configuration.js';
|
|
4
4
|
import { getCatalogContainer } from './catalog.js';
|
|
5
|
+
import { parseNumericOption } from './cli-arguments.js';
|
|
5
6
|
import { ConfigurationError } from './errors.js';
|
|
6
7
|
import { findFile, loadJSON } from './fs.js';
|
|
7
8
|
import { getIncludedIssueTypes, shorthandCycles, shorthandDeps, shorthandExports, shorthandFiles, } from './get-included-issue-types.js';
|
|
@@ -150,7 +151,8 @@ export const createOptions = async (options) => {
|
|
|
150
151
|
isTreatTagHintsAsErrors: args['treat-tag-hints-as-errors'] ?? parsedConfig.treatTagHintsAsErrors ?? false,
|
|
151
152
|
isUseTscFiles: options.isUseTscFiles ?? args['use-tsconfig-files'] ?? (options.isSession && !configFilePath),
|
|
152
153
|
isWatch: args.watch ?? options.isWatch ?? false,
|
|
153
|
-
|
|
154
|
+
maxIssues: parseNumericOption(args['max-issues'], 'max-issues') ?? 0,
|
|
155
|
+
maxShowIssues: parseNumericOption(args['max-show-issues'], 'max-show-issues'),
|
|
154
156
|
parsedConfig,
|
|
155
157
|
rules,
|
|
156
158
|
tags,
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "6.
|
|
1
|
+
export declare const version = "6.34.0";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '6.
|
|
1
|
+
export const version = '6.34.0';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knip",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.34.0",
|
|
4
4
|
"description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"analysis",
|
|
@@ -96,14 +96,14 @@
|
|
|
96
96
|
"zod": "^4.4.3"
|
|
97
97
|
},
|
|
98
98
|
"devDependencies": {
|
|
99
|
-
"@jest/types": "^30.
|
|
99
|
+
"@jest/types": "^30.5.0",
|
|
100
100
|
"@types/bun": "^1.4.0",
|
|
101
101
|
"@types/picomatch": "^4.0.3",
|
|
102
|
-
"@types/webpack": "^5.28.5",
|
|
103
102
|
"codeclimate-types": "^0.3.1",
|
|
104
103
|
"prettier": "^3.9.6",
|
|
105
104
|
"tsx": "^4.23.12",
|
|
106
|
-
"typescript": "7.0.2"
|
|
105
|
+
"typescript": "7.0.2",
|
|
106
|
+
"webpack": "^5.110.1"
|
|
107
107
|
},
|
|
108
108
|
"engines": {
|
|
109
109
|
"node": "^20.19.0 || >=22.12.0"
|