knip 5.30.6 → 5.32.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.
Files changed (50) hide show
  1. package/dist/ConfigurationChief.d.ts +1 -0
  2. package/dist/ConfigurationValidator.d.ts +56 -0
  3. package/dist/ConfigurationValidator.js +1 -0
  4. package/dist/IssueFixer.d.ts +4 -4
  5. package/dist/IssueFixer.js +9 -12
  6. package/dist/WorkspaceWorker.d.ts +2 -2
  7. package/dist/binaries/bash-parser.js +3 -4
  8. package/dist/compilers/index.d.ts +10 -0
  9. package/dist/constants.d.ts +5 -0
  10. package/dist/constants.js +6 -1
  11. package/dist/index.js +10 -4
  12. package/dist/plugins/index.d.ts +1 -0
  13. package/dist/plugins/index.js +1 -0
  14. package/dist/plugins/nyc/index.js +4 -2
  15. package/dist/plugins/nyc/types.d.ts +1 -0
  16. package/dist/plugins/stylelint/index.js +4 -3
  17. package/dist/plugins/stylelint/types.d.ts +1 -0
  18. package/dist/plugins/travis/index.d.ts +9 -0
  19. package/dist/plugins/travis/index.js +22 -0
  20. package/dist/reporters/symbols.js +2 -2
  21. package/dist/types/config.d.ts +2 -1
  22. package/dist/types/exports.d.ts +1 -1
  23. package/dist/typescript/SourceFile.d.ts +10 -1
  24. package/dist/typescript/ast-helpers.d.ts +1 -0
  25. package/dist/typescript/ast-helpers.js +9 -1
  26. package/dist/typescript/find-internal-references.d.ts +1 -0
  27. package/dist/typescript/find-internal-references.js +3 -1
  28. package/dist/typescript/get-imports-and-exports.d.ts +2 -1
  29. package/dist/typescript/get-imports-and-exports.js +68 -63
  30. package/dist/typescript/visitors/dynamic-imports/index.js +2 -2
  31. package/dist/typescript/visitors/exports/exportAssignment.js +2 -1
  32. package/dist/typescript/visitors/exports/exportDeclaration.js +6 -2
  33. package/dist/typescript/visitors/exports/exportKeyword.js +9 -7
  34. package/dist/typescript/visitors/exports/exportsAccessExpression.js +2 -1
  35. package/dist/typescript/visitors/exports/moduleExportsAccessExpression.js +4 -3
  36. package/dist/typescript/visitors/helpers.js +2 -1
  37. package/dist/util/fs.d.ts +0 -1
  38. package/dist/util/fs.js +2 -17
  39. package/dist/util/glob-core.js +1 -1
  40. package/dist/util/jiti.d.ts +1 -2
  41. package/dist/util/jiti.js +3 -8
  42. package/dist/util/loader.js +2 -12
  43. package/dist/util/remove-export.d.ts +8 -0
  44. package/dist/util/remove-export.js +68 -0
  45. package/dist/version.d.ts +1 -1
  46. package/dist/version.js +1 -1
  47. package/package.json +3 -3
  48. package/schema.json +4 -0
  49. /package/dist/typescript/visitors/dynamic-imports/{propertyAccessCall.d.ts → resolveCall.d.ts} +0 -0
  50. /package/dist/typescript/visitors/dynamic-imports/{propertyAccessCall.js → resolveCall.js} +0 -0
@@ -6,8 +6,8 @@ import { addNsValue, addValue, createImports } from '../util/dependency-graph.js
6
6
  import { getPackageNameFromFilePath, isStartsLikePackageName, sanitizeSpecifier } from '../util/modules.js';
7
7
  import { extname, isInNodeModules } from '../util/path.js';
8
8
  import { shouldIgnore } from '../util/tag.js';
9
- import { getAccessMembers, getDestructuredIds, getJSDocTags, getLineAndCharacterOfPosition, getTypeName, isAccessExpression, isConsiderReferencedNS, isDestructuring, isImportSpecifier, isReferencedInExportedType, } from './ast-helpers.js';
10
- import { findInternalReferences } from './find-internal-references.js';
9
+ import { getAccessMembers, getDestructuredIds, getJSDocTags, getLineAndCharacterOfPosition, getTypeName, isAccessExpression, isConsiderReferencedNS, isDestructuring, isImportSpecifier, isObjectEnumerationCallExpressionArgument, isReferencedInExportedType, } from './ast-helpers.js';
10
+ import { findInternalReferences, isType } from './find-internal-references.js';
11
11
  import getDynamicImportVisitors from './visitors/dynamic-imports/index.js';
12
12
  import getExportVisitors from './visitors/exports/index.js';
13
13
  import { getImportsFromPragmas } from './visitors/helpers.js';
@@ -47,6 +47,35 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
47
47
  const importedInternalSymbols = new Map();
48
48
  const referencedSymbolsInExportedTypes = new Set();
49
49
  const visitors = getVisitors(sourceFile);
50
+ const addNsMemberRefs = (internalImport, namespace, member) => {
51
+ if (typeof member === 'string') {
52
+ internalImport.refs.add(`${namespace}.${member}`);
53
+ traceRefs.add(`${namespace}.${member}`);
54
+ }
55
+ else {
56
+ for (const m of member) {
57
+ internalImport.refs.add(`${namespace}.${m}`);
58
+ traceRefs.add(`${namespace}.${m}`);
59
+ }
60
+ }
61
+ };
62
+ const maybeAddAliasedExport = (node, alias) => {
63
+ const identifier = node?.getText();
64
+ if (node && identifier) {
65
+ const symbol = sourceFile.symbol?.exports?.get(identifier);
66
+ if (symbol?.valueDeclaration) {
67
+ if (!aliasedExports.has(identifier)) {
68
+ const pos = getLineAndCharacterOfPosition(symbol.valueDeclaration, symbol.valueDeclaration.pos);
69
+ aliasedExports.set(identifier, [{ symbol: identifier, ...pos }]);
70
+ }
71
+ const aliasedExport = aliasedExports.get(identifier);
72
+ if (aliasedExport) {
73
+ const pos = getLineAndCharacterOfPosition(node, node.pos);
74
+ aliasedExport.push({ symbol: alias, ...pos });
75
+ }
76
+ }
77
+ }
78
+ };
50
79
  const addInternalImport = (options) => {
51
80
  const { identifier, symbol, filePath, namespace, alias, specifier, isReExport } = options;
52
81
  const isStar = identifier === IMPORT_STAR;
@@ -124,27 +153,6 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
124
153
  }
125
154
  }
126
155
  };
127
- const maybeAddAccessExpressionAsNsImport = (namespace, member) => {
128
- const symbol = sourceFile.locals?.get(namespace);
129
- if (symbol) {
130
- const importedSymbolFilePath = importedInternalSymbols.get(symbol);
131
- if (importedSymbolFilePath) {
132
- const internalImport = internalImports.get(importedSymbolFilePath);
133
- if (internalImport) {
134
- if (typeof member === 'string') {
135
- internalImport.refs.add(`${namespace}.${member}`);
136
- traceRefs.add(`${namespace}.${member}`);
137
- }
138
- else {
139
- for (const m of member) {
140
- internalImport.refs.add(`${namespace}.${m}`);
141
- traceRefs.add(`${namespace}.${m}`);
142
- }
143
- }
144
- }
145
- }
146
- }
147
- };
148
156
  const addExport = ({ node, symbol, identifier, type, pos, members = [], fix }) => {
149
157
  if (options.skipExports)
150
158
  return;
@@ -200,33 +208,15 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
200
208
  }
201
209
  };
202
210
  const addScript = (script) => scripts.add(script);
203
- const maybeAddAliasedExport = (node, alias) => {
204
- const identifier = node?.getText();
205
- if (node && identifier) {
206
- const symbol = sourceFile.symbol?.exports?.get(identifier);
207
- if (symbol?.valueDeclaration) {
208
- if (!aliasedExports.has(identifier)) {
209
- const pos = getLineAndCharacterOfPosition(symbol.valueDeclaration, symbol.valueDeclaration.pos);
210
- aliasedExports.set(identifier, [{ symbol: identifier, ...pos }]);
211
- }
212
- const aliasedExport = aliasedExports.get(identifier);
213
- if (aliasedExport) {
214
- const pos = getLineAndCharacterOfPosition(node, node.pos);
215
- aliasedExport.push({ symbol: alias, ...pos });
216
- }
217
- }
218
- }
211
+ const getImport = (id, node) => {
212
+ const local = sourceFile.locals?.get(id);
213
+ const symbol = node.symbol ?? node.parent.symbol ?? local;
214
+ const filePath = importedInternalSymbols.get(symbol) ?? (local && importedInternalSymbols.get(local));
215
+ return { symbol, filePath };
219
216
  };
220
217
  const visit = (node) => {
221
218
  const addImportWithNode = (result) => addImport(result, node);
222
- for (const visitor of visitors.dynamicImport) {
223
- const result = visitor(node, options);
224
- result && (Array.isArray(result) ? result.forEach(addImportWithNode) : addImportWithNode(result));
225
- }
226
- const isTopLevel = node.parent &&
227
- ('commonJsModuleIndicator' in sourceFile
228
- ? node.parent.parent === sourceFile || node.parent === sourceFile
229
- : node.parent === sourceFile);
219
+ const isTopLevel = node !== sourceFile && ts.isInTopLevelContext(node);
230
220
  if (isTopLevel) {
231
221
  for (const visitor of visitors.import) {
232
222
  const result = visitor(node, options);
@@ -237,18 +227,21 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
237
227
  result && (Array.isArray(result) ? result.forEach(addExport) : addExport(result));
238
228
  }
239
229
  }
230
+ for (const visitor of visitors.dynamicImport) {
231
+ const result = visitor(node, options);
232
+ result && (Array.isArray(result) ? result.forEach(addImportWithNode) : addImportWithNode(result));
233
+ }
240
234
  for (const visitor of visitors.script) {
241
235
  const result = visitor(node, options);
242
236
  result && (Array.isArray(result) ? result.forEach(addScript) : addScript(result));
243
237
  }
244
238
  if (ts.isIdentifier(node)) {
245
239
  const id = String(node.escapedText);
246
- const symbol = sourceFile.locals?.get(id);
240
+ const { symbol, filePath } = getImport(id, node);
247
241
  if (symbol) {
248
- const importedSymbolFilePath = importedInternalSymbols.get(symbol);
249
- if (importedSymbolFilePath) {
242
+ if (filePath) {
250
243
  if (!isImportSpecifier(node)) {
251
- const imports = internalImports.get(importedSymbolFilePath);
244
+ const imports = internalImports.get(filePath);
252
245
  if (imports) {
253
246
  traceRefs.add(id);
254
247
  if (isAccessExpression(node.parent)) {
@@ -257,38 +250,40 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
257
250
  const ns = String(symbol.escapedName);
258
251
  const key = String(node.parent.name.escapedText);
259
252
  const members = getDestructuredIds(node.parent.parent.name).map(n => `${key}.${n}`);
260
- maybeAddAccessExpressionAsNsImport(ns, key);
261
- maybeAddAccessExpressionAsNsImport(ns, members);
253
+ addNsMemberRefs(imports, ns, key);
254
+ addNsMemberRefs(imports, ns, members);
262
255
  }
263
256
  }
264
257
  else {
265
258
  const members = getAccessMembers(typeChecker, node);
266
- maybeAddAccessExpressionAsNsImport(id, members);
259
+ addNsMemberRefs(imports, id, members);
267
260
  }
268
261
  }
269
262
  else if (isDestructuring(node)) {
270
263
  const members = getDestructuredIds(node.parent.name);
271
- maybeAddAccessExpressionAsNsImport(id, members);
264
+ addNsMemberRefs(imports, id, members);
272
265
  }
273
266
  else {
274
267
  const typeName = getTypeName(node);
275
268
  if (typeName) {
276
269
  const [ns, ...right] = [typeName.left.getText(), typeName.right.getText()].join('.').split('.');
277
270
  const members = right.map((_r, index) => right.slice(0, index + 1).join('.'));
278
- maybeAddAccessExpressionAsNsImport(ns, members);
271
+ addNsMemberRefs(imports, ns, members);
279
272
  }
280
273
  else if (imports.importedNs.has(id) && isConsiderReferencedNS(node)) {
281
274
  imports.refs.add(id);
282
275
  }
283
- else {
276
+ else if (isObjectEnumerationCallExpressionArgument(node)) {
284
277
  imports.refs.add(id);
285
278
  }
286
279
  }
287
280
  }
288
281
  }
289
282
  }
290
- if (ignoreExportsUsedInFile && !isTopLevel && isReferencedInExportedType(node)) {
291
- referencedSymbolsInExportedTypes.add(symbol.exportSymbol);
283
+ if (!isTopLevel && symbol.exportSymbol) {
284
+ if (ts.isTypeQueryNode(node.parent) || isReferencedInExportedType(node)) {
285
+ referencedSymbolsInExportedTypes.add(symbol.exportSymbol);
286
+ }
292
287
  }
293
288
  }
294
289
  }
@@ -297,8 +292,13 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
297
292
  ts.isQualifiedName(node.moduleReference) &&
298
293
  ts.isIdentifier(node.moduleReference.left)) {
299
294
  const { left, right } = node.moduleReference;
300
- if (sourceFile.locals?.get(left.text))
301
- maybeAddAccessExpressionAsNsImport(left.text, right.text);
295
+ const namespace = left.text;
296
+ const { filePath } = getImport(namespace, node);
297
+ if (filePath) {
298
+ const internalImport = internalImports.get(filePath);
299
+ if (internalImport)
300
+ addNsMemberRefs(internalImport, namespace, right.text);
301
+ }
302
302
  }
303
303
  ts.forEachChild(node, visit);
304
304
  };
@@ -307,9 +307,14 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
307
307
  if (pragmaImports)
308
308
  for (const node of pragmaImports)
309
309
  addImport(node, sourceFile);
310
- const isSetRefs = ignoreExportsUsedInFile;
311
310
  for (const item of exports.values()) {
312
- if (isSetRefs === true || (typeof isSetRefs === 'object' && item.type !== 'unknown' && !!isSetRefs[item.type])) {
311
+ const isType_ = isType(item);
312
+ if (item.symbol && referencedSymbolsInExportedTypes.has(item.symbol)) {
313
+ item.refs = [1, true];
314
+ }
315
+ else if (ignoreExportsUsedInFile === true ||
316
+ (typeof ignoreExportsUsedInFile === 'object' && item.type !== 'unknown' && ignoreExportsUsedInFile[item.type]) ||
317
+ isType_) {
313
318
  item.refs = findInternalReferences(item, sourceFile, typeChecker, referencedSymbolsInExportedTypes);
314
319
  }
315
320
  for (const member of item.members) {
@@ -1,7 +1,7 @@
1
1
  import importCall from './importCall.js';
2
2
  import importType from './importType.js';
3
3
  import jsDocType from './jsDocType.js';
4
- import propertyAccessCall from './propertyAccessCall.js';
5
4
  import requireCall from './requireCall.js';
6
- const visitors = [importCall, importType, jsDocType, propertyAccessCall, requireCall];
5
+ import resolveCall from './resolveCall.js';
6
+ const visitors = [importCall, importType, jsDocType, resolveCall, requireCall];
7
7
  export default (sourceFile) => visitors.map(v => v(sourceFile));
@@ -1,10 +1,11 @@
1
1
  import ts from 'typescript';
2
+ import { FIX_FLAGS } from '../../../constants.js';
2
3
  import { SymbolType } from '../../../types/issues.js';
3
4
  import { exportVisitor as visit } from '../index.js';
4
5
  export default visit(() => true, (node, { isFixExports }) => {
5
6
  if (ts.isExportAssignment(node)) {
6
7
  const pos = node.getChildAt(1).getStart();
7
- const fix = isFixExports ? [node.getStart(), node.getEnd() + 1] : undefined;
8
+ const fix = isFixExports ? [node.getStart(), node.getEnd() + 1, FIX_FLAGS.NONE] : undefined;
8
9
  const symbol = node.getSourceFile().locals?.get(node.expression.escapedText);
9
10
  return { node, symbol, identifier: 'default', type: SymbolType.UNKNOWN, pos, fix };
10
11
  }
@@ -1,10 +1,11 @@
1
1
  import ts from 'typescript';
2
+ import { FIX_FLAGS } from '../../../constants.js';
2
3
  import { SymbolType } from '../../../types/issues.js';
3
4
  import { exportVisitor as visit } from '../index.js';
4
5
  export default visit(() => true, (node, { isFixExports, isFixTypes }) => {
5
6
  if (ts.isExportDeclaration(node)) {
6
7
  if (node.exportClause && ts.isNamedExports(node.exportClause)) {
7
- const type = node.isTypeOnly ? SymbolType.TYPE : SymbolType.UNKNOWN;
8
+ const nodeType = node.isTypeOnly ? SymbolType.TYPE : SymbolType.UNKNOWN;
8
9
  const sourceFile = node.getSourceFile();
9
10
  const declarations = sourceFile.getNamedDeclarations?.();
10
11
  return node.exportClause.elements.map(element => {
@@ -12,7 +13,10 @@ export default visit(() => true, (node, { isFixExports, isFixTypes }) => {
12
13
  const propName = element.propertyName?.text;
13
14
  const symbol = declarations?.get(propName ?? identifier)?.[0]?.symbol;
14
15
  const pos = element.name.pos;
15
- const fix = isFixExports || isFixTypes ? [element.getStart(), element.getEnd()] : undefined;
16
+ const type = element.isTypeOnly ? SymbolType.TYPE : nodeType;
17
+ const fix = (isFixExports && type !== SymbolType.TYPE) || (isFixTypes && type === SymbolType.TYPE)
18
+ ? [element.getStart(), element.getEnd(), FIX_FLAGS.OBJECT_BINDING | FIX_FLAGS.EMPTY_DECLARATION]
19
+ : undefined;
16
20
  return { node: element, symbol, identifier, type, pos, fix };
17
21
  });
18
22
  }
@@ -1,4 +1,5 @@
1
1
  import ts from 'typescript';
2
+ import { FIX_FLAGS } from '../../../constants.js';
2
3
  import { SymbolType } from '../../../types/issues.js';
3
4
  import { compact } from '../../../util/array.js';
4
5
  import { getDefaultKeywordNode, getExportKeywordNode, isGetOrSetAccessorDeclaration, isPrivateMember, stripQuotes, } from '../../ast-helpers.js';
@@ -6,15 +7,16 @@ import { exportVisitor as visit } from '../index.js';
6
7
  export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClassMembers }) => {
7
8
  const exportKeyword = getExportKeywordNode(node);
8
9
  if (exportKeyword) {
9
- const getFix = (node, defaultKeyword) => isFixExports ? [node.getStart(), (defaultKeyword ?? node).getEnd() + 1] : undefined;
10
- const getElementFix = (node) => (isFixExports ? [node.getStart(), node.getEnd()] : undefined);
11
- const getTypeFix = (node) => (isFixTypes ? [node.getStart(), node.getEnd() + 1] : undefined);
10
+ const getFix = (node, defaultKeyword) => isFixExports ? [node.getStart(), (defaultKeyword ?? node).getEnd() + 1, FIX_FLAGS.NONE] : undefined;
11
+ const getTypeFix = (node) => isFixTypes ? [node.getStart(), node.getEnd() + 1, FIX_FLAGS.NONE] : undefined;
12
12
  if (ts.isVariableStatement(node)) {
13
13
  return node.declarationList.declarations.flatMap(declaration => {
14
14
  if (ts.isObjectBindingPattern(declaration.name)) {
15
15
  return compact(declaration.name.elements.map(element => {
16
16
  if (ts.isIdentifier(element.name)) {
17
- const fix = getElementFix(element);
17
+ const fix = isFixExports
18
+ ? [element.getStart(), element.getEnd(), FIX_FLAGS.OBJECT_BINDING]
19
+ : undefined;
18
20
  return {
19
21
  node: element,
20
22
  identifier: element.name.escapedText.toString(),
@@ -28,7 +30,7 @@ export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClas
28
30
  if (ts.isArrayBindingPattern(declaration.name)) {
29
31
  return compact(declaration.name.elements.map(element => {
30
32
  if (ts.isBindingElement(element)) {
31
- const fix = getElementFix(element);
33
+ const fix = isFixExports ? [element.getStart(), element.getEnd(), FIX_FLAGS.NONE] : undefined;
32
34
  return {
33
35
  node: element,
34
36
  identifier: element.getText(),
@@ -67,7 +69,7 @@ export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClas
67
69
  identifier: member.name.getText(),
68
70
  pos: member.name.getStart() + (ts.isComputedPropertyName(member.name) ? 1 : 0),
69
71
  type: SymbolType.MEMBER,
70
- fix: undefined,
72
+ fix: isFixTypes ? [member.getStart(), member.getEnd(), FIX_FLAGS.NONE] : undefined,
71
73
  }))
72
74
  : [];
73
75
  return { node, identifier, type: SymbolType.CLASS, pos, members, fix };
@@ -93,7 +95,7 @@ export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClas
93
95
  identifier: stripQuotes(member.name.getText()),
94
96
  pos: member.name.getStart(),
95
97
  type: SymbolType.MEMBER,
96
- fix: undefined,
98
+ fix: isFixTypes ? [member.getStart(), member.getEnd(), FIX_FLAGS.OBJECT_BINDING] : undefined,
97
99
  }));
98
100
  return { node, identifier, type: SymbolType.ENUM, pos, members, fix };
99
101
  }
@@ -1,4 +1,5 @@
1
1
  import ts from 'typescript';
2
+ import { FIX_FLAGS } from '../../../constants.js';
2
3
  import { SymbolType } from '../../../types/issues.js';
3
4
  import { isJS } from '../helpers.js';
4
5
  import { exportVisitor as visit } from '../index.js';
@@ -7,7 +8,7 @@ export default visit(isJS, (node, { isFixExports }) => {
7
8
  if (ts.isIdentifier(node.left.expression) && node.left.expression.escapedText === 'exports') {
8
9
  const identifier = node.left.name.getText();
9
10
  const pos = node.left.name.pos;
10
- const fix = isFixExports ? [node.getStart(), node.getEnd()] : undefined;
11
+ const fix = isFixExports ? [node.getStart(), node.getEnd(), FIX_FLAGS.NONE] : undefined;
11
12
  return {
12
13
  node: node.left.name,
13
14
  identifier,
@@ -1,4 +1,5 @@
1
1
  import ts from 'typescript';
2
+ import { FIX_FLAGS } from '../../../constants.js';
2
3
  import { SymbolType } from '../../../types/issues.js';
3
4
  import { hasRequireCall, isModuleExportsAccess, stripQuotes } from '../../ast-helpers.js';
4
5
  import { isJS } from '../helpers.js';
@@ -11,7 +12,7 @@ export default visit(isJS, (node, { isFixExports }) => {
11
12
  isModuleExportsAccess(node.expression.left.expression)) {
12
13
  const identifier = node.expression.left.name.getText();
13
14
  const pos = node.expression.left.name.pos;
14
- const fix = isFixExports ? [node.getStart(), node.getEnd()] : undefined;
15
+ const fix = isFixExports ? [node.getStart(), node.getEnd(), FIX_FLAGS.NONE] : undefined;
15
16
  return {
16
17
  node: node.expression.left.name,
17
18
  identifier,
@@ -24,7 +25,7 @@ export default visit(isJS, (node, { isFixExports }) => {
24
25
  const expr = node.expression.right;
25
26
  if (ts.isObjectLiteralExpression(expr) && expr.properties.every(ts.isShorthandPropertyAssignment)) {
26
27
  return expr.properties.map(node => {
27
- const fix = isFixExports ? [node.getStart(), node.getEnd()] : undefined;
28
+ const fix = isFixExports ? [node.getStart(), node.getEnd(), FIX_FLAGS.NONE] : undefined;
28
29
  return { node, identifier: node.getText(), type: SymbolType.UNKNOWN, pos: node.getStart(), fix };
29
30
  });
30
31
  }
@@ -40,7 +41,7 @@ export default visit(isJS, (node, { isFixExports }) => {
40
41
  isModuleExportsAccess(node.expression.left.expression)) {
41
42
  const identifier = stripQuotes(node.expression.left.argumentExpression.getText());
42
43
  const pos = node.expression.left.argumentExpression.pos;
43
- const fix = isFixExports ? [node.getStart(), node.getEnd()] : undefined;
44
+ const fix = isFixExports ? [node.getStart(), node.getEnd(), FIX_FLAGS.NONE] : undefined;
44
45
  return {
45
46
  node: node.expression.left.argumentExpression,
46
47
  identifier,
@@ -10,8 +10,9 @@ export function getImportsFromPragmas(sourceFile) {
10
10
  ? jsxImportSourcePragmas[jsxImportSourcePragmas.length - 1]
11
11
  : jsxImportSourcePragmas;
12
12
  const { factory: specifier } = jsxImportSourcePragma?.arguments ?? {};
13
+ const pos = jsxImportSourcePragma.range?.pos ?? 0;
13
14
  if (specifier)
14
- importNodes.push({ specifier, isTypeOnly: true, identifier: '__jsx', pos: 0 });
15
+ importNodes.push({ specifier, isTypeOnly: true, identifier: '__jsx', pos });
15
16
  }
16
17
  const referencePragma = sourceFile.pragmas.get('reference');
17
18
  if (referencePragma) {
package/dist/util/fs.d.ts CHANGED
@@ -7,5 +7,4 @@ export declare const loadYAML: (filePath: string) => Promise<unknown>;
7
7
  export declare const loadTOML: (filePath: string) => Promise<Record<string, import("smol-toml").TomlPrimitive>>;
8
8
  export declare const parseJSON: (filePath: string, contents: string) => Promise<any>;
9
9
  export declare const parseYAML: (contents: string) => unknown;
10
- export declare function isTypeModule(path: string): boolean;
11
10
  export declare const _loadJSON: (filePath: string) => Promise<any>;
package/dist/util/fs.js CHANGED
@@ -1,11 +1,11 @@
1
- import { readFileSync, statSync } from 'node:fs';
1
+ import { statSync } from 'node:fs';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import yaml from 'js-yaml';
4
4
  import { parse as parseTOML } from 'smol-toml';
5
5
  import stripJsonComments from 'strip-json-comments';
6
6
  import { timerify } from './Performance.js';
7
7
  import { LoaderError } from './errors.js';
8
- import { dirname, join } from './path.js';
8
+ import { join } from './path.js';
9
9
  export const isDirectory = (filePath) => {
10
10
  try {
11
11
  return statSync(filePath).isDirectory();
@@ -58,19 +58,4 @@ export const parseJSON = async (filePath, contents) => {
58
58
  export const parseYAML = (contents) => {
59
59
  return yaml.load(contents);
60
60
  };
61
- export function isTypeModule(path) {
62
- while (path && path !== '.' && path !== '/') {
63
- path = dirname(path);
64
- try {
65
- const pkg = readFileSync(join(path, 'package.json'), 'utf-8');
66
- try {
67
- return JSON.parse(pkg).type === 'module';
68
- }
69
- catch { }
70
- break;
71
- }
72
- catch { }
73
- }
74
- return false;
75
- }
76
61
  export const _loadJSON = timerify(loadJSON);
@@ -36,7 +36,7 @@ export const parseAndConvertGitignorePatterns = (patterns, ancestor) => {
36
36
  .split(/\r?\n/)
37
37
  .filter(line => line.trim() && !line.startsWith('#'))
38
38
  .flatMap(line => {
39
- const pattern = line.replace(/(?<!\\)#.*/, '').trim();
39
+ const pattern = line.replace(/^\\(?=#)/, '').trim();
40
40
  if (ancestor && matchFrom) {
41
41
  if (pattern.match(matchFrom))
42
42
  return [pattern.replace(matchFrom, '$1')];
@@ -1,2 +1 @@
1
- export declare const jitiCJS: any;
2
- export declare const jitiESM: any;
1
+ export declare const jiti: import("jiti").Jiti;
package/dist/util/jiti.js CHANGED
@@ -1,17 +1,12 @@
1
1
  import { fileURLToPath } from 'node:url';
2
- import createJITI, {} from 'jiti';
3
- import { DEFAULT_EXTENSIONS } from '../constants.js';
2
+ import { createJiti } from 'jiti';
4
3
  import { join } from './path.js';
5
4
  const empty = join(fileURLToPath(import.meta.url), '../empty.js');
6
5
  const options = {
7
- interopDefault: true,
8
- extensions: DEFAULT_EXTENSIONS,
9
- esmResolve: false,
10
6
  alias: {
11
7
  '@rushstack/eslint-config/patch/modern-module-resolution': empty,
12
8
  '@rushstack/eslint-patch/modern-module-resolution': empty,
13
9
  },
14
10
  };
15
- const createLoader = (options) => createJITI(process.cwd(), options);
16
- export const jitiCJS = createLoader(options);
17
- export const jitiESM = createLoader({ ...options, esmResolve: true });
11
+ const createLoader = (options) => createJiti(process.cwd(), options);
12
+ export const jiti = createLoader(options);
@@ -1,9 +1,7 @@
1
- import { pathToFileURL } from 'node:url';
2
1
  import { timerify } from './Performance.js';
3
2
  import { LoaderError } from './errors.js';
4
3
  import { loadFile, loadJSON, loadTOML, loadYAML, parseJSON, parseYAML } from './fs.js';
5
- import { isTypeModule } from './fs.js';
6
- import { jitiCJS, jitiESM } from './jiti.js';
4
+ import { jiti } from './jiti.js';
7
5
  import { extname, isInternal } from './path.js';
8
6
  const load = async (filePath) => {
9
7
  try {
@@ -33,15 +31,7 @@ const load = async (filePath) => {
33
31
  if (ext === '.toml') {
34
32
  return await loadTOML(filePath);
35
33
  }
36
- if (ext === '.mjs' || (ext === '.js' && isTypeModule(filePath))) {
37
- const fileUrl = pathToFileURL(filePath);
38
- const imported = await import(fileUrl.href);
39
- return imported.default ?? imported;
40
- }
41
- if (ext === '.mts' || ((ext === '.ts' || ext === '.tsx') && isTypeModule(filePath))) {
42
- return await jitiESM(filePath);
43
- }
44
- return await jitiCJS(filePath);
34
+ return await jiti.import(filePath, { default: true });
45
35
  }
46
36
  catch (error) {
47
37
  throw new LoaderError(`Error loading ${filePath}`, { cause: error });
@@ -0,0 +1,8 @@
1
+ interface FixerOptions {
2
+ text: string;
3
+ start: number;
4
+ end: number;
5
+ flags: number;
6
+ }
7
+ export declare const removeExport: ({ text, start, end, flags }: FixerOptions) => string;
8
+ export {};
@@ -0,0 +1,68 @@
1
+ import { FIX_FLAGS } from '../constants.js';
2
+ const getOpeningBracketIndex = (text) => {
3
+ let bracketOpenIndex = -1;
4
+ let j = text.length - 1;
5
+ while (j >= 0) {
6
+ const char = text[j];
7
+ if (char === '{') {
8
+ bracketOpenIndex = j;
9
+ break;
10
+ }
11
+ if (!/\s/.test(char) && char !== ',') {
12
+ if (text.substring(j - 3, j + 1) === 'type') {
13
+ j = j - 4;
14
+ continue;
15
+ }
16
+ break;
17
+ }
18
+ j--;
19
+ }
20
+ return bracketOpenIndex;
21
+ };
22
+ export const removeExport = ({ text, start, end, flags }) => {
23
+ const beforeStart = text.substring(0, start);
24
+ const afterEnd = text.substring(end);
25
+ if (flags % FIX_FLAGS.NONE)
26
+ return beforeStart + afterEnd;
27
+ const subject = text.substring(start, end).trim();
28
+ if (subject === 'export' || subject === 'export default')
29
+ return beforeStart + afterEnd;
30
+ let closingBracketOffset = -1;
31
+ let commaOffset = -1;
32
+ if (flags & FIX_FLAGS.OBJECT_BINDING) {
33
+ let i = 0;
34
+ while (i <= afterEnd.length) {
35
+ const char = afterEnd[i];
36
+ if (char === ',') {
37
+ commaOffset = i + 1;
38
+ }
39
+ else if (char === '}') {
40
+ closingBracketOffset = i + 1;
41
+ break;
42
+ }
43
+ else if (!/\s/.test(char))
44
+ break;
45
+ i++;
46
+ }
47
+ }
48
+ if (flags & FIX_FLAGS.EMPTY_DECLARATION && closingBracketOffset !== -1) {
49
+ const openingBracketIndex = getOpeningBracketIndex(beforeStart);
50
+ if (closingBracketOffset !== -1 && openingBracketIndex !== -1) {
51
+ const beforeBracket = beforeStart.substring(0, openingBracketIndex).trim();
52
+ const exportLength = beforeBracket.endsWith('export') ? 6 : beforeBracket.endsWith('export type') ? 12 : 0;
53
+ const exportKeywordOffset = beforeBracket.length - exportLength;
54
+ if (exportLength) {
55
+ const fromBracket = afterEnd.substring(closingBracketOffset).trim();
56
+ if (fromBracket.startsWith('from')) {
57
+ const specifierQuoteMatch = afterEnd.match(/['"][^'"]+['"]/);
58
+ if (specifierQuoteMatch?.index) {
59
+ const fromSpecifierLength = specifierQuoteMatch.index + specifierQuoteMatch[0].length;
60
+ return beforeBracket.substring(0, exportKeywordOffset) + afterEnd.substring(fromSpecifierLength);
61
+ }
62
+ }
63
+ return beforeBracket.substring(0, exportKeywordOffset) + afterEnd.substring(closingBracketOffset);
64
+ }
65
+ }
66
+ }
67
+ return beforeStart + (commaOffset === -1 ? afterEnd : afterEnd.substring(commaOffset));
68
+ };
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.30.6";
1
+ export declare const version = "5.32.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.30.6';
1
+ export const version = '5.32.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.30.6",
3
+ "version": "5.32.0",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://knip.dev",
6
6
  "repository": {
@@ -66,7 +66,7 @@
66
66
  "easy-table": "1.2.0",
67
67
  "enhanced-resolve": "^5.17.1",
68
68
  "fast-glob": "^3.3.2",
69
- "jiti": "^1.21.6",
69
+ "jiti": "^2.3.1",
70
70
  "js-yaml": "^4.1.0",
71
71
  "minimist": "^1.2.8",
72
72
  "picocolors": "^1.0.0",
@@ -90,7 +90,7 @@
90
90
  "@types/minimist": "^1.2.5",
91
91
  "@types/picomatch": "3.0.1",
92
92
  "@types/webpack": "^5.28.5",
93
- "@wdio/types": "^9.0.8",
93
+ "@wdio/types": "^9.1.2",
94
94
  "glob": "^10.4.2",
95
95
  "release-it": "^17.6.0",
96
96
  "type-fest": "^4.20.0",
package/schema.json CHANGED
@@ -520,6 +520,10 @@
520
520
  "title": "tailwind plugin configuration (https://knip.dev/reference/plugins/tailwind)",
521
521
  "$ref": "#/definitions/plugin"
522
522
  },
523
+ "travis": {
524
+ "title": "travis plugin configuration (https://knip.dev/reference/plugins/travis)",
525
+ "$ref": "#/definitions/plugin"
526
+ },
523
527
  "tsup": {
524
528
  "title": "tsup plugin configuration (https://knip.dev/reference/plugins/tsup)",
525
529
  "$ref": "#/definitions/plugin"