@openrewrite/rewrite 8.72.2 → 8.72.3

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 (197) hide show
  1. package/dist/execution.js +3 -16
  2. package/dist/execution.js.map +1 -1
  3. package/dist/index.js +34 -49
  4. package/dist/index.js.map +1 -1
  5. package/dist/java/markers.js +12 -29
  6. package/dist/java/markers.js.map +1 -1
  7. package/dist/java/print.js +2 -13
  8. package/dist/java/print.js.map +1 -1
  9. package/dist/java/rpc.js +1344 -1725
  10. package/dist/java/rpc.js.map +1 -1
  11. package/dist/java/type-visitor.js +143 -184
  12. package/dist/java/type-visitor.js.map +1 -1
  13. package/dist/java/visitor.js +1072 -1249
  14. package/dist/java/visitor.js.map +1 -1
  15. package/dist/javascript/add-import.js +495 -534
  16. package/dist/javascript/add-import.js.map +1 -1
  17. package/dist/javascript/autodetect.js +116 -159
  18. package/dist/javascript/autodetect.js.map +1 -1
  19. package/dist/javascript/cleanup/add-parse-int-radix.js +41 -57
  20. package/dist/javascript/cleanup/add-parse-int-radix.js.map +1 -1
  21. package/dist/javascript/cleanup/prefer-optional-chain.js +89 -105
  22. package/dist/javascript/cleanup/prefer-optional-chain.js.map +1 -1
  23. package/dist/javascript/cleanup/use-object-property-shorthand.js +74 -95
  24. package/dist/javascript/cleanup/use-object-property-shorthand.js.map +1 -1
  25. package/dist/javascript/comparator.js +815 -1167
  26. package/dist/javascript/comparator.js.map +1 -1
  27. package/dist/javascript/dependency-workspace.js +206 -219
  28. package/dist/javascript/dependency-workspace.js.map +1 -1
  29. package/dist/javascript/format/format.js +682 -908
  30. package/dist/javascript/format/format.js.map +1 -1
  31. package/dist/javascript/format/minimum-viable-spacing-visitor.js +152 -231
  32. package/dist/javascript/format/minimum-viable-spacing-visitor.js.map +1 -1
  33. package/dist/javascript/format/normalize-whitespace-visitor.js +12 -31
  34. package/dist/javascript/format/normalize-whitespace-visitor.js.map +1 -1
  35. package/dist/javascript/format/prettier-config-loader.js +134 -153
  36. package/dist/javascript/format/prettier-config-loader.js.map +1 -1
  37. package/dist/javascript/format/prettier-format.js +112 -129
  38. package/dist/javascript/format/prettier-format.js.map +1 -1
  39. package/dist/javascript/format/tabs-and-indents-visitor.js +112 -136
  40. package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
  41. package/dist/javascript/markers.js +59 -92
  42. package/dist/javascript/markers.js.map +1 -1
  43. package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js +39 -52
  44. package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js.map +1 -1
  45. package/dist/javascript/migrate/es6/modernize-octal-literals.js +25 -38
  46. package/dist/javascript/migrate/es6/modernize-octal-literals.js.map +1 -1
  47. package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js +66 -82
  48. package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js.map +1 -1
  49. package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js +10 -23
  50. package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js.map +1 -1
  51. package/dist/javascript/node-resolution-result.js +137 -166
  52. package/dist/javascript/node-resolution-result.js.map +1 -1
  53. package/dist/javascript/package-json-parser.js +312 -343
  54. package/dist/javascript/package-json-parser.js.map +1 -1
  55. package/dist/javascript/package-manager.js +145 -170
  56. package/dist/javascript/package-manager.js.map +1 -1
  57. package/dist/javascript/parser.d.ts.map +1 -1
  58. package/dist/javascript/parser.js +94 -68
  59. package/dist/javascript/parser.js.map +1 -1
  60. package/dist/javascript/print.js +1572 -1835
  61. package/dist/javascript/print.js.map +1 -1
  62. package/dist/javascript/project-parser.js +151 -172
  63. package/dist/javascript/project-parser.js.map +1 -1
  64. package/dist/javascript/recipes/add-dependency.js +140 -175
  65. package/dist/javascript/recipes/add-dependency.js.map +1 -1
  66. package/dist/javascript/recipes/async-callback-in-sync-array-method.js +20 -36
  67. package/dist/javascript/recipes/async-callback-in-sync-array-method.js.map +1 -1
  68. package/dist/javascript/recipes/auto-format.js +3 -14
  69. package/dist/javascript/recipes/auto-format.js.map +1 -1
  70. package/dist/javascript/recipes/change-import.js +447 -495
  71. package/dist/javascript/recipes/change-import.js.map +1 -1
  72. package/dist/javascript/recipes/order-imports.js +162 -175
  73. package/dist/javascript/recipes/order-imports.js.map +1 -1
  74. package/dist/javascript/recipes/upgrade-dependency-version.js +167 -197
  75. package/dist/javascript/recipes/upgrade-dependency-version.js.map +1 -1
  76. package/dist/javascript/recipes/upgrade-transitive-dependency-version.js +166 -193
  77. package/dist/javascript/recipes/upgrade-transitive-dependency-version.js.map +1 -1
  78. package/dist/javascript/remove-import.js +689 -724
  79. package/dist/javascript/remove-import.js.map +1 -1
  80. package/dist/javascript/rpc.js +1007 -1332
  81. package/dist/javascript/rpc.js.map +1 -1
  82. package/dist/javascript/search/find-dependency.js +84 -110
  83. package/dist/javascript/search/find-dependency.js.map +1 -1
  84. package/dist/javascript/search/uses-method.js +5 -19
  85. package/dist/javascript/search/uses-method.js.map +1 -1
  86. package/dist/javascript/search/uses-type.js +9 -20
  87. package/dist/javascript/search/uses-type.js.map +1 -1
  88. package/dist/javascript/templating/comparator.js +737 -822
  89. package/dist/javascript/templating/comparator.js.map +1 -1
  90. package/dist/javascript/templating/engine.js +211 -245
  91. package/dist/javascript/templating/engine.js.map +1 -1
  92. package/dist/javascript/templating/pattern.js +169 -190
  93. package/dist/javascript/templating/pattern.js.map +1 -1
  94. package/dist/javascript/templating/placeholder-replacement.js +172 -210
  95. package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
  96. package/dist/javascript/templating/rewrite.js +75 -97
  97. package/dist/javascript/templating/rewrite.js.map +1 -1
  98. package/dist/javascript/templating/template.js +69 -82
  99. package/dist/javascript/templating/template.js.map +1 -1
  100. package/dist/javascript/tree-debug.js +109 -137
  101. package/dist/javascript/tree-debug.js.map +1 -1
  102. package/dist/javascript/visitor.js +1090 -1254
  103. package/dist/javascript/visitor.js.map +1 -1
  104. package/dist/json/print.js +72 -103
  105. package/dist/json/print.js.map +1 -1
  106. package/dist/json/rpc.js +120 -181
  107. package/dist/json/rpc.js.map +1 -1
  108. package/dist/json/visitor.js +69 -100
  109. package/dist/json/visitor.js.map +1 -1
  110. package/dist/marketplace.js +20 -33
  111. package/dist/marketplace.js.map +1 -1
  112. package/dist/parse-error.js +41 -62
  113. package/dist/parse-error.js.map +1 -1
  114. package/dist/parser.js +7 -18
  115. package/dist/parser.js.map +1 -1
  116. package/dist/path-utils.js +46 -59
  117. package/dist/path-utils.js.map +1 -1
  118. package/dist/preconditions.js +30 -47
  119. package/dist/preconditions.js.map +1 -1
  120. package/dist/print.js +6 -19
  121. package/dist/print.js.map +1 -1
  122. package/dist/recipe.js +42 -73
  123. package/dist/recipe.js.map +1 -1
  124. package/dist/rpc/index.js +74 -115
  125. package/dist/rpc/index.js.map +1 -1
  126. package/dist/rpc/queue.js +71 -90
  127. package/dist/rpc/queue.js.map +1 -1
  128. package/dist/rpc/recipe.js +32 -57
  129. package/dist/rpc/recipe.js.map +1 -1
  130. package/dist/rpc/request/generate.js +4 -13
  131. package/dist/rpc/request/generate.js.map +1 -1
  132. package/dist/rpc/request/get-languages.js +2 -11
  133. package/dist/rpc/request/get-languages.js.map +1 -1
  134. package/dist/rpc/request/get-marketplace.js +9 -20
  135. package/dist/rpc/request/get-marketplace.js.map +1 -1
  136. package/dist/rpc/request/get-object.js +4 -13
  137. package/dist/rpc/request/get-object.js.map +1 -1
  138. package/dist/rpc/request/install-recipes.js +25 -36
  139. package/dist/rpc/request/install-recipes.js.map +1 -1
  140. package/dist/rpc/request/metrics.js +8 -17
  141. package/dist/rpc/request/metrics.js.map +1 -1
  142. package/dist/rpc/request/parse-project.js +36 -45
  143. package/dist/rpc/request/parse-project.js.map +1 -1
  144. package/dist/rpc/request/parse.js +5 -14
  145. package/dist/rpc/request/parse.js.map +1 -1
  146. package/dist/rpc/request/prepare-recipe.js +37 -52
  147. package/dist/rpc/request/prepare-recipe.js.map +1 -1
  148. package/dist/rpc/request/print.js +5 -14
  149. package/dist/rpc/request/print.js.map +1 -1
  150. package/dist/rpc/request/visit.js +56 -71
  151. package/dist/rpc/request/visit.js.map +1 -1
  152. package/dist/rpc/rewrite-rpc.js +70 -97
  153. package/dist/rpc/rewrite-rpc.js.map +1 -1
  154. package/dist/rpc/server.js +76 -89
  155. package/dist/rpc/server.js.map +1 -1
  156. package/dist/run.js +47 -66
  157. package/dist/run.js.map +1 -1
  158. package/dist/search/is-source-file.js +8 -19
  159. package/dist/search/is-source-file.js.map +1 -1
  160. package/dist/test/rewrite-test.js +154 -188
  161. package/dist/test/rewrite-test.js.map +1 -1
  162. package/dist/text/print.js +23 -38
  163. package/dist/text/print.js.map +1 -1
  164. package/dist/text/rpc.js +29 -44
  165. package/dist/text/rpc.js.map +1 -1
  166. package/dist/text/visitor.js +16 -33
  167. package/dist/text/visitor.js.map +1 -1
  168. package/dist/util.js +13 -24
  169. package/dist/util.js.map +1 -1
  170. package/dist/version.txt +1 -1
  171. package/dist/visitor.js +84 -115
  172. package/dist/visitor.js.map +1 -1
  173. package/dist/yaml/index.d.ts +2 -0
  174. package/dist/yaml/index.d.ts.map +1 -1
  175. package/dist/yaml/index.js +2 -0
  176. package/dist/yaml/index.js.map +1 -1
  177. package/dist/yaml/markers.d.ts +21 -0
  178. package/dist/yaml/markers.d.ts.map +1 -0
  179. package/dist/yaml/markers.js +37 -0
  180. package/dist/yaml/markers.js.map +1 -0
  181. package/dist/yaml/parser.d.ts.map +1 -1
  182. package/dist/yaml/parser.js +4 -1
  183. package/dist/yaml/parser.js.map +1 -1
  184. package/dist/yaml/print.d.ts +1 -1
  185. package/dist/yaml/print.d.ts.map +1 -1
  186. package/dist/yaml/print.js +175 -208
  187. package/dist/yaml/print.js.map +1 -1
  188. package/dist/yaml/rpc.js +154 -219
  189. package/dist/yaml/rpc.js.map +1 -1
  190. package/dist/yaml/visitor.js +78 -113
  191. package/dist/yaml/visitor.js.map +1 -1
  192. package/package.json +1 -1
  193. package/src/javascript/parser.ts +56 -14
  194. package/src/yaml/index.ts +2 -0
  195. package/src/yaml/markers.ts +70 -0
  196. package/src/yaml/parser.ts +5 -1
  197. package/src/yaml/print.ts +5 -2
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.AddImport = exports.ImportStyle = void 0;
13
4
  exports.maybeAddImport = maybeAddImport;
@@ -267,260 +258,254 @@ class AddImport extends visitor_1.JavaScriptVisitor {
267
258
  }
268
259
  return null;
269
260
  }
270
- visitJsCompilationUnit(compilationUnit, p) {
271
- return __awaiter(this, void 0, void 0, function* () {
272
- // First, check if the import already exists
273
- const hasImport = yield this.checkImportExists(compilationUnit);
274
- if (hasImport) {
261
+ async visitJsCompilationUnit(compilationUnit, p) {
262
+ // First, check if the import already exists
263
+ const hasImport = await this.checkImportExists(compilationUnit);
264
+ if (hasImport) {
265
+ return compilationUnit;
266
+ }
267
+ // If onlyIfReferenced is true, check if the identifier is actually used
268
+ // Skip this check for side-effect imports
269
+ if (!this.sideEffectOnly && this.onlyIfReferenced) {
270
+ const isReferenced = await this.checkIdentifierReferenced(compilationUnit);
271
+ if (!isReferenced) {
275
272
  return compilationUnit;
276
273
  }
277
- // If onlyIfReferenced is true, check if the identifier is actually used
278
- // Skip this check for side-effect imports
279
- if (!this.sideEffectOnly && this.onlyIfReferenced) {
280
- const isReferenced = yield this.checkIdentifierReferenced(compilationUnit);
281
- if (!isReferenced) {
282
- return compilationUnit;
283
- }
284
- }
285
- // Determine the appropriate import style
286
- const importStyle = this.determineImportStyle(compilationUnit);
287
- // For named imports, check if we can merge into an existing import from the same module
288
- // This handles both:
289
- // - Case 1: Existing import has named bindings - merge into them
290
- // - Case 2: Default import without named bindings - add named bindings
291
- // Don't try to merge default imports (member === 'default'), side-effect imports, or namespace imports (member === '*')
292
- if (!this.sideEffectOnly && this.member !== undefined && this.member !== 'default' && this.member !== '*') {
293
- const mergedCu = yield this.tryMergeIntoExistingImport(compilationUnit, p);
294
- if (mergedCu !== compilationUnit) {
295
- return mergedCu;
296
- }
274
+ }
275
+ // Determine the appropriate import style
276
+ const importStyle = this.determineImportStyle(compilationUnit);
277
+ // For named imports, check if we can merge into an existing import from the same module
278
+ // This handles both:
279
+ // - Case 1: Existing import has named bindings - merge into them
280
+ // - Case 2: Default import without named bindings - add named bindings
281
+ // Don't try to merge default imports (member === 'default'), side-effect imports, or namespace imports (member === '*')
282
+ if (!this.sideEffectOnly && this.member !== undefined && this.member !== 'default' && this.member !== '*') {
283
+ const mergedCu = await this.tryMergeIntoExistingImport(compilationUnit, p);
284
+ if (mergedCu !== compilationUnit) {
285
+ return mergedCu;
297
286
  }
298
- // Add the import using the appropriate style
299
- if (importStyle === ImportStyle.CommonJS) {
300
- // TODO: Implement CommonJS require creation
301
- // For now, fall back to ES6 imports
302
- // return this.addCommonJSRequire(compilationUnit, p);
287
+ }
288
+ // Add the import using the appropriate style
289
+ if (importStyle === ImportStyle.CommonJS) {
290
+ // TODO: Implement CommonJS require creation
291
+ // For now, fall back to ES6 imports
292
+ // return this.addCommonJSRequire(compilationUnit, p);
293
+ }
294
+ // Add ES6 import (handles ES6Named, ES6Namespace, ES6Default)
295
+ return this.produceJavaScript(compilationUnit, p, async (draft) => {
296
+ // Find the position to insert the import
297
+ const insertionIndex = this.findImportInsertionIndex(compilationUnit);
298
+ const newImport = await this.createImportStatement(compilationUnit, insertionIndex, p);
299
+ // Insert the import at the appropriate position
300
+ // Create semicolon marker for the import statement
301
+ const semicolonMarkers = (0, markers_1.markers)({
302
+ kind: java_1.J.Markers.Semicolon,
303
+ id: (0, uuid_1.randomId)()
304
+ });
305
+ if (insertionIndex === 0) {
306
+ // Insert at the beginning
307
+ // The `after` space should be empty since semicolon is printed after it
308
+ // The spacing comes from updating the next statement's prefix
309
+ const updatedStatements = compilationUnit.statements.length > 0
310
+ ? [
311
+ (0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
312
+ Object.assign(Object.assign({}, compilationUnit.statements[0]), { element: compilationUnit.statements[0].element
313
+ ? Object.assign(Object.assign({}, compilationUnit.statements[0].element), { prefix: (0, java_1.space)("\n\n") }) : undefined }),
314
+ ...compilationUnit.statements.slice(1)
315
+ ]
316
+ : [(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers)];
317
+ draft.statements = updatedStatements;
303
318
  }
304
- // Add ES6 import (handles ES6Named, ES6Namespace, ES6Default)
305
- return this.produceJavaScript(compilationUnit, p, (draft) => __awaiter(this, void 0, void 0, function* () {
306
- // Find the position to insert the import
307
- const insertionIndex = this.findImportInsertionIndex(compilationUnit);
308
- const newImport = yield this.createImportStatement(compilationUnit, insertionIndex, p);
309
- // Insert the import at the appropriate position
310
- // Create semicolon marker for the import statement
311
- const semicolonMarkers = (0, markers_1.markers)({
312
- kind: java_1.J.Markers.Semicolon,
313
- id: (0, uuid_1.randomId)()
314
- });
315
- if (insertionIndex === 0) {
316
- // Insert at the beginning
317
- // The `after` space should be empty since semicolon is printed after it
318
- // The spacing comes from updating the next statement's prefix
319
- const updatedStatements = compilationUnit.statements.length > 0
320
- ? [
321
- (0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
322
- Object.assign(Object.assign({}, compilationUnit.statements[0]), { element: compilationUnit.statements[0].element
323
- ? Object.assign(Object.assign({}, compilationUnit.statements[0].element), { prefix: (0, java_1.space)("\n\n") }) : undefined }),
324
- ...compilationUnit.statements.slice(1)
325
- ]
326
- : [(0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers)];
327
- draft.statements = updatedStatements;
319
+ else {
320
+ // Insert after existing imports
321
+ const before = compilationUnit.statements.slice(0, insertionIndex);
322
+ const after = compilationUnit.statements.slice(insertionIndex);
323
+ //The `after` space is empty, spacing comes from next statement's prefix
324
+ // Ensure the next statement has at least one newline in its prefix
325
+ if (after.length > 0 && after[0].element) {
326
+ const currentPrefix = after[0].element.prefix;
327
+ const needsNewline = !currentPrefix.whitespace.includes('\n');
328
+ const updatedNextStatement = needsNewline ? Object.assign(Object.assign({}, after[0]), { element: Object.assign(Object.assign({}, after[0].element), { prefix: (0, java_1.space)("\n" + currentPrefix.whitespace) }) }) : after[0];
329
+ draft.statements = [
330
+ ...before,
331
+ (0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
332
+ updatedNextStatement,
333
+ ...after.slice(1)
334
+ ];
328
335
  }
329
336
  else {
330
- // Insert after existing imports
331
- const before = compilationUnit.statements.slice(0, insertionIndex);
332
- const after = compilationUnit.statements.slice(insertionIndex);
333
- //The `after` space is empty, spacing comes from next statement's prefix
334
- // Ensure the next statement has at least one newline in its prefix
335
- if (after.length > 0 && after[0].element) {
336
- const currentPrefix = after[0].element.prefix;
337
- const needsNewline = !currentPrefix.whitespace.includes('\n');
338
- const updatedNextStatement = needsNewline ? Object.assign(Object.assign({}, after[0]), { element: Object.assign(Object.assign({}, after[0].element), { prefix: (0, java_1.space)("\n" + currentPrefix.whitespace) }) }) : after[0];
339
- draft.statements = [
340
- ...before,
341
- (0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
342
- updatedNextStatement,
343
- ...after.slice(1)
344
- ];
345
- }
346
- else {
347
- draft.statements = [
348
- ...before,
349
- (0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
350
- ...after
351
- ];
352
- }
337
+ draft.statements = [
338
+ ...before,
339
+ (0, java_1.rightPadded)(newImport, java_1.emptySpace, semicolonMarkers),
340
+ ...after
341
+ ];
353
342
  }
354
- }));
343
+ }
355
344
  });
356
345
  }
357
346
  /**
358
347
  * Try to merge the new member into an existing import from the same module
359
348
  */
360
- tryMergeIntoExistingImport(compilationUnit, p) {
361
- return __awaiter(this, void 0, void 0, function* () {
362
- var _a;
363
- for (let i = 0; i < compilationUnit.statements.length; i++) {
364
- const stmt = compilationUnit.statements[i];
365
- const statement = stmt.element;
366
- if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
367
- const jsImport = statement;
368
- const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
369
- if (!moduleSpecifier) {
370
- continue;
371
- }
372
- const moduleName = this.getModuleName(moduleSpecifier);
373
- // Check if this is an import from our target module
374
- if (moduleName !== this.module) {
375
- continue;
376
- }
377
- const importClause = jsImport.importClause;
378
- if (!importClause) {
379
- continue;
380
- }
381
- // Only merge into imports with matching typeOnly - don't mix type and value imports
382
- if (importClause.typeOnly !== this.typeOnly) {
349
+ async tryMergeIntoExistingImport(compilationUnit, p) {
350
+ var _a;
351
+ for (let i = 0; i < compilationUnit.statements.length; i++) {
352
+ const stmt = compilationUnit.statements[i];
353
+ const statement = stmt.element;
354
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
355
+ const jsImport = statement;
356
+ const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
357
+ if (!moduleSpecifier) {
358
+ continue;
359
+ }
360
+ const moduleName = this.getModuleName(moduleSpecifier);
361
+ // Check if this is an import from our target module
362
+ if (moduleName !== this.module) {
363
+ continue;
364
+ }
365
+ const importClause = jsImport.importClause;
366
+ if (!importClause) {
367
+ continue;
368
+ }
369
+ // Only merge into imports with matching typeOnly - don't mix type and value imports
370
+ if (importClause.typeOnly !== this.typeOnly) {
371
+ continue;
372
+ }
373
+ // Case 1: Existing import has named bindings - merge into them
374
+ if (importClause.namedBindings) {
375
+ // Only merge into NamedImports, not namespace imports
376
+ if (importClause.namedBindings.kind !== tree_1.JS.Kind.NamedImports) {
383
377
  continue;
384
378
  }
385
- // Case 1: Existing import has named bindings - merge into them
386
- if (importClause.namedBindings) {
387
- // Only merge into NamedImports, not namespace imports
388
- if (importClause.namedBindings.kind !== tree_1.JS.Kind.NamedImports) {
389
- continue;
390
- }
391
- // We found a matching import with named bindings - merge into it
392
- return this.produceJavaScript(compilationUnit, p, (draft) => __awaiter(this, void 0, void 0, function* () {
393
- var _a, _b, _c;
394
- const namedImports = importClause.namedBindings;
395
- const existingElements = namedImports.elements.elements;
396
- // Find the correct insertion position (alphabetical, case-insensitive)
397
- const newName = (this.alias || this.member).toLowerCase();
398
- let insertIndex = existingElements.findIndex(elem => {
399
- var _a;
400
- if (((_a = elem.element) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.ImportSpecifier) {
401
- const name = this.getImportAlias(elem.element) || this.getImportName(elem.element);
402
- return newName.localeCompare(name.toLowerCase()) < 0;
379
+ // We found a matching import with named bindings - merge into it
380
+ return this.produceJavaScript(compilationUnit, p, async (draft) => {
381
+ var _a, _b, _c;
382
+ const namedImports = importClause.namedBindings;
383
+ const existingElements = namedImports.elements.elements;
384
+ // Find the correct insertion position (alphabetical, case-insensitive)
385
+ const newName = (this.alias || this.member).toLowerCase();
386
+ let insertIndex = existingElements.findIndex(elem => {
387
+ var _a;
388
+ if (((_a = elem.element) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.ImportSpecifier) {
389
+ const name = this.getImportAlias(elem.element) || this.getImportName(elem.element);
390
+ return newName.localeCompare(name.toLowerCase()) < 0;
391
+ }
392
+ return false;
393
+ });
394
+ if (insertIndex === -1)
395
+ insertIndex = existingElements.length;
396
+ // Detect spacing style from existing elements:
397
+ // - firstElementPrefix: space after { (from first element's prefix)
398
+ // - trailingSpace: space before } (from last element's after)
399
+ const firstElementPrefix = (_c = (_b = (_a = existingElements[0]) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.prefix) !== null && _c !== void 0 ? _c : java_1.emptySpace;
400
+ const lastIndex = existingElements.length - 1;
401
+ const trailingSpace = existingElements[lastIndex].after;
402
+ // Build the new elements array with proper spacing
403
+ const updatedNamedImports = await this.produceJavaScript(namedImports, p, async (namedDraft) => {
404
+ const newSpecifier = this.createImportSpecifier();
405
+ const newElements = existingElements.flatMap((elem, j) => {
406
+ const results = [];
407
+ if (j === insertIndex) {
408
+ // Insert new element here
409
+ // First element gets the same prefix as the original first element
410
+ // Other positions get a single space (separator after comma)
411
+ const prefix = j === 0 ? firstElementPrefix : java_1.singleSpace;
412
+ results.push((0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix }), java_1.emptySpace));
403
413
  }
404
- return false;
405
- });
406
- if (insertIndex === -1)
407
- insertIndex = existingElements.length;
408
- // Detect spacing style from existing elements:
409
- // - firstElementPrefix: space after { (from first element's prefix)
410
- // - trailingSpace: space before } (from last element's after)
411
- const firstElementPrefix = (_c = (_b = (_a = existingElements[0]) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.prefix) !== null && _c !== void 0 ? _c : java_1.emptySpace;
412
- const lastIndex = existingElements.length - 1;
413
- const trailingSpace = existingElements[lastIndex].after;
414
- // Build the new elements array with proper spacing
415
- const updatedNamedImports = yield this.produceJavaScript(namedImports, p, (namedDraft) => __awaiter(this, void 0, void 0, function* () {
416
- const newSpecifier = this.createImportSpecifier();
417
- const newElements = existingElements.flatMap((elem, j) => {
418
- const results = [];
419
- if (j === insertIndex) {
420
- // Insert new element here
421
- // First element gets the same prefix as the original first element
422
- // Other positions get a single space (separator after comma)
423
- const prefix = j === 0 ? firstElementPrefix : java_1.singleSpace;
424
- results.push((0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix }), java_1.emptySpace));
425
- }
426
- // Adjust existing element: if inserting before first, give it space prefix
427
- let adjusted = elem;
428
- if (j === 0 && insertIndex === 0 && elem.element) {
429
- adjusted = Object.assign(Object.assign({}, elem), { element: Object.assign(Object.assign({}, elem.element), { prefix: java_1.singleSpace }) });
430
- }
431
- // Last element before a new trailing element loses its trailing space
432
- if (j === lastIndex && insertIndex > lastIndex) {
433
- adjusted = Object.assign(Object.assign({}, adjusted), { after: java_1.emptySpace });
434
- }
435
- results.push(adjusted);
436
- return results;
437
- });
438
- // Append at end if inserting after all existing elements
439
- if (insertIndex > lastIndex) {
440
- newElements.push((0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix: java_1.singleSpace }), trailingSpace));
414
+ // Adjust existing element: if inserting before first, give it space prefix
415
+ let adjusted = elem;
416
+ if (j === 0 && insertIndex === 0 && elem.element) {
417
+ adjusted = Object.assign(Object.assign({}, elem), { element: Object.assign(Object.assign({}, elem.element), { prefix: java_1.singleSpace }) });
441
418
  }
442
- namedDraft.elements = Object.assign(Object.assign({}, namedImports.elements), { elements: newElements });
443
- }));
444
- // Update the import with the new named imports
445
- const updatedImport = yield this.produceJavaScript(jsImport, p, (importDraft) => __awaiter(this, void 0, void 0, function* () {
446
- importDraft.importClause = yield this.produceJavaScript(importClause, p, (clauseDraft) => __awaiter(this, void 0, void 0, function* () {
447
- clauseDraft.namedBindings = updatedNamedImports;
448
- }));
449
- }));
450
- // Replace the statement in the compilation unit
451
- draft.statements = compilationUnit.statements.map((s, idx) => idx === i ? Object.assign(Object.assign({}, s), { element: updatedImport }) : s);
452
- }));
453
- }
454
- // Case 2: Default import without named bindings - add named bindings
455
- // Transform: import React from 'react' -> import React, { useState } from 'react'
456
- if (importClause.name && !importClause.namedBindings) {
457
- return this.produceJavaScript(compilationUnit, p, (draft) => __awaiter(this, void 0, void 0, function* () {
458
- const newSpecifier = this.createImportSpecifier();
459
- // Get the spaces style for brace spacing
460
- const spacesStyle = (0, style_1.getStyle)(style_1.StyleKind.SpacesStyle, compilationUnit);
461
- const braceSpace = spacesStyle.within.es6ImportExportBraces ? java_1.singleSpace : java_1.emptySpace;
462
- // Create new NamedImports with a single element
463
- // Apply brace spacing: space after { is in specifier's prefix, space before } is in after
464
- const namedImports = {
465
- id: (0, uuid_1.randomId)(),
466
- kind: tree_1.JS.Kind.NamedImports,
467
- prefix: java_1.singleSpace,
468
- markers: markers_1.emptyMarkers,
469
- elements: {
470
- kind: java_1.J.Kind.Container,
471
- before: java_1.emptySpace,
472
- elements: [(0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix: braceSpace }), braceSpace)],
473
- markers: markers_1.emptyMarkers
419
+ // Last element before a new trailing element loses its trailing space
420
+ if (j === lastIndex && insertIndex > lastIndex) {
421
+ adjusted = Object.assign(Object.assign({}, adjusted), { after: java_1.emptySpace });
474
422
  }
475
- };
476
- // Update the import clause to include named bindings
477
- // Also update name.after to emptySpace since the comma goes right after the name
478
- const updatedImport = yield this.produceJavaScript(jsImport, p, (importDraft) => __awaiter(this, void 0, void 0, function* () {
479
- importDraft.importClause = yield this.produceJavaScript(importClause, p, (clauseDraft) => __awaiter(this, void 0, void 0, function* () {
480
- // Remove space after default name (comma goes right after)
481
- if (clauseDraft.name) {
482
- clauseDraft.name = Object.assign(Object.assign({}, clauseDraft.name), { after: java_1.emptySpace });
483
- }
484
- clauseDraft.namedBindings = namedImports;
485
- }));
486
- // Ensure moduleSpecifier has proper space before 'from'
487
- if (importDraft.moduleSpecifier) {
488
- importDraft.moduleSpecifier = Object.assign(Object.assign({}, importDraft.moduleSpecifier), { before: java_1.singleSpace });
423
+ results.push(adjusted);
424
+ return results;
425
+ });
426
+ // Append at end if inserting after all existing elements
427
+ if (insertIndex > lastIndex) {
428
+ newElements.push((0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix: java_1.singleSpace }), trailingSpace));
429
+ }
430
+ namedDraft.elements = Object.assign(Object.assign({}, namedImports.elements), { elements: newElements });
431
+ });
432
+ // Update the import with the new named imports
433
+ const updatedImport = await this.produceJavaScript(jsImport, p, async (importDraft) => {
434
+ importDraft.importClause = await this.produceJavaScript(importClause, p, async (clauseDraft) => {
435
+ clauseDraft.namedBindings = updatedNamedImports;
436
+ });
437
+ });
438
+ // Replace the statement in the compilation unit
439
+ draft.statements = compilationUnit.statements.map((s, idx) => idx === i ? Object.assign(Object.assign({}, s), { element: updatedImport }) : s);
440
+ });
441
+ }
442
+ // Case 2: Default import without named bindings - add named bindings
443
+ // Transform: import React from 'react' -> import React, { useState } from 'react'
444
+ if (importClause.name && !importClause.namedBindings) {
445
+ return this.produceJavaScript(compilationUnit, p, async (draft) => {
446
+ const newSpecifier = this.createImportSpecifier();
447
+ // Get the spaces style for brace spacing
448
+ const spacesStyle = (0, style_1.getStyle)(style_1.StyleKind.SpacesStyle, compilationUnit);
449
+ const braceSpace = spacesStyle.within.es6ImportExportBraces ? java_1.singleSpace : java_1.emptySpace;
450
+ // Create new NamedImports with a single element
451
+ // Apply brace spacing: space after { is in specifier's prefix, space before } is in after
452
+ const namedImports = {
453
+ id: (0, uuid_1.randomId)(),
454
+ kind: tree_1.JS.Kind.NamedImports,
455
+ prefix: java_1.singleSpace,
456
+ markers: markers_1.emptyMarkers,
457
+ elements: {
458
+ kind: java_1.J.Kind.Container,
459
+ before: java_1.emptySpace,
460
+ elements: [(0, java_1.rightPadded)(Object.assign(Object.assign({}, newSpecifier), { prefix: braceSpace }), braceSpace)],
461
+ markers: markers_1.emptyMarkers
462
+ }
463
+ };
464
+ // Update the import clause to include named bindings
465
+ // Also update name.after to emptySpace since the comma goes right after the name
466
+ const updatedImport = await this.produceJavaScript(jsImport, p, async (importDraft) => {
467
+ importDraft.importClause = await this.produceJavaScript(importClause, p, async (clauseDraft) => {
468
+ // Remove space after default name (comma goes right after)
469
+ if (clauseDraft.name) {
470
+ clauseDraft.name = Object.assign(Object.assign({}, clauseDraft.name), { after: java_1.emptySpace });
489
471
  }
490
- }));
491
- // Replace the statement in the compilation unit
492
- draft.statements = compilationUnit.statements.map((s, idx) => idx === i ? Object.assign(Object.assign({}, s), { element: updatedImport }) : s);
493
- }));
494
- }
472
+ clauseDraft.namedBindings = namedImports;
473
+ });
474
+ // Ensure moduleSpecifier has proper space before 'from'
475
+ if (importDraft.moduleSpecifier) {
476
+ importDraft.moduleSpecifier = Object.assign(Object.assign({}, importDraft.moduleSpecifier), { before: java_1.singleSpace });
477
+ }
478
+ });
479
+ // Replace the statement in the compilation unit
480
+ draft.statements = compilationUnit.statements.map((s, idx) => idx === i ? Object.assign(Object.assign({}, s), { element: updatedImport }) : s);
481
+ });
495
482
  }
496
483
  }
497
- return compilationUnit;
498
- });
484
+ }
485
+ return compilationUnit;
499
486
  }
500
487
  /**
501
488
  * Check if the import already exists in the compilation unit
502
489
  */
503
- checkImportExists(compilationUnit) {
504
- return __awaiter(this, void 0, void 0, function* () {
505
- for (const stmt of compilationUnit.statements) {
506
- const statement = stmt.element;
507
- // Check ES6 imports
508
- if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
509
- const jsImport = statement;
510
- if (this.isMatchingImport(jsImport)) {
511
- return true;
512
- }
490
+ async checkImportExists(compilationUnit) {
491
+ for (const stmt of compilationUnit.statements) {
492
+ const statement = stmt.element;
493
+ // Check ES6 imports
494
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
495
+ const jsImport = statement;
496
+ if (this.isMatchingImport(jsImport)) {
497
+ return true;
513
498
  }
514
- // Check CommonJS require statements
515
- if ((statement === null || statement === void 0 ? void 0 : statement.kind) === java_1.J.Kind.VariableDeclarations) {
516
- const varDecl = statement;
517
- if (this.isMatchingRequire(varDecl)) {
518
- return true;
519
- }
499
+ }
500
+ // Check CommonJS require statements
501
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === java_1.J.Kind.VariableDeclarations) {
502
+ const varDecl = statement;
503
+ if (this.isMatchingRequire(varDecl)) {
504
+ return true;
520
505
  }
521
506
  }
522
- return false;
523
- });
507
+ }
508
+ return false;
524
509
  }
525
510
  /**
526
511
  * Check if the import matches what we're trying to add
@@ -714,335 +699,311 @@ class AddImport extends visitor_1.JavaScriptVisitor {
714
699
  /**
715
700
  * Check if the identifier is actually referenced in the file
716
701
  */
717
- checkIdentifierReferenced(compilationUnit) {
718
- return __awaiter(this, void 0, void 0, function* () {
719
- var _a, _b, _c, _d, _e;
720
- // For namespace imports, we cannot use type attribution to detect usage
721
- // because the namespace itself is used as an identifier, not individual members.
722
- // For simplicity, we skip the onlyIfReferenced check for namespace imports.
723
- if (this.member === '*') {
724
- // TODO: Implement proper namespace usage detection by checking if alias identifier is used
725
- return true;
726
- }
727
- // Step 1: Find the expected declaring type by examining existing imports from the same module
728
- let expectedDeclaringType;
729
- for (const stmt of compilationUnit.statements) {
730
- const statement = stmt.element;
731
- if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
732
- const jsImport = statement;
733
- const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
734
- if (!moduleSpecifier) {
735
- continue;
736
- }
737
- const moduleName = this.getModuleName(moduleSpecifier);
738
- if (moduleName !== this.module) {
739
- continue; // Not the module we're interested in
740
- }
741
- // Found an existing import from our target module
742
- // Extract the declaring type from any imported member with type attribution
743
- const importClause = jsImport.importClause;
744
- if (((_b = importClause === null || importClause === void 0 ? void 0 : importClause.namedBindings) === null || _b === void 0 ? void 0 : _b.kind) === tree_1.JS.Kind.NamedImports) {
745
- const namedImports = importClause.namedBindings;
746
- for (const elem of namedImports.elements.elements) {
747
- const specifier = elem.element;
748
- if ((specifier === null || specifier === void 0 ? void 0 : specifier.kind) === tree_1.JS.Kind.ImportSpecifier) {
749
- const importSpec = specifier;
750
- let identifier;
751
- if (((_c = importSpec.specifier) === null || _c === void 0 ? void 0 : _c.kind) === java_1.J.Kind.Identifier) {
752
- identifier = importSpec.specifier;
753
- }
754
- else if (((_d = importSpec.specifier) === null || _d === void 0 ? void 0 : _d.kind) === tree_1.JS.Kind.Alias) {
755
- const aliasSpec = importSpec.specifier;
756
- if (((_e = aliasSpec.alias) === null || _e === void 0 ? void 0 : _e.kind) === java_1.J.Kind.Identifier) {
757
- identifier = aliasSpec.alias;
758
- }
759
- }
760
- expectedDeclaringType = this.getModuleFromType(identifier === null || identifier === void 0 ? void 0 : identifier.type, identifier === null || identifier === void 0 ? void 0 : identifier.fieldType);
761
- if (expectedDeclaringType) {
762
- break; // Found it!
702
+ async checkIdentifierReferenced(compilationUnit) {
703
+ var _a, _b, _c, _d, _e;
704
+ // For namespace imports, we cannot use type attribution to detect usage
705
+ // because the namespace itself is used as an identifier, not individual members.
706
+ // For simplicity, we skip the onlyIfReferenced check for namespace imports.
707
+ if (this.member === '*') {
708
+ // TODO: Implement proper namespace usage detection by checking if alias identifier is used
709
+ return true;
710
+ }
711
+ // Step 1: Find the expected declaring type by examining existing imports from the same module
712
+ let expectedDeclaringType;
713
+ for (const stmt of compilationUnit.statements) {
714
+ const statement = stmt.element;
715
+ if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
716
+ const jsImport = statement;
717
+ const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
718
+ if (!moduleSpecifier) {
719
+ continue;
720
+ }
721
+ const moduleName = this.getModuleName(moduleSpecifier);
722
+ if (moduleName !== this.module) {
723
+ continue; // Not the module we're interested in
724
+ }
725
+ // Found an existing import from our target module
726
+ // Extract the declaring type from any imported member with type attribution
727
+ const importClause = jsImport.importClause;
728
+ if (((_b = importClause === null || importClause === void 0 ? void 0 : importClause.namedBindings) === null || _b === void 0 ? void 0 : _b.kind) === tree_1.JS.Kind.NamedImports) {
729
+ const namedImports = importClause.namedBindings;
730
+ for (const elem of namedImports.elements.elements) {
731
+ const specifier = elem.element;
732
+ if ((specifier === null || specifier === void 0 ? void 0 : specifier.kind) === tree_1.JS.Kind.ImportSpecifier) {
733
+ const importSpec = specifier;
734
+ let identifier;
735
+ if (((_c = importSpec.specifier) === null || _c === void 0 ? void 0 : _c.kind) === java_1.J.Kind.Identifier) {
736
+ identifier = importSpec.specifier;
737
+ }
738
+ else if (((_d = importSpec.specifier) === null || _d === void 0 ? void 0 : _d.kind) === tree_1.JS.Kind.Alias) {
739
+ const aliasSpec = importSpec.specifier;
740
+ if (((_e = aliasSpec.alias) === null || _e === void 0 ? void 0 : _e.kind) === java_1.J.Kind.Identifier) {
741
+ identifier = aliasSpec.alias;
763
742
  }
764
743
  }
744
+ expectedDeclaringType = this.getModuleFromType(identifier === null || identifier === void 0 ? void 0 : identifier.type, identifier === null || identifier === void 0 ? void 0 : identifier.fieldType);
745
+ if (expectedDeclaringType) {
746
+ break; // Found it!
747
+ }
765
748
  }
766
749
  }
767
- if (expectedDeclaringType) {
768
- break; // No need to scan more imports
769
- }
750
+ }
751
+ if (expectedDeclaringType) {
752
+ break; // No need to scan more imports
770
753
  }
771
754
  }
772
- // Step 2: Look for references that match
773
- const targetName = this.alias || this.member;
774
- const targetModule = this.module;
775
- let found = false;
776
- const self = this;
777
- // If no existing imports from this module, look for unresolved references
778
- // If there ARE existing imports, look for references with the expected declaring type
779
- const collector = new class extends visitor_1.JavaScriptVisitor {
780
- visitIdentifier(identifier, p) {
781
- const _super = Object.create(null, {
782
- visitIdentifier: { get: () => super.visitIdentifier }
783
- });
784
- return __awaiter(this, void 0, void 0, function* () {
785
- if (identifier.simpleName === targetName) {
786
- const type = identifier.type;
787
- const fieldType = identifier.fieldType;
788
- if (expectedDeclaringType) {
789
- // We have an expected declaring type - check for exact match
790
- if (type && java_1.Type.isMethod(type)) {
791
- const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(type.declaringType);
792
- if (declaringTypeName === expectedDeclaringType) {
793
- found = true;
794
- }
795
- }
796
- else if (type && java_1.Type.isClass(type)) {
797
- if (self.classTypeMatchesModule(type, expectedDeclaringType)) {
798
- found = true;
799
- }
800
- }
801
- else if ((fieldType === null || fieldType === void 0 ? void 0 : fieldType.kind) === java_1.Type.Kind.Variable) {
802
- const ownerTypeName = fieldType.owner
803
- ? java_1.Type.FullyQualified.getFullyQualifiedName(fieldType.owner)
804
- : undefined;
805
- if (ownerTypeName === expectedDeclaringType) {
806
- found = true;
807
- }
755
+ }
756
+ // Step 2: Look for references that match
757
+ const targetName = this.alias || this.member;
758
+ const targetModule = this.module;
759
+ let found = false;
760
+ const self = this;
761
+ // If no existing imports from this module, look for unresolved references
762
+ // If there ARE existing imports, look for references with the expected declaring type
763
+ const collector = new class extends visitor_1.JavaScriptVisitor {
764
+ async visitIdentifier(identifier, p) {
765
+ if (identifier.simpleName === targetName) {
766
+ const type = identifier.type;
767
+ const fieldType = identifier.fieldType;
768
+ if (expectedDeclaringType) {
769
+ // We have an expected declaring type - check for exact match
770
+ if (type && java_1.Type.isMethod(type)) {
771
+ const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(type.declaringType);
772
+ if (declaringTypeName === expectedDeclaringType) {
773
+ found = true;
774
+ }
775
+ }
776
+ else if (type && java_1.Type.isClass(type)) {
777
+ if (self.classTypeMatchesModule(type, expectedDeclaringType)) {
778
+ found = true;
779
+ }
780
+ }
781
+ else if ((fieldType === null || fieldType === void 0 ? void 0 : fieldType.kind) === java_1.Type.Kind.Variable) {
782
+ const ownerTypeName = fieldType.owner
783
+ ? java_1.Type.FullyQualified.getFullyQualifiedName(fieldType.owner)
784
+ : undefined;
785
+ if (ownerTypeName === expectedDeclaringType) {
786
+ found = true;
787
+ }
788
+ }
789
+ // Also check for unresolved references (member isn't imported yet)
790
+ else if (!type && !fieldType) {
791
+ found = true;
792
+ }
793
+ }
794
+ else {
795
+ // No existing imports from this module - look for references that match
796
+ // 1. Unresolved references (no type/unknown type and no fieldType)
797
+ const isUnknownType = !type || type.kind === java_1.Type.Kind.Unknown;
798
+ if (isUnknownType && !fieldType) {
799
+ found = true;
800
+ }
801
+ // 2. References with fieldType matching the target module
802
+ else if ((fieldType === null || fieldType === void 0 ? void 0 : fieldType.kind) === java_1.Type.Kind.Variable) {
803
+ const variableType = fieldType;
804
+ if (variableType.owner && java_1.Type.isClass(variableType.owner)) {
805
+ // Traverse owningClass chain to find the root module (handles nested namespaces)
806
+ // For example: React.forwardRef -> owner is "React" namespace -> owningClass is "react" module
807
+ let current = variableType.owner;
808
+ // Walk up the owningClass chain until we reach the root
809
+ while (current.owningClass && java_1.Type.isClass(current.owningClass)) {
810
+ current = current.owningClass;
808
811
  }
809
- // Also check for unresolved references (member isn't imported yet)
810
- else if (!type && !fieldType) {
812
+ const moduleName = java_1.Type.FullyQualified.getFullyQualifiedName(current);
813
+ if (moduleName === targetModule) {
811
814
  found = true;
812
815
  }
813
816
  }
814
- else {
815
- // No existing imports from this module - look for references that match
816
- // 1. Unresolved references (no type/unknown type and no fieldType)
817
- const isUnknownType = !type || type.kind === java_1.Type.Kind.Unknown;
818
- if (isUnknownType && !fieldType) {
819
- found = true;
820
- }
821
- // 2. References with fieldType matching the target module
822
- else if ((fieldType === null || fieldType === void 0 ? void 0 : fieldType.kind) === java_1.Type.Kind.Variable) {
823
- const variableType = fieldType;
824
- if (variableType.owner && java_1.Type.isClass(variableType.owner)) {
825
- // Traverse owningClass chain to find the root module (handles nested namespaces)
826
- // For example: React.forwardRef -> owner is "React" namespace -> owningClass is "react" module
827
- let current = variableType.owner;
828
- // Walk up the owningClass chain until we reach the root
829
- while (current.owningClass && java_1.Type.isClass(current.owningClass)) {
830
- current = current.owningClass;
831
- }
832
- const moduleName = java_1.Type.FullyQualified.getFullyQualifiedName(current);
833
- if (moduleName === targetModule) {
834
- found = true;
835
- }
836
- }
837
- }
838
- // 3. References with method type matching the target module
839
- else if (type && java_1.Type.isMethod(type)) {
840
- const methodType = type;
841
- const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodType.declaringType);
842
- if (declaringTypeName === targetModule) {
843
- found = true;
844
- }
845
- }
817
+ }
818
+ // 3. References with method type matching the target module
819
+ else if (type && java_1.Type.isMethod(type)) {
820
+ const methodType = type;
821
+ const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodType.declaringType);
822
+ if (declaringTypeName === targetModule) {
823
+ found = true;
846
824
  }
847
825
  }
848
- return _super.visitIdentifier.call(this, identifier, p);
849
- });
826
+ }
850
827
  }
851
- visitMethodInvocation(methodInvocation, p) {
852
- const _super = Object.create(null, {
853
- visitMethodInvocation: { get: () => super.visitMethodInvocation }
854
- });
855
- return __awaiter(this, void 0, void 0, function* () {
856
- if (methodInvocation.methodType && methodInvocation.methodType.name === targetName) {
857
- if (expectedDeclaringType) {
858
- const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodInvocation.methodType.declaringType);
859
- if (declaringTypeName === expectedDeclaringType) {
860
- found = true;
861
- }
862
- }
828
+ return super.visitIdentifier(identifier, p);
829
+ }
830
+ async visitMethodInvocation(methodInvocation, p) {
831
+ if (methodInvocation.methodType && methodInvocation.methodType.name === targetName) {
832
+ if (expectedDeclaringType) {
833
+ const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodInvocation.methodType.declaringType);
834
+ if (declaringTypeName === expectedDeclaringType) {
835
+ found = true;
863
836
  }
864
- return _super.visitMethodInvocation.call(this, methodInvocation, p);
865
- });
837
+ }
866
838
  }
867
- visitFunctionCall(functionCall, p) {
868
- const _super = Object.create(null, {
869
- visitFunctionCall: { get: () => super.visitFunctionCall }
870
- });
871
- return __awaiter(this, void 0, void 0, function* () {
872
- if (functionCall.methodType && functionCall.methodType.name === targetName) {
873
- if (expectedDeclaringType) {
874
- const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(functionCall.methodType.declaringType);
875
- if (declaringTypeName === expectedDeclaringType) {
876
- found = true;
877
- }
878
- }
839
+ return super.visitMethodInvocation(methodInvocation, p);
840
+ }
841
+ async visitFunctionCall(functionCall, p) {
842
+ if (functionCall.methodType && functionCall.methodType.name === targetName) {
843
+ if (expectedDeclaringType) {
844
+ const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(functionCall.methodType.declaringType);
845
+ if (declaringTypeName === expectedDeclaringType) {
846
+ found = true;
879
847
  }
880
- return _super.visitFunctionCall.call(this, functionCall, p);
881
- });
848
+ }
882
849
  }
883
- visitFieldAccess(fieldAccess, p) {
884
- const _super = Object.create(null, {
885
- visitFieldAccess: { get: () => super.visitFieldAccess }
886
- });
887
- return __awaiter(this, void 0, void 0, function* () {
888
- const type = fieldAccess.type;
889
- if (type && java_1.Type.isMethod(type)) {
890
- const methodType = type;
891
- if (methodType.name === targetName) {
892
- if (expectedDeclaringType) {
893
- const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodType.declaringType);
894
- if (declaringTypeName === expectedDeclaringType) {
895
- found = true;
896
- }
897
- }
850
+ return super.visitFunctionCall(functionCall, p);
851
+ }
852
+ async visitFieldAccess(fieldAccess, p) {
853
+ const type = fieldAccess.type;
854
+ if (type && java_1.Type.isMethod(type)) {
855
+ const methodType = type;
856
+ if (methodType.name === targetName) {
857
+ if (expectedDeclaringType) {
858
+ const declaringTypeName = java_1.Type.FullyQualified.getFullyQualifiedName(methodType.declaringType);
859
+ if (declaringTypeName === expectedDeclaringType) {
860
+ found = true;
898
861
  }
899
862
  }
900
- return _super.visitFieldAccess.call(this, fieldAccess, p);
901
- });
863
+ }
902
864
  }
903
- };
904
- yield collector.visit(compilationUnit, undefined);
905
- return found;
906
- });
865
+ return super.visitFieldAccess(fieldAccess, p);
866
+ }
867
+ };
868
+ await collector.visit(compilationUnit, undefined);
869
+ return found;
907
870
  }
908
871
  /**
909
872
  * Create a new import statement
910
873
  */
911
- createImportStatement(compilationUnit, insertionIndex, p) {
912
- return __awaiter(this, void 0, void 0, function* () {
913
- // Determine the appropriate prefix (spacing before the import)
914
- const prefix = this.determineImportPrefix(compilationUnit, insertionIndex);
915
- // Create the module specifier
916
- // For side-effect imports, use emptySpace since space comes from LeftPadded.before
917
- // For regular imports with import clause, use emptySpace since space comes from LeftPadded.before
918
- // However, the printer expects the space after 'from' in the literal's prefix
919
- // Note: value contains the unquoted string, valueSource contains the quoted version for printing
920
- const moduleSpecifier = {
874
+ async createImportStatement(compilationUnit, insertionIndex, p) {
875
+ // Determine the appropriate prefix (spacing before the import)
876
+ const prefix = this.determineImportPrefix(compilationUnit, insertionIndex);
877
+ // Create the module specifier
878
+ // For side-effect imports, use emptySpace since space comes from LeftPadded.before
879
+ // For regular imports with import clause, use emptySpace since space comes from LeftPadded.before
880
+ // However, the printer expects the space after 'from' in the literal's prefix
881
+ // Note: value contains the unquoted string, valueSource contains the quoted version for printing
882
+ const moduleSpecifier = {
883
+ id: (0, uuid_1.randomId)(),
884
+ kind: java_1.J.Kind.Literal,
885
+ prefix: this.sideEffectOnly ? java_1.emptySpace : java_1.singleSpace,
886
+ markers: markers_1.emptyMarkers,
887
+ value: this.module,
888
+ valueSource: `'${this.module}'`,
889
+ unicodeEscapes: [],
890
+ type: undefined
891
+ };
892
+ let importClause;
893
+ if (this.sideEffectOnly) {
894
+ // Side-effect import: import 'module'
895
+ importClause = undefined;
896
+ }
897
+ else if (this.member === '*') {
898
+ // Namespace import: import * as alias from 'module'
899
+ const propertyName = {
921
900
  id: (0, uuid_1.randomId)(),
922
- kind: java_1.J.Kind.Literal,
923
- prefix: this.sideEffectOnly ? java_1.emptySpace : java_1.singleSpace,
901
+ kind: java_1.J.Kind.Identifier,
902
+ prefix: java_1.emptySpace,
924
903
  markers: markers_1.emptyMarkers,
925
- value: this.module,
926
- valueSource: `'${this.module}'`,
927
- unicodeEscapes: [],
928
- type: undefined
904
+ annotations: [],
905
+ simpleName: '*',
906
+ type: undefined,
907
+ fieldType: undefined
929
908
  };
930
- let importClause;
931
- if (this.sideEffectOnly) {
932
- // Side-effect import: import 'module'
933
- importClause = undefined;
934
- }
935
- else if (this.member === '*') {
936
- // Namespace import: import * as alias from 'module'
937
- const propertyName = {
938
- id: (0, uuid_1.randomId)(),
939
- kind: java_1.J.Kind.Identifier,
940
- prefix: java_1.emptySpace,
941
- markers: markers_1.emptyMarkers,
942
- annotations: [],
943
- simpleName: '*',
944
- type: undefined,
945
- fieldType: undefined
946
- };
947
- const aliasIdentifier = {
948
- id: (0, uuid_1.randomId)(),
949
- kind: java_1.J.Kind.Identifier,
950
- prefix: java_1.singleSpace,
951
- markers: markers_1.emptyMarkers,
952
- annotations: [],
953
- simpleName: this.alias,
954
- type: undefined,
955
- fieldType: undefined
956
- };
957
- const namespaceBinding = {
958
- id: (0, uuid_1.randomId)(),
959
- kind: tree_1.JS.Kind.Alias,
960
- prefix: java_1.singleSpace,
961
- markers: markers_1.emptyMarkers,
962
- propertyName: (0, java_1.rightPadded)(propertyName, java_1.singleSpace),
963
- alias: aliasIdentifier
964
- };
965
- importClause = {
966
- id: (0, uuid_1.randomId)(),
967
- kind: tree_1.JS.Kind.ImportClause,
968
- prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
969
- markers: markers_1.emptyMarkers,
970
- typeOnly: this.typeOnly,
971
- name: undefined,
972
- namedBindings: namespaceBinding
973
- };
974
- }
975
- else if (this.member === undefined || this.member === 'default') {
976
- // Default import: import target from 'module'
977
- // or: import alias from 'module' (when member === 'default')
978
- const defaultName = {
979
- id: (0, uuid_1.randomId)(),
980
- kind: java_1.J.Kind.Identifier,
981
- prefix: java_1.singleSpace,
982
- markers: markers_1.emptyMarkers,
983
- annotations: [],
984
- simpleName: this.alias || this.module,
985
- type: undefined,
986
- fieldType: undefined
987
- };
988
- importClause = {
989
- id: (0, uuid_1.randomId)(),
990
- kind: tree_1.JS.Kind.ImportClause,
991
- prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
992
- markers: markers_1.emptyMarkers,
993
- typeOnly: this.typeOnly,
994
- name: (0, java_1.rightPadded)(defaultName, java_1.emptySpace),
995
- namedBindings: undefined
996
- };
997
- }
998
- else {
999
- // Named import: import { member } from 'module'
1000
- // Get the spaces style for brace spacing
1001
- const spacesStyle = (0, style_1.getStyle)(style_1.StyleKind.SpacesStyle, compilationUnit);
1002
- const braceSpace = spacesStyle.within.es6ImportExportBraces ? java_1.singleSpace : java_1.emptySpace;
1003
- const importSpec = this.createImportSpecifier();
1004
- // Apply brace spacing: the space after { is in the specifier's prefix,
1005
- // and the space before } is in the rightPadded's after
1006
- const importSpecWithSpacing = Object.assign(Object.assign({}, importSpec), { prefix: braceSpace });
1007
- const namedImports = {
1008
- id: (0, uuid_1.randomId)(),
1009
- kind: tree_1.JS.Kind.NamedImports,
1010
- prefix: java_1.singleSpace,
1011
- markers: markers_1.emptyMarkers,
1012
- elements: {
1013
- kind: java_1.J.Kind.Container,
1014
- before: java_1.emptySpace,
1015
- elements: [(0, java_1.rightPadded)(importSpecWithSpacing, braceSpace)],
1016
- markers: markers_1.emptyMarkers
1017
- }
1018
- };
1019
- importClause = {
1020
- id: (0, uuid_1.randomId)(),
1021
- kind: tree_1.JS.Kind.ImportClause,
1022
- prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
1023
- markers: markers_1.emptyMarkers,
1024
- typeOnly: this.typeOnly,
1025
- name: undefined,
1026
- namedBindings: namedImports
1027
- };
1028
- }
1029
- const jsImport = {
909
+ const aliasIdentifier = {
910
+ id: (0, uuid_1.randomId)(),
911
+ kind: java_1.J.Kind.Identifier,
912
+ prefix: java_1.singleSpace,
913
+ markers: markers_1.emptyMarkers,
914
+ annotations: [],
915
+ simpleName: this.alias,
916
+ type: undefined,
917
+ fieldType: undefined
918
+ };
919
+ const namespaceBinding = {
920
+ id: (0, uuid_1.randomId)(),
921
+ kind: tree_1.JS.Kind.Alias,
922
+ prefix: java_1.singleSpace,
923
+ markers: markers_1.emptyMarkers,
924
+ propertyName: (0, java_1.rightPadded)(propertyName, java_1.singleSpace),
925
+ alias: aliasIdentifier
926
+ };
927
+ importClause = {
1030
928
  id: (0, uuid_1.randomId)(),
1031
- kind: tree_1.JS.Kind.Import,
1032
- prefix,
929
+ kind: tree_1.JS.Kind.ImportClause,
930
+ prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
1033
931
  markers: markers_1.emptyMarkers,
1034
- modifiers: [],
1035
- importClause,
1036
- moduleSpecifier: {
1037
- kind: java_1.J.Kind.LeftPadded,
1038
- before: java_1.singleSpace,
1039
- element: moduleSpecifier,
932
+ typeOnly: this.typeOnly,
933
+ name: undefined,
934
+ namedBindings: namespaceBinding
935
+ };
936
+ }
937
+ else if (this.member === undefined || this.member === 'default') {
938
+ // Default import: import target from 'module'
939
+ // or: import alias from 'module' (when member === 'default')
940
+ const defaultName = {
941
+ id: (0, uuid_1.randomId)(),
942
+ kind: java_1.J.Kind.Identifier,
943
+ prefix: java_1.singleSpace,
944
+ markers: markers_1.emptyMarkers,
945
+ annotations: [],
946
+ simpleName: this.alias || this.module,
947
+ type: undefined,
948
+ fieldType: undefined
949
+ };
950
+ importClause = {
951
+ id: (0, uuid_1.randomId)(),
952
+ kind: tree_1.JS.Kind.ImportClause,
953
+ prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
954
+ markers: markers_1.emptyMarkers,
955
+ typeOnly: this.typeOnly,
956
+ name: (0, java_1.rightPadded)(defaultName, java_1.emptySpace),
957
+ namedBindings: undefined
958
+ };
959
+ }
960
+ else {
961
+ // Named import: import { member } from 'module'
962
+ // Get the spaces style for brace spacing
963
+ const spacesStyle = (0, style_1.getStyle)(style_1.StyleKind.SpacesStyle, compilationUnit);
964
+ const braceSpace = spacesStyle.within.es6ImportExportBraces ? java_1.singleSpace : java_1.emptySpace;
965
+ const importSpec = this.createImportSpecifier();
966
+ // Apply brace spacing: the space after { is in the specifier's prefix,
967
+ // and the space before } is in the rightPadded's after
968
+ const importSpecWithSpacing = Object.assign(Object.assign({}, importSpec), { prefix: braceSpace });
969
+ const namedImports = {
970
+ id: (0, uuid_1.randomId)(),
971
+ kind: tree_1.JS.Kind.NamedImports,
972
+ prefix: java_1.singleSpace,
973
+ markers: markers_1.emptyMarkers,
974
+ elements: {
975
+ kind: java_1.J.Kind.Container,
976
+ before: java_1.emptySpace,
977
+ elements: [(0, java_1.rightPadded)(importSpecWithSpacing, braceSpace)],
1040
978
  markers: markers_1.emptyMarkers
1041
- },
1042
- initializer: undefined
979
+ }
1043
980
  };
1044
- return jsImport;
1045
- });
981
+ importClause = {
982
+ id: (0, uuid_1.randomId)(),
983
+ kind: tree_1.JS.Kind.ImportClause,
984
+ prefix: this.typeOnly ? java_1.singleSpace : java_1.emptySpace,
985
+ markers: markers_1.emptyMarkers,
986
+ typeOnly: this.typeOnly,
987
+ name: undefined,
988
+ namedBindings: namedImports
989
+ };
990
+ }
991
+ const jsImport = {
992
+ id: (0, uuid_1.randomId)(),
993
+ kind: tree_1.JS.Kind.Import,
994
+ prefix,
995
+ markers: markers_1.emptyMarkers,
996
+ modifiers: [],
997
+ importClause,
998
+ moduleSpecifier: {
999
+ kind: java_1.J.Kind.LeftPadded,
1000
+ before: java_1.singleSpace,
1001
+ element: moduleSpecifier,
1002
+ markers: markers_1.emptyMarkers
1003
+ },
1004
+ initializer: undefined
1005
+ };
1006
+ return jsImport;
1046
1007
  }
1047
1008
  /**
1048
1009
  * Create an import specifier for a named import