@openrewrite/rewrite 8.92.16 → 8.92.18

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 (254) hide show
  1. package/README.md +48 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/java/formatting-utils.d.ts +2 -1
  6. package/dist/java/formatting-utils.d.ts.map +1 -1
  7. package/dist/java/formatting-utils.js +4 -3
  8. package/dist/java/formatting-utils.js.map +1 -1
  9. package/dist/java/rpc.d.ts.map +1 -1
  10. package/dist/java/rpc.js +2 -0
  11. package/dist/java/rpc.js.map +1 -1
  12. package/dist/java/tree.d.ts +8 -0
  13. package/dist/java/tree.d.ts.map +1 -1
  14. package/dist/java/tree.js +11 -1
  15. package/dist/java/tree.js.map +1 -1
  16. package/dist/java/type.d.ts +7 -1
  17. package/dist/java/type.d.ts.map +1 -1
  18. package/dist/java/type.js +16 -1
  19. package/dist/java/type.js.map +1 -1
  20. package/dist/javascript/add-import.d.ts +27 -21
  21. package/dist/javascript/add-import.d.ts.map +1 -1
  22. package/dist/javascript/add-import.js +303 -143
  23. package/dist/javascript/add-import.js.map +1 -1
  24. package/dist/javascript/amd.d.ts.map +1 -1
  25. package/dist/javascript/amd.js +25 -10
  26. package/dist/javascript/amd.js.map +1 -1
  27. package/dist/javascript/autodetect.js +36 -45
  28. package/dist/javascript/autodetect.js.map +1 -1
  29. package/dist/javascript/binding.d.ts +6 -4
  30. package/dist/javascript/binding.d.ts.map +1 -1
  31. package/dist/javascript/binding.js +54 -18
  32. package/dist/javascript/binding.js.map +1 -1
  33. package/dist/javascript/comparator.d.ts +22 -5
  34. package/dist/javascript/comparator.d.ts.map +1 -1
  35. package/dist/javascript/comparator.js +120 -38
  36. package/dist/javascript/comparator.js.map +1 -1
  37. package/dist/javascript/format/format.d.ts +2 -0
  38. package/dist/javascript/format/format.d.ts.map +1 -1
  39. package/dist/javascript/format/format.js +11 -1
  40. package/dist/javascript/format/format.js.map +1 -1
  41. package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
  42. package/dist/javascript/format/tabs-and-indents-visitor.js +31 -4
  43. package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
  44. package/dist/javascript/index.d.ts +4 -2
  45. package/dist/javascript/index.d.ts.map +1 -1
  46. package/dist/javascript/index.js +10 -1
  47. package/dist/javascript/index.js.map +1 -1
  48. package/dist/javascript/markers.d.ts +12 -0
  49. package/dist/javascript/markers.d.ts.map +1 -1
  50. package/dist/javascript/markers.js +81 -2
  51. package/dist/javascript/markers.js.map +1 -1
  52. package/dist/javascript/method-matcher.d.ts +13 -2
  53. package/dist/javascript/method-matcher.d.ts.map +1 -1
  54. package/dist/javascript/method-matcher.js +32 -19
  55. package/dist/javascript/method-matcher.js.map +1 -1
  56. package/dist/javascript/node-resolution-result.js +3 -2
  57. package/dist/javascript/node-resolution-result.js.map +1 -1
  58. package/dist/javascript/package-name.d.ts +6 -0
  59. package/dist/javascript/package-name.d.ts.map +1 -0
  60. package/dist/javascript/package-name.js +47 -0
  61. package/dist/javascript/package-name.js.map +1 -0
  62. package/dist/javascript/parser.d.ts +9 -0
  63. package/dist/javascript/parser.d.ts.map +1 -1
  64. package/dist/javascript/parser.js +185 -88
  65. package/dist/javascript/parser.js.map +1 -1
  66. package/dist/javascript/preconditions.d.ts +4 -1
  67. package/dist/javascript/preconditions.d.ts.map +1 -1
  68. package/dist/javascript/preconditions.js +7 -4
  69. package/dist/javascript/preconditions.js.map +1 -1
  70. package/dist/javascript/print.d.ts +10 -1
  71. package/dist/javascript/print.d.ts.map +1 -1
  72. package/dist/javascript/print.js +120 -77
  73. package/dist/javascript/print.js.map +1 -1
  74. package/dist/javascript/recipes/change-method-target-to-import.d.ts +29 -0
  75. package/dist/javascript/recipes/change-method-target-to-import.d.ts.map +1 -0
  76. package/dist/javascript/recipes/change-method-target-to-import.js +164 -0
  77. package/dist/javascript/recipes/change-method-target-to-import.js.map +1 -0
  78. package/dist/javascript/recipes/index.d.ts +1 -0
  79. package/dist/javascript/recipes/index.d.ts.map +1 -1
  80. package/dist/javascript/recipes/index.js +1 -0
  81. package/dist/javascript/recipes/index.js.map +1 -1
  82. package/dist/javascript/scope.d.ts +60 -16
  83. package/dist/javascript/scope.d.ts.map +1 -1
  84. package/dist/javascript/scope.js +596 -131
  85. package/dist/javascript/scope.js.map +1 -1
  86. package/dist/javascript/search/uses-method.d.ts +1 -1
  87. package/dist/javascript/search/uses-method.d.ts.map +1 -1
  88. package/dist/javascript/search/uses-method.js +2 -2
  89. package/dist/javascript/search/uses-method.js.map +1 -1
  90. package/dist/javascript/search/uses-type.d.ts +14 -1
  91. package/dist/javascript/search/uses-type.d.ts.map +1 -1
  92. package/dist/javascript/search/uses-type.js +24 -9
  93. package/dist/javascript/search/uses-type.js.map +1 -1
  94. package/dist/javascript/templating/bindings.d.ts +1 -1
  95. package/dist/javascript/templating/bindings.d.ts.map +1 -1
  96. package/dist/javascript/templating/bindings.js +10 -50
  97. package/dist/javascript/templating/bindings.js.map +1 -1
  98. package/dist/javascript/templating/comparator.d.ts +8 -11
  99. package/dist/javascript/templating/comparator.d.ts.map +1 -1
  100. package/dist/javascript/templating/comparator.js +12 -110
  101. package/dist/javascript/templating/comparator.js.map +1 -1
  102. package/dist/javascript/templating/engine.d.ts +34 -24
  103. package/dist/javascript/templating/engine.d.ts.map +1 -1
  104. package/dist/javascript/templating/engine.js +208 -115
  105. package/dist/javascript/templating/engine.js.map +1 -1
  106. package/dist/javascript/templating/pattern.d.ts +11 -5
  107. package/dist/javascript/templating/pattern.d.ts.map +1 -1
  108. package/dist/javascript/templating/pattern.js +86 -20
  109. package/dist/javascript/templating/pattern.js.map +1 -1
  110. package/dist/javascript/templating/placeholder-replacement.d.ts +34 -3
  111. package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
  112. package/dist/javascript/templating/placeholder-replacement.js +126 -60
  113. package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
  114. package/dist/javascript/templating/precedence.d.ts +3 -1
  115. package/dist/javascript/templating/precedence.d.ts.map +1 -1
  116. package/dist/javascript/templating/precedence.js +28 -8
  117. package/dist/javascript/templating/precedence.js.map +1 -1
  118. package/dist/javascript/templating/template.d.ts +7 -6
  119. package/dist/javascript/templating/template.d.ts.map +1 -1
  120. package/dist/javascript/templating/template.js +31 -28
  121. package/dist/javascript/templating/template.js.map +1 -1
  122. package/dist/javascript/templating/types.d.ts +6 -3
  123. package/dist/javascript/templating/types.d.ts.map +1 -1
  124. package/dist/javascript/templating/utils.d.ts +10 -1
  125. package/dist/javascript/templating/utils.d.ts.map +1 -1
  126. package/dist/javascript/templating/utils.js +22 -3
  127. package/dist/javascript/templating/utils.js.map +1 -1
  128. package/dist/javascript/tree-debug.d.ts +2 -0
  129. package/dist/javascript/tree-debug.d.ts.map +1 -1
  130. package/dist/javascript/tree-debug.js +6 -0
  131. package/dist/javascript/tree-debug.js.map +1 -1
  132. package/dist/javascript/tsconfig.d.ts.map +1 -1
  133. package/dist/javascript/tsconfig.js +7 -17
  134. package/dist/javascript/tsconfig.js.map +1 -1
  135. package/dist/javascript/type-mapping.d.ts +35 -16
  136. package/dist/javascript/type-mapping.d.ts.map +1 -1
  137. package/dist/javascript/type-mapping.js +271 -252
  138. package/dist/javascript/type-mapping.js.map +1 -1
  139. package/dist/javascript/type-report-cli.d.ts +7 -0
  140. package/dist/javascript/type-report-cli.d.ts.map +1 -0
  141. package/dist/javascript/type-report-cli.js +129 -0
  142. package/dist/javascript/type-report-cli.js.map +1 -0
  143. package/dist/javascript/type-report.d.ts +61 -0
  144. package/dist/javascript/type-report.d.ts.map +1 -0
  145. package/dist/javascript/type-report.js +488 -0
  146. package/dist/javascript/type-report.js.map +1 -0
  147. package/dist/markers.d.ts +4 -0
  148. package/dist/markers.d.ts.map +1 -1
  149. package/dist/markers.js +8 -0
  150. package/dist/markers.js.map +1 -1
  151. package/dist/print.d.ts +6 -1
  152. package/dist/print.d.ts.map +1 -1
  153. package/dist/print.js +21 -7
  154. package/dist/print.js.map +1 -1
  155. package/dist/recipe.d.ts +5 -0
  156. package/dist/recipe.d.ts.map +1 -1
  157. package/dist/recipe.js +5 -0
  158. package/dist/recipe.js.map +1 -1
  159. package/dist/rewrite-javascript-version.txt +1 -1
  160. package/dist/rpc/java-rpc-client.d.ts +2 -0
  161. package/dist/rpc/java-rpc-client.d.ts.map +1 -1
  162. package/dist/rpc/java-rpc-client.js +1 -0
  163. package/dist/rpc/java-rpc-client.js.map +1 -1
  164. package/dist/rpc/queue.d.ts +24 -0
  165. package/dist/rpc/queue.d.ts.map +1 -1
  166. package/dist/rpc/queue.js +71 -11
  167. package/dist/rpc/queue.js.map +1 -1
  168. package/dist/rpc/request/get-object.d.ts +4 -0
  169. package/dist/rpc/request/get-object.d.ts.map +1 -1
  170. package/dist/rpc/request/get-object.js +23 -1
  171. package/dist/rpc/request/get-object.js.map +1 -1
  172. package/dist/rpc/request/parse.d.ts.map +1 -1
  173. package/dist/rpc/request/parse.js +3 -1
  174. package/dist/rpc/request/parse.js.map +1 -1
  175. package/dist/rpc/request/prepare-recipe.d.ts +3 -1
  176. package/dist/rpc/request/prepare-recipe.d.ts.map +1 -1
  177. package/dist/rpc/request/prepare-recipe.js +13 -6
  178. package/dist/rpc/request/prepare-recipe.js.map +1 -1
  179. package/dist/rpc/request/print.d.ts +8 -2
  180. package/dist/rpc/request/print.d.ts.map +1 -1
  181. package/dist/rpc/request/print.js +12 -9
  182. package/dist/rpc/request/print.js.map +1 -1
  183. package/dist/rpc/rewrite-rpc.d.ts +3 -2
  184. package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
  185. package/dist/rpc/rewrite-rpc.js +9 -3
  186. package/dist/rpc/rewrite-rpc.js.map +1 -1
  187. package/dist/rpc/server.d.ts.map +1 -1
  188. package/dist/rpc/server.js +19 -5
  189. package/dist/rpc/server.js.map +1 -1
  190. package/dist/search/is-source-file.d.ts +1 -0
  191. package/dist/search/is-source-file.d.ts.map +1 -1
  192. package/dist/search/is-source-file.js +7 -2
  193. package/dist/search/is-source-file.js.map +1 -1
  194. package/dist/test/java-rpc.d.ts.map +1 -1
  195. package/dist/test/java-rpc.js +3 -0
  196. package/dist/test/java-rpc.js.map +1 -1
  197. package/dist/test/rewrite-test.d.ts +5 -0
  198. package/dist/test/rewrite-test.d.ts.map +1 -1
  199. package/dist/test/rewrite-test.js +14 -3
  200. package/dist/test/rewrite-test.js.map +1 -1
  201. package/package.json +4 -3
  202. package/src/index.ts +3 -1
  203. package/src/java/formatting-utils.ts +5 -4
  204. package/src/java/rpc.ts +2 -0
  205. package/src/java/tree.ts +15 -0
  206. package/src/java/type.ts +19 -2
  207. package/src/javascript/add-import.ts +338 -152
  208. package/src/javascript/amd.ts +28 -12
  209. package/src/javascript/autodetect.ts +32 -41
  210. package/src/javascript/binding.ts +64 -22
  211. package/src/javascript/comparator.ts +129 -43
  212. package/src/javascript/format/format.ts +9 -0
  213. package/src/javascript/format/tabs-and-indents-visitor.ts +30 -3
  214. package/src/javascript/index.ts +6 -3
  215. package/src/javascript/markers.ts +77 -5
  216. package/src/javascript/method-matcher.ts +34 -22
  217. package/src/javascript/node-resolution-result.ts +3 -2
  218. package/src/javascript/package-name.ts +45 -0
  219. package/src/javascript/parser.ts +200 -91
  220. package/src/javascript/preconditions.ts +7 -4
  221. package/src/javascript/print.ts +123 -76
  222. package/src/javascript/recipes/change-method-target-to-import.ts +178 -0
  223. package/src/javascript/recipes/index.ts +1 -0
  224. package/src/javascript/scope.ts +705 -169
  225. package/src/javascript/search/uses-method.ts +2 -2
  226. package/src/javascript/search/uses-type.ts +30 -9
  227. package/src/javascript/templating/bindings.ts +13 -38
  228. package/src/javascript/templating/comparator.ts +16 -127
  229. package/src/javascript/templating/engine.ts +236 -129
  230. package/src/javascript/templating/pattern.ts +107 -28
  231. package/src/javascript/templating/placeholder-replacement.ts +154 -62
  232. package/src/javascript/templating/precedence.ts +33 -11
  233. package/src/javascript/templating/template.ts +35 -30
  234. package/src/javascript/templating/types.ts +6 -3
  235. package/src/javascript/templating/utils.ts +24 -2
  236. package/src/javascript/tree-debug.ts +9 -0
  237. package/src/javascript/tsconfig.ts +7 -17
  238. package/src/javascript/type-mapping.ts +277 -255
  239. package/src/javascript/type-report-cli.ts +96 -0
  240. package/src/javascript/type-report.ts +575 -0
  241. package/src/markers.ts +8 -0
  242. package/src/print.ts +23 -8
  243. package/src/recipe.ts +6 -0
  244. package/src/rpc/java-rpc-client.ts +3 -0
  245. package/src/rpc/queue.ts +80 -7
  246. package/src/rpc/request/get-object.ts +24 -0
  247. package/src/rpc/request/parse.ts +4 -1
  248. package/src/rpc/request/prepare-recipe.ts +16 -6
  249. package/src/rpc/request/print.ts +12 -8
  250. package/src/rpc/rewrite-rpc.ts +16 -5
  251. package/src/rpc/server.ts +18 -6
  252. package/src/search/is-source-file.ts +8 -3
  253. package/src/test/java-rpc.ts +3 -0
  254. package/src/test/rewrite-test.ts +14 -3
@@ -11,16 +11,19 @@ exports.requiredModuleOf = requiredModuleOf;
11
11
  exports.takenNames = takenNames;
12
12
  exports.nameTaken = nameTaken;
13
13
  exports.moduleNameOf = moduleNameOf;
14
+ exports.bindingShape = bindingShape;
14
15
  exports.existingImportBinding = existingImportBinding;
15
16
  const visitor_1 = require("./visitor");
16
17
  const java_1 = require("../java");
17
18
  const tree_1 = require("./tree");
18
19
  const uuid_1 = require("../uuid");
20
+ const type_visitor_1 = require("../java/type-visitor");
21
+ const util_1 = require("../util");
22
+ const package_name_1 = require("./package-name");
19
23
  const markers_1 = require("../markers");
20
24
  const style_1 = require("./style");
21
25
  const scope_1 = require("./scope");
22
26
  const mutative_1 = require("mutative");
23
- const type_visitor_1 = require("../java/type-visitor");
24
27
  const format_1 = require("./format");
25
28
  const prettier_format_1 = require("./format/prettier-format");
26
29
  var ImportStyle;
@@ -37,7 +40,7 @@ var ImportStyle;
37
40
  * without affecting whether an existing binding answers the request first.
38
41
  */
39
42
  function bindImport(visitor, options, refuseCreate) {
40
- var _a, _b;
43
+ var _a, _b, _c;
41
44
  validate(options);
42
45
  const module = moduleNameOf(options.module);
43
46
  const sideEffectOnly = (_a = options.sideEffectOnly) !== null && _a !== void 0 ? _a : false;
@@ -45,8 +48,13 @@ function bindImport(visitor, options, refuseCreate) {
45
48
  // A queued import binds the module as much as one already in the file, so it answers a later
46
49
  // request the same way; a name a merged request never emits would be referenced but not bound.
47
50
  for (const v of visitor.afterVisit || []) {
51
+ if (v instanceof RebindImport && !sideEffectOnly && v.to.module === module &&
52
+ memberName(v.to.member) === memberName(options.member) &&
53
+ (options.alias === undefined || options.alias === v.boundName)) {
54
+ return v.boundName;
55
+ }
48
56
  if (!(v instanceof AddImport) || v.module !== module ||
49
- v.sideEffectOnly !== sideEffectOnly || v.typeOnly !== typeOnly) {
57
+ v.sideEffectOnly !== sideEffectOnly || !answersTypeOnly(v.typeOnly, typeOnly)) {
50
58
  continue;
51
59
  }
52
60
  // How a specifier prints, or what name would be nice, does not say which binding is wanted.
@@ -89,7 +97,11 @@ function bindImport(visitor, options, refuseCreate) {
89
97
  const scope = (0, scope_1.scopeOf)(cursor);
90
98
  for (const binding of moduleScopeBindings(cu)) {
91
99
  if (binding.module === module && binding.member === memberName(options.member) &&
92
- binding.typeOnly === typeOnly && scope.declaringScope(binding.name) === cu) {
100
+ scope.declaringScope(binding.name) === cu) {
101
+ if (!answersTypeOnly((_c = binding.typeOnly) !== null && _c !== void 0 ? _c : false, typeOnly)) {
102
+ // The queued request finds this binding and drops its `type`, so the name stays
103
+ visitor.afterVisit.push(new AddImport(options, binding.name));
104
+ }
93
105
  return binding.name;
94
106
  }
95
107
  }
@@ -266,6 +278,54 @@ function requireBindings(pattern, module) {
266
278
  ? { name: bound.name }
267
279
  : { name: bound.name, module, member: bound.member, typeOnly: false });
268
280
  }
281
+ /** Whether a binding answers a request, given which of the two is type-only. A value import binds the type too. */
282
+ function answersTypeOnly(bindingTypeOnly, requestTypeOnly) {
283
+ return requestTypeOnly || !bindingTypeOnly;
284
+ }
285
+ /**
286
+ * `jsImport` binding `member` as a value. A `type` on the member's specifier goes, and one on the
287
+ * clause moves onto the clause's other specifiers.
288
+ */
289
+ function asValueImport(jsImport, member) {
290
+ var _a;
291
+ const clause = jsImport.importClause;
292
+ const named = ((_a = clause.namedBindings) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.NamedImports ? clause.namedBindings : undefined;
293
+ const imports = (specifier) => { var _a; return specifier.kind === tree_1.JS.Kind.ImportSpecifier && ((_a = specifierBinding(specifier)) === null || _a === void 0 ? void 0 : _a.member) === member; };
294
+ if (!clause.typeOnly) {
295
+ return !named ? jsImport : (0, mutative_1.create)(jsImport, draft => {
296
+ for (const elem of draft.importClause.namedBindings.elements.elements) {
297
+ const specifier = elem.element;
298
+ if (member !== undefined && imports(elem.element) && specifier.importType.element) {
299
+ specifier.specifier.prefix = specifier.importType.before;
300
+ specifier.importType = Object.assign(Object.assign({}, specifier.importType), { before: java_1.emptySpace, element: false });
301
+ }
302
+ }
303
+ });
304
+ }
305
+ return (0, mutative_1.create)(jsImport, draft => {
306
+ const draftClause = draft.importClause;
307
+ draftClause.typeOnly = false;
308
+ // The space after `type` separates nothing once it is gone
309
+ if (draftClause.name) {
310
+ draftClause.name.element.prefix = java_1.emptySpace;
311
+ }
312
+ else if (draftClause.namedBindings) {
313
+ draftClause.namedBindings.prefix = java_1.emptySpace;
314
+ if (named) {
315
+ draftClause.namedBindings.elements.before = java_1.emptySpace;
316
+ }
317
+ }
318
+ if (named) {
319
+ for (const elem of draftClause.namedBindings.elements.elements) {
320
+ const specifier = elem.element;
321
+ if (!imports(elem.element) && specifier.kind === tree_1.JS.Kind.ImportSpecifier) {
322
+ specifier.importType = Object.assign(Object.assign({}, specifier.importType), { before: java_1.emptySpace, element: true });
323
+ specifier.specifier.prefix = java_1.singleSpace;
324
+ }
325
+ }
326
+ }
327
+ });
328
+ }
269
329
  /** The member a specifier imports and the name it binds it under, which are the same absent an alias. */
270
330
  function specifierBinding(specifier) {
271
331
  var _a, _b, _c, _d, _e;
@@ -312,30 +372,34 @@ function importBindings(jsImport) {
312
372
  ? specifierBinding(elem.element)
313
373
  : undefined;
314
374
  if (bound) {
315
- bindings.push(Object.assign(Object.assign({}, bound), { module, typeOnly }));
375
+ const specifier = elem.element;
376
+ bindings.push(Object.assign(Object.assign({}, bound), { module, typeOnly: typeOnly || specifier.importType.element }));
316
377
  }
317
378
  }
318
379
  }
319
380
  return bindings;
320
381
  }
321
382
  /**
322
- * `names`, plus those pending `AddImport`s on the `afterVisit` queue have claimed. A queued
323
- * `RemoveImport` does not free one: it removes only what the file leaves unused, and binding a name
324
- * it keeps is an error, where an unnecessary suffix merely reads oddly.
383
+ * `names`, plus those pending `AddImport`s and `RebindImport`s on the `afterVisit` queue have
384
+ * claimed. A queued `RemoveImport` does not free one: it removes only what the file leaves unused,
385
+ * and binding a name it keeps is an error, where an unnecessary suffix merely reads oddly.
325
386
  */
326
387
  function takenNames(names, visitor) {
327
388
  const taken = new Set(names);
328
389
  for (const v of visitor.afterVisit || []) {
329
- if (v instanceof AddImport && v.bindingName) {
330
- taken.add(v.bindingName);
390
+ const claimed = claimedName(v);
391
+ if (claimed) {
392
+ taken.add(claimed);
331
393
  }
332
394
  }
333
395
  return taken;
334
396
  }
335
397
  /** As {@link takenNames}, for a caller asking about one name rather than probing repeatedly. */
336
398
  function nameTaken(name, names, visitor) {
337
- return names.has(name) ||
338
- (visitor.afterVisit || []).some(v => v instanceof AddImport && v.bindingName === name);
399
+ return names.has(name) || (visitor.afterVisit || []).some(v => claimedName(v) === name);
400
+ }
401
+ function claimedName(v) {
402
+ return v instanceof AddImport ? v.bindingName : v instanceof RebindImport ? v.boundName : undefined;
339
403
  }
340
404
  /**
341
405
  * The parser lifts surrogate pairs out of `valueSource` into `unicodeEscapes` and, when it does,
@@ -733,6 +797,19 @@ class AddImport extends visitor_1.JavaScriptVisitor {
733
797
  if (hasImport) {
734
798
  return compilationUnit;
735
799
  }
800
+ // A type-only binding of the member would leave a value use unbound, and a second binding
801
+ // of the same name would not compile, so the binding the file has loses its `type`
802
+ if (!this.typeOnly && !this.sideEffectOnly) {
803
+ const statements = compilationUnit.statements.map(stmt => {
804
+ const element = stmt.element;
805
+ return (element === null || element === void 0 ? void 0 : element.kind) === tree_1.JS.Kind.Import &&
806
+ importBindings(element).some(b => b.typeOnly && this.bindsSameName(b))
807
+ ? Object.assign(Object.assign({}, stmt), { element: asValueImport(element, memberName(this.member)) }) : stmt;
808
+ });
809
+ if (statements.some((stmt, i) => stmt !== compilationUnit.statements[i])) {
810
+ return Object.assign(Object.assign({}, compilationUnit), { statements });
811
+ }
812
+ }
736
813
  // If onlyIfReferenced is true, check if the identifier is actually used
737
814
  // Skip this check for side-effect imports
738
815
  if (!this.sideEffectOnly && this.onlyIfReferenced) {
@@ -816,35 +893,17 @@ class AddImport extends visitor_1.JavaScriptVisitor {
816
893
  * Try to merge the new member into an existing import from the same module
817
894
  */
818
895
  async tryMergeIntoExistingImport(compilationUnit, p) {
819
- var _a;
820
896
  for (let i = 0; i < compilationUnit.statements.length; i++) {
821
897
  const stmt = compilationUnit.statements[i];
822
898
  const statement = stmt.element;
823
899
  if ((statement === null || statement === void 0 ? void 0 : statement.kind) === tree_1.JS.Kind.Import) {
824
900
  const jsImport = statement;
825
- const moduleSpecifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
826
- if (!moduleSpecifier) {
827
- continue;
828
- }
829
- const moduleName = this.getModuleName(moduleSpecifier);
830
- // Check if this is an import from our target module
831
- if (moduleName !== this.module) {
901
+ if (!acceptsNamedMember(jsImport, this.module, this.typeOnly)) {
832
902
  continue;
833
903
  }
834
904
  const importClause = jsImport.importClause;
835
- if (!importClause) {
836
- continue;
837
- }
838
- // Only merge into imports with matching typeOnly - don't mix type and value imports
839
- if (importClause.typeOnly !== this.typeOnly) {
840
- continue;
841
- }
842
905
  // Case 1: Existing import has named bindings - merge into them
843
906
  if (importClause.namedBindings) {
844
- // Only merge into NamedImports, not namespace imports
845
- if (importClause.namedBindings.kind !== tree_1.JS.Kind.NamedImports) {
846
- continue;
847
- }
848
907
  // We found a matching import with named bindings - merge into it
849
908
  return formatMergedImport(await this.produceJavaScript(compilationUnit, p, async (draft) => {
850
909
  var _a, _b, _c, _d, _e, _f;
@@ -919,7 +978,7 @@ class AddImport extends visitor_1.JavaScriptVisitor {
919
978
  }
920
979
  // Case 2: Default import without named bindings - add named bindings
921
980
  // Transform: import React from 'react' -> import React, { useState } from 'react'
922
- if (importClause.name && !importClause.namedBindings) {
981
+ if (importClause.name) {
923
982
  return formatMergedImport(await this.produceJavaScript(compilationUnit, p, async (draft) => {
924
983
  const newSpecifier = this.createImportSpecifier();
925
984
  // Get the spaces style for brace spacing
@@ -1004,9 +1063,13 @@ class AddImport extends visitor_1.JavaScriptVisitor {
1004
1063
  }
1005
1064
  /** Whether a binding the file already has serves this request. */
1006
1065
  answeredBy(binding) {
1066
+ var _a;
1067
+ return this.bindsSameName(binding) && answersTypeOnly((_a = binding.typeOnly) !== null && _a !== void 0 ? _a : false, this.typeOnly);
1068
+ }
1069
+ /** Whether `binding` binds this request's member under its name, whether or not it is type-only. */
1070
+ bindsSameName(binding) {
1007
1071
  return binding.module === this.module &&
1008
1072
  binding.member === memberName(this.member) &&
1009
- binding.typeOnly === this.typeOnly &&
1010
1073
  (this.anyNameAnswers || binding.name === this.bindingName);
1011
1074
  }
1012
1075
  /**
@@ -1551,6 +1614,13 @@ function namedSpecifierImports(specifier, key) {
1551
1614
  }
1552
1615
  return false;
1553
1616
  }
1617
+ /** Whether `imp` binds `member` type-only, by its clause's `type` or the specifier's own. */
1618
+ function bindsTypeOnly(imp, member) {
1619
+ var _a, _b;
1620
+ const key = memberName(member);
1621
+ return ((_b = (_a = imp.importClause) === null || _a === void 0 ? void 0 : _a.typeOnly) !== null && _b !== void 0 ? _b : false) ||
1622
+ (key !== undefined && key !== '*' && namedSpecifierIsTypeOnly(imp, key));
1623
+ }
1554
1624
  /** Whether the named specifier binding `key` carries its own inline `type`, as in `{type a, b}`. */
1555
1625
  function namedSpecifierIsTypeOnly(imp, key) {
1556
1626
  var _a;
@@ -1586,6 +1656,29 @@ function isOnlyMember(jsImport) {
1586
1656
  const hasNamespace = ((_a = importClause.namedBindings) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.Alias;
1587
1657
  return (hasDefault ? 1 : 0) + (hasNamespace ? 1 : 0) + namedImportCount(jsImport) === 1;
1588
1658
  }
1659
+ function importedModule(jsImport) {
1660
+ var _a;
1661
+ const specifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
1662
+ return jsImport.importClause !== undefined && (specifier === null || specifier === void 0 ? void 0 : specifier.kind) === java_1.J.Kind.Literal
1663
+ ? moduleNameOf(specifier)
1664
+ : undefined;
1665
+ }
1666
+ /** Whether `AddImport` merges a named member of `module` into `jsImport` rather than adding a statement. */
1667
+ function acceptsNamedMember(jsImport, module, typeOnly) {
1668
+ var _a;
1669
+ const clause = jsImport.importClause;
1670
+ const specifier = (_a = jsImport.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element;
1671
+ if (!clause || clause.typeOnly !== typeOnly || (specifier === null || specifier === void 0 ? void 0 : specifier.kind) !== java_1.J.Kind.Literal ||
1672
+ moduleNameOf(specifier) !== module) {
1673
+ return false;
1674
+ }
1675
+ return clause.namedBindings ? clause.namedBindings.kind === tree_1.JS.Kind.NamedImports : clause.name !== undefined;
1676
+ }
1677
+ /** Which of an import clause's three slots `member` binds — `import`, `import *`, or `import {}`. */
1678
+ function bindingShape(member) {
1679
+ const key = memberName(member);
1680
+ return key === undefined ? "default" : key === "*" ? "namespace" : "named";
1681
+ }
1589
1682
  /**
1590
1683
  * The existing binding for `member` of `module`, read from `cu`'s own import statements — what
1591
1684
  * `maybeRebind` reads before committing to a `RebindImport` edit.
@@ -1601,7 +1694,8 @@ function existingImportBinding(cu, module, member) {
1601
1694
  return {
1602
1695
  localName,
1603
1696
  onlyMemberOfStatement: isOnlyMember(element),
1604
- aliased: localName !== memberName(member)
1697
+ aliased: localName !== memberName(member),
1698
+ typeOnly: bindsTypeOnly(element, member)
1605
1699
  };
1606
1700
  }
1607
1701
  }
@@ -1696,11 +1790,39 @@ function removeBinding(jsImport, member) {
1696
1790
  const updatedNamedImports = Object.assign(Object.assign({}, namedImports), { elements: Object.assign(Object.assign({}, namedImports.elements), { elements: kept }) });
1697
1791
  return Object.assign(Object.assign({}, jsImport), { importClause: Object.assign(Object.assign({}, importClause), { namedBindings: updatedNamedImports }) });
1698
1792
  }
1793
+ /** `cu` without the statement `id`, its prefix carried onto the next one so a file header survives. */
1794
+ function withoutStatement(cu, id) {
1795
+ var _a;
1796
+ const formatter = new java_1.ElementRemovalFormatter(true);
1797
+ const statements = [];
1798
+ for (const stmt of cu.statements) {
1799
+ if (((_a = stmt.element) === null || _a === void 0 ? void 0 : _a.id) === id) {
1800
+ formatter.markRemoved(stmt.element);
1801
+ }
1802
+ else {
1803
+ const kept = stmt.element && formatter.processKept(stmt.element);
1804
+ statements.push(kept === stmt.element ? stmt : Object.assign(Object.assign({}, stmt), { element: kept }));
1805
+ }
1806
+ }
1807
+ return Object.assign(Object.assign({}, cu), { statements });
1808
+ }
1809
+ /**
1810
+ * Whether moving the only binding of `jsImport` to `to` replaces the statement rather than rewriting
1811
+ * it in place. A different shape needs a different clause, and another import of `to` takes it in.
1812
+ */
1813
+ function replacesStatement(cu, jsImport, from, to, typeOnly) {
1814
+ const shape = bindingShape(to.member);
1815
+ return shape !== bindingShape(from.member) || (shape === "named" && cu.statements.some(s => {
1816
+ var _a;
1817
+ return s.element !== jsImport && ((_a = s.element) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.Import &&
1818
+ acceptsNamedMember(s.element, to.module, typeOnly);
1819
+ }));
1820
+ }
1821
+ const esmStyle = { default: ImportStyle.ES6Default, namespace: ImportStyle.ES6Namespace, named: ImportStyle.ES6Named };
1699
1822
  /**
1700
- * Moves the binding `from` names to `to`, binding it under `boundName`. In place when the
1701
- * statement that carries it binds nothing else — module and member specifier rewritten there
1702
- * directly; otherwise the old specifier drops and {@link bindImport} queues the replacement.
1703
- * A `boundName` of its own renames the binding, and the file's references to it follow.
1823
+ * Moves the binding `from` names to `to`, binding it under `boundName`, and the file's references
1824
+ * follow a `boundName` of its own. Whether the statement is rewritten in place or replaced is decided
1825
+ * when this visitor runs, because a sibling rebind may empty the statement first.
1704
1826
  *
1705
1827
  * Not built on `RemoveImport`/`maybeUnbind`: those only drop a binding once nothing references
1706
1828
  * it, but a rebind moves one that is still in use — removal here has to be unconditional.
@@ -1714,42 +1836,66 @@ class RebindImport extends visitor_1.JavaScriptVisitor {
1714
1836
  this.boundName = boundName;
1715
1837
  this.transformedInPlace = false;
1716
1838
  this.typeOnly = false;
1717
- this.movedTypes = new MovedTypes(this.from, this.to);
1718
- /** Identifiers settled as references to the binding, so a parent need not settle it again. */
1719
- this.references = new Set();
1720
1839
  }
1721
1840
  get renaming() {
1722
1841
  return this.boundName !== this.localName;
1723
1842
  }
1724
1843
  async visitJsCompilationUnit(cu, p) {
1725
- const visited = await super.visitJsCompilationUnit(cu, p);
1844
+ this.cu = cu;
1845
+ const imports = cu.statements
1846
+ .filter(s => { var _a; return ((_a = s.element) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.Import; })
1847
+ .map(s => s.element);
1848
+ const ofModule = imports.filter(imp => importedModule(imp) === this.from.module);
1849
+ const fromPackage = packageOf(this.from.module);
1850
+ const member = declaredMember(this.from);
1851
+ this.movedTypes = new MovedTypes(this.from, this.to, {
1852
+ module: ofModule.length > 1 || ofModule.some(imp => !isOnlyMember(imp)),
1853
+ // Same-named classes from two subpaths of one package share a name.
1854
+ className: member !== undefined && imports.filter(imp => {
1855
+ const module = importedModule(imp);
1856
+ return module !== undefined && packageOf(module) === fromPackage &&
1857
+ importBinds(imp, module, member) !== undefined;
1858
+ }).length > 1
1859
+ });
1860
+ let visited = await super.visitJsCompilationUnit(cu, p);
1861
+ if (this.dropped !== undefined) {
1862
+ visited = withoutStatement(visited, this.dropped);
1863
+ }
1726
1864
  if (!this.transformedInPlace) {
1727
1865
  bindImport(this, {
1728
1866
  module: this.to.module,
1729
1867
  member: this.to.member,
1730
1868
  alias: this.boundName,
1731
1869
  typeOnly: this.typeOnly,
1732
- onlyIfReferenced: false
1870
+ onlyIfReferenced: false,
1871
+ quoteStyle: this.droppedQuote,
1872
+ // The binding was an ES import, though the file may no longer read as a module without it.
1873
+ style: esmStyle[bindingShape(this.to.member)]
1733
1874
  });
1734
1875
  }
1735
1876
  return visited;
1736
1877
  }
1737
1878
  async visitImportDeclaration(jsImport, p) {
1738
- var _a, _b;
1879
+ var _a;
1739
1880
  const imp = await super.visitImportDeclaration(jsImport, p);
1740
1881
  const key = memberName(this.from.member);
1741
- // One call moves one binding, and no two imports bind the same local name, so the name
1742
- // read from the matched statement is what picks it back out of the file.
1743
- if (importBinds(imp, this.from.module, this.from.member) !== this.localName) {
1882
+ // One call moves one module-scope binding, and no two of those share a local name, so the
1883
+ // name read from the matched statement is what picks it back out of the file.
1884
+ const cu = this.cu;
1885
+ if (!(cu === null || cu === void 0 ? void 0 : cu.statements.some(s => s.element === jsImport)) ||
1886
+ importBinds(imp, this.from.module, this.from.member) !== this.localName) {
1744
1887
  return imp;
1745
1888
  }
1746
- // A moved named specifier's own inline `type` marks it type-only even where the clause
1747
- // it's leaving is not — the replacement needs the same answer to stay type-safe.
1748
- this.typeOnly = ((_b = (_a = imp.importClause) === null || _a === void 0 ? void 0 : _a.typeOnly) !== null && _b !== void 0 ? _b : false) ||
1749
- (key !== undefined && key !== '*' && namedSpecifierIsTypeOnly(imp, key));
1889
+ // The replacement takes the moved binding's `type` marking to stay type-safe.
1890
+ this.typeOnly = bindsTypeOnly(imp, this.from.member);
1750
1891
  if (!isOnlyMember(imp)) {
1751
1892
  return removeBinding(imp, this.from.member);
1752
1893
  }
1894
+ if (replacesStatement(cu, jsImport, this.from, this.to, this.typeOnly)) {
1895
+ this.dropped = imp.id;
1896
+ this.droppedQuote = quoteOf((_a = imp.moduleSpecifier) === null || _a === void 0 ? void 0 : _a.element);
1897
+ return imp;
1898
+ }
1753
1899
  this.transformedInPlace = true;
1754
1900
  return (0, mutative_1.create)(imp, draft => {
1755
1901
  var _a;
@@ -1771,53 +1917,13 @@ class RebindImport extends visitor_1.JavaScriptVisitor {
1771
1917
  });
1772
1918
  }
1773
1919
  async visitIdentifier(identifier, p) {
1774
- if (!this.referencesBinding(identifier)) {
1775
- return super.visitIdentifier(identifier, p);
1776
- }
1777
- this.references.add(identifier.id);
1778
- // The name follows the binding, and so does what the name is attributed to; an aliased
1779
- // binding keeps its name and still resolves somewhere new.
1780
- const type = await this.movedTypes.visit(identifier.type, undefined);
1781
- const fieldType = await this.movedTypes.visit(identifier.fieldType, undefined);
1782
- return !this.renaming && type === identifier.type && fieldType === identifier.fieldType
1783
- ? identifier
1784
- : Object.assign(Object.assign({}, identifier), { simpleName: this.boundName, type, fieldType });
1785
- }
1786
- async visitMethodInvocation(method, p) {
1787
- const m = await super.visitMethodInvocation(method, p);
1788
- if (!this.referencesMovedBinding(m.name)) {
1789
- return m;
1790
- }
1791
- const methodType = await this.movedTypes.visit(m.methodType, undefined);
1792
- return methodType === m.methodType ? m : Object.assign(Object.assign({}, m), { methodType });
1793
- }
1794
- async visitNewClass(newClass, p) {
1795
- const nc = await super.visitNewClass(newClass, p);
1796
- if (!this.referencesMovedBinding(nc.class)) {
1797
- return nc;
1798
- }
1799
- const type = await this.movedTypes.visit(nc.type, undefined);
1800
- const methodType = await this.movedTypes.visit(nc.methodType, undefined);
1801
- const constructorType = await this.movedTypes.visit(nc.constructorType, undefined);
1802
- return type === nc.type && methodType === nc.methodType && constructorType === nc.constructorType
1803
- ? nc
1804
- : Object.assign(Object.assign({}, nc), { type, methodType, constructorType });
1805
- }
1806
- async visitFunctionCall(functionCall, p) {
1807
- var _a;
1808
- const fc = await super.visitFunctionCall(functionCall, p);
1809
- if (!this.referencesMovedBinding((_a = fc.function) === null || _a === void 0 ? void 0 : _a.element)) {
1810
- return fc;
1811
- }
1812
- const methodType = await this.movedTypes.visit(fc.methodType, undefined);
1813
- return methodType === fc.methodType ? fc : Object.assign(Object.assign({}, fc), { methodType });
1920
+ const renamed = this.renaming && this.referencesBinding(identifier);
1921
+ const visited = await super.visitIdentifier(identifier, p);
1922
+ return renamed ? Object.assign(Object.assign({}, visited), { simpleName: this.boundName }) : visited;
1814
1923
  }
1815
- /**
1816
- * Whether `callee` is the identifier `visitIdentifier` settled as a reference to the binding.
1817
- * A rewrite keeps the identifier's id, so the one it settled is the one still standing here.
1818
- */
1819
- referencesMovedBinding(callee) {
1820
- return (callee === null || callee === void 0 ? void 0 : callee.kind) === java_1.J.Kind.Identifier && this.references.has(callee.id);
1924
+ /** Any type in the file can name what moved, whether or not it references the binding. */
1925
+ async visitType(javaType, p) {
1926
+ return this.movedTypes.visit(javaType, undefined);
1821
1927
  }
1822
1928
  /**
1823
1929
  * A decorator and the other type-name positions reach the tree through this hook, which the
@@ -1841,65 +1947,100 @@ class RebindImport extends visitor_1.JavaScriptVisitor {
1841
1947
  }
1842
1948
  const specifier = exportSpecifier.specifier;
1843
1949
  if (specifier.kind === java_1.J.Kind.Identifier && specifier.simpleName === this.localName) {
1844
- return Object.assign(Object.assign({}, exportSpecifier), { specifier: aliasing(specifier, this.boundName) });
1950
+ const retyped = await this.retyped(specifier);
1951
+ const alias = aliasing(retyped, this.boundName);
1952
+ // The property name is the reference here, so it carries the binding's attribution.
1953
+ const reference = Object.assign(Object.assign({}, alias.propertyName.element), { type: retyped.type, fieldType: retyped.fieldType });
1954
+ return Object.assign(Object.assign({}, exportSpecifier), { specifier: Object.assign(Object.assign({}, alias), { propertyName: Object.assign(Object.assign({}, alias.propertyName), { element: reference }) }) });
1845
1955
  }
1846
1956
  if (specifier.kind === tree_1.JS.Kind.Alias) {
1847
1957
  const alias = specifier;
1848
1958
  const propertyName = alias.propertyName.element;
1849
1959
  return propertyName.kind === java_1.J.Kind.Identifier && propertyName.simpleName === this.localName
1850
- ? Object.assign(Object.assign({}, exportSpecifier), { specifier: Object.assign(Object.assign({}, alias), { propertyName: Object.assign(Object.assign({}, alias.propertyName), { element: Object.assign(Object.assign({}, propertyName), { simpleName: this.boundName }) }) }) })
1960
+ ? Object.assign(Object.assign({}, exportSpecifier), { specifier: Object.assign(Object.assign({}, alias), { propertyName: Object.assign(Object.assign({}, alias.propertyName), { element: Object.assign(Object.assign({}, await this.retyped(propertyName)), { simpleName: this.boundName }) }) }) })
1851
1961
  : exportSpecifier;
1852
1962
  }
1853
1963
  return super.visitExportSpecifier(exportSpecifier, p);
1854
1964
  }
1965
+ /** `identifier` attributed to what moved, for a rewrite that does not visit it again. */
1966
+ async retyped(identifier) {
1967
+ return Object.assign(Object.assign({}, identifier), { type: await this.movedTypes.visit(identifier.type, undefined), fieldType: await this.movedTypes.visit(identifier.fieldType, undefined) });
1968
+ }
1855
1969
  /**
1856
1970
  * Whether the identifier at the cursor stands for the moved binding: the right name, in a
1857
- * position that references rather than declares, reaching the module scope that binds it.
1971
+ * position a rename may rewrite, resolving to the module scope that binds it.
1858
1972
  */
1859
1973
  referencesBinding(identifier) {
1974
+ return identifier.simpleName === this.localName && this.readsModuleBinding(identifier);
1975
+ }
1976
+ readsModuleBinding(identifier) {
1860
1977
  var _a;
1861
- return identifier.simpleName === this.localName &&
1862
- // The specifier binding the name is the one edit that is not a reference to it.
1863
- !this.cursor.firstEnclosing((v) => (v === null || v === void 0 ? void 0 : v.kind) === tree_1.JS.Kind.Import) &&
1864
- (0, scope_1.isValueReference)(this.cursor, identifier) &&
1865
- ((_a = (0, scope_1.scopeOf)(this.cursor).declaringScope(this.localName)) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.CompilationUnit;
1978
+ return ((_a = (0, scope_1.resolve)(this.cursor, identifier)) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.CompilationUnit;
1866
1979
  }
1867
- /** A shorthand property's name slot is also the reference to the binding. */
1980
+ /**
1981
+ * A shorthand property's name slot is also the reference to the binding: `{x}` becomes
1982
+ * `{x: y}`, and `{x = 1}` becomes `{x: y = 1}`.
1983
+ */
1868
1984
  async visitPropertyAssignment(propertyAssignment, p) {
1869
- var _a;
1870
1985
  const name = propertyAssignment.name.element;
1871
- if (this.renaming && propertyAssignment.initializer === undefined &&
1986
+ if (this.renaming && propertyAssignment.assigmentToken === tree_1.JS.PropertyAssignment.Token.Equals &&
1872
1987
  name.kind === java_1.J.Kind.Identifier && name.simpleName === this.localName &&
1873
- ((_a = (0, scope_1.scopeOf)(this.cursor).declaringScope(this.localName)) === null || _a === void 0 ? void 0 : _a.kind) === tree_1.JS.Kind.CompilationUnit) {
1874
- // The key names a property rather than the binding, so it carries no attribution,
1875
- // the same way `aliasing` builds a property name that stands for nothing.
1876
- return Object.assign(Object.assign({}, propertyAssignment), { name: Object.assign(Object.assign({}, propertyAssignment.name), { element: Object.assign(Object.assign({}, name), { type: undefined, fieldType: undefined }) }), assigmentToken: tree_1.JS.PropertyAssignment.Token.Colon, initializer: Object.assign(Object.assign({}, name), { prefix: java_1.singleSpace, simpleName: this.boundName }) });
1988
+ this.readsModuleBinding(name)) {
1989
+ const reference = Object.assign(Object.assign({}, await this.retyped(name)), { simpleName: this.boundName });
1990
+ const fallback = propertyAssignment.initializer;
1991
+ // The key names a property rather than the binding, so it is a new node carrying no
1992
+ // attribution, the same way `aliasing` builds a property name that stands for nothing.
1993
+ return Object.assign(Object.assign({}, propertyAssignment), { name: Object.assign(Object.assign({}, propertyAssignment.name), { element: Object.assign(Object.assign({}, name), { id: (0, uuid_1.randomId)(), type: undefined, fieldType: undefined }), after: java_1.emptySpace }), assigmentToken: tree_1.JS.PropertyAssignment.Token.Colon, initializer: fallback === undefined ? Object.assign(Object.assign({}, reference), { prefix: java_1.singleSpace }) : {
1994
+ id: (0, uuid_1.randomId)(),
1995
+ kind: java_1.J.Kind.Assignment,
1996
+ prefix: java_1.singleSpace,
1997
+ markers: markers_1.emptyMarkers,
1998
+ variable: Object.assign(Object.assign({}, reference), { prefix: java_1.emptySpace }),
1999
+ assignment: {
2000
+ kind: java_1.J.Kind.LeftPadded,
2001
+ before: propertyAssignment.name.after,
2002
+ element: fallback,
2003
+ markers: markers_1.emptyMarkers
2004
+ },
2005
+ type: reference.type
2006
+ } });
1877
2007
  }
1878
2008
  return super.visitPropertyAssignment(propertyAssignment, p);
1879
2009
  }
1880
2010
  }
1881
2011
  exports.RebindImport = RebindImport;
1882
- /**
1883
- * Rewrites the attribution a move invalidates, onto the module and member it moved to. Applied at
1884
- * a reference to the moved binding. See CLAUDE.md: What a rebind's attribution follows.
1885
- */
2012
+ /** Rewrites a file's attribution onto the module and member a binding moved to. */
1886
2013
  class MovedTypes extends type_visitor_1.TypeVisitor {
1887
- constructor(from, to) {
2014
+ /**
2015
+ * `shared` says what another binding in the file shares with the moved one. A shared module
2016
+ * object or package-qualified class name stands for that binding too, so it keeps its name.
2017
+ */
2018
+ constructor(from, to, shared) {
2019
+ var _a;
1888
2020
  super();
2021
+ this.from = from;
2022
+ this.to = to;
1889
2023
  this.onPath = new Set();
1890
2024
  this.answered = new Map();
1891
- // Where no member is named the two keys coincide, and both name the module.
1892
- this.renamed = new Map([[from.module, to.module], [qualifiedName(from), qualifiedName(to)]]);
2025
+ this.modules = new Map();
1893
2026
  this.fromMember = declaredMember(from);
1894
2027
  this.toMember = declaredMember(to);
1895
- this.toModule = to.module;
2028
+ if (this.fromMember === undefined) {
2029
+ this.classes = new Map(shared.module ? [] : [[from.module, qualifiedName(to)]]);
2030
+ }
2031
+ else {
2032
+ // A default export declares no member name, so the class keeps its own.
2033
+ const toClass = `${packageOf(to.module)}.${(_a = this.toMember) !== null && _a !== void 0 ? _a : this.fromMember}`;
2034
+ const packaged = `${packageOf(from.module)}.${this.fromMember}`;
2035
+ // The type mapper names an imported alias symbol after the specifier.
2036
+ this.classes = new Map([packaged, qualifiedName(from)]
2037
+ .filter(name => !shared.className || name !== packaged)
2038
+ .map(name => [name, toClass]));
2039
+ }
1896
2040
  }
1897
2041
  /**
1898
- * A type reached while it is still being visited is a cycle — a class holds a method whose
1899
- * declaring type is that class — and answers with itself, which is what ends the walk. Every
1900
- * type visited is remembered by its answer, so a graph whose references fan out or rejoin is
1901
- * walked once rather than once per path that reaches into it. An answer settled inside a cycle
1902
- * stands for the path it was on, so a walk reusing it can leave a rename unapplied.
2042
+ * A type reached while it is still being visited answers with itself, which ends a cycle
2043
+ * through a type variable's bounds. An answer settled inside such a cycle can miss a rename.
1903
2044
  */
1904
2045
  async visit(type, p) {
1905
2046
  if (type === undefined || this.onPath.has(type)) {
@@ -1918,35 +2059,54 @@ class MovedTypes extends type_visitor_1.TypeVisitor {
1918
2059
  this.onPath.delete(type);
1919
2060
  }
1920
2061
  }
2062
+ /** A class's members are left out, which keeps the walk to a type's signature, as in Java's `ChangeType`. */
1921
2063
  async visitClass(aClass, p) {
1922
- const visited = await super.visitClass(aClass, p);
1923
- const moved = this.renamed.get(visited.fullyQualifiedName);
1924
- return moved === undefined || moved === visited.fullyQualifiedName
1925
- ? visited
1926
- : Object.assign(Object.assign({}, visited), { fullyQualifiedName: moved });
2064
+ const visited = (0, util_1.updateIfChanged)(aClass, {
2065
+ supertype: await this.visit(aClass.supertype, p),
2066
+ owningClass: await this.visit(aClass.owningClass, p),
2067
+ interfaces: aClass.interfaces && await (0, util_1.mapAsync)(aClass.interfaces, i => this.visit(i, p)),
2068
+ typeParameters: aClass.typeParameters && await (0, util_1.mapAsync)(aClass.typeParameters, t => this.visit(t, p))
2069
+ });
2070
+ const moved = this.classes.get(visited.fullyQualifiedName);
2071
+ return moved === undefined ? visited : Object.assign(Object.assign({}, visited), { fullyQualifiedName: moved });
1927
2072
  }
1928
2073
  async visitMethod(method, p) {
2074
+ var _a;
1929
2075
  const visited = await super.visitMethod(method, p);
1930
- return this.declaresMovedMember(visited.name, visited.declaringType)
1931
- ? Object.assign(Object.assign({}, visited), { name: this.toMember })
1932
- : visited;
2076
+ if (!this.isMovedMember(method.name, method.declaringType)) {
2077
+ return visited;
2078
+ }
2079
+ const declaringType = this.movedModule(method.declaringType);
2080
+ return Object.assign(Object.assign({}, visited), { declaringType, name: (_a = this.toMember) !== null && _a !== void 0 ? _a : visited.name });
1933
2081
  }
1934
2082
  async visitVariable(variable, p) {
2083
+ var _a;
1935
2084
  const visited = await super.visitVariable(variable, p);
1936
- return this.declaresMovedMember(visited.name, visited.owner)
1937
- ? Object.assign(Object.assign({}, visited), { name: this.toMember })
1938
- : visited;
2085
+ if (!this.isMovedMember(variable.name, variable.owner)) {
2086
+ return visited;
2087
+ }
2088
+ return Object.assign(Object.assign({}, visited), { owner: this.movedModule(variable.owner), name: (_a = this.toMember) !== null && _a !== void 0 ? _a : visited.name });
1939
2089
  }
1940
2090
  /**
1941
- * Whether `name`, declared on `owner`, is the member that moved. `owner` has already followed
1942
- * the move by the time this runs, so it is the module moved *to* that it has to name. A
1943
- * default or namespace binding declares no member, so there is no name for one to take.
2091
+ * Whether `name` is the moved member as the module object `owner` declares it. That covers a
2092
+ * function, a constant and a moved class's constructor. A sibling declared beside it is not one.
1944
2093
  */
1945
- declaresMovedMember(name, owner) {
1946
- return this.toMember !== undefined && name === this.fromMember && this.toMember !== this.fromMember &&
1947
- owner !== undefined && java_1.Type.isFullyQualified(owner) &&
1948
- java_1.Type.FullyQualified.getFullyQualifiedName(owner) === this.toModule;
2094
+ isMovedMember(name, owner) {
2095
+ return this.fromMember !== undefined && name === this.fromMember && owner !== undefined &&
2096
+ java_1.Type.isFullyQualified(owner) && java_1.Type.FullyQualified.getFullyQualifiedName(owner) === this.from.module;
1949
2097
  }
2098
+ movedModule(owner) {
2099
+ let moved = this.modules.get(owner);
2100
+ if (moved === undefined) {
2101
+ moved = Object.assign(Object.assign({}, owner), { fullyQualifiedName: this.to.module });
2102
+ this.modules.set(owner, moved);
2103
+ }
2104
+ return moved;
2105
+ }
2106
+ }
2107
+ /** The package a class `module` exports is named after. A relative specifier names none, so it stands for itself. */
2108
+ function packageOf(module) {
2109
+ return module.startsWith('.') || module.startsWith('/') ? module : (0, package_name_1.packageNameOf)(module);
1950
2110
  }
1951
2111
  /** A member's qualified name, or the module's own where no member is named. */
1952
2112
  function qualifiedName(binding) {