knip 6.19.0 → 6.20.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.
@@ -219,22 +219,37 @@ export class WorkspaceWorker {
219
219
  const hasProductionInput = (input) => productionInputsFromManifest.find(d => d.specifier === input.specifier && d.type === input.type);
220
220
  const createGetInputsFromScripts = (containingFilePath) => (scripts, options) => _getInputsFromScripts(scripts, { ...baseOptions, ...options, containingFilePath });
221
221
  const inputs = [];
222
- const remainingPlugins = new Set(this.enabledPlugins);
222
+ const enabledPlugins = new Set(this.enabledPlugins);
223
223
  const configFilesMap = this.configFilesMap;
224
- const configFiles = this.configFilesMap.get(wsName);
225
224
  const seen = new Map();
226
225
  const parsedConfigCache = new Map();
226
+ const getSeenConfigFiles = (pluginName) => {
227
+ let configFilePaths = seen.get(pluginName);
228
+ if (!configFilePaths) {
229
+ configFilePaths = new Set();
230
+ seen.set(pluginName, configFilePaths);
231
+ }
232
+ return configFilePaths;
233
+ };
227
234
  const storeConfigFilePath = (pluginName, input) => {
228
235
  const configFilePath = this.handleInput(input);
229
236
  if (configFilePath) {
230
237
  const workspace = this.findWorkspaceByFilePath(configFilePath);
231
238
  if (workspace) {
232
239
  const name = this.name === ROOT_WORKSPACE_NAME ? workspace.name : this.name;
233
- if (!configFilesMap.has(name))
234
- configFilesMap.set(name, new Map());
235
- if (!configFilesMap.get(name)?.has(pluginName))
236
- configFilesMap.get(name)?.set(pluginName, new Set());
237
- configFilesMap.get(name)?.get(pluginName)?.add(configFilePath);
240
+ if (name === wsName && seen.get(pluginName)?.has(configFilePath))
241
+ return;
242
+ let configFiles = configFilesMap.get(name);
243
+ if (!configFiles) {
244
+ configFiles = new Map();
245
+ configFilesMap.set(name, configFiles);
246
+ }
247
+ let configFilePaths = configFiles.get(pluginName);
248
+ if (!configFilePaths) {
249
+ configFilePaths = new Set();
250
+ configFiles.set(pluginName, configFilePaths);
251
+ }
252
+ configFilePaths.add(configFilePath);
238
253
  }
239
254
  }
240
255
  };
@@ -246,12 +261,13 @@ export class WorkspaceWorker {
246
261
  inputs.push({ ...input, containingFilePath });
247
262
  }
248
263
  }
249
- const runPlugin = async (pluginName, patterns) => {
264
+ const runPlugin = async (pluginName, patterns, isResolvedConfigFiles = false) => {
250
265
  const plugin = Plugins[pluginName];
251
266
  const config = this.getConfigForPlugin(pluginName);
252
267
  if (!config)
253
268
  return [];
254
269
  const inputs = [];
270
+ const seenConfigFiles = getSeenConfigFiles(pluginName);
255
271
  const addInput = (input, containingFilePath = input.containingFilePath) => {
256
272
  if (isConfig(input)) {
257
273
  storeConfigFilePath(input.pluginName, { ...input, containingFilePath });
@@ -262,6 +278,13 @@ export class WorkspaceWorker {
262
278
  };
263
279
  const label = 'config file';
264
280
  const configFilePaths = await _glob({ patterns, cwd: rootCwd, dir: cwd, gitignore: false, label });
281
+ if (isResolvedConfigFiles) {
282
+ const foundConfigFilePaths = new Set(configFilePaths);
283
+ for (const filePath of patterns) {
284
+ if (!foundConfigFilePaths.has(filePath))
285
+ seenConfigFiles.add(filePath);
286
+ }
287
+ }
265
288
  const options = {
266
289
  ...baseScriptOptions,
267
290
  config,
@@ -289,6 +312,9 @@ export class WorkspaceWorker {
289
312
  if (typeof plugin.setup === 'function')
290
313
  await plugin.setup();
291
314
  for (const configFilePath of configFilePaths) {
315
+ if (seenConfigFiles.has(configFilePath))
316
+ continue;
317
+ seenConfigFiles.add(configFilePath);
292
318
  const isManifest = basename(configFilePath) === 'package.json';
293
319
  const fd = isManifest ? undefined : this.cache.getFileDescriptor(configFilePath);
294
320
  if (fd?.meta?.data && !fd.changed) {
@@ -323,8 +349,7 @@ export class WorkspaceWorker {
323
349
  };
324
350
  const cache = {};
325
351
  let hasLoadConfigError = false;
326
- const key = `${wsName}:${pluginName}`;
327
- if (plugin.resolveConfig && !seen.get(key)?.has(configFilePath)) {
352
+ if (plugin.resolveConfig) {
328
353
  if (parsed && isExternalReExportsOnly(parsed)) {
329
354
  cache.resolveConfig = [];
330
355
  }
@@ -369,12 +394,9 @@ export class WorkspaceWorker {
369
394
  if (hasLoadConfigError) {
370
395
  this.cache.removeEntry(configFilePath);
371
396
  }
372
- else if (fd?.changed && fd.meta && !seen.get(key)?.has(configFilePath)) {
397
+ else if (fd?.meta) {
373
398
  fd.meta.data = cache;
374
399
  }
375
- if (!seen.has(key))
376
- seen.set(key, new Set());
377
- seen.get(key)?.add(configFilePath);
378
400
  }
379
401
  }
380
402
  if (plugin.resolve) {
@@ -390,27 +412,38 @@ export class WorkspaceWorker {
390
412
  const enabledPluginTitles = this.enabledPlugins.map(name => Plugins[name].title);
391
413
  debugLogObject(this.name, 'Enabled plugins', enabledPluginTitles);
392
414
  for (const pluginName of this.enabledPlugins) {
415
+ const configFiles = this.configFilesMap.get(wsName);
393
416
  const patterns = [...this.getConfigurationFilePatterns(pluginName), ...(configFiles?.get(pluginName) ?? [])];
394
417
  configFiles?.delete(pluginName);
395
418
  for (const input of await runPlugin(pluginName, compact(patterns)))
396
419
  inputs.push(input);
397
- remainingPlugins.delete(pluginName);
398
420
  }
399
421
  {
400
422
  const configFiles = this.configFilesMap.get(wsName);
401
423
  if (configFiles) {
402
- do {
403
- for (const [pluginName, dependencies] of configFiles) {
404
- configFiles.delete(pluginName);
405
- if (this.enabledPlugins.includes(pluginName)) {
406
- for (const input of await runPlugin(pluginName, Array.from(dependencies)))
424
+ while (configFiles.size > 0) {
425
+ const entry = configFiles.entries().next().value;
426
+ if (!entry)
427
+ break;
428
+ const [pluginName, dependencies] = entry;
429
+ configFiles.delete(pluginName);
430
+ if (enabledPlugins.has(pluginName)) {
431
+ const seenConfigFiles = getSeenConfigFiles(pluginName);
432
+ const unprocessed = [];
433
+ for (const filePath of dependencies) {
434
+ if (!seenConfigFiles.has(filePath))
435
+ unprocessed.push(filePath);
436
+ }
437
+ if (unprocessed.length > 0) {
438
+ for (const input of await runPlugin(pluginName, unprocessed, true))
407
439
  inputs.push(input);
408
440
  }
409
- else
410
- for (const id of dependencies)
411
- inputs.push(toEntry(id));
412
441
  }
413
- } while (remainingPlugins.size > 0 && configFiles.size > 0);
442
+ else {
443
+ for (const id of dependencies)
444
+ inputs.push(toEntry(id));
445
+ }
446
+ }
414
447
  }
415
448
  }
416
449
  debugLogArray(wsName, 'Plugin dependencies', () => compact(inputs.map(input => toDebugString(input, rootCwd))));
@@ -5,7 +5,7 @@ import { timerify } from '../util/Performance.js';
5
5
  import { EMPTY_TAGS } from './visitors/jsdoc.js';
6
6
  const defaultParseOptions = {
7
7
  sourceType: 'unambiguous',
8
- experimentalRawTransfer: rawTransferSupported(),
8
+ experimentalRawTransfer: process.env.KNIP_DISABLE_RAW_TRANSFER !== '1' && rawTransferSupported(),
9
9
  };
10
10
  const parseFile = (filePath, sourceText) => {
11
11
  const ext = extname(filePath);
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "6.19.0";
1
+ export declare const version = "6.20.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '6.19.0';
1
+ export const version = '6.20.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "6.19.0",
3
+ "version": "6.20.0",
4
4
  "description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
5
5
  "keywords": [
6
6
  "analysis",