knip 6.0.2 → 6.0.4
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/graph/build.js +4 -2
- package/dist/plugins/qwik/resolveFromAST.js +3 -3
- package/dist/reporters/trace.js +18 -3
- package/dist/typescript/visitors/members.js +7 -27
- package/dist/typescript/visitors/walk.d.ts +1 -0
- package/dist/typescript/visitors/walk.js +72 -21
- package/dist/util/fs.d.ts +1 -0
- package/dist/util/fs.js +10 -2
- package/dist/util/load-tsconfig.js +5 -7
- package/dist/util/trace.d.ts +5 -1
- package/dist/util/trace.js +8 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/graph/build.js
CHANGED
|
@@ -5,6 +5,7 @@ import { partition } from "../util/array.js";
|
|
|
5
5
|
import { createInputHandler } from "../util/create-input-handler.js";
|
|
6
6
|
import { debugLog, debugLogArray } from "../util/debug.js";
|
|
7
7
|
import { existsSync } from 'node:fs';
|
|
8
|
+
import { tryRealpath } from "../util/fs.js";
|
|
8
9
|
import { _glob, _syncGlob, negate, prependDirToPattern as prependDir } from "../util/glob.js";
|
|
9
10
|
import { isAlias, isConfig, isDeferResolveEntry, isDeferResolveProductionEntry, isEntry, isIgnore, isProductionEntry, isProject, toProductionEntry, } from "../util/input.js";
|
|
10
11
|
import { loadTSConfig } from "../util/load-tsconfig.js";
|
|
@@ -92,7 +93,7 @@ export async function build({ chief, collector, counselor, deputy, principal, is
|
|
|
92
93
|
if (definitionPaths.length > 0) {
|
|
93
94
|
debugLogArray(name, 'Definition paths', definitionPaths);
|
|
94
95
|
for (const id of definitionPaths)
|
|
95
|
-
inputs.add(toProductionEntry(id, { containingFilePath: tsConfigFilePath }));
|
|
96
|
+
inputs.add(toProductionEntry(tryRealpath(id), { containingFilePath: tsConfigFilePath }));
|
|
96
97
|
}
|
|
97
98
|
const sharedGlobOptions = { cwd: options.cwd, dir, gitignore: options.gitignore };
|
|
98
99
|
const fn = (id) => ({ pattern: prependDir(options.cwd, prependDir(name, id)), id, workspaceName: name });
|
|
@@ -234,7 +235,8 @@ export async function build({ chief, collector, counselor, deputy, principal, is
|
|
|
234
235
|
if (options.isUseTscFiles && isFile) {
|
|
235
236
|
const isIgnoredWorkspace = chief.createIgnoredWorkspaceMatcher(name, dir);
|
|
236
237
|
debugLogArray(name, 'Using tsconfig files as project files', tscSourcePaths);
|
|
237
|
-
for (const
|
|
238
|
+
for (const tscPath of tscSourcePaths) {
|
|
239
|
+
const filePath = tryRealpath(tscPath);
|
|
238
240
|
if (!isGitIgnored(filePath) && !isIgnoredWorkspace(filePath)) {
|
|
239
241
|
principal.addProgramPath(filePath);
|
|
240
242
|
principal.addProjectPath(filePath);
|
|
@@ -11,9 +11,9 @@ export const getSrcDir = (program) => {
|
|
|
11
11
|
export const getRoutesDirs = (program, srcDir) => {
|
|
12
12
|
const arg = findCallArg(program, 'qwikCity');
|
|
13
13
|
if (arg) {
|
|
14
|
-
const values = getPropertyValues(arg, 'routesDir');
|
|
15
|
-
if (values.
|
|
16
|
-
return
|
|
14
|
+
const values = Array.from(getPropertyValues(arg, 'routesDir')).filter(Boolean);
|
|
15
|
+
if (values.length > 0)
|
|
16
|
+
return values;
|
|
17
17
|
}
|
|
18
18
|
return [`${srcDir}/routes`];
|
|
19
19
|
};
|
package/dist/reporters/trace.js
CHANGED
|
@@ -27,7 +27,11 @@ export default ({ graph, explorer, options, workspaceFilePathFilter }) => {
|
|
|
27
27
|
console.log(line);
|
|
28
28
|
}
|
|
29
29
|
else {
|
|
30
|
-
|
|
30
|
+
let nodes = explorer.buildExportsTree({ filePath: options.traceFile, identifier: options.traceExport });
|
|
31
|
+
if (nodes.length === 0 && options.traceExport?.includes('.')) {
|
|
32
|
+
const nsName = options.traceExport.substring(0, options.traceExport.indexOf('.'));
|
|
33
|
+
nodes = explorer.buildExportsTree({ filePath: options.traceFile, identifier: nsName });
|
|
34
|
+
}
|
|
31
35
|
nodes.sort((a, b) => a.filePath.localeCompare(b.filePath) || a.identifier.localeCompare(b.identifier));
|
|
32
36
|
const toRel = (path) => toRelative(path, options.cwd);
|
|
33
37
|
const isReferenced = (node) => {
|
|
@@ -37,7 +41,18 @@ export default ({ graph, explorer, options, workspaceFilePathFilter }) => {
|
|
|
37
41
|
return true;
|
|
38
42
|
return !!graph.get(node.filePath)?.exports.get(node.identifier)?.hasRefsInFile;
|
|
39
43
|
};
|
|
40
|
-
for (const node of nodes)
|
|
41
|
-
|
|
44
|
+
for (const node of nodes) {
|
|
45
|
+
const exp = graph.get(node.filePath)?.exports.get(node.identifier);
|
|
46
|
+
let memberStatuses;
|
|
47
|
+
if (exp && exp.members.length > 0) {
|
|
48
|
+
memberStatuses = [];
|
|
49
|
+
for (const m of exp.members) {
|
|
50
|
+
const id = `${node.identifier}.${m.identifier}`;
|
|
51
|
+
const referenced = m.hasRefsInFile || explorer.isReferenced(node.filePath, id, { includeEntryExports: true })[0];
|
|
52
|
+
memberStatuses.push({ identifier: m.identifier, referenced });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
console.log(formatTrace(node, toRel, isReferenced(node), memberStatuses));
|
|
56
|
+
}
|
|
42
57
|
}
|
|
43
58
|
};
|
|
@@ -37,13 +37,7 @@ export function handleMemberExpression(node, s) {
|
|
|
37
37
|
else if (!shadowed) {
|
|
38
38
|
const memberName = node.computed === false && node.property.type === 'Identifier' ? node.property.name : undefined;
|
|
39
39
|
if (memberName) {
|
|
40
|
-
|
|
41
|
-
if (exp) {
|
|
42
|
-
for (const member of exp.members) {
|
|
43
|
-
if (member.identifier === memberName)
|
|
44
|
-
member.hasRefsInFile = true;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
40
|
+
s.memberRefsInFile.push(localName, memberName);
|
|
47
41
|
}
|
|
48
42
|
}
|
|
49
43
|
const aliases = s.importAliases.get(localName);
|
|
@@ -95,15 +89,8 @@ export function handleMemberExpression(node, s) {
|
|
|
95
89
|
}
|
|
96
90
|
}
|
|
97
91
|
else {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
const mid = node.object.property.name;
|
|
101
|
-
const dottedName = `${mid}.${node.property.name}`;
|
|
102
|
-
for (const member of exp.members) {
|
|
103
|
-
if (member.identifier === mid || member.identifier === dottedName)
|
|
104
|
-
member.hasRefsInFile = true;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
92
|
+
const mid = node.object.property.name;
|
|
93
|
+
s.memberRefsInFile.push(rootName, mid, rootName, `${mid}.${node.property.name}`);
|
|
107
94
|
}
|
|
108
95
|
}
|
|
109
96
|
}
|
|
@@ -131,17 +118,10 @@ export function handleMemberExpression(node, s) {
|
|
|
131
118
|
}
|
|
132
119
|
}
|
|
133
120
|
else {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const c = node.property.name;
|
|
139
|
-
const dottedName = `${a}.${b}.${c}`;
|
|
140
|
-
for (const member of exp.members) {
|
|
141
|
-
if (member.identifier === a || member.identifier === `${a}.${b}` || member.identifier === dottedName)
|
|
142
|
-
member.hasRefsInFile = true;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
121
|
+
const a = node.object.object.property.name;
|
|
122
|
+
const b = node.object.property.name;
|
|
123
|
+
const c = node.property.name;
|
|
124
|
+
s.memberRefsInFile.push(rootName, a, rootName, `${a}.${b}`, rootName, `${a}.${b}.${c}`);
|
|
145
125
|
}
|
|
146
126
|
}
|
|
147
127
|
}
|
|
@@ -112,15 +112,48 @@ const _addLocalRef = (name, pos) => {
|
|
|
112
112
|
if (!state.localImportMap.has(name) && !isShadowed(name, pos))
|
|
113
113
|
state.localRefs.add(name);
|
|
114
114
|
};
|
|
115
|
-
const
|
|
116
|
-
const i = state.scopeDepth - 1;
|
|
117
|
-
const range = [state.scopeStarts[i], state.scopeEnds[i]];
|
|
115
|
+
const _addShadowRange = (name, range) => {
|
|
118
116
|
const ranges = state.shadowScopes.get(name);
|
|
119
117
|
if (ranges)
|
|
120
118
|
ranges.push(range);
|
|
121
119
|
else
|
|
122
120
|
state.shadowScopes.set(name, [range]);
|
|
123
121
|
};
|
|
122
|
+
const _addShadow = (name) => {
|
|
123
|
+
const i = state.scopeDepth - 1;
|
|
124
|
+
_addShadowRange(name, [state.scopeStarts[i], state.scopeEnds[i]]);
|
|
125
|
+
};
|
|
126
|
+
const _collectBindingNames = (pattern, range) => {
|
|
127
|
+
if (!pattern)
|
|
128
|
+
return;
|
|
129
|
+
if (pattern.type === 'Identifier') {
|
|
130
|
+
_addShadowRange(pattern.name, range);
|
|
131
|
+
}
|
|
132
|
+
else if (pattern.type === 'ObjectPattern') {
|
|
133
|
+
for (const prop of pattern.properties ?? []) {
|
|
134
|
+
_collectBindingNames(prop.value ?? prop.argument, range);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else if (pattern.type === 'ArrayPattern') {
|
|
138
|
+
for (const el of pattern.elements ?? []) {
|
|
139
|
+
_collectBindingNames(el, range);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (pattern.type === 'AssignmentPattern') {
|
|
143
|
+
_collectBindingNames(pattern.left, range);
|
|
144
|
+
}
|
|
145
|
+
else if (pattern.type === 'RestElement') {
|
|
146
|
+
_collectBindingNames(pattern.argument, range);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const _addParamShadows = (params, body) => {
|
|
150
|
+
if (!body || !params)
|
|
151
|
+
return;
|
|
152
|
+
const range = [body.start, body.end];
|
|
153
|
+
const items = Array.isArray(params) ? params : params.items ?? params;
|
|
154
|
+
for (const param of items)
|
|
155
|
+
_collectBindingNames(param, range);
|
|
156
|
+
};
|
|
124
157
|
const coreVisitorObject = {
|
|
125
158
|
BlockStatement(node) {
|
|
126
159
|
state.scopeStarts[state.scopeDepth] = node.start;
|
|
@@ -143,6 +176,18 @@ const coreVisitorObject = {
|
|
|
143
176
|
if (state.scopeDepth > 0)
|
|
144
177
|
_addShadow(node.id.name);
|
|
145
178
|
}
|
|
179
|
+
_addParamShadows(node.params, node.body);
|
|
180
|
+
},
|
|
181
|
+
FunctionExpression(node) {
|
|
182
|
+
_addParamShadows(node.params, node.body);
|
|
183
|
+
},
|
|
184
|
+
ArrowFunctionExpression(node) {
|
|
185
|
+
_addParamShadows(node.params, node.body);
|
|
186
|
+
},
|
|
187
|
+
CatchClause(node) {
|
|
188
|
+
if (node.param?.type === 'Identifier' && node.body) {
|
|
189
|
+
_addShadowRange(node.param.name, [node.body.start, node.body.end]);
|
|
190
|
+
}
|
|
146
191
|
},
|
|
147
192
|
VariableDeclaration(node) {
|
|
148
193
|
state.currentVarDeclStart = node.start;
|
|
@@ -196,6 +241,10 @@ const coreVisitorObject = {
|
|
|
196
241
|
handleJSXMemberExpression(node, state);
|
|
197
242
|
},
|
|
198
243
|
ForInStatement(node) {
|
|
244
|
+
if (node.left.type === 'VariableDeclaration' && node.body) {
|
|
245
|
+
for (const decl of node.left.declarations)
|
|
246
|
+
_collectBindingNames(decl.id, [node.body.start, node.body.end]);
|
|
247
|
+
}
|
|
199
248
|
if (node.right.type === 'Identifier' && !isShadowed(node.right.name, node.right.start)) {
|
|
200
249
|
const _import = state.localImportMap.get(node.right.name);
|
|
201
250
|
if (_import?.isNamespace) {
|
|
@@ -206,6 +255,10 @@ const coreVisitorObject = {
|
|
|
206
255
|
}
|
|
207
256
|
},
|
|
208
257
|
ForOfStatement(node) {
|
|
258
|
+
if (node.left.type === 'VariableDeclaration' && node.body) {
|
|
259
|
+
for (const decl of node.left.declarations)
|
|
260
|
+
_collectBindingNames(decl.id, [node.body.start, node.body.end]);
|
|
261
|
+
}
|
|
209
262
|
if (node.right.type === 'Identifier' && !isShadowed(node.right.name, node.right.start)) {
|
|
210
263
|
const _import = state.localImportMap.get(node.right.name);
|
|
211
264
|
if (_import?.isNamespace) {
|
|
@@ -242,16 +295,10 @@ const coreVisitorObject = {
|
|
|
242
295
|
}
|
|
243
296
|
}
|
|
244
297
|
else if (parts.length > 0) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
path = path ? `${path}.${part}` : part;
|
|
250
|
-
for (const member of exp.members) {
|
|
251
|
-
if (member.identifier === path)
|
|
252
|
-
member.hasRefsInFile = true;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
298
|
+
let path = '';
|
|
299
|
+
for (const part of parts) {
|
|
300
|
+
path = path ? `${path}.${part}` : part;
|
|
301
|
+
state.memberRefsInFile.push(rootName, path);
|
|
255
302
|
}
|
|
256
303
|
}
|
|
257
304
|
}
|
|
@@ -525,14 +572,7 @@ const localRefsVisitorObject = {
|
|
|
525
572
|
if (left.type === 'Identifier') {
|
|
526
573
|
const rootName = left.name;
|
|
527
574
|
if (!state.localImportMap.has(rootName) && !isShadowed(rootName, left.start) && parts.length > 0) {
|
|
528
|
-
|
|
529
|
-
if (exp) {
|
|
530
|
-
state.localRefs.add(rootName);
|
|
531
|
-
for (const member of exp.members) {
|
|
532
|
-
if (member.identifier === parts[0])
|
|
533
|
-
member.hasRefsInFile = true;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
575
|
+
state.localRefs.add(rootName);
|
|
536
576
|
}
|
|
537
577
|
}
|
|
538
578
|
},
|
|
@@ -606,6 +646,7 @@ export function walkAST(program, sourceText, filePath, ctx) {
|
|
|
606
646
|
chainedMemberExprs: new WeakSet(),
|
|
607
647
|
currentVarDeclStart: -1,
|
|
608
648
|
nsRanges: [],
|
|
649
|
+
memberRefsInFile: [],
|
|
609
650
|
scopeDepth: 0,
|
|
610
651
|
scopeStarts: [],
|
|
611
652
|
scopeEnds: [],
|
|
@@ -618,6 +659,16 @@ export function walkAST(program, sourceText, filePath, ctx) {
|
|
|
618
659
|
isInNamespace: _isInNamespace,
|
|
619
660
|
};
|
|
620
661
|
ctx.visitor.visit(program);
|
|
662
|
+
for (let i = 0; i < state.memberRefsInFile.length; i += 2) {
|
|
663
|
+
const exp = state.exports.get(state.memberRefsInFile[i]);
|
|
664
|
+
if (exp) {
|
|
665
|
+
const id = state.memberRefsInFile[i + 1];
|
|
666
|
+
for (const member of exp.members) {
|
|
667
|
+
if (member.identifier === id)
|
|
668
|
+
member.hasRefsInFile = true;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
621
672
|
for (const [aliasName, aliasSet] of state.importAliases) {
|
|
622
673
|
if (!state.accessedAliases.has(aliasName)) {
|
|
623
674
|
for (const alias of aliasSet) {
|
package/dist/util/fs.d.ts
CHANGED
|
@@ -10,3 +10,4 @@ export declare const loadYAML: (filePath: string) => Promise<any>;
|
|
|
10
10
|
export declare const loadTOML: (filePath: string) => Promise<import("smol-toml").TomlTable>;
|
|
11
11
|
export declare const parseJSONC: (filePath: string, contents: string) => Promise<any>;
|
|
12
12
|
export declare const parseYAML: (contents: string) => any;
|
|
13
|
+
export declare const tryRealpath: (filePath: string) => string;
|
package/dist/util/fs.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readdirSync, realpathSync, statSync } from 'node:fs';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { parse as parseYAMLContents } from 'yaml';
|
|
4
4
|
import { parse as parseTOML } from 'smol-toml';
|
|
5
5
|
import stripJsonComments from 'strip-json-comments';
|
|
6
6
|
import { LoaderError } from "./errors.js";
|
|
7
|
-
import { extname, join } from "./path.js";
|
|
7
|
+
import { extname, join, toPosix } from "./path.js";
|
|
8
8
|
export const isDirectory = (cwdOrPath, name) => {
|
|
9
9
|
try {
|
|
10
10
|
return statSync(name ? join(cwdOrPath, name) : cwdOrPath).isDirectory();
|
|
@@ -86,3 +86,11 @@ export const parseJSONC = async (filePath, contents) => {
|
|
|
86
86
|
export const parseYAML = (contents) => {
|
|
87
87
|
return parseYAMLContents(contents, { logLevel: 'error' });
|
|
88
88
|
};
|
|
89
|
+
export const tryRealpath = (filePath) => {
|
|
90
|
+
try {
|
|
91
|
+
return toPosix(realpathSync.native(filePath));
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return filePath;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
@@ -3,7 +3,7 @@ import { parseTsconfig } from 'get-tsconfig';
|
|
|
3
3
|
import stripJsonComments from 'strip-json-comments';
|
|
4
4
|
import { isFile as _isFile } from "./fs.js";
|
|
5
5
|
import { _syncGlob } from "./glob.js";
|
|
6
|
-
import { dirname, isAbsolute, join } from "./path.js";
|
|
6
|
+
import { dirname, isAbsolute, join, toAbsolute } from "./path.js";
|
|
7
7
|
const hasGlobChar = (p) => p.includes('*') || p.includes('?');
|
|
8
8
|
const hasExtension = (p) => {
|
|
9
9
|
const last = p.lastIndexOf('/');
|
|
@@ -81,12 +81,10 @@ export const loadTSConfig = async (tsConfigFilePath) => {
|
|
|
81
81
|
return { isFile: true, compilerOptions: {}, fileNames: [] };
|
|
82
82
|
const dir = dirname(tsConfigFilePath);
|
|
83
83
|
const compilerOptions = (config.compilerOptions ?? {});
|
|
84
|
-
if (compilerOptions.outDir
|
|
85
|
-
compilerOptions.outDir =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
compilerOptions.rootDir = join(dir, compilerOptions.rootDir);
|
|
89
|
-
}
|
|
84
|
+
if (compilerOptions.outDir)
|
|
85
|
+
compilerOptions.outDir = toAbsolute(compilerOptions.outDir, dir).replace(/\/+$/, '');
|
|
86
|
+
if (compilerOptions.rootDir)
|
|
87
|
+
compilerOptions.rootDir = toAbsolute(compilerOptions.rootDir, dir).replace(/\/+$/, '');
|
|
90
88
|
if (compilerOptions.paths) {
|
|
91
89
|
compilerOptions.pathsBasePath ??= dir;
|
|
92
90
|
}
|
package/dist/util/trace.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import type { ExportsTreeNode } from '../graph-explorer/operations/build-exports-tree.ts';
|
|
2
|
-
export
|
|
2
|
+
export interface TraceMemberStatus {
|
|
3
|
+
identifier: string;
|
|
4
|
+
referenced: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const formatTrace: (node: ExportsTreeNode, toRelative: (path: string) => string, isReferenced: boolean, memberStatuses?: TraceMemberStatus[]) => string;
|
package/dist/util/trace.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
|
-
export const formatTrace = (node, toRelative, isReferenced) => {
|
|
2
|
+
export const formatTrace = (node, toRelative, isReferenced, memberStatuses) => {
|
|
3
3
|
const lines = [];
|
|
4
4
|
const file = pc.white;
|
|
5
5
|
const id = pc.cyanBright;
|
|
@@ -41,5 +41,12 @@ export const formatTrace = (node, toRelative, isReferenced) => {
|
|
|
41
41
|
const leafMarker = isReferenced ? ok(' ✓') : fail(' ✗');
|
|
42
42
|
lines.push(`${dim('└── (no imports found)')}${leafMarker}`);
|
|
43
43
|
}
|
|
44
|
+
if (memberStatuses && memberStatuses.length > 0) {
|
|
45
|
+
const parts = memberStatuses.map(m => {
|
|
46
|
+
const marker = m.referenced ? ok(' ✓') : fail(' ✗');
|
|
47
|
+
return `${id(m.identifier)}${marker}`;
|
|
48
|
+
});
|
|
49
|
+
lines.push(`${dim(' members: [')}${parts.join(dim(', '))}${dim(']')}`);
|
|
50
|
+
}
|
|
44
51
|
return lines.join('\n');
|
|
45
52
|
};
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "6.0.
|
|
1
|
+
export declare const version = "6.0.4";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '6.0.
|
|
1
|
+
export const version = '6.0.4';
|