knip 4.6.0 → 5.0.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/constants.js +2 -2
- package/dist/index.js +5 -3
- package/dist/reporters/json.js +8 -8
- package/dist/types/issues.d.ts +2 -1
- package/dist/typescript/getImportsAndExports.js +48 -13
- package/dist/util/get-included-issue-types.d.ts +1 -0
- package/dist/util/get-included-issue-types.js +1 -1
- package/dist/util/type.d.ts +3 -0
- package/dist/util/type.js +16 -0
- package/package.json +1 -1
package/dist/constants.js
CHANGED
|
@@ -94,9 +94,9 @@ export const ISSUE_TYPE_TITLE = {
|
|
|
94
94
|
binaries: 'Unlisted binaries',
|
|
95
95
|
unresolved: 'Unresolved imports',
|
|
96
96
|
exports: 'Unused exports',
|
|
97
|
-
nsExports: '
|
|
97
|
+
nsExports: 'Exports in used namespace',
|
|
98
98
|
types: 'Unused exported types',
|
|
99
|
-
nsTypes: '
|
|
99
|
+
nsTypes: 'Exported types in used namespace',
|
|
100
100
|
enumMembers: 'Unused exported enum members',
|
|
101
101
|
classMembers: 'Unused exported class members',
|
|
102
102
|
duplicates: 'Duplicate exports',
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { fromBinary, isBinary } from './util/protocols.js';
|
|
|
18
18
|
import { _resolveSpecifier } from './util/require.js';
|
|
19
19
|
import { shouldIgnore } from './util/tag.js';
|
|
20
20
|
import { loadTSConfig } from './util/tsconfig-loader.js';
|
|
21
|
+
import { getType, getHasStrictlyNsReferences } from './util/type.js';
|
|
21
22
|
import { WorkspaceWorker } from './WorkspaceWorker.js';
|
|
22
23
|
export const main = async (unresolvedConfiguration) => {
|
|
23
24
|
const { cwd, tsConfigFile, gitignore, isStrict, isProduction, isShowProgress, isIncludeEntryExports, isIsolateWorkspaces, tags, isFix, fixTypes, } = unresolvedConfiguration;
|
|
@@ -457,17 +458,18 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
457
458
|
continue;
|
|
458
459
|
}
|
|
459
460
|
}
|
|
460
|
-
const
|
|
461
|
+
const [hasStrictlyNsReferences, namespace] = getHasStrictlyNsReferences(importsForExport);
|
|
461
462
|
const isType = ['enum', 'type', 'interface'].includes(exportedItem.type);
|
|
462
|
-
if (
|
|
463
|
+
if (hasStrictlyNsReferences && ((!report.nsTypes && isType) || (!report.nsExports && !isType)))
|
|
463
464
|
continue;
|
|
464
465
|
if (!isExportedItemReferenced(exportedItem)) {
|
|
465
|
-
const type =
|
|
466
|
+
const type = getType(hasStrictlyNsReferences, isType);
|
|
466
467
|
collector.addIssue({
|
|
467
468
|
type,
|
|
468
469
|
filePath,
|
|
469
470
|
symbol: identifier,
|
|
470
471
|
symbolType: exportedItem.type,
|
|
472
|
+
parentSymbol: namespace,
|
|
471
473
|
pos: exportedItem.pos,
|
|
472
474
|
line: exportedItem.line,
|
|
473
475
|
col: exportedItem.col,
|
package/dist/reporters/json.js
CHANGED
|
@@ -2,7 +2,6 @@ import { OwnershipEngine } from '@snyk/github-codeowners/dist/lib/ownership/inde
|
|
|
2
2
|
import { isFile } from '../util/fs.js';
|
|
3
3
|
import { relative, resolve } from '../util/path.js';
|
|
4
4
|
import { convert } from './util.js';
|
|
5
|
-
const mergeTypes = (type) => type === 'exports' || type === 'nsExports' ? 'exports' : type === 'types' || type === 'nsTypes' ? 'types' : type;
|
|
6
5
|
export default async ({ report, issues, options }) => {
|
|
7
6
|
let opts = {};
|
|
8
7
|
try {
|
|
@@ -26,21 +25,22 @@ export default async ({ report, issues, options }) => {
|
|
|
26
25
|
...(report.unlisted && { unlisted: [] }),
|
|
27
26
|
...(report.binaries && { binaries: [] }),
|
|
28
27
|
...(report.unresolved && { unresolved: [] }),
|
|
29
|
-
...(
|
|
30
|
-
...(
|
|
28
|
+
...(report.exports && { exports: [] }),
|
|
29
|
+
...(report.nsExports && { nsExports: [] }),
|
|
30
|
+
...(report.types && { types: [] }),
|
|
31
|
+
...(report.nsTypes && { nsTypes: [] }),
|
|
31
32
|
...(report.enumMembers && { enumMembers: {} }),
|
|
32
33
|
...(report.classMembers && { classMembers: {} }),
|
|
33
34
|
...(report.duplicates && { duplicates: [] }),
|
|
34
35
|
};
|
|
35
36
|
return row;
|
|
36
37
|
};
|
|
37
|
-
for (const [
|
|
38
|
+
for (const [type, isReportType] of Object.entries(report)) {
|
|
38
39
|
if (isReportType) {
|
|
39
|
-
if (
|
|
40
|
+
if (type === 'files') {
|
|
40
41
|
}
|
|
41
42
|
else {
|
|
42
|
-
|
|
43
|
-
flatten(issues[reportType]).forEach(issue => {
|
|
43
|
+
flatten(issues[type]).forEach(issue => {
|
|
44
44
|
const { filePath, symbol, symbols, parentSymbol } = issue;
|
|
45
45
|
json[filePath] = json[filePath] ?? initRow(filePath);
|
|
46
46
|
if (type === 'duplicates') {
|
|
@@ -54,7 +54,7 @@ export default async ({ report, issues, options }) => {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
else {
|
|
57
|
-
if (
|
|
57
|
+
if (['exports', 'nsExports', 'types', 'nsTypes', 'unresolved'].includes(type)) {
|
|
58
58
|
json[filePath][type]?.push(convert(issue));
|
|
59
59
|
}
|
|
60
60
|
else {
|
package/dist/types/issues.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export type Issues = {
|
|
|
44
44
|
classMembers: IssueRecords;
|
|
45
45
|
};
|
|
46
46
|
export type IssueType = keyof Issues;
|
|
47
|
-
|
|
47
|
+
type SymbolIssueType = Exclude<IssueType, 'files'>;
|
|
48
48
|
export type Report = {
|
|
49
49
|
[key in keyof Issues]: boolean;
|
|
50
50
|
};
|
|
@@ -71,3 +71,4 @@ export type ConfigurationHint = {
|
|
|
71
71
|
identifier: string | RegExp;
|
|
72
72
|
workspaceName?: string;
|
|
73
73
|
};
|
|
74
|
+
export {};
|
|
@@ -225,20 +225,55 @@ const getImportsAndExports = (sourceFile, getResolvedModule, typeChecker, option
|
|
|
225
225
|
const result = visitor(node, options);
|
|
226
226
|
result && (Array.isArray(result) ? result.forEach(addScript) : addScript(result));
|
|
227
227
|
}
|
|
228
|
-
if (ts.isIdentifier(node)
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
228
|
+
if (ts.isIdentifier(node)) {
|
|
229
|
+
if (isAccessExpression(node.parent)) {
|
|
230
|
+
const symbol = sourceFile.locals?.get(String(node.escapedText));
|
|
231
|
+
if (symbol) {
|
|
232
|
+
if (importedInternalSymbols.has(symbol)) {
|
|
233
|
+
let members = [];
|
|
234
|
+
let current = node.parent;
|
|
235
|
+
while (current) {
|
|
236
|
+
const ms = getMemberStringLiterals(typeChecker, current);
|
|
237
|
+
if (!ms)
|
|
238
|
+
break;
|
|
239
|
+
members = members.concat(ms.flatMap(id => (members.length === 0 ? id : members.map(ns => `${ns}.${id}`))));
|
|
240
|
+
current = current.parent;
|
|
241
|
+
}
|
|
242
|
+
maybeAddAccessExpressionAsNsImport(String(node.escapedText), members);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else if (ts.isShorthandPropertyAssignment(node.parent) ||
|
|
247
|
+
(ts.isCallExpression(node.parent) && node.parent.arguments.includes(node)) ||
|
|
248
|
+
ts.isSpreadAssignment(node.parent) ||
|
|
249
|
+
ts.isExportAssignment(node.parent)) {
|
|
250
|
+
const symbol = sourceFile.locals?.get(String(node.escapedText));
|
|
251
|
+
if (symbol) {
|
|
252
|
+
const importedSymbolFilePath = importedInternalSymbols.get(symbol);
|
|
253
|
+
if (importedSymbolFilePath) {
|
|
254
|
+
internalImports[importedSymbolFilePath].identifiers.add(String(node.escapedText));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else if (ts.isVariableDeclaration(node.parent)) {
|
|
259
|
+
if (ts.isVariableDeclarationList(node.parent.parent) && ts.isObjectBindingPattern(node.parent.name)) {
|
|
260
|
+
const symbol = sourceFile.locals?.get(String(node.escapedText));
|
|
261
|
+
if (symbol) {
|
|
262
|
+
const importedSymbolFilePath = importedInternalSymbols.get(symbol);
|
|
263
|
+
if (importedSymbolFilePath) {
|
|
264
|
+
const members = node.parent.name.elements.flatMap(decl => decl.name.getText());
|
|
265
|
+
maybeAddAccessExpressionAsNsImport(String(node.escapedText), members);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else if (node.parent.initializer === node) {
|
|
270
|
+
const symbol = sourceFile.locals?.get(String(node.escapedText));
|
|
271
|
+
if (symbol) {
|
|
272
|
+
const importedSymbolFilePath = importedInternalSymbols.get(symbol);
|
|
273
|
+
if (importedSymbolFilePath) {
|
|
274
|
+
internalImports[importedSymbolFilePath].identifiers.add(String(node.escapedText));
|
|
275
|
+
}
|
|
240
276
|
}
|
|
241
|
-
maybeAddAccessExpressionAsNsImport(String(node.escapedText), members);
|
|
242
277
|
}
|
|
243
278
|
}
|
|
244
279
|
}
|
|
@@ -12,5 +12,6 @@ type Options = {
|
|
|
12
12
|
dependencies?: boolean;
|
|
13
13
|
exports?: boolean;
|
|
14
14
|
};
|
|
15
|
+
export declare const defaultExcludedIssueTypes: string[];
|
|
15
16
|
export declare const getIncludedIssueTypes: (cliArgs: CLIArguments, { include, exclude, isProduction }?: Options) => Report;
|
|
16
17
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ISSUE_TYPES } from '../constants.js';
|
|
2
2
|
import { ConfigurationError } from './errors.js';
|
|
3
|
-
const defaultExcludedIssueTypes = ['classMembers'];
|
|
3
|
+
export const defaultExcludedIssueTypes = ['classMembers', 'nsExports', 'nsTypes'];
|
|
4
4
|
const defaultIssueTypes = ISSUE_TYPES.filter(type => !defaultExcludedIssueTypes.includes(type));
|
|
5
5
|
const normalize = (values) => values.map(value => value.split(',')).flat();
|
|
6
6
|
export const getIncludedIssueTypes = (cliArgs, { include = [], exclude = [], isProduction = false } = {}) => {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { SerializableImports } from '../types/imports.js';
|
|
2
|
+
export declare const getHasStrictlyNsReferences: (importsForExport: SerializableImports) => [boolean, string?];
|
|
3
|
+
export declare const getType: (hasOnlyNsReference: boolean, isType: boolean) => "exports" | "nsExports" | "types" | "nsTypes";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const getHasStrictlyNsReferences = (importsForExport) => {
|
|
2
|
+
if (!importsForExport || !importsForExport.hasStar || importsForExport.importedNs.size === 0)
|
|
3
|
+
return [false];
|
|
4
|
+
let namespace;
|
|
5
|
+
for (const ns of importsForExport.importedNs) {
|
|
6
|
+
const hasNs = importsForExport.identifiers.has(ns);
|
|
7
|
+
if (!hasNs)
|
|
8
|
+
return [false, ns];
|
|
9
|
+
for (const id of importsForExport.identifiers)
|
|
10
|
+
if (id.startsWith(ns + '.'))
|
|
11
|
+
return [false, ns];
|
|
12
|
+
namespace = ns;
|
|
13
|
+
}
|
|
14
|
+
return [true, namespace];
|
|
15
|
+
};
|
|
16
|
+
export const getType = (hasOnlyNsReference, isType) => hasOnlyNsReference ? (isType ? 'nsTypes' : 'nsExports') : isType ? 'types' : 'exports';
|