knip 5.23.0 → 5.23.2

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/index.js CHANGED
@@ -317,8 +317,17 @@ export const main = async (unresolvedConfiguration) => {
317
317
  if (shouldIgnore(exportedItem.jsDocTags))
318
318
  continue;
319
319
  const isIgnored = shouldIgnoreTags(exportedItem.jsDocTags);
320
- if (!isIgnored && importsForExport) {
320
+ if (importsForExport) {
321
321
  const { isReferenced, reExportingEntryFile, traceNode } = isIdentifierReferenced(filePath, identifier, isIncludeEntryExports);
322
+ if ((isReferenced || exportedItem.refs[1]) && isIgnored) {
323
+ for (const tagName of exportedItem.jsDocTags) {
324
+ if (tags[1].includes(tagName.replace(/^\@/, ''))) {
325
+ collector.addTagHint({ type: 'tag', filePath, identifier, tagName });
326
+ }
327
+ }
328
+ }
329
+ if (isIgnored)
330
+ continue;
322
331
  if (reExportingEntryFile) {
323
332
  if (!isIncludeEntryExports) {
324
333
  createAndPrintTrace(filePath, { identifier, isEntry, hasRef: isReferenced });
@@ -339,7 +348,7 @@ export const main = async (unresolvedConfiguration) => {
339
348
  continue;
340
349
  if (member.refs[0] === 0) {
341
350
  const id = `${identifier}.${member.identifier}`;
342
- const { isReferenced } = isIdentifierReferenced(filePath, id);
351
+ const { isReferenced } = isIdentifierReferenced(filePath, id, true);
343
352
  const isIgnored = shouldIgnoreTags(member.jsDocTags);
344
353
  if (!isReferenced) {
345
354
  if (isIgnored)
@@ -413,20 +422,13 @@ export const main = async (unresolvedConfiguration) => {
413
422
  line: exportedItem.line,
414
423
  col: exportedItem.col,
415
424
  });
416
- if (isIssueAdded) {
425
+ if (isFix && isIssueAdded) {
417
426
  if (isType)
418
427
  fixer.addUnusedTypeNode(filePath, exportedItem.fixes);
419
428
  else
420
429
  fixer.addUnusedExportNode(filePath, exportedItem.fixes);
421
430
  }
422
431
  }
423
- else if (isIgnored) {
424
- for (const tagName of exportedItem.jsDocTags) {
425
- if (tags[1].includes(tagName.replace(/^\@/, ''))) {
426
- collector.addTagHint({ type: 'tag', filePath, identifier, tagName });
427
- }
428
- }
429
- }
430
432
  }
431
433
  }
432
434
  }
@@ -1,13 +1,8 @@
1
- import { hasDependency } from '#p/util/plugin.js';
1
+ import { hasDependency, toCosmiconfig } from '#p/util/plugin.js';
2
2
  const title = 'commitlint';
3
3
  const enablers = ['@commitlint/cli'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
- const config = [
6
- '.commitlintrc',
7
- '.commitlintrc.{json,yaml,yml,js,cjs,ts,cts}',
8
- 'commitlint.config.{js,cjs,ts,cts}',
9
- 'package.json',
10
- ];
5
+ const config = ['package.json', 'package.yaml', ...toCosmiconfig('commitlint', { additionalExtensions: ['cts'] })];
11
6
  const resolveConfig = async (config) => {
12
7
  const extendsConfigs = config.extends
13
8
  ? [config.extends]
@@ -9,7 +9,7 @@ const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
9
9
  const packageJsonPath = manifest => get(manifest, 'codegen') ?? get(manifest, 'graphql');
10
10
  const config = [
11
11
  'package.json',
12
- 'codegen.{json,yml,yaml,js,ts,mjs,cts}',
12
+ 'codegen.{json,yml,yaml,js,ts}',
13
13
  '.codegenrc.{json,yml,yaml,js,ts}',
14
14
  'codegen.config.js',
15
15
  '.graphqlrc',
@@ -1,15 +1,14 @@
1
- import { getDependenciesFromScripts, hasDependency } from '#p/util/plugin.js';
1
+ import { getDependenciesFromScripts, hasDependency, toLilconfig } from '#p/util/plugin.js';
2
2
  const title = 'lint-staged';
3
3
  const enablers = ['lint-staged'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
5
  const packageJsonPath = 'lint-staged';
6
6
  const config = [
7
- '.lintstagedrc',
8
- '.lintstagedrc.json',
9
- '.lintstagedrc.{yml,yaml}',
10
- '.lintstagedrc.{js,mjs,cjs}',
11
- 'lint-staged.config.{js,mjs,cjs}',
12
7
  'package.json',
8
+ 'package.yaml',
9
+ 'package.yml',
10
+ ...toLilconfig('lint-staged'),
11
+ ...toLilconfig('lintstaged'),
13
12
  ];
14
13
  const resolveConfig = async (config, options) => {
15
14
  if (typeof config === 'function')
@@ -1,18 +1,11 @@
1
1
  import { isInternal } from '#p/util/path.js';
2
- import { hasDependency } from '#p/util/plugin.js';
2
+ import { hasDependency, toCosmiconfig } from '#p/util/plugin.js';
3
3
  import { toEntryPattern } from '#p/util/protocols.js';
4
4
  const title = 'LintHTML';
5
5
  const packageJsonPath = 'linthtmlConfig';
6
6
  const enablers = ['@linthtml/linthtml'];
7
7
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
8
- const config = [
9
- '.linthtmlrc',
10
- '.linthtmlrc.json',
11
- '.linthtmlrc.yml',
12
- '.linthtmlrc.{js,cjs}',
13
- 'linthtml.config.js',
14
- 'package.json',
15
- ];
8
+ const config = ['package.json', ...toCosmiconfig('linthtml')];
16
9
  const resolveConfig = config => {
17
10
  const extensions = [config.extends ?? []]
18
11
  .flat()
@@ -1,8 +1,8 @@
1
- import { hasDependency } from '#p/util/plugin.js';
1
+ import { hasDependency, toCosmiconfig } from '#p/util/plugin.js';
2
2
  const title = 'lockfile-lint';
3
3
  const enablers = ['lockfile-lint'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
- const config = ['.lockfile-lintrc', '.lockfile-lint.{js,toml}', 'lockfile-lint.config.js', 'package.json'];
5
+ const config = ['package.json', ...toCosmiconfig('lockfile-lint', { additionalExtensions: ['toml'] })];
6
6
  export default {
7
7
  title,
8
8
  enablers,
@@ -1,9 +1,9 @@
1
- import { hasDependency } from '#p/util/plugin.js';
1
+ import { hasDependency, toCosmiconfig } from '#p/util/plugin.js';
2
2
  const title = 'npm-package-json-lint';
3
3
  const enablers = ['npm-package-json-lint'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
5
  const packageJsonPath = 'npmpackagejsonlint';
6
- const config = ['.npmpackagejsonlintrc.json', 'npmpackagejsonlint.config.js', 'package.json'];
6
+ const config = ['package.json', ...toCosmiconfig('npmpackagejsonlint')];
7
7
  const resolveConfig = localConfig => {
8
8
  return localConfig?.extends ? [localConfig.extends] : [];
9
9
  };
@@ -1,8 +1,12 @@
1
- import { hasDependency } from '#p/util/plugin.js';
1
+ import { hasDependency, toLilconfig } from '#p/util/plugin.js';
2
2
  const title = 'PostCSS';
3
3
  const enablers = ['postcss', 'postcss-cli', 'next'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
- const config = ['postcss.config.{cjs,js}', 'postcss.config.json', 'package.json'];
5
+ const config = [
6
+ 'package.json',
7
+ 'postcss.config.json',
8
+ ...toLilconfig('postcss', { configDir: false, additionalExtensions: ['ts', 'mts', 'cts', 'yaml', 'yml'] }),
9
+ ];
6
10
  const resolveConfig = config => {
7
11
  return config.plugins
8
12
  ? (Array.isArray(config.plugins) ? config.plugins : Object.keys(config.plugins)).flatMap(plugin => {
@@ -4,9 +4,9 @@ const enablers = ['prettier'];
4
4
  const isEnabled = ({ dependencies, config }) => hasDependency(dependencies, enablers) || 'prettier' in config;
5
5
  const config = [
6
6
  '.prettierrc',
7
- '.prettierrc.{json,js,cjs,mjs,yml,yaml}',
7
+ '.prettierrc.{json,js,cjs,mjs,yml,yaml,toml,json5}',
8
8
  'prettier.config.{js,cjs,mjs}',
9
- 'package.json',
9
+ 'package.{json,yaml}',
10
10
  ];
11
11
  const resolveConfig = config => {
12
12
  if (typeof config === 'string') {
@@ -3,7 +3,7 @@ const title = 'Release It';
3
3
  const enablers = ['release-it'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
5
  const packageJsonPath = 'release-it';
6
- const config = ['.release-it.json', '.release-it.{js,cjs}', '.release-it.{yml,yaml}', 'package.json'];
6
+ const config = ['.release-it.{json,js,cjs,ts,yml,yaml,toml}', 'package.json'];
7
7
  const resolveConfig = (config, options) => {
8
8
  const plugins = config.plugins ? Object.keys(config.plugins) : [];
9
9
  const scripts = config.hooks ? Object.values(config.hooks).flat() : [];
@@ -1,9 +1,9 @@
1
- import { hasDependency } from '#p/util/plugin.js';
1
+ import { hasDependency, toCosmiconfig } from '#p/util/plugin.js';
2
2
  const title = 'Semantic Release';
3
3
  const enablers = ['semantic-release'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
5
  const packageJsonPath = 'release';
6
- const config = ['.releaserc', '.releaserc.{yaml,yml,json,js,cjs}', 'release.config.{js,cjs}', 'package.json'];
6
+ const config = ['package.json', ...toCosmiconfig('release')];
7
7
  const resolveConfig = config => {
8
8
  const plugins = (config?.plugins ?? []).map(plugin => (Array.isArray(plugin) ? plugin[0] : plugin));
9
9
  return plugins;
@@ -1,8 +1,11 @@
1
- import { hasDependency } from '#p/util/plugin.js';
1
+ import { hasDependency, toLilconfig } from '#p/util/plugin.js';
2
2
  const title = 'size-limit';
3
3
  const enablers = ['size-limit'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
- const config = ['.size-limit.{json,js,cjs,ts}', 'package.json'];
5
+ const config = [
6
+ 'package.json',
7
+ ...toLilconfig('size-limit', { configDir: false, additionalExtensions: ['ts', 'mts', 'cts'], rcSuffix: '' }),
8
+ ];
6
9
  export default {
7
10
  title,
8
11
  enablers,
@@ -1,9 +1,9 @@
1
1
  import { isInternal } from '#p/util/path.js';
2
- import { hasDependency } from '#p/util/plugin.js';
2
+ import { hasDependency, toCosmiconfig } from '#p/util/plugin.js';
3
3
  const title = 'Stylelint';
4
4
  const enablers = ['stylelint'];
5
5
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
6
- const config = ['.stylelintrc', '.stylelintrc.{cjs,js,json,yaml,yml}', 'stylelint.config.{cjs,mjs,js}'];
6
+ const config = ['package.json', ...toCosmiconfig('stylelint')];
7
7
  const resolve = (config) => {
8
8
  const extend = config.extends ? [config.extends].flat().filter(id => !isInternal(id)) : [];
9
9
  const plugins = config.plugins ? [config.plugins].flat().filter(id => !isInternal(id)) : [];
@@ -4,5 +4,6 @@ declare const _default: {
4
4
  enablers: import("#p/types/config.js").IgnorePatterns;
5
5
  isEnabled: IsPluginEnabled;
6
6
  config: string[];
7
+ packageJsonPath: (manifest: import("../../types/package-json.js").PackageJson) => string;
7
8
  };
8
9
  export default _default;
@@ -1,11 +1,14 @@
1
- import { hasDependency } from '#p/util/plugin.js';
1
+ import { get } from '#p/util/object.js';
2
+ import { hasDependency, toCosmiconfig } from '#p/util/plugin.js';
2
3
  const title = 'Syncpack';
3
4
  const enablers = ['syncpack'];
4
5
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
- const config = ['.syncpackrc', '.syncpackrc.{json,yaml,yml,js,cjs}', '.syncpack.config.{js,cjs}'];
6
+ const config = ['package.json', ...toCosmiconfig('syncpack')];
7
+ const packageJsonPath = manifest => get(manifest, 'syncpack');
6
8
  export default {
7
9
  title,
8
10
  enablers,
9
11
  isEnabled,
10
12
  config,
13
+ packageJsonPath,
11
14
  };
@@ -3,7 +3,7 @@ import { toProductionEntryPattern } from '#p/util/protocols.js';
3
3
  const title = 'tsup';
4
4
  const enablers = ['tsup'];
5
5
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
6
- const config = ['tsup.config.{js,ts,cjs,json}', 'package.json'];
6
+ const config = ['tsup.config.{js,ts,cjs,mjs,json}', 'package.json'];
7
7
  const resolveConfig = async (config) => {
8
8
  if (typeof config === 'function')
9
9
  config = await config({});
@@ -4,10 +4,10 @@ const enablers = ['typedoc'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
5
  const packageJsonPath = 'typedocOptions';
6
6
  const config = [
7
- 'typedoc.{js,cjs,json,jsonc}',
8
- 'typedoc.config.{js,cjs}',
9
- '.config/typedoc.{js,cjs,json,jsonc}',
10
- '.config/typedoc.config.{js,cjs}',
7
+ 'typedoc.{js,cjs,mjs,json,jsonc}',
8
+ 'typedoc.config.{js,cjs,mjs}',
9
+ '.config/typedoc.{js,cjs,mjs,json,jsonc}',
10
+ '.config/typedoc.config.{js,cjs,mjs}',
11
11
  'package.json',
12
12
  'tsconfig.json',
13
13
  ];
@@ -1,8 +1,8 @@
1
- import { hasDependency } from '#p/util/plugin.js';
1
+ import { hasDependency, toUnconfig } from '#p/util/plugin.js';
2
2
  const title = 'UnoCSS';
3
3
  const enablers = ['unocss'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
- const config = ['uno.config.{js,ts,mjs,mts}', 'unocss.config.{js,ts,mjs,mts}'];
5
+ const config = [...toUnconfig('uno.config'), ...toUnconfig('unocss.config')];
6
6
  export default {
7
7
  title,
8
8
  enablers,
@@ -4,8 +4,8 @@ const title = 'xo';
4
4
  const enablers = ['xo'];
5
5
  const isEnabled = ({ dependencies, config }) => hasDependency(dependencies, enablers) || 'xo' in config;
6
6
  const packageJsonPath = 'xo';
7
- const config = ['{.,}xo-config.{js,cjs,json,}', 'package.json'];
8
- const entry = ['{.,}xo-config.{js,cjs}'];
7
+ const config = ['package.json', '.xo-config', '.xo-config.{js,cjs,json}', 'xo.config.{js,cjs}'];
8
+ const entry = ['.xo-config.{js,cjs}', 'xo.config.{js,cjs}'];
9
9
  const resolveConfig = async (config, options) => {
10
10
  const dependencies = await getDependenciesDeep(config, options);
11
11
  return [...dependencies];
@@ -23,4 +23,6 @@ export declare const isConsiderReferencedNS: (node: ts.Identifier) => boolean;
23
23
  export declare const isTopLevel: (node: ts.Node) => boolean;
24
24
  export declare const getTypeName: (node: ts.Identifier) => ts.QualifiedName | undefined;
25
25
  export declare const isImportSpecifier: (node: ts.Node) => boolean;
26
- export declare const isReferencedInExportedType: (node: ts.Node, symbol: ts.Symbol) => any;
26
+ export declare const isReferencedInExportedType: (node: ts.Node) => boolean;
27
+ export declare const getExportKeywordNode: (node: ts.Node) => ts.ExportKeyword | undefined;
28
+ export declare const getDefaultKeywordNode: (node: ts.Node) => ts.DefaultKeyword | undefined;
@@ -152,11 +152,21 @@ export const isImportSpecifier = (node) => ts.isImportSpecifier(node.parent) ||
152
152
  ts.isImportClause(node.parent) ||
153
153
  ts.isNamespaceImport(node.parent);
154
154
  const isExported = (node) => {
155
- if (node.modifiers?.find(mod => mod.kind === ts.SyntaxKind.ExportKeyword))
155
+ if (getExportKeywordNode(node))
156
156
  return true;
157
157
  return node.parent ? isExported(node.parent) : false;
158
158
  };
159
- export const isReferencedInExportedType = (node, symbol) => symbol.exportSymbol &&
160
- !(node.transformFlags & ts.TransformFlags.ContainsTypeScript) &&
161
- Boolean(node.parent.transformFlags & ts.TransformFlags.ContainsTypeScript) &&
162
- isExported(node.parent);
159
+ const isTypeDeclaration = (node) => ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node);
160
+ const getAncestorTypeDeclaration = (node) => {
161
+ while (node) {
162
+ if (isTypeDeclaration(node))
163
+ return node;
164
+ node = node.parent;
165
+ }
166
+ };
167
+ export const isReferencedInExportedType = (node) => {
168
+ const typeNode = getAncestorTypeDeclaration(node);
169
+ return Boolean(typeNode && isExported(typeNode));
170
+ };
171
+ export const getExportKeywordNode = (node) => node.modifiers?.find(mod => mod.kind === ts.SyntaxKind.ExportKeyword);
172
+ export const getDefaultKeywordNode = (node) => node.modifiers?.find(mod => mod.kind === ts.SyntaxKind.DefaultKeyword);
@@ -49,14 +49,14 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
49
49
  const referencedSymbolsInExportedTypes = new Set();
50
50
  const visitors = getVisitors(sourceFile);
51
51
  const addInternalImport = (options) => {
52
- const { identifier, symbol, filePath, namespace, specifier, isReExport } = options;
52
+ const { identifier, symbol, filePath, namespace, alias, specifier, isReExport } = options;
53
53
  const isStar = identifier === IMPORT_STAR;
54
54
  specifiers.add([specifier, filePath]);
55
55
  const file = internalImports.get(filePath);
56
56
  const imports = file ?? createImports();
57
57
  if (!file)
58
58
  internalImports.set(filePath, imports);
59
- const nsOrAlias = symbol ? String(symbol.escapedName) : options.alias;
59
+ const nsOrAlias = symbol ? String(symbol.escapedName) : alias;
60
60
  if (isReExport) {
61
61
  if (isStar && namespace) {
62
62
  addValue(imports.reExportedNs, namespace, sourceFile.fileName);
@@ -224,7 +224,10 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
224
224
  const result = visitor(node, options);
225
225
  result && (Array.isArray(result) ? result.forEach(addImportWithNode) : addImportWithNode(result));
226
226
  }
227
- const isTopLevel = node.parent === sourceFile || node.parent?.parent === sourceFile;
227
+ const isTopLevel = node.parent &&
228
+ ('commonJsModuleIndicator' in sourceFile
229
+ ? node.parent.parent === sourceFile || node.parent === sourceFile
230
+ : node.parent === sourceFile);
228
231
  if (isTopLevel) {
229
232
  for (const visitor of visitors.import) {
230
233
  const result = visitor(node, options);
@@ -285,7 +288,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
285
288
  }
286
289
  }
287
290
  }
288
- if (ignoreExportsUsedInFile && !isTopLevel && isReferencedInExportedType(node, symbol)) {
291
+ if (ignoreExportsUsedInFile && !isTopLevel && isReferencedInExportedType(node)) {
289
292
  referencedSymbolsInExportedTypes.add(symbol.exportSymbol);
290
293
  }
291
294
  }
@@ -308,14 +311,18 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
308
311
  const setRefs = (item) => {
309
312
  if (!item.symbol)
310
313
  return;
314
+ if (item.symbol.flags & ts.SymbolFlags.AliasExcludes) {
315
+ item.refs = [1, false];
316
+ return;
317
+ }
311
318
  const symbols = new Set();
312
319
  let index = 0;
313
320
  const text = sourceFile.text;
314
321
  const id = item.identifier;
315
322
  while (index < text.length && (index = text.indexOf(id, index)) !== -1) {
316
323
  if (!isIdChar(text.charAt(index - 1)) && !isIdChar(text.charAt(index + id.length))) {
317
- const isDeclaration = index === item.pos || index === item.pos + 1;
318
- if (!isDeclaration) {
324
+ const isExportDeclaration = index === item.pos || index === item.pos + 1;
325
+ if (!isExportDeclaration) {
319
326
  const symbol = typeChecker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, index));
320
327
  if (symbol) {
321
328
  const isInExportedType = referencedSymbolsInExportedTypes.has(symbol);
@@ -342,9 +349,11 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
342
349
  index += id.length;
343
350
  }
344
351
  };
352
+ const isSetRefs = ignoreExportsUsedInFile;
345
353
  for (const item of exports.values()) {
346
- if (ignoreExportsUsedInFile)
354
+ if (isSetRefs === true || (typeof isSetRefs === 'object' && item.type !== 'unknown' && !!isSetRefs[item.type])) {
347
355
  setRefs(item);
356
+ }
348
357
  for (const member of item.members) {
349
358
  setRefs(member);
350
359
  member.symbol = undefined;
@@ -1,17 +1,20 @@
1
1
  import ts from 'typescript';
2
2
  import { SymbolType } from '../../../types/issues.js';
3
3
  import { compact } from '../../../util/array.js';
4
- import { isGetOrSetAccessorDeclaration, isPrivateMember, stripQuotes } from '../../ast-helpers.js';
4
+ import { getDefaultKeywordNode, getExportKeywordNode, isGetOrSetAccessorDeclaration, isPrivateMember, stripQuotes, } from '../../ast-helpers.js';
5
5
  import { exportVisitor as visit } from '../index.js';
6
6
  export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClassMembers }) => {
7
- const exportKeyword = node.modifiers?.find(mod => mod.kind === ts.SyntaxKind.ExportKeyword);
7
+ const exportKeyword = getExportKeywordNode(node);
8
8
  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);
9
12
  if (ts.isVariableStatement(node)) {
10
13
  return node.declarationList.declarations.flatMap(declaration => {
11
14
  if (ts.isObjectBindingPattern(declaration.name)) {
12
15
  return compact(declaration.name.elements.map(element => {
13
16
  if (ts.isIdentifier(element.name)) {
14
- const fix = isFixExports ? [element.getStart(), element.getEnd()] : undefined;
17
+ const fix = getElementFix(element);
15
18
  return {
16
19
  node: element,
17
20
  identifier: element.name.escapedText.toString(),
@@ -25,7 +28,7 @@ export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClas
25
28
  if (ts.isArrayBindingPattern(declaration.name)) {
26
29
  return compact(declaration.name.elements.map(element => {
27
30
  if (ts.isBindingElement(element)) {
28
- const fix = isFixExports ? [element.getStart(), element.getEnd()] : undefined;
31
+ const fix = getElementFix(element);
29
32
  return {
30
33
  node: element,
31
34
  identifier: element.getText(),
@@ -37,34 +40,22 @@ export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClas
37
40
  }));
38
41
  }
39
42
  const identifier = declaration.name.getText();
40
- const fix = isFixExports ? [exportKeyword.getStart(), exportKeyword.getEnd() + 1] : undefined;
41
- return {
42
- node: declaration,
43
- identifier,
44
- type: SymbolType.UNKNOWN,
45
- pos: declaration.name.getStart(),
46
- fix,
47
- };
43
+ const pos = declaration.name.getStart();
44
+ const fix = getFix(exportKeyword);
45
+ return { node: declaration, identifier, type: SymbolType.UNKNOWN, pos, fix };
48
46
  });
49
47
  }
50
- const defaultKeyword = node.modifiers?.find(mod => mod.kind === ts.SyntaxKind.DefaultKeyword);
48
+ const defaultKeyword = getDefaultKeywordNode(node);
51
49
  if (ts.isFunctionDeclaration(node) && node.name) {
52
50
  const identifier = defaultKeyword ? 'default' : node.name.getText();
53
51
  const pos = (node.name ?? node.body ?? node).getStart();
54
- const fix = isFixExports
55
- ? [exportKeyword.getStart(), (defaultKeyword ?? exportKeyword).getEnd() + 1]
56
- : undefined;
57
- return {
58
- node,
59
- identifier,
60
- pos,
61
- type: SymbolType.FUNCTION,
62
- fix,
63
- };
52
+ const fix = getFix(exportKeyword, defaultKeyword);
53
+ return { node, identifier, pos, type: SymbolType.FUNCTION, fix };
64
54
  }
65
55
  if (ts.isClassDeclaration(node) && node.name) {
66
56
  const identifier = defaultKeyword ? 'default' : node.name.getText();
67
57
  const pos = (node.name ?? node).getStart();
58
+ const fix = getFix(exportKeyword, defaultKeyword);
68
59
  const members = isReportClassMembers
69
60
  ? node.members
70
61
  .filter((member) => (ts.isPropertyDeclaration(member) ||
@@ -79,43 +70,24 @@ export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClas
79
70
  fix: undefined,
80
71
  }))
81
72
  : [];
82
- const fix = isFixExports
83
- ? [exportKeyword.getStart(), (defaultKeyword ?? exportKeyword).getEnd() + 1]
84
- : undefined;
85
- return {
86
- node,
87
- identifier,
88
- type: SymbolType.CLASS,
89
- pos,
90
- members,
91
- fix,
92
- };
73
+ return { node, identifier, type: SymbolType.CLASS, pos, members, fix };
93
74
  }
94
75
  if (ts.isTypeAliasDeclaration(node)) {
95
- const identifier = defaultKeyword ? 'default' : node.name.getText();
96
- const fix = isFixTypes ? [exportKeyword.getStart(), exportKeyword.getEnd() + 1] : undefined;
97
- return {
98
- node,
99
- identifier,
100
- type: SymbolType.TYPE,
101
- pos: node.name.getStart(),
102
- fix,
103
- };
76
+ const identifier = node.name.getText();
77
+ const pos = node.name.getStart();
78
+ const fix = getTypeFix(exportKeyword);
79
+ return { node, identifier, type: SymbolType.TYPE, pos, fix };
104
80
  }
105
81
  if (ts.isInterfaceDeclaration(node)) {
106
- const identifier = defaultKeyword ? 'default' : node.name.getText();
107
- const fix = isFixTypes ? [exportKeyword.getStart(), exportKeyword.getEnd() + 1] : undefined;
108
- return {
109
- node,
110
- identifier,
111
- type: SymbolType.INTERFACE,
112
- pos: node.name.getStart(),
113
- fix,
114
- };
82
+ const identifier = node.name.getText();
83
+ const pos = node.name.getStart();
84
+ const fix = getTypeFix(exportKeyword);
85
+ return { node, identifier, type: SymbolType.INTERFACE, pos, fix };
115
86
  }
116
87
  if (ts.isEnumDeclaration(node)) {
117
- const identifier = defaultKeyword ? 'default' : node.name.getText();
88
+ const identifier = node.name.getText();
118
89
  const pos = node.name.getStart();
90
+ const fix = getTypeFix(exportKeyword);
119
91
  const members = node.members.map(member => ({
120
92
  node: member,
121
93
  identifier: stripQuotes(member.name.getText()),
@@ -123,15 +95,7 @@ export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClas
123
95
  type: SymbolType.MEMBER,
124
96
  fix: undefined,
125
97
  }));
126
- const fix = isFixTypes ? [exportKeyword.getStart(), exportKeyword.getEnd() + 1] : undefined;
127
- return {
128
- node,
129
- identifier,
130
- type: SymbolType.ENUM,
131
- pos,
132
- members,
133
- fix,
134
- };
98
+ return { node, identifier, type: SymbolType.ENUM, pos, members, fix };
135
99
  }
136
100
  }
137
101
  });
@@ -16,7 +16,7 @@ export const getIncludedIssueTypes = (cliArgs, { include = [], exclude = [], isP
16
16
  incl = [...incl, 'dependencies', 'optionalPeerDependencies', 'unlisted', 'binaries', 'unresolved'];
17
17
  }
18
18
  if (cliArgs.exports) {
19
- incl = [...incl, 'exports', 'nsExports', 'classMembers', 'types', 'nsTypes', 'enumMembers', 'duplicates'];
19
+ incl = [...incl, 'exports', 'types', 'enumMembers', 'duplicates'];
20
20
  }
21
21
  if (cliArgs.files) {
22
22
  incl = [...incl, 'files'];
@@ -1,7 +1,7 @@
1
- export { _load as load } from './loader.js';
1
+ export { _getDependenciesFromScripts as getDependenciesFromScripts } from '../binaries/index.js';
2
2
  export { _loadJSON as loadJSON } from './fs.js';
3
+ export { _load as load } from './loader.js';
3
4
  export { _tryResolve as tryResolve } from './require.js';
4
- export { _getDependenciesFromScripts as getDependenciesFromScripts } from '../binaries/index.js';
5
5
  import type { RawPluginConfiguration } from '../types/config.js';
6
6
  import type { Plugin, PluginOptions } from '../types/plugins.js';
7
7
  export declare const toCamelCase: (name: string) => string;
@@ -13,3 +13,27 @@ export declare const normalizePluginConfig: (pluginConfig: RawPluginConfiguratio
13
13
  };
14
14
  export declare const loadConfigForPlugin: (configFilePath: string, plugin: Plugin, options: PluginOptions, pluginName: string) => Promise<any>;
15
15
  export declare const getFinalEntryPaths: (plugin: Plugin, options: PluginOptions, configEntryPaths: string[]) => string[];
16
+ export declare const toCosmiconfig: (moduleName: string, options?: {
17
+ rcPrefix?: string;
18
+ rcSuffix?: string;
19
+ configDir?: boolean;
20
+ configFiles?: boolean;
21
+ configFilesAllExtensions?: boolean;
22
+ additionalExtensions?: string[];
23
+ }) => string[];
24
+ export declare const toLilconfig: (moduleName: string, options?: {
25
+ rcPrefix?: string;
26
+ rcSuffix?: string;
27
+ configDir?: boolean;
28
+ configFiles?: boolean;
29
+ configFilesAllExtensions?: boolean;
30
+ additionalExtensions?: string[];
31
+ }) => string[];
32
+ export declare const toUnconfig: (moduleName: string, options?: {
33
+ rcPrefix?: string;
34
+ rcSuffix?: string;
35
+ configDir?: boolean;
36
+ configFiles?: boolean;
37
+ configFilesAllExtensions?: boolean;
38
+ additionalExtensions?: string[];
39
+ }) => string[];
@@ -1,7 +1,7 @@
1
- export { _load as load } from './loader.js';
1
+ export { _getDependenciesFromScripts as getDependenciesFromScripts } from '../binaries/index.js';
2
2
  export { _loadJSON as loadJSON } from './fs.js';
3
+ export { _load as load } from './loader.js';
3
4
  export { _tryResolve as tryResolve } from './require.js';
4
- export { _getDependenciesFromScripts as getDependenciesFromScripts } from '../binaries/index.js';
5
5
  import { arrayify } from './array.js';
6
6
  import { _load as load } from './loader.js';
7
7
  import { get } from './object.js';
@@ -61,3 +61,35 @@ export const getFinalEntryPaths = (plugin, options, configEntryPaths) => {
61
61
  ? configEntryPaths
62
62
  : [...(plugin.entry ?? []).map(toEntryPattern), ...(plugin.production ?? []).map(toProductionEntryPattern)];
63
63
  };
64
+ const toConfigMap = (defaultExtensions, builderConfig) => (moduleName, options) => {
65
+ const config = {
66
+ rcPrefix: '.',
67
+ rcSuffix: 'rc',
68
+ configDir: true,
69
+ configFiles: true,
70
+ configFilesAllExtensions: false,
71
+ additionalExtensions: [],
72
+ ...builderConfig,
73
+ ...options,
74
+ };
75
+ const { rcPrefix, rcSuffix } = config;
76
+ const jsTypeExtensions = ['js', 'ts', 'cjs', 'mjs', 'cts', 'mts'];
77
+ const extensions = [...defaultExtensions, ...config.additionalExtensions];
78
+ const baseFiles = [
79
+ `${rcPrefix}${moduleName}${rcSuffix}`,
80
+ ...(config.configDir ? [`.config/${moduleName}${rcSuffix}`] : []),
81
+ ];
82
+ const rcFiles = `${rcPrefix}${moduleName}${rcSuffix}.{${extensions.join(',')}}`;
83
+ const configExtensions = extensions.filter(ext => config.configFilesAllExtensions || jsTypeExtensions.includes(ext));
84
+ const configFiles = !!config.configFiles && `${moduleName}.config.{${configExtensions.join(',')}}`;
85
+ const configDirFiles = !!config.configDir && `.config/${moduleName}${rcSuffix}.{${extensions.join(',')}}`;
86
+ return [...baseFiles, rcFiles, configFiles, configDirFiles].filter(item => item !== false);
87
+ };
88
+ export const toCosmiconfig = toConfigMap(['json', 'yaml', 'yml', 'js', 'ts', 'cjs', 'mjs'], { configDir: true });
89
+ export const toLilconfig = toConfigMap(['json', 'js', 'cjs', 'mjs'], { configDir: true });
90
+ export const toUnconfig = toConfigMap(['json', 'ts', 'mts', 'cts', 'js', 'mjs', 'cjs'], {
91
+ configDir: false,
92
+ rcPrefix: '',
93
+ rcSuffix: '',
94
+ configFiles: false,
95
+ });
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.23.0";
1
+ export declare const version = "5.23.2";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.23.0';
1
+ export const version = '5.23.2';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.23.0",
3
+ "version": "5.23.2",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://knip.dev",
6
6
  "repository": {
@@ -21,7 +21,11 @@
21
21
  },
22
22
  {
23
23
  "type": "opencollective",
24
- "url": "https://opencollective.com/webpro"
24
+ "url": "https://opencollective.com/knip"
25
+ },
26
+ {
27
+ "type": "polar",
28
+ "url": "https://polar.sh/webpro-nl"
25
29
  }
26
30
  ],
27
31
  "main": "./dist/index.js",