@openrewrite/rewrite 8.91.3 → 8.91.5

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 (47) hide show
  1. package/dist/javascript/index.d.ts +1 -1
  2. package/dist/javascript/index.d.ts.map +1 -1
  3. package/dist/javascript/index.js +2 -1
  4. package/dist/javascript/index.js.map +1 -1
  5. package/dist/javascript/parser.d.ts +3 -2
  6. package/dist/javascript/parser.d.ts.map +1 -1
  7. package/dist/javascript/parser.js +154 -114
  8. package/dist/javascript/parser.js.map +1 -1
  9. package/dist/javascript/remove-import.d.ts +0 -18
  10. package/dist/javascript/remove-import.d.ts.map +1 -1
  11. package/dist/javascript/remove-import.js +50 -438
  12. package/dist/javascript/remove-import.js.map +1 -1
  13. package/dist/javascript/scope.d.ts +6 -0
  14. package/dist/javascript/scope.d.ts.map +1 -1
  15. package/dist/javascript/scope.js +87 -7
  16. package/dist/javascript/scope.js.map +1 -1
  17. package/dist/javascript/tsconfig.d.ts +32 -0
  18. package/dist/javascript/tsconfig.d.ts.map +1 -0
  19. package/dist/javascript/tsconfig.js +205 -0
  20. package/dist/javascript/tsconfig.js.map +1 -0
  21. package/dist/rewrite-javascript-version.txt +1 -1
  22. package/dist/rpc/index.d.ts +1 -1
  23. package/dist/rpc/index.d.ts.map +1 -1
  24. package/dist/rpc/index.js +2 -1
  25. package/dist/rpc/index.js.map +1 -1
  26. package/dist/rpc/java-recipe.d.ts +32 -22
  27. package/dist/rpc/java-recipe.d.ts.map +1 -1
  28. package/dist/rpc/java-recipe.js +91 -30
  29. package/dist/rpc/java-recipe.js.map +1 -1
  30. package/dist/rpc/request/prepare-recipe.d.ts +10 -14
  31. package/dist/rpc/request/prepare-recipe.d.ts.map +1 -1
  32. package/dist/rpc/request/prepare-recipe.js +53 -88
  33. package/dist/rpc/request/prepare-recipe.js.map +1 -1
  34. package/dist/rpc/rewrite-rpc.d.ts +5 -12
  35. package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
  36. package/dist/rpc/rewrite-rpc.js +5 -12
  37. package/dist/rpc/rewrite-rpc.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/javascript/index.ts +1 -1
  40. package/src/javascript/parser.ts +104 -58
  41. package/src/javascript/remove-import.ts +50 -424
  42. package/src/javascript/scope.ts +103 -7
  43. package/src/javascript/tsconfig.ts +177 -0
  44. package/src/rpc/index.ts +1 -1
  45. package/src/rpc/java-recipe.ts +107 -33
  46. package/src/rpc/request/prepare-recipe.ts +55 -90
  47. package/src/rpc/rewrite-rpc.ts +5 -12
@@ -80,12 +80,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
80
80
  });
81
81
  }
82
82
  async visitJsCompilationUnit(compilationUnit, p) {
83
- // First, collect all used identifiers in the file
84
- const usedIdentifiers = new Set();
85
- const usedTypes = new Set();
86
- // Traverse the AST to collect used identifiers
87
- await this.collectUsedIdentifiers(compilationUnit, usedIdentifiers, usedTypes);
88
- // Now process imports with knowledge of what's used
83
+ const usedNames = collectUsedNames(compilationUnit);
89
84
  return this.produceJavaScript(compilationUnit, p, async (draft) => {
90
85
  const formatter = new java_2.ElementRemovalFormatter(true); // Preserve file headers from first import
91
86
  const newStatements = await (0, util_1.mapAsync)(compilationUnit.statements, async (stmt) => {
@@ -93,7 +88,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
93
88
  // Handle ES6 imports
94
89
  if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
95
90
  const jsImport = statement;
96
- const result = await this.processImport(jsImport, usedIdentifiers, usedTypes, p);
91
+ const result = await this.processImport(jsImport, usedNames, p);
97
92
  if (result === undefined) {
98
93
  formatter.markRemoved(statement);
99
94
  return undefined;
@@ -106,7 +101,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
106
101
  // Multi-variable declarations might come as JS.ScopedVariableDeclarations
107
102
  if ((statement === null || statement === void 0 ? void 0 : statement.kind) === java_1.J.Kind.VariableDeclarations) {
108
103
  const varDecl = statement;
109
- const result = await this.processRequireFromVarDecls(varDecl, usedIdentifiers, p);
104
+ const result = await this.processRequireFromVarDecls(varDecl, usedNames, p);
110
105
  if (result === undefined) {
111
106
  formatter.markRemoved(statement);
112
107
  return undefined;
@@ -124,7 +119,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
124
119
  for (const v of scopedVarDecl.variables) {
125
120
  const varDecl = v.element;
126
121
  if ((varDecl === null || varDecl === void 0 ? void 0 : varDecl.kind) === java_1.J.Kind.VariableDeclarations) {
127
- const result = await this.processRequireFromVarDecls(varDecl, usedIdentifiers, p);
122
+ const result = await this.processRequireFromVarDecls(varDecl, usedNames, p);
128
123
  if (result === undefined) {
129
124
  hasChanges = true;
130
125
  varFormatter.markRemoved(varDecl);
@@ -160,10 +155,10 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
160
155
  draft.eof = await this.visitSpace(compilationUnit.eof, p);
161
156
  });
162
157
  }
163
- async processImport(jsImport, usedIdentifiers, usedTypes, p) {
158
+ async processImport(jsImport, usedNames, p) {
164
159
  // Handle import-equals-require syntax: import util = require("util");
165
160
  if (jsImport.initializer) {
166
- return this.processImportEqualsRequire(jsImport, usedIdentifiers, usedTypes, p);
161
+ return this.processImportEqualsRequire(jsImport, usedNames, p);
167
162
  }
168
163
  // Check if this import is from the target module
169
164
  if (!this.isTargetModule(jsImport)) {
@@ -187,11 +182,11 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
187
182
  let shouldRemove;
188
183
  if (this.member === 'default') {
189
184
  // Special case: member 'default' means remove any default import from the target module if unused
190
- shouldRemove = !usedIdentifiers.has(name) && !usedTypes.has(name);
185
+ shouldRemove = !usedNames.has(name);
191
186
  }
192
187
  else {
193
188
  // Regular case: check if the import name matches the removal criteria
194
- shouldRemove = this.shouldRemoveImport(name, usedIdentifiers, usedTypes, name);
189
+ shouldRemove = this.shouldRemoveImport(name, usedNames, name);
195
190
  }
196
191
  if (shouldRemove) {
197
192
  // If there are no named imports, remove the entire import
@@ -230,7 +225,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
230
225
  if (this.member !== undefined) {
231
226
  // We're trying to remove a specific member from this namespace
232
227
  // Check if the namespace itself is used
233
- if (!usedIdentifiers.has(name) && !usedTypes.has(name)) {
228
+ if (!usedNames.has(name)) {
234
229
  // Namespace is not used, remove the entire import
235
230
  if (!importClause.name) {
236
231
  return undefined;
@@ -241,7 +236,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
241
236
  }
242
237
  // Namespace is used, we can't remove individual members from it
243
238
  }
244
- else if (this.shouldRemoveImport(name, usedIdentifiers, usedTypes, name)) {
239
+ else if (this.shouldRemoveImport(name, usedNames, name)) {
245
240
  // If there's no default import, remove the entire import
246
241
  if (!importClause.name) {
247
242
  return undefined;
@@ -261,7 +256,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
261
256
  if (this.member !== undefined) {
262
257
  // We're trying to remove a specific member from this namespace
263
258
  // Check if the namespace itself is used
264
- if (!usedIdentifiers.has(aliasName) && !usedTypes.has(aliasName)) {
259
+ if (!usedNames.has(aliasName)) {
265
260
  // Namespace is not used, remove the entire import
266
261
  if (!importClause.name) {
267
262
  return undefined;
@@ -272,7 +267,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
272
267
  }
273
268
  // Namespace is used, we can't remove individual members from it
274
269
  }
275
- else if (this.shouldRemoveImport(aliasName, usedIdentifiers, usedTypes, aliasName)) {
270
+ else if (this.shouldRemoveImport(aliasName, usedNames, aliasName)) {
276
271
  // If there's no default import, remove the entire import
277
272
  if (!importClause.name) {
278
273
  return undefined;
@@ -286,7 +281,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
286
281
  // Handle named imports: import { a, b } from 'module'
287
282
  if (namedBindings.kind === tree_1.JS.Kind.NamedImports) {
288
283
  const namedImports = namedBindings;
289
- const updatedImports = await this.processNamedImports(namedImports, usedIdentifiers, usedTypes, p);
284
+ const updatedImports = await this.processNamedImports(namedImports, usedNames, p);
290
285
  if (updatedImports === undefined) {
291
286
  // All named imports were removed
292
287
  if (!importClause.name) {
@@ -312,10 +307,10 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
312
307
  * Process TypeScript import-equals-require syntax: import util = require("util");
313
308
  * This is represented as a JS.Import with an initializer containing the require() call.
314
309
  */
315
- async processImportEqualsRequire(jsImport, usedIdentifiers, usedTypes, p) {
310
+ async processImportEqualsRequire(jsImport, usedNames, p) {
316
311
  var _a;
317
312
  const initializer = (_a = jsImport.initializer) === null || _a === void 0 ? void 0 : _a.element;
318
- if (!initializer || !this.isRequireCall(initializer)) {
313
+ if (!initializer || !isRequireCall(initializer)) {
319
314
  return jsImport;
320
315
  }
321
316
  const methodInv = initializer;
@@ -332,23 +327,11 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
332
327
  const importedName = importClause.name.element.simpleName;
333
328
  // For import-equals-require, we can only remove the entire import since
334
329
  // it imports the whole module as a single identifier
335
- if (this.shouldRemoveIdentifier(importedName, usedIdentifiers, usedTypes)) {
330
+ if (this.shouldRemoveIdentifier(importedName, usedNames)) {
336
331
  return undefined;
337
332
  }
338
333
  return jsImport;
339
334
  }
340
- /**
341
- * Check if a node is a require() method invocation
342
- */
343
- isRequireCall(node) {
344
- var _a;
345
- if (node.kind !== java_1.J.Kind.MethodInvocation) {
346
- return false;
347
- }
348
- const methodInv = node;
349
- return ((_a = methodInv.name) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier &&
350
- methodInv.name.simpleName === 'require';
351
- }
352
335
  /**
353
336
  * Check if the module name matches the target module
354
337
  */
@@ -358,13 +341,13 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
358
341
  /**
359
342
  * Check if an identifier should be removed based on usage
360
343
  */
361
- shouldRemoveIdentifier(name, usedIdentifiers, usedTypes) {
344
+ shouldRemoveIdentifier(name, usedNames) {
362
345
  // For CommonJS and import-equals-require, we're removing the entire import
363
346
  // if the identifier is not used (member is typically undefined for these cases,
364
347
  // or we're checking if a specific binding is used)
365
- return !usedIdentifiers.has(name) && !usedTypes.has(name);
348
+ return !usedNames.has(name);
366
349
  }
367
- async processNamedImports(namedImports, usedIdentifiers, usedTypes, p) {
350
+ async processNamedImports(namedImports, usedNames, p) {
368
351
  const { filtered, allRemoved } = await this.filterElementsWithPrefixPreservation(namedImports.elements.elements, (elem) => {
369
352
  if (elem.kind === tree_1.JS.Kind.ImportSpecifier) {
370
353
  const specifier = elem;
@@ -378,13 +361,13 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
378
361
  // We're removing a specific member - check if this matches
379
362
  if (this.member === importName) {
380
363
  // This is the member we want to remove - check if it's used
381
- return usedIdentifiers.has(nameToCheck) || usedTypes.has(nameToCheck);
364
+ return usedNames.has(nameToCheck);
382
365
  }
383
366
  return true; // Keep imports that don't match the member
384
367
  }
385
368
  else {
386
369
  // We're removing based on the import name itself
387
- return !this.shouldRemoveImport(importName, usedIdentifiers, usedTypes, importName);
370
+ return !this.shouldRemoveImport(importName, usedNames, importName);
388
371
  }
389
372
  }
390
373
  return true; // Keep non-ImportSpecifier elements
@@ -407,7 +390,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
407
390
  draft.elements = Object.assign(Object.assign({}, namedImports.elements), { elements: filtered });
408
391
  });
409
392
  }
410
- async processRequireFromVarDecls(varDecls, usedIdentifiers, p) {
393
+ async processRequireFromVarDecls(varDecls, usedNames, p) {
411
394
  var _a;
412
395
  // Check if this is a require() call
413
396
  if (varDecls.variables.length !== 1) {
@@ -418,7 +401,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
418
401
  return varDecls;
419
402
  }
420
403
  const initializer = (_a = namedVar.initializer) === null || _a === void 0 ? void 0 : _a.element;
421
- if (!initializer || !this.isRequireCall(initializer)) {
404
+ if (!initializer || !isRequireCall(initializer)) {
422
405
  return varDecls;
423
406
  }
424
407
  const methodInv = initializer;
@@ -432,14 +415,14 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
432
415
  const varName = pattern.simpleName;
433
416
  // For require() statements, check the module name from the require call
434
417
  const moduleName = this.getModuleNameFromRequire(methodInv);
435
- if (moduleName && this.matchesTargetModule(moduleName) && !usedIdentifiers.has(varName)) {
418
+ if (moduleName && this.matchesTargetModule(moduleName) && !usedNames.has(varName)) {
436
419
  return undefined; // Remove the entire require statement
437
420
  }
438
421
  }
439
422
  // Handle: const { readFile } = require('fs')
440
423
  if (pattern.kind === tree_1.JS.Kind.ObjectBindingPattern && this.member !== undefined) {
441
424
  const objectPattern = pattern;
442
- const updatedPattern = await this.processObjectBindingPattern(objectPattern, usedIdentifiers, p);
425
+ const updatedPattern = await this.processObjectBindingPattern(objectPattern, usedNames, p);
443
426
  if (updatedPattern === undefined) {
444
427
  return undefined; // Remove entire require
445
428
  }
@@ -470,12 +453,12 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
470
453
  }
471
454
  return (_b = firstArg.value) === null || _b === void 0 ? void 0 : _b.toString();
472
455
  }
473
- async processObjectBindingPattern(pattern, usedIdentifiers, p) {
456
+ async processObjectBindingPattern(pattern, usedNames, p) {
474
457
  const { filtered, allRemoved } = await this.filterElementsWithPrefixPreservation(pattern.bindings.elements, (elem) => {
475
458
  const bound = this.boundByPatternElement(elem);
476
459
  // An element whose names cannot be read is left alone.
477
460
  return bound.length === 0 ||
478
- bound.some(b => !this.shouldRemoveImport(b.name, usedIdentifiers, new Set(), b.member));
461
+ bound.some(b => !this.shouldRemoveImport(b.name, usedNames, b.member));
479
462
  }, async (elem, prefix) => {
480
463
  if (elem.kind === java_1.J.Kind.Identifier) {
481
464
  return this.produceJava(elem, p, async (draft) => {
@@ -537,7 +520,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
537
520
  ? [{ name: elem.simpleName, member: elem.simpleName }]
538
521
  : (0, scope_1.bindingNames)(elem);
539
522
  }
540
- shouldRemoveImport(name, usedIdentifiers, usedTypes, member) {
523
+ shouldRemoveImport(name, usedNames, member) {
541
524
  // If member is specified, we're removing a specific member from the module
542
525
  if (this.member !== undefined) {
543
526
  // A name bound under an alias reads one member and is referenced by another, and a name
@@ -549,7 +532,7 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
549
532
  // If no member specified, we're removing all unused imports from the module
550
533
  // So we check if this particular import is unused
551
534
  // Check if it's used
552
- return !(usedIdentifiers.has(name) || usedTypes.has(name));
535
+ return !usedNames.has(name);
553
536
  }
554
537
  isTargetModule(jsImport) {
555
538
  var _a, _b;
@@ -563,399 +546,28 @@ class RemoveImport extends visitor_1.JavaScriptVisitor {
563
546
  // Match the module name
564
547
  return moduleName === this.module;
565
548
  }
566
- /**
567
- * Helper to traverse parameters from various node types
568
- */
569
- async traverseParameters(params, usedIdentifiers, usedTypes) {
570
- if (!params || typeof params !== 'object')
571
- return;
572
- if (Array.isArray(params)) {
573
- for (const p of params) {
574
- // Array elements might be RightPadded, so unwrap them
575
- const elem = p.element || p;
576
- await this.collectUsedIdentifiers(elem, usedIdentifiers, usedTypes);
577
- }
578
- }
579
- else if (params.elements) {
580
- for (const p of params.elements) {
581
- if (p.element) {
582
- await this.collectUsedIdentifiers(p.element, usedIdentifiers, usedTypes);
583
- }
584
- }
585
- }
586
- else if (params.parameters) {
587
- for (const p of params.parameters) {
588
- const elem = p.element || p;
589
- await this.collectUsedIdentifiers(elem, usedIdentifiers, usedTypes);
590
- }
591
- }
592
- }
593
- /**
594
- * Helper to traverse statements from various node types
595
- */
596
- async traverseStatements(statements, usedIdentifiers, usedTypes) {
597
- if (!statements)
598
- return;
599
- if (Array.isArray(statements)) {
600
- for (const stmt of statements) {
601
- const element = stmt.element || stmt;
602
- if (element) {
603
- await this.collectUsedIdentifiers(element, usedIdentifiers, usedTypes);
604
- }
605
- }
606
- }
607
- }
608
- /**
609
- * Helper to check for type expressions and collect type usage
610
- */
611
- async checkTypeExpression(node, usedTypes) {
612
- if (node.typeExpression) {
613
- await this.collectTypeUsage(node.typeExpression, usedTypes);
614
- }
615
- }
616
- async collectUsedIdentifiers(node, usedIdentifiers, usedTypes) {
617
- // This is a simplified version - in a real implementation,
618
- // we'd need to traverse the entire AST and collect all identifier usages
619
- // For now, we'll implement a basic traversal
620
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _q, _r;
621
- if (node.kind === java_1.J.Kind.Identifier) {
622
- const identifier = node;
623
- usedIdentifiers.add(identifier.simpleName);
624
- }
625
- else if (node.kind === java_1.J.Kind.VariableDeclarations) {
626
- const varDecls = node;
627
- // Check the type expression on the VariableDeclarations itself
628
- await this.checkTypeExpression(varDecls, usedTypes);
629
- for (const v of varDecls.variables) {
630
- // Check the initializer
631
- if ((_a = v.element.initializer) === null || _a === void 0 ? void 0 : _a.element) {
632
- await this.collectUsedIdentifiers(v.element.initializer.element, usedIdentifiers, usedTypes);
633
- }
634
- }
635
- }
636
- else if (node.kind === java_1.J.Kind.MethodInvocation) {
637
- const methodInv = node;
638
- // Check if this is a member access pattern like fs.readFileSync
639
- if (((_c = (_b = methodInv.select) === null || _b === void 0 ? void 0 : _b.element) === null || _c === void 0 ? void 0 : _c.kind) === java_1.J.Kind.FieldAccess) {
640
- const fieldAccess = methodInv.select.element;
641
- if (((_d = fieldAccess.target) === null || _d === void 0 ? void 0 : _d.kind) === java_1.J.Kind.Identifier) {
642
- usedIdentifiers.add(fieldAccess.target.simpleName);
643
- }
644
- }
645
- else if (((_f = (_e = methodInv.select) === null || _e === void 0 ? void 0 : _e.element) === null || _f === void 0 ? void 0 : _f.kind) === java_1.J.Kind.Identifier) {
646
- // Direct identifier like fs in fs.method() - though this is rare
647
- usedIdentifiers.add(methodInv.select.element.simpleName);
648
- }
649
- else if (!methodInv.select) {
650
- // No select means this is a direct function call like isArray()
651
- // Only in this case should we add the method name as a used identifier
652
- if (methodInv.name && methodInv.name.kind === java_1.J.Kind.Identifier) {
653
- usedIdentifiers.add(methodInv.name.simpleName);
654
- }
655
- }
656
- // Note: We don't add method names for calls like Array.isArray() or obj.method()
657
- // because those are methods on objects, not standalone imported functions
658
- // Recursively check arguments
659
- if (methodInv.arguments) {
660
- for (const arg of methodInv.arguments.elements) {
661
- if (arg.element) {
662
- await this.collectUsedIdentifiers(arg.element, usedIdentifiers, usedTypes);
663
- }
664
- }
665
- }
666
- // Check select (object being called on)
667
- if ((_g = methodInv.select) === null || _g === void 0 ? void 0 : _g.element) {
668
- await this.collectUsedIdentifiers(methodInv.select.element, usedIdentifiers, usedTypes);
669
- }
670
- }
671
- else if (node.kind === java_1.J.Kind.MemberReference) {
672
- const memberRef = node;
673
- if (memberRef.containing && ((_h = memberRef.containing.element) === null || _h === void 0 ? void 0 : _h.kind) === java_1.J.Kind.Identifier) {
674
- usedIdentifiers.add(memberRef.containing.element.simpleName);
675
- }
676
- }
677
- else if (node.kind === java_1.J.Kind.FieldAccess) {
678
- // Handle field access like fs.readFileSync
679
- const fieldAccess = node;
680
- if (((_j = fieldAccess.target) === null || _j === void 0 ? void 0 : _j.kind) === java_1.J.Kind.Identifier) {
681
- usedIdentifiers.add(fieldAccess.target.simpleName);
682
- }
683
- // Recursively check the target
684
- if (fieldAccess.target) {
685
- await this.collectUsedIdentifiers(fieldAccess.target, usedIdentifiers, usedTypes);
686
- }
687
- }
688
- else if (node.kind === tree_1.JS.Kind.CompilationUnit) {
689
- const cu = node;
690
- for (const stmt of cu.statements) {
691
- if (stmt.element && stmt.element.kind !== tree_1.JS.Kind.Import) {
692
- // Skip require() statements at the top level
693
- if (stmt.element.kind === java_1.J.Kind.VariableDeclarations) {
694
- const varDecls = stmt.element;
695
- // Check if this is a require() statement
696
- let isRequire = false;
697
- for (const v of varDecls.variables) {
698
- const namedVar = v.element;
699
- if (((_l = (_k = namedVar === null || namedVar === void 0 ? void 0 : namedVar.initializer) === null || _k === void 0 ? void 0 : _k.element) === null || _l === void 0 ? void 0 : _l.kind) === java_1.J.Kind.MethodInvocation) {
700
- const methodInv = namedVar.initializer.element;
701
- if (((_m = methodInv.name) === null || _m === void 0 ? void 0 : _m.kind) === java_1.J.Kind.Identifier &&
702
- methodInv.name.simpleName === 'require') {
703
- isRequire = true;
704
- break;
705
- }
706
- }
707
- }
708
- if (!isRequire) {
709
- // Not a require statement, process normally
710
- await this.collectUsedIdentifiers(stmt.element, usedIdentifiers, usedTypes);
711
- }
712
- }
713
- else if (stmt.element.kind !== tree_1.JS.Kind.ScopedVariableDeclarations) {
714
- // Process other non-import, non-require statements normally
715
- await this.collectUsedIdentifiers(stmt.element, usedIdentifiers, usedTypes);
716
- }
717
- }
718
- }
719
- }
720
- else if (node.kind === java_1.J.Kind.Return) {
721
- // Handle return statements
722
- const returnStmt = node;
723
- if (returnStmt.expression) {
724
- await this.collectUsedIdentifiers(returnStmt.expression, usedIdentifiers, usedTypes);
725
- }
726
- }
727
- else if (node.kind === java_1.J.Kind.Block) {
728
- const block = node;
729
- for (const stmt of block.statements) {
730
- if (stmt.element) {
731
- await this.collectUsedIdentifiers(stmt.element, usedIdentifiers, usedTypes);
732
- }
733
- }
734
- }
735
- else if (node.kind === java_1.J.Kind.MethodDeclaration) {
736
- const method = node;
737
- // Check parameters for type usage
738
- if (method.parameters) {
739
- for (const param of method.parameters.elements) {
740
- // Parameters can be various types, handle them recursively
741
- if (param.element) {
742
- await this.collectUsedIdentifiers(param.element, usedIdentifiers, usedTypes);
743
- }
744
- }
745
- }
746
- // Check body
747
- if (method.body) {
748
- await this.collectUsedIdentifiers(method.body, usedIdentifiers, usedTypes);
749
- }
750
- }
751
- else if (node.kind === tree_1.JS.Kind.TypeOf) {
752
- // Handle typeof expressions like: typeof util
753
- const typeOf = node;
754
- if (typeOf.expression) {
755
- await this.collectUsedIdentifiers(typeOf.expression, usedIdentifiers, usedTypes);
756
- }
757
- }
758
- else if (node.kind === tree_1.JS.Kind.TypeQuery) {
759
- // Handle typeof type queries like: const x: typeof util
760
- const typeQuery = node;
761
- if (typeQuery.typeExpression) {
762
- await this.collectUsedIdentifiers(typeQuery.typeExpression, usedIdentifiers, usedTypes);
763
- }
764
- }
765
- else if (node.typeExpression) {
766
- // Handle nodes with type expressions (parameters, variables, etc.)
767
- await this.checkTypeExpression(node, usedTypes);
768
- // Continue traversing other parts
769
- if (node.name) {
770
- await this.collectUsedIdentifiers(node.name, usedIdentifiers, usedTypes);
771
- }
772
- if (node.initializer) {
773
- await this.collectUsedIdentifiers(node.initializer, usedIdentifiers, usedTypes);
774
- }
775
- }
776
- else if (node.kind === tree_1.JS.Kind.ArrowFunction || node.kind === java_1.J.Kind.Lambda) {
777
- // Handle arrow functions and lambdas
778
- const func = node;
779
- if (func.parameters) {
780
- await this.collectUsedIdentifiers(func.parameters, usedIdentifiers, usedTypes);
781
- }
782
- if (func.lambda) {
783
- await this.collectUsedIdentifiers(func.lambda, usedIdentifiers, usedTypes);
784
- }
785
- if (func.body) {
786
- await this.collectUsedIdentifiers(func.body, usedIdentifiers, usedTypes);
787
- }
788
- }
789
- else if (node.kind === java_1.J.Kind.Lambda) {
790
- const lambda = node;
791
- if ((_o = lambda.parameters) === null || _o === void 0 ? void 0 : _o.parameters) {
792
- for (const param of lambda.parameters.parameters) {
793
- if (param.element) {
794
- await this.collectUsedIdentifiers(param.element, usedIdentifiers, usedTypes);
795
- }
796
- }
797
- }
798
- if (lambda.body) {
799
- await this.collectUsedIdentifiers(lambda.body, usedIdentifiers, usedTypes);
800
- }
801
- }
802
- else if (node.kind === tree_1.JS.Kind.JsxTag) {
803
- // Handle JSX tags like <div>content</div>
804
- const jsxTag = node;
805
- // Check attributes
806
- if (jsxTag.attributes) {
807
- for (const attr of jsxTag.attributes) {
808
- if (attr.element) {
809
- await this.collectUsedIdentifiers(attr.element, usedIdentifiers, usedTypes);
810
- }
811
- }
812
- }
813
- // Check children
814
- if (jsxTag.children) {
815
- for (const child of jsxTag.children) {
816
- if (child) {
817
- await this.collectUsedIdentifiers(child, usedIdentifiers, usedTypes);
818
- }
819
- }
820
- }
821
- }
822
- else if (node.kind === tree_1.JS.Kind.JsxEmbeddedExpression) {
823
- // Handle JSX embedded expressions like {React.version}
824
- const embedded = node;
825
- // The expression is wrapped in RightPadded, so unwrap it
826
- const expr = ((_q = embedded.expression) === null || _q === void 0 ? void 0 : _q.element) || embedded.expression;
827
- if (expr) {
828
- await this.collectUsedIdentifiers(expr, usedIdentifiers, usedTypes);
829
- }
830
- }
831
- else if (node.kind === tree_1.JS.Kind.JsxAttribute) {
832
- // Handle JSX attributes like onClick={handler}
833
- const jsxAttr = node;
834
- if (jsxAttr.value) {
835
- await this.collectUsedIdentifiers(jsxAttr.value, usedIdentifiers, usedTypes);
836
- }
837
- }
838
- else if (node.kind === tree_1.JS.Kind.TypeDeclaration) {
839
- // Handle type alias declarations like: type Props = { children: React.ReactNode }
840
- const typeDecl = node;
841
- // The initializer contains the type expression (the right side of the =)
842
- if ((_r = typeDecl.initializer) === null || _r === void 0 ? void 0 : _r.element) {
843
- await this.collectTypeUsage(typeDecl.initializer.element, usedTypes);
844
- }
845
- }
846
- else if (node.statements) {
847
- // Generic handler for nodes with statements
848
- await this.traverseStatements(node.statements, usedIdentifiers, usedTypes);
849
- }
850
- else if (node.body) {
851
- // Generic handler for nodes with body
852
- await this.collectUsedIdentifiers(node.body, usedIdentifiers, usedTypes);
853
- }
854
- else if (node.parameters) {
855
- // Handle anything with parameters (functions, methods, etc.)
856
- await this.traverseParameters(node.parameters, usedIdentifiers, usedTypes);
857
- // Continue with the body if it exists
858
- if (node.body) {
859
- await this.collectUsedIdentifiers(node.body, usedIdentifiers, usedTypes);
860
- }
861
- }
549
+ }
550
+ exports.RemoveImport = RemoveImport;
551
+ /**
552
+ * The names the file references, less its own imports: a specifier names what it binds, so counting
553
+ * one would read an import as a use of itself.
554
+ */
555
+ function collectUsedNames(cu) {
556
+ const used = new Set();
557
+ for (const statement of cu.statements) {
558
+ const element = statement.element;
559
+ if (!element || element.kind === tree_1.JS.Kind.Import) {
560
+ continue;
561
+ }
562
+ (0, scope_1.namesReferencedWithin)(element).forEach(name => used.add(name));
862
563
  }
863
- async collectTypeUsage(typeExpr, usedTypes) {
864
- var _a;
865
- if (typeExpr.kind === java_1.J.Kind.Identifier) {
866
- usedTypes.add(typeExpr.simpleName);
867
- }
868
- else if (typeExpr.kind === java_1.J.Kind.ParameterizedType) {
869
- const paramType = typeExpr;
870
- // First, collect usage from the base type (e.g., React.Ref from React.Ref<T>)
871
- if (paramType.class) {
872
- await this.collectTypeUsage(paramType.class, usedTypes);
873
- }
874
- // Then collect usage from type parameters (e.g., HTMLButtonElement from React.Ref<HTMLButtonElement>)
875
- if (paramType.typeParameters) {
876
- for (const typeParam of paramType.typeParameters.elements) {
877
- if (typeParam.element) {
878
- await this.collectTypeUsage(typeParam.element, usedTypes);
879
- }
880
- }
881
- }
882
- }
883
- else if (typeExpr.kind === java_1.J.Kind.FieldAccess) {
884
- // Handle qualified names in type positions like React.Ref
885
- const fieldAccess = typeExpr;
886
- if (((_a = fieldAccess.target) === null || _a === void 0 ? void 0 : _a.kind) === java_1.J.Kind.Identifier) {
887
- usedTypes.add(fieldAccess.target.simpleName);
888
- }
889
- else if (fieldAccess.target) {
890
- // Recursively handle nested field accesses
891
- await this.collectTypeUsage(fieldAccess.target, usedTypes);
892
- }
893
- }
894
- else if (typeExpr.kind === tree_1.JS.Kind.Intersection) {
895
- // Handle intersection types like ButtonProps & { ref?: React.Ref<HTMLButtonElement> }
896
- const intersection = typeExpr;
897
- for (const typeElem of intersection.types) {
898
- if (typeElem.element) {
899
- await this.collectTypeUsage(typeElem.element, usedTypes);
900
- }
901
- }
902
- }
903
- else if (typeExpr.kind === tree_1.JS.Kind.TypeLiteral) {
904
- // Handle type literals like { ref?: React.Ref<HTMLButtonElement> }
905
- const typeLiteral = typeExpr;
906
- // TypeLiteral members are in a Block, which contains statements
907
- for (const stmt of typeLiteral.members.statements) {
908
- if (stmt.element) {
909
- // Each statement is typically a VariableDeclarations representing a property
910
- await this.collectUsedIdentifiers(stmt.element, new Set(), usedTypes);
911
- }
912
- }
913
- }
914
- else if (typeExpr.kind === tree_1.JS.Kind.TypeQuery) {
915
- // Handle typeof type queries like: const x: typeof util
916
- const typeQuery = typeExpr;
917
- if (typeQuery.typeExpression) {
918
- await this.collectTypeUsage(typeQuery.typeExpression, usedTypes);
919
- }
920
- }
921
- else if (typeExpr.kind === tree_1.JS.Kind.TypeOf) {
922
- // Handle typeof expressions in types
923
- const typeOf = typeExpr;
924
- if (typeOf.expression) {
925
- // For typeof expressions, the expression contains the identifier
926
- // Add it to usedTypes since it's used in a type context
927
- if (typeOf.expression.kind === java_1.J.Kind.Identifier) {
928
- usedTypes.add(typeOf.expression.simpleName);
929
- }
930
- else {
931
- await this.collectTypeUsage(typeOf.expression, usedTypes);
932
- }
933
- }
934
- }
935
- else if (typeExpr.kind === tree_1.JS.Kind.TypeTreeExpression) {
936
- // Handle TypeTreeExpression which wraps type identifiers
937
- const typeTree = typeExpr;
938
- if (typeTree.expression) {
939
- await this.collectTypeUsage(typeTree.expression, usedTypes);
940
- }
941
- }
942
- else if (typeExpr.kind === tree_1.JS.Kind.TypeInfo) {
943
- // Handle TypeInfo which contains type identifiers
944
- const typeInfo = typeExpr;
945
- if (typeInfo.typeIdentifier) {
946
- await this.collectTypeUsage(typeInfo.typeIdentifier, usedTypes);
947
- }
948
- }
949
- else if (typeExpr.expression) {
950
- // Generic handler for nodes with expression property
951
- await this.collectTypeUsage(typeExpr.expression, usedTypes);
952
- }
953
- else if (typeExpr.typeIdentifier) {
954
- // Generic handler for nodes with typeIdentifier property
955
- await this.collectTypeUsage(typeExpr.typeIdentifier, usedTypes);
956
- }
957
- // Add more type expression handlers as needed
564
+ return used;
565
+ }
566
+ function isRequireCall(node) {
567
+ if (node.kind !== java_1.J.Kind.MethodInvocation) {
568
+ return false;
958
569
  }
570
+ const name = node.name;
571
+ return (name === null || name === void 0 ? void 0 : name.kind) === java_1.J.Kind.Identifier && name.simpleName === 'require';
959
572
  }
960
- exports.RemoveImport = RemoveImport;
961
573
  //# sourceMappingURL=remove-import.js.map