knip 2.12.3 → 2.13.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.
@@ -51,6 +51,7 @@ export declare class ConfigurationChief {
51
51
  ignore: string[];
52
52
  ignoreBinaries: string[];
53
53
  ignoreDependencies: string[];
54
+ ignoreExportsUsedInFile: boolean | Partial<Record<"function" | "type" | "enum" | "class" | "interface" | "member", boolean>>;
54
55
  ignoreWorkspaces: string[];
55
56
  syncCompilers: Map<string, (args_0: string, ...args_1: unknown[]) => string>;
56
57
  asyncCompilers: Map<string, (args_0: string, ...args_1: unknown[]) => Promise<string>>;
@@ -36,6 +36,7 @@ const defaultConfig = {
36
36
  ignore: [],
37
37
  ignoreBinaries: [],
38
38
  ignoreDependencies: [],
39
+ ignoreExportsUsedInFile: false,
39
40
  ignoreWorkspaces: [],
40
41
  syncCompilers: new Map(),
41
42
  asyncCompilers: new Map(),
@@ -107,6 +108,7 @@ export class ConfigurationChief {
107
108
  const exclude = rawLocalConfig.exclude ?? defaultConfig.exclude;
108
109
  const ignore = arrayify(rawLocalConfig.ignore ?? defaultConfig.ignore);
109
110
  const ignoreBinaries = rawLocalConfig.ignoreBinaries ?? [];
111
+ const ignoreExportsUsedInFile = rawLocalConfig.ignoreExportsUsedInFile ?? false;
110
112
  const ignoreDependencies = rawLocalConfig.ignoreDependencies ?? [];
111
113
  const ignoreWorkspaces = rawLocalConfig.ignoreWorkspaces ?? defaultConfig.ignoreWorkspaces;
112
114
  const { syncCompilers, asyncCompilers } = rawLocalConfig;
@@ -155,6 +157,7 @@ export class ConfigurationChief {
155
157
  ignore,
156
158
  ignoreBinaries,
157
159
  ignoreDependencies,
160
+ ignoreExportsUsedInFile,
158
161
  ignoreWorkspaces,
159
162
  syncCompilers: new Map(Object.entries(syncCompilers ?? {})),
160
163
  asyncCompilers: new Map(Object.entries(asyncCompilers ?? {})),
@@ -7,6 +7,7 @@ export declare const ConfigurationValidator: z.ZodObject<{
7
7
  paths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
8
8
  ignore: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
9
9
  ignoreBinaries: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
10
+ ignoreExportsUsedInFile: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodRecord<z.ZodUnion<[z.ZodLiteral<"class">, z.ZodLiteral<"enum">, z.ZodLiteral<"function">, z.ZodLiteral<"interface">, z.ZodLiteral<"member">, z.ZodLiteral<"type">]>, z.ZodBoolean>]>>;
10
11
  ignoreDependencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
11
12
  ignoreWorkspaces: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
12
13
  compilers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodFunction<z.ZodTuple<[z.ZodString], z.ZodUnknown>, z.ZodString>, z.ZodFunction<z.ZodTuple<[z.ZodString], z.ZodUnknown>, z.ZodPromise<z.ZodString>>]>>>;
@@ -1411,6 +1412,7 @@ export declare const ConfigurationValidator: z.ZodObject<{
1411
1412
  paths?: Record<string, string[]> | undefined;
1412
1413
  ignore?: string | string[] | undefined;
1413
1414
  ignoreBinaries?: string[] | undefined;
1415
+ ignoreExportsUsedInFile?: boolean | Partial<Record<"function" | "type" | "enum" | "class" | "interface" | "member", boolean>> | undefined;
1414
1416
  ignoreDependencies?: string[] | undefined;
1415
1417
  ignoreWorkspaces?: string[] | undefined;
1416
1418
  compilers?: Record<string, ((args_0: string, ...args_1: unknown[]) => string) | ((args_0: string, ...args_1: unknown[]) => Promise<string>)> | undefined;
@@ -1813,6 +1815,7 @@ export declare const ConfigurationValidator: z.ZodObject<{
1813
1815
  paths?: Record<string, string[]> | undefined;
1814
1816
  ignore?: string | string[] | undefined;
1815
1817
  ignoreBinaries?: string[] | undefined;
1818
+ ignoreExportsUsedInFile?: boolean | Partial<Record<"function" | "type" | "enum" | "class" | "interface" | "member", boolean>> | undefined;
1816
1819
  ignoreDependencies?: string[] | undefined;
1817
1820
  ignoreWorkspaces?: string[] | undefined;
1818
1821
  compilers?: Record<string, ((args_0: string, ...args_1: unknown[]) => string) | ((args_0: string, ...args_1: unknown[]) => Promise<string>)> | undefined;
@@ -28,6 +28,19 @@ const rootConfigurationSchema = z.object({
28
28
  paths: pathsSchema.optional(),
29
29
  ignore: globSchema.optional(),
30
30
  ignoreBinaries: z.array(z.string()).optional(),
31
+ ignoreExportsUsedInFile: z
32
+ .union([
33
+ z.boolean(),
34
+ z.record(z.union([
35
+ z.literal('class'),
36
+ z.literal('enum'),
37
+ z.literal('function'),
38
+ z.literal('interface'),
39
+ z.literal('member'),
40
+ z.literal('type'),
41
+ ]), z.boolean()),
42
+ ])
43
+ .optional(),
31
44
  ignoreDependencies: z.array(z.string()).optional(),
32
45
  ignoreWorkspaces: z.array(z.string()).optional(),
33
46
  compilers: compilersSchema.optional(),
@@ -49,7 +49,10 @@ export declare class ProjectPrincipal {
49
49
  scripts: Set<string>;
50
50
  };
51
51
  private resolveModule;
52
- hasExternalReferences(filePath: string, exportedItem: ExportItem): boolean;
52
+ getHasReferences(filePath: string, exportedItem: ExportItem): {
53
+ external: boolean;
54
+ internal: boolean;
55
+ };
53
56
  findUnusedMembers(filePath: string, members: ExportItemMember[]): string[];
54
57
  private findReferences;
55
58
  isPublicExport(exportedItem: ExportItem): ts.JSDocPublicTag | undefined;
@@ -148,10 +148,20 @@ export class ProjectPrincipal {
148
148
  const module = ts.resolveModuleName(specifier, filePath, this.compilerOptions, this.backend.languageServiceHost);
149
149
  return module?.resolvedModule;
150
150
  }
151
- hasExternalReferences(filePath, exportedItem) {
152
- const referencedSymbols = this.findReferences(filePath, exportedItem.node);
153
- const externalRefs = referencedSymbols.flatMap(f => f.references).filter(ref => ref.fileName !== filePath);
154
- return externalRefs.length > 0;
151
+ getHasReferences(filePath, exportedItem) {
152
+ const hasReferences = { external: false, internal: false };
153
+ const symbolReferences = this.findReferences(filePath, (ts.isExportAssignment(exportedItem.node) && exportedItem.node.getChildAt(1)) || exportedItem.node).flatMap(f => f.references);
154
+ for (const reference of symbolReferences) {
155
+ if (reference.fileName === filePath) {
156
+ if (!reference.isDefinition) {
157
+ hasReferences.internal = true;
158
+ }
159
+ }
160
+ else {
161
+ hasReferences.external = true;
162
+ }
163
+ }
164
+ return hasReferences;
155
165
  }
156
166
  findUnusedMembers(filePath, members) {
157
167
  return members
package/dist/index.js CHANGED
@@ -282,9 +282,16 @@ export const main = async (unresolvedConfiguration) => {
282
282
  }
283
283
  continue;
284
284
  }
285
+ const exportedItemAllowsInternalReferences = typeof chief.config.ignoreExportsUsedInFile === 'object'
286
+ ? exportedItem.type !== 'unknown' && !!chief.config.ignoreExportsUsedInFile[exportedItem.type]
287
+ : chief.config.ignoreExportsUsedInFile;
288
+ const isExportedItemReferenced = () => {
289
+ const hasReferences = principal.getHasReferences(filePath, exportedItem);
290
+ return hasReferences.external || (exportedItemAllowsInternalReferences && hasReferences.internal);
291
+ };
285
292
  if (importedModule.isStar) {
286
293
  const isReExportedByEntryFile = isExportedInEntryFile(importedModule);
287
- if (!isReExportedByEntryFile && !principal.hasExternalReferences(filePath, exportedItem)) {
294
+ if (!isReExportedByEntryFile && !isExportedItemReferenced()) {
288
295
  if (['enum', 'type', 'interface'].includes(exportedItem.type)) {
289
296
  collector.addIssue({ type: 'nsTypes', filePath, symbol, symbolType: exportedItem.type });
290
297
  }
@@ -295,13 +302,12 @@ export const main = async (unresolvedConfiguration) => {
295
302
  }
296
303
  else {
297
304
  if (['enum', 'type', 'interface'].includes(exportedItem.type)) {
298
- collector.addIssue({ type: 'types', filePath, symbol, symbolType: exportedItem.type });
305
+ if (!isExportedItemReferenced()) {
306
+ collector.addIssue({ type: 'types', filePath, symbol, symbolType: exportedItem.type });
307
+ }
299
308
  }
300
309
  else {
301
- if (importedModule.isReExport && !principal.hasExternalReferences(filePath, exportedItem)) {
302
- collector.addIssue({ type: 'exports', filePath, symbol });
303
- }
304
- else if (!importedModule.isDynamic || !principal.hasExternalReferences(filePath, exportedItem)) {
310
+ if ((importedModule.isReExport || !importedModule.isDynamic) && !isExportedItemReferenced()) {
305
311
  collector.addIssue({ type: 'exports', filePath, symbol });
306
312
  }
307
313
  }
@@ -22,6 +22,7 @@ interface BaseWorkspaceConfiguration {
22
22
  }
23
23
  export interface WorkspaceConfiguration extends BaseWorkspaceConfiguration, Partial<PluginsConfiguration> {
24
24
  }
25
+ type IgnorableExport = 'class' | 'enum' | 'function' | 'interface' | 'member' | 'type';
25
26
  export interface Configuration {
26
27
  rules: Rules;
27
28
  include: string[];
@@ -29,6 +30,7 @@ export interface Configuration {
29
30
  ignore: NormalizedGlob;
30
31
  ignoreBinaries: string[];
31
32
  ignoreDependencies: string[];
33
+ ignoreExportsUsedInFile: boolean | Partial<Record<IgnorableExport, boolean>>;
32
34
  ignoreWorkspaces: string[];
33
35
  workspaces: Record<string, WorkspaceConfiguration>;
34
36
  syncCompilers: SyncCompilers;
@@ -10,6 +10,7 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
10
10
  paths?: Record<string, string[]> | undefined;
11
11
  ignore?: string | string[] | undefined;
12
12
  ignoreBinaries?: string[] | undefined;
13
+ ignoreExportsUsedInFile?: boolean | Partial<Record<"function" | "type" | "enum" | "class" | "interface" | "member", boolean>> | undefined;
13
14
  ignoreDependencies?: string[] | undefined;
14
15
  ignoreWorkspaces?: string[] | undefined;
15
16
  compilers?: Record<string, ((args_0: string, ...args_1: unknown[]) => string) | ((args_0: string, ...args_1: unknown[]) => Promise<string>)> | undefined;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.12.3";
1
+ export declare const version = "2.13.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.12.3';
1
+ export const version = '2.13.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "2.12.3",
3
+ "version": "2.13.0",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://github.com/webpro/knip",
6
6
  "repository": "github:webpro/knip",
@@ -67,7 +67,7 @@
67
67
  "@types/js-yaml": "4.0.5",
68
68
  "@types/micromatch": "4.0.2",
69
69
  "@types/minimist": "1.2.2",
70
- "@types/node": "20.2.3",
70
+ "@types/node": "20.2.5",
71
71
  "@types/npmcli__map-workspaces": "3.0.1",
72
72
  "@types/webpack": "5.28.1",
73
73
  "@typescript-eslint/eslint-plugin": "5.59.7",