knip 5.1.6 → 5.2.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.
@@ -45,7 +45,10 @@ export class IssueFixer {
45
45
  ].sort((a, b) => b[0] - a[0]);
46
46
  if (exportPositions.length > 0) {
47
47
  const sourceFileText = exportPositions.reduce((text, [start, end]) => text.substring(0, start) + text.substring(end), await readFile(filePath, 'utf-8'));
48
- await writeFile(filePath, sourceFileText);
48
+ const withoutEmptyReExports = sourceFileText
49
+ .replaceAll(/export \{[ ,]+\} from ('|")[^'"]+('|");?\n?/g, '')
50
+ .replaceAll(/export \{[ ,]+\};?\n?/g, '');
51
+ await writeFile(filePath, withoutEmptyReExports);
49
52
  }
50
53
  }
51
54
  }
@@ -1,4 +1,5 @@
1
1
  import ts from 'typescript';
2
+ import { type GetImportsAndExportsOptions } from './typescript/getImportsAndExports.js';
2
3
  import { createCustomModuleResolver } from './typescript/resolveModuleNames.js';
3
4
  import { SourceFileManager } from './typescript/SourceFileManager.js';
4
5
  import type { SyncCompilers, AsyncCompilers } from './compilers/types.js';
@@ -7,12 +8,6 @@ import type { SerializableExportMember } from './types/exports.js';
7
8
  import type { UnresolvedImport } from './types/imports.js';
8
9
  import type { ProgramMaybe53 } from './typescript/SourceFile.js';
9
10
  import type { ReferencedDependencies } from './WorkspaceWorker.js';
10
- type AnalyzeSourceFileOptions = {
11
- skipTypeOnly: boolean;
12
- isFixExports: boolean;
13
- isFixTypes: boolean;
14
- ignoreExportsUsedInFile: boolean;
15
- };
16
11
  export declare class ProjectPrincipal {
17
12
  entryPaths: Set<string>;
18
13
  projectPaths: Set<string>;
@@ -52,7 +47,7 @@ export declare class ProjectPrincipal {
52
47
  getUsedResolvedFiles(): string[];
53
48
  private getProgramSourceFiles;
54
49
  getUnreferencedFiles(): string[];
55
- analyzeSourceFile(filePath: string, options: AnalyzeSourceFileOptions): {
50
+ analyzeSourceFile(filePath: string, options: Omit<GetImportsAndExportsOptions, 'skipExports'>): {
56
51
  imports: {
57
52
  internal: import("./types/imports.js").SerializableImportMap;
58
53
  unresolved: Set<UnresolvedImport>;
@@ -67,4 +62,3 @@ export declare class ProjectPrincipal {
67
62
  resolveModule(specifier: string, filePath?: string): ts.ResolvedModuleFull | undefined;
68
63
  findUnusedMembers(filePath: string, members: SerializableExportMember[]): SerializableExportMember[];
69
64
  }
70
- export {};
package/dist/index.js CHANGED
@@ -227,6 +227,7 @@ export const main = async (unresolvedConfiguration) => {
227
227
  isFixExports: fixer.isEnabled && fixer.isFixUnusedExports,
228
228
  isFixTypes: fixer.isEnabled && fixer.isFixUnusedTypes,
229
229
  ignoreExportsUsedInFile: Boolean(chief.config.ignoreExportsUsedInFile),
230
+ tags,
230
231
  });
231
232
  const { internal, external, unresolved } = imports;
232
233
  const { exported, duplicate } = exports;
@@ -423,7 +424,7 @@ export const main = async (unresolvedConfiguration) => {
423
424
  continue;
424
425
  if (exportedItem.jsDocTags.includes('@alias'))
425
426
  continue;
426
- if (shouldIgnore(exportedItem, tags))
427
+ if (shouldIgnore(exportedItem.jsDocTags, tags))
427
428
  continue;
428
429
  if (isProduction && exportedItem.jsDocTags.includes('@internal'))
429
430
  continue;
@@ -437,7 +438,7 @@ export const main = async (unresolvedConfiguration) => {
437
438
  if (isIdentifierReferenced(filePath, identifier, importsForExport)) {
438
439
  if (exportedItem.type === 'enum') {
439
440
  exportedItem.members?.forEach(member => {
440
- if (shouldIgnore(member, tags))
441
+ if (shouldIgnore(member.jsDocTags, tags))
441
442
  return;
442
443
  if (member.refs === 0) {
443
444
  exportLookupLog(-1, `Looking up export member ${identifier}.${member.identifier} from`, filePath);
@@ -507,7 +508,7 @@ export const main = async (unresolvedConfiguration) => {
507
508
  const workspace = chief.findWorkspaceByFilePath(filePath);
508
509
  const principal = workspace && factory.getPrincipalByPackageName(workspace.pkgName);
509
510
  if (principal) {
510
- const members = exportedItem.members.filter(member => !shouldIgnore(member, tags));
511
+ const members = exportedItem.members.filter(member => !shouldIgnore(member.jsDocTags, tags));
511
512
  principal.findUnusedMembers(filePath, members).forEach(member => {
512
513
  collector.addIssue({
513
514
  type: 'classMembers',
@@ -89,6 +89,9 @@ export const getJSDocTags = (node) => {
89
89
  else if (ts.isEnumMember(node) || ts.isClassElement(node)) {
90
90
  tagNodes = [...tagNodes, ...ts.getJSDocTags(node.parent)];
91
91
  }
92
+ else if (ts.isCallExpression(node)) {
93
+ tagNodes = [...tagNodes, ...ts.getJSDocTags(node.parent)];
94
+ }
92
95
  for (const tagNode of tagNodes) {
93
96
  const match = tagNode.getText()?.match(/@\S+/);
94
97
  if (match)
@@ -1,5 +1,6 @@
1
1
  import ts from 'typescript';
2
2
  import type { BoundSourceFile, GetResolvedModule } from './SourceFile.js';
3
+ import type { Tags } from '../types/cli.js';
3
4
  import type { SerializableExports } from '../types/exports.js';
4
5
  import type { SerializableImportMap, UnresolvedImport } from '../types/imports.js';
5
6
  import type { IssueSymbol } from '../types/issues.js';
@@ -9,6 +10,7 @@ export type GetImportsAndExportsOptions = {
9
10
  isFixExports: boolean;
10
11
  isFixTypes: boolean;
11
12
  ignoreExportsUsedInFile: boolean;
13
+ tags: Tags;
12
14
  };
13
15
  export declare const _getImportsAndExports: (sourceFile: BoundSourceFile, getResolvedModule: GetResolvedModule, typeChecker: ts.TypeChecker, options: GetImportsAndExportsOptions) => {
14
16
  imports: {
@@ -3,6 +3,7 @@ import ts from 'typescript';
3
3
  import { isStartsLikePackageName, sanitizeSpecifier } from '../util/modules.js';
4
4
  import { isInNodeModules } from '../util/path.js';
5
5
  import { timerify } from '../util/Performance.js';
6
+ import { shouldIgnore } from '../util/tag.js';
6
7
  import { isAccessExpression, getJSDocTags, getLineAndCharacterOfPosition, getMemberStringLiterals, } from './ast-helpers.js';
7
8
  import getDynamicImportVisitors from './visitors/dynamic-imports/index.js';
8
9
  import getExportVisitors from './visitors/exports/index.js';
@@ -30,7 +31,7 @@ const createSerializableMember = (node, member, pos) => {
30
31
  };
31
32
  };
32
33
  const getImportsAndExports = (sourceFile, getResolvedModule, typeChecker, options) => {
33
- const { skipTypeOnly } = options;
34
+ const { skipTypeOnly, tags } = options;
34
35
  const internalImports = {};
35
36
  const externalImports = new Set();
36
37
  const unresolvedImports = new Set();
@@ -75,7 +76,7 @@ const getImportsAndExports = (sourceFile, getResolvedModule, typeChecker, option
75
76
  if (symbol)
76
77
  importedInternalSymbols.set(symbol, filePath);
77
78
  };
78
- const addImport = (options) => {
79
+ const addImport = (options, node) => {
79
80
  const { specifier, isTypeOnly, pos, identifier = '__anonymous', isReExport = false } = options;
80
81
  if (isBuiltin(specifier))
81
82
  return;
@@ -103,6 +104,8 @@ const getImportsAndExports = (sourceFile, getResolvedModule, typeChecker, option
103
104
  else {
104
105
  if (skipTypeOnly && isTypeOnly)
105
106
  return;
107
+ if (shouldIgnore(getJSDocTags(node), tags))
108
+ return;
106
109
  if (typeof pos === 'number') {
107
110
  const { line, character } = sourceFile.getLineAndCharacterOfPosition(pos);
108
111
  unresolvedImports.add({ specifier, pos, line: line + 1, col: character + 1 });
@@ -208,13 +211,13 @@ const getImportsAndExports = (sourceFile, getResolvedModule, typeChecker, option
208
211
  const visit = (node) => {
209
212
  for (const visitor of visitors.dynamicImport) {
210
213
  const result = visitor(node, options);
211
- result && (Array.isArray(result) ? result.forEach(addImport) : addImport(result));
214
+ result && (Array.isArray(result) ? result.forEach(r => addImport(r, node)) : addImport(result, node));
212
215
  }
213
216
  const isTopLevel = node.parent === sourceFile || node.parent?.parent === sourceFile;
214
217
  if (isTopLevel) {
215
218
  for (const visitor of visitors.import) {
216
219
  const result = visitor(node, options);
217
- result && (Array.isArray(result) ? result.forEach(addImport) : addImport(result));
220
+ result && (Array.isArray(result) ? result.forEach(r => addImport(r, node)) : addImport(result, node));
218
221
  }
219
222
  for (const visitor of visitors.export) {
220
223
  const result = visitor(node, options);
@@ -1,4 +1,3 @@
1
1
  import type { Tags } from '../types/cli.js';
2
- import type { SerializableExport, SerializableExportMember } from '../types/exports.js';
3
2
  export declare const splitTags: (tags: string[]) => Tags;
4
- export declare const shouldIgnore: (exportedItem: SerializableExport | SerializableExportMember, tags: Tags) => boolean;
3
+ export declare const shouldIgnore: (jsDocTags: string[], tags: Tags) => boolean;
package/dist/util/tag.js CHANGED
@@ -5,11 +5,11 @@ export const splitTags = (tags) => tags
5
5
  return [incl, excl];
6
6
  }, [[], []]);
7
7
  const hasTag = (tags, jsDocTags) => tags.some(tag => jsDocTags.includes('@' + tag));
8
- export const shouldIgnore = (exportedItem, tags) => {
8
+ export const shouldIgnore = (jsDocTags, tags) => {
9
9
  const [includeJSDocTags, excludeJSDocTags] = tags;
10
- if (includeJSDocTags.length > 0 && !hasTag(includeJSDocTags, exportedItem.jsDocTags))
10
+ if (includeJSDocTags.length > 0 && !hasTag(includeJSDocTags, jsDocTags))
11
11
  return true;
12
- if (excludeJSDocTags.length > 0 && hasTag(excludeJSDocTags, exportedItem.jsDocTags))
12
+ if (excludeJSDocTags.length > 0 && hasTag(excludeJSDocTags, jsDocTags))
13
13
  return true;
14
14
  return false;
15
15
  };
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.1.6";
1
+ export declare const version = "5.2.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.1.6';
1
+ export const version = '5.2.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.1.6",
3
+ "version": "5.2.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": {