@openrewrite/rewrite 8.70.0-20251222-101414 → 8.70.0-20251222-213047

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 (149) hide show
  1. package/dist/index.js +8 -8
  2. package/dist/index.js.map +1 -1
  3. package/dist/java/formatting-utils.d.ts +1 -1
  4. package/dist/java/formatting-utils.js +4 -4
  5. package/dist/java/formatting-utils.js.map +1 -1
  6. package/dist/java/markers.js +8 -8
  7. package/dist/java/markers.js.map +1 -1
  8. package/dist/java/type-visitor.d.ts +0 -3
  9. package/dist/java/type-visitor.d.ts.map +1 -1
  10. package/dist/java/type-visitor.js +67 -68
  11. package/dist/java/type-visitor.js.map +1 -1
  12. package/dist/java/visitor.d.ts +3 -3
  13. package/dist/java/visitor.d.ts.map +1 -1
  14. package/dist/java/visitor.js +5 -5
  15. package/dist/java/visitor.js.map +1 -1
  16. package/dist/javascript/assertions.js +4 -3
  17. package/dist/javascript/assertions.js.map +1 -1
  18. package/dist/javascript/cleanup/use-object-property-shorthand.js +3 -3
  19. package/dist/javascript/cleanup/use-object-property-shorthand.js.map +1 -1
  20. package/dist/javascript/format/format.d.ts +28 -7
  21. package/dist/javascript/format/format.d.ts.map +1 -1
  22. package/dist/javascript/format/format.js +149 -158
  23. package/dist/javascript/format/format.js.map +1 -1
  24. package/dist/javascript/format/minimum-viable-spacing-visitor.js +23 -23
  25. package/dist/javascript/format/minimum-viable-spacing-visitor.js.map +1 -1
  26. package/dist/javascript/format/prettier-format.d.ts.map +1 -1
  27. package/dist/javascript/format/prettier-format.js +8 -11
  28. package/dist/javascript/format/prettier-format.js.map +1 -1
  29. package/dist/javascript/format/tabs-and-indents-visitor.js +7 -7
  30. package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
  31. package/dist/javascript/format/whitespace-reconciler.d.ts.map +1 -1
  32. package/dist/javascript/format/whitespace-reconciler.js +12 -11
  33. package/dist/javascript/format/whitespace-reconciler.js.map +1 -1
  34. package/dist/javascript/markers.d.ts.map +1 -1
  35. package/dist/javascript/markers.js +6 -5
  36. package/dist/javascript/markers.js.map +1 -1
  37. package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js +2 -2
  38. package/dist/javascript/migrate/es6/modernize-octal-escape-sequences.js.map +1 -1
  39. package/dist/javascript/migrate/es6/modernize-octal-literals.js +2 -2
  40. package/dist/javascript/migrate/es6/modernize-octal-literals.js.map +1 -1
  41. package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js +2 -2
  42. package/dist/javascript/migrate/es6/remove-duplicate-object-keys.js.map +1 -1
  43. package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js +2 -2
  44. package/dist/javascript/migrate/typescript/export-assignment-to-export-default.js.map +1 -1
  45. package/dist/javascript/node-resolution-result.js +3 -9
  46. package/dist/javascript/node-resolution-result.js.map +1 -1
  47. package/dist/javascript/parser.d.ts.map +1 -1
  48. package/dist/javascript/parser.js +35 -35
  49. package/dist/javascript/parser.js.map +1 -1
  50. package/dist/javascript/project-parser.d.ts.map +1 -1
  51. package/dist/javascript/project-parser.js +6 -5
  52. package/dist/javascript/project-parser.js.map +1 -1
  53. package/dist/javascript/recipes/auto-format.d.ts +7 -23
  54. package/dist/javascript/recipes/auto-format.d.ts.map +1 -1
  55. package/dist/javascript/recipes/auto-format.js +8 -54
  56. package/dist/javascript/recipes/auto-format.js.map +1 -1
  57. package/dist/javascript/recipes/change-import.js +8 -8
  58. package/dist/javascript/recipes/change-import.js.map +1 -1
  59. package/dist/javascript/recipes/order-imports.js +4 -4
  60. package/dist/javascript/recipes/order-imports.js.map +1 -1
  61. package/dist/javascript/templating/engine.js +2 -2
  62. package/dist/javascript/templating/engine.js.map +1 -1
  63. package/dist/javascript/templating/index.d.ts +1 -0
  64. package/dist/javascript/templating/index.d.ts.map +1 -1
  65. package/dist/javascript/templating/index.js +4 -1
  66. package/dist/javascript/templating/index.js.map +1 -1
  67. package/dist/javascript/templating/placeholder-replacement.js +16 -16
  68. package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
  69. package/dist/javascript/type-mapping.d.ts.map +1 -1
  70. package/dist/javascript/type-mapping.js +49 -58
  71. package/dist/javascript/type-mapping.js.map +1 -1
  72. package/dist/javascript/visitor.d.ts +3 -3
  73. package/dist/javascript/visitor.d.ts.map +1 -1
  74. package/dist/javascript/visitor.js +3 -3
  75. package/dist/javascript/visitor.js.map +1 -1
  76. package/dist/json/rpc.js +48 -49
  77. package/dist/json/rpc.js.map +1 -1
  78. package/dist/json/visitor.d.ts +3 -3
  79. package/dist/json/visitor.d.ts.map +1 -1
  80. package/dist/json/visitor.js +3 -3
  81. package/dist/json/visitor.js.map +1 -1
  82. package/dist/parse-error.js +11 -11
  83. package/dist/parse-error.js.map +1 -1
  84. package/dist/reference.d.ts.map +1 -1
  85. package/dist/reference.js +0 -3
  86. package/dist/reference.js.map +1 -1
  87. package/dist/rpc/index.js +42 -42
  88. package/dist/rpc/index.js.map +1 -1
  89. package/dist/rpc/queue.d.ts.map +1 -1
  90. package/dist/rpc/queue.js +6 -8
  91. package/dist/rpc/queue.js.map +1 -1
  92. package/dist/rpc/request/install-recipes.js +1 -1
  93. package/dist/rpc/request/install-recipes.js.map +1 -1
  94. package/dist/rpc/request/parse-project.d.ts.map +1 -1
  95. package/dist/rpc/request/parse-project.js +12 -32
  96. package/dist/rpc/request/parse-project.js.map +1 -1
  97. package/dist/rpc/request/parse.d.ts.map +1 -1
  98. package/dist/rpc/request/parse.js +1 -4
  99. package/dist/rpc/request/parse.js.map +1 -1
  100. package/dist/text/rpc.js +18 -18
  101. package/dist/text/rpc.js.map +1 -1
  102. package/dist/version.txt +1 -1
  103. package/dist/visitor.d.ts +6 -4
  104. package/dist/visitor.d.ts.map +1 -1
  105. package/dist/visitor.js +19 -17
  106. package/dist/visitor.js.map +1 -1
  107. package/dist/yaml/rpc.js +65 -65
  108. package/dist/yaml/rpc.js.map +1 -1
  109. package/package.json +2 -2
  110. package/src/index.ts +8 -8
  111. package/src/java/formatting-utils.ts +2 -2
  112. package/src/java/markers.ts +8 -8
  113. package/src/java/type-visitor.ts +59 -68
  114. package/src/java/visitor.ts +8 -8
  115. package/src/javascript/assertions.ts +3 -3
  116. package/src/javascript/cleanup/use-object-property-shorthand.ts +1 -1
  117. package/src/javascript/format/format.ts +109 -107
  118. package/src/javascript/format/minimum-viable-spacing-visitor.ts +1 -1
  119. package/src/javascript/format/prettier-format.ts +9 -12
  120. package/src/javascript/format/tabs-and-indents-visitor.ts +1 -1
  121. package/src/javascript/format/whitespace-reconciler.ts +12 -11
  122. package/src/javascript/markers.ts +6 -6
  123. package/src/javascript/migrate/es6/modernize-octal-escape-sequences.ts +1 -1
  124. package/src/javascript/migrate/es6/modernize-octal-literals.ts +1 -1
  125. package/src/javascript/migrate/es6/remove-duplicate-object-keys.ts +1 -1
  126. package/src/javascript/migrate/typescript/export-assignment-to-export-default.ts +1 -1
  127. package/src/javascript/node-resolution-result.ts +8 -14
  128. package/src/javascript/parser.ts +5 -4
  129. package/src/javascript/project-parser.ts +4 -4
  130. package/src/javascript/recipes/auto-format.ts +9 -71
  131. package/src/javascript/recipes/change-import.ts +4 -4
  132. package/src/javascript/recipes/order-imports.ts +1 -1
  133. package/src/javascript/templating/engine.ts +1 -1
  134. package/src/javascript/templating/index.ts +5 -0
  135. package/src/javascript/templating/placeholder-replacement.ts +2 -2
  136. package/src/javascript/type-mapping.ts +28 -34
  137. package/src/javascript/visitor.ts +6 -6
  138. package/src/json/rpc.ts +51 -52
  139. package/src/json/visitor.ts +6 -6
  140. package/src/parse-error.ts +11 -11
  141. package/src/reference.ts +0 -5
  142. package/src/rpc/index.ts +43 -43
  143. package/src/rpc/queue.ts +6 -8
  144. package/src/rpc/request/install-recipes.ts +1 -1
  145. package/src/rpc/request/parse-project.ts +20 -32
  146. package/src/rpc/request/parse.ts +1 -4
  147. package/src/text/rpc.ts +18 -18
  148. package/src/visitor.ts +29 -30
  149. package/src/yaml/rpc.ts +80 -81
@@ -20,7 +20,7 @@ import {ExecutionContext} from "../../execution";
20
20
  import {JavaScriptVisitor} from "../visitor";
21
21
  import {J} from "../../java";
22
22
  import {JS} from "../tree";
23
- import {produce} from "immer";
23
+ import {create as produce} from "mutative";
24
24
  import {findMarker} from "../../markers";
25
25
 
26
26
  /**
@@ -16,7 +16,7 @@
16
16
  import {JS} from "../tree";
17
17
  import {JavaScriptVisitor} from "../visitor";
18
18
  import {Comment, J, lastWhitespace, replaceLastWhitespace, Statement} from "../../java";
19
- import {Draft, produce} from "immer";
19
+ import {create as produce, Draft} from "mutative";
20
20
  import {Cursor, isScope, Tree} from "../../tree";
21
21
  import {BlankLinesStyle, getStyle, SpacesStyle, StyleKind, TabsAndIndentsStyle, WrappingAndBracesStyle} from "../style";
22
22
  import {NamedStyles} from "../../style";
@@ -296,28 +296,31 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
296
296
  }
297
297
  }
298
298
  oneInit.after.whitespace = "";
299
- return await this.spaceBeforeRightPaddedElement(oneInit, index === 0 ? this.style.within.forParentheses : true);
299
+ this.spaceBeforeRightPaddedElementDraft(oneInit, index === 0 ? this.style.within.forParentheses : true);
300
+ return oneInit;
300
301
  }));
301
302
  if (draft.control.condition) {
302
303
  draft.control.condition.element.prefix.whitespace = " ";
303
304
  draft.control.condition.after.whitespace = this.style.other.beforeForSemicolon ? " " : "";
304
305
  }
305
- draft.control.update = await Promise.all(draft.control.update.map(async (oneUpdate, index) => {
306
+ draft.control.update.forEach((oneUpdate, index) => {
306
307
  oneUpdate.element.prefix.whitespace = " ";
307
308
  oneUpdate.after.whitespace = (index === draft.control.update.length - 1 ? this.style.within.forParentheses : this.style.other.beforeForSemicolon) ? " " : "";
308
- return oneUpdate;
309
- }));
309
+ });
310
310
 
311
- draft.body = await this.spaceAfterRightPadded(await this.spaceBeforeRightPaddedElement(ret.body, this.style.beforeLeftBrace.forLeftBrace), false);
311
+ this.spaceBeforeRightPaddedElementDraft(draft.body, this.style.beforeLeftBrace.forLeftBrace);
312
+ this.spaceAfterRightPaddedDraft(draft.body, false);
312
313
  });
313
314
  }
314
315
 
315
316
  protected async visitIf(iff: J.If, p: P): Promise<J | undefined> {
316
317
  const ret = await super.visitIf(iff, p) as J.If;
317
318
  return produceAsync(ret, async draft => {
318
- draft.ifCondition = await this.spaceBefore(draft.ifCondition, this.style.beforeParentheses.ifParentheses);
319
- draft.ifCondition.tree = await this.spaceAfterRightPadded(await this.spaceBeforeRightPaddedElement(draft.ifCondition.tree, this.style.within.ifParentheses), this.style.within.ifParentheses);
320
- draft.thenPart = await this.spaceAfterRightPadded(await this.spaceBeforeRightPaddedElement(ret.thenPart, this.style.beforeLeftBrace.ifLeftBrace), false);
319
+ this.spaceBeforeDraft(draft.ifCondition, this.style.beforeParentheses.ifParentheses);
320
+ this.spaceBeforeRightPaddedElementDraft(draft.ifCondition.tree, this.style.within.ifParentheses);
321
+ this.spaceAfterRightPaddedDraft(draft.ifCondition.tree, this.style.within.ifParentheses);
322
+ this.spaceBeforeRightPaddedElementDraft(draft.thenPart, this.style.beforeLeftBrace.ifLeftBrace);
323
+ this.spaceAfterRightPaddedDraft(draft.thenPart, false);
321
324
  });
322
325
  }
323
326
 
@@ -378,20 +381,22 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
378
381
  protected async visitMethodDeclaration(methodDecl: J.MethodDeclaration, p: P): Promise<J | undefined> {
379
382
  const ret = await super.visitMethodDeclaration(methodDecl, p) as J.MethodDeclaration;
380
383
  return produceAsync(ret, async draft => {
381
- draft.body = ret.body && await this.spaceBefore(ret.body, this.style.beforeLeftBrace.functionLeftBrace);
384
+ if (draft.body) {
385
+ this.spaceBeforeDraft(draft.body, this.style.beforeLeftBrace.functionLeftBrace);
386
+ }
382
387
 
383
388
  if (draft.parameters.elements.length > 0 && draft.parameters.elements[0].element.kind != J.Kind.Empty) {
384
- draft.parameters.elements = await Promise.all(draft.parameters.elements.map(async (param, index) => {
385
- param = await this.spaceAfterRightPadded(param, index === draft.parameters.elements.length - 1 ? this.style.within.functionDeclarationParentheses : this.style.other.beforeComma);
386
- param.element = await this.spaceBefore(param.element, index === 0 ? this.style.within.functionDeclarationParentheses : this.style.other.afterComma);
389
+ draft.parameters.elements.forEach((param, index) => {
390
+ this.spaceAfterRightPaddedDraft(param, index === draft.parameters.elements.length - 1 ? this.style.within.functionDeclarationParentheses : this.style.other.beforeComma);
391
+ this.spaceBeforeDraft(param.element, index === 0 ? this.style.within.functionDeclarationParentheses : this.style.other.afterComma);
387
392
  (param.element as Draft<J.VariableDeclarations>).variables[0].element.name.prefix.whitespace = "";
388
393
  (param.element as Draft<J.VariableDeclarations>).variables[0].after.whitespace = "";
389
- return param;
390
- }));
394
+ });
391
395
  } else if (draft.parameters.elements.length == 1) {
392
- draft.parameters.elements[0] = await this.spaceAfterRightPadded(await this.spaceBeforeRightPaddedElement(draft.parameters.elements[0], this.style.within.functionDeclarationParentheses), false);
396
+ this.spaceBeforeRightPaddedElementDraft(draft.parameters.elements[0], this.style.within.functionDeclarationParentheses);
397
+ this.spaceAfterRightPaddedDraft(draft.parameters.elements[0], false);
393
398
  }
394
- draft.parameters = await this.spaceBeforeContainer(draft.parameters, this.style.beforeParentheses.functionDeclarationParentheses);
399
+ this.spaceBeforeContainerDraft(draft.parameters, this.style.beforeParentheses.functionDeclarationParentheses);
395
400
 
396
401
  // Handle generator asterisk spacing
397
402
  // - space before * is in the Generator marker's prefix
@@ -411,16 +416,16 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
411
416
  const ret = await super.visitMethodInvocation(methodInv, p) as J.MethodInvocation;
412
417
  return produceAsync(ret, async draft => {
413
418
  if (draft.select) {
414
- draft.arguments = await this.spaceBeforeContainer(draft.arguments, this.style.beforeParentheses.functionCallParentheses);
419
+ this.spaceBeforeContainerDraft(draft.arguments, this.style.beforeParentheses.functionCallParentheses);
415
420
  }
416
421
  if (ret.arguments.elements.length > 0 && ret.arguments.elements[0].element.kind != J.Kind.Empty) {
417
- draft.arguments.elements = await Promise.all(draft.arguments.elements.map(async (arg, index) => {
418
- arg = await this.spaceAfterRightPadded(arg, index === draft.arguments.elements.length - 1 ? this.style.within.functionCallParentheses : this.style.other.beforeComma);
419
- arg.element = await this.spaceBefore(arg.element, index === 0 ? this.style.within.functionCallParentheses : this.style.other.afterComma);
420
- return arg;
421
- }));
422
+ draft.arguments.elements.forEach((arg, index) => {
423
+ this.spaceAfterRightPaddedDraft(arg, index === draft.arguments.elements.length - 1 ? this.style.within.functionCallParentheses : this.style.other.beforeComma);
424
+ this.spaceBeforeDraft(arg.element, index === 0 ? this.style.within.functionCallParentheses : this.style.other.afterComma);
425
+ });
422
426
  } else if (ret.arguments.elements.length == 1) {
423
- draft.arguments.elements[0] = await this.spaceAfterRightPadded(await this.spaceBeforeRightPaddedElement(draft.arguments.elements[0], this.style.within.functionCallParentheses), false);
427
+ this.spaceBeforeRightPaddedElementDraft(draft.arguments.elements[0], this.style.within.functionCallParentheses);
428
+ this.spaceAfterRightPaddedDraft(draft.arguments.elements[0], false);
424
429
  }
425
430
  // TODO typeParameters handling - see visitClassDeclaration
426
431
  });
@@ -440,12 +445,10 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
440
445
  protected async visitSwitch(switchNode: J.Switch, p: P): Promise<J | undefined> {
441
446
  const ret = await super.visitSwitch(switchNode, p) as J.Switch;
442
447
  return produceAsync(ret, async draft => {
443
- draft.selector = await this.spaceBefore(draft.selector, this.style.beforeParentheses.switchParentheses);
444
- draft.selector.tree = await this.spaceAfterRightPadded(
445
- await this.spaceBeforeRightPaddedElement(draft.selector.tree, this.style.within.switchParentheses),
446
- this.style.within.switchParentheses
447
- );
448
- draft.cases = await this.spaceBefore(draft.cases, this.style.beforeLeftBrace.switchLeftBrace);
448
+ this.spaceBeforeDraft(draft.selector, this.style.beforeParentheses.switchParentheses);
449
+ this.spaceBeforeRightPaddedElementDraft(draft.selector.tree, this.style.within.switchParentheses);
450
+ this.spaceAfterRightPaddedDraft(draft.selector.tree, this.style.within.switchParentheses);
451
+ this.spaceBeforeDraft(draft.cases, this.style.beforeLeftBrace.switchLeftBrace);
449
452
 
450
453
  for (const case_ of draft.cases.statements) {
451
454
  if (case_.element.kind === J.Kind.Case) {
@@ -458,8 +461,8 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
458
461
  protected async visitTernary(ternary: J.Ternary, p: P): Promise<J | undefined> {
459
462
  const ret = await super.visitTernary(ternary, p) as J.Ternary;
460
463
  return produceAsync(ret, async draft => {
461
- draft.truePart = await this.spaceBeforeLeftPaddedElement(draft.truePart, this.style.ternaryOperator.beforeQuestionMark, this.style.ternaryOperator.afterQuestionMark);
462
- draft.falsePart = await this.spaceBeforeLeftPaddedElement(draft.falsePart, this.style.ternaryOperator.beforeColon, this.style.ternaryOperator.afterColon);
464
+ this.spaceBeforeLeftPaddedElementDraft(draft.truePart, this.style.ternaryOperator.beforeQuestionMark, this.style.ternaryOperator.afterQuestionMark);
465
+ this.spaceBeforeLeftPaddedElementDraft(draft.falsePart, this.style.ternaryOperator.beforeColon, this.style.ternaryOperator.afterColon);
463
466
  });
464
467
  }
465
468
 
@@ -467,17 +470,19 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
467
470
  const ret = await super.visitTry(try_, p) as J.Try;
468
471
  return produceAsync(ret, async draft => {
469
472
  draft.body.prefix.whitespace = this.style.beforeLeftBrace.tryLeftBrace ? " " : "";
470
- draft.catches = await Promise.all(draft.catches.map(async (catch_, index) => {
471
- catch_ = await this.spaceBefore(catch_, this.style.beforeKeywords.catchKeyword);
473
+ draft.catches.forEach(catch_ => {
474
+ this.spaceBeforeDraft(catch_, this.style.beforeKeywords.catchKeyword);
472
475
  catch_.parameter.prefix.whitespace = this.style.beforeParentheses.catchParentheses ? " " : "";
473
- catch_.parameter.tree = await this.spaceAfterRightPadded(await this.spaceBeforeRightPaddedElement(catch_.parameter.tree, this.style.within.catchParentheses), this.style.within.catchParentheses);
476
+ this.spaceBeforeRightPaddedElementDraft(catch_.parameter.tree, this.style.within.catchParentheses);
477
+ this.spaceAfterRightPaddedDraft(catch_.parameter.tree, this.style.within.catchParentheses);
474
478
  if (catch_.parameter.tree.element.variables.length > 0) {
475
479
  catch_.parameter.tree.element.variables[catch_.parameter.tree.element.variables.length - 1].after.whitespace = "";
476
480
  }
477
481
  catch_.body.prefix.whitespace = this.style.beforeLeftBrace.catchLeftBrace ? " " : "";
478
- return catch_;
479
- }));
480
- draft.finally = draft.finally && await this.spaceBeforeLeftPaddedElement(draft.finally, this.style.beforeKeywords.finallyKeyword, this.style.beforeLeftBrace.finallyLeftBrace) as Draft<J.LeftPadded<J.Block>>;
482
+ });
483
+ if (draft.finally) {
484
+ this.spaceBeforeLeftPaddedElementDraft(draft.finally, this.style.beforeKeywords.finallyKeyword, this.style.beforeLeftBrace.finallyLeftBrace);
485
+ }
481
486
  });
482
487
  }
483
488
 
@@ -502,7 +507,7 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
502
507
  const ret = await super.visitTypeInfo(typeInfo, p) as JS.TypeInfo;
503
508
  return produceAsync(ret, async draft => {
504
509
  draft.prefix.whitespace = this.style.other.beforeTypeReferenceColon ? " " : "";
505
- draft.typeIdentifier = await this.spaceBefore(draft.typeIdentifier, this.style.other.afterTypeReferenceColon);
510
+ this.spaceBeforeDraft(draft.typeIdentifier, this.style.other.afterTypeReferenceColon);
506
511
  });
507
512
  }
508
513
 
@@ -571,9 +576,11 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
571
576
  protected async visitWhileLoop(whileLoop: J.WhileLoop, p: P): Promise<J | undefined> {
572
577
  const ret = await super.visitWhileLoop(whileLoop, p) as J.WhileLoop;
573
578
  return produceAsync(ret, async draft => {
574
- draft.body = await this.spaceAfterRightPadded(await this.spaceBeforeRightPaddedElement(ret.body, this.style.beforeLeftBrace.whileLeftBrace), false);
575
- draft.condition = await this.spaceBefore(draft.condition, this.style.beforeParentheses.whileParentheses);
576
- draft.condition.tree = await this.spaceAfterRightPadded(await this.spaceBeforeRightPaddedElement(draft.condition.tree, this.style.within.whileParentheses), this.style.within.whileParentheses);
579
+ this.spaceBeforeRightPaddedElementDraft(draft.body, this.style.beforeLeftBrace.whileLeftBrace);
580
+ this.spaceAfterRightPaddedDraft(draft.body, false);
581
+ this.spaceBeforeDraft(draft.condition, this.style.beforeParentheses.whileParentheses);
582
+ this.spaceBeforeRightPaddedElementDraft(draft.condition.tree, this.style.within.whileParentheses);
583
+ this.spaceAfterRightPaddedDraft(draft.condition.tree, this.style.within.whileParentheses);
577
584
  });
578
585
  }
579
586
 
@@ -601,94 +608,89 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
601
608
  });
602
609
  }
603
610
 
604
- private async spaceAfterRightPadded<T extends J>(right: J.RightPadded<T>, spaceAfter: boolean): Promise<J.RightPadded<T>> {
605
- if (right.after.comments.length > 0) {
611
+ /**
612
+ * Modifies the after space of a RightPadded draft in place.
613
+ */
614
+ private spaceAfterRightPaddedDraft<T extends J>(draft: Draft<J.RightPadded<T>>, spaceAfter: boolean): void {
615
+ if (draft.after.comments.length > 0) {
606
616
  // Perform the space rule for the suffix of the last comment only. Same as IntelliJ.
607
- const comments = SpacesVisitor.spaceLastCommentSuffix(right.after.comments, spaceAfter);
608
- return {...right, after: {...right.after, comments}};
617
+ SpacesVisitor.spaceLastCommentSuffixDraft(draft.after.comments, spaceAfter);
618
+ return;
609
619
  }
610
620
 
611
- if (spaceAfter && SpacesVisitor.isNotSingleSpace(right.after.whitespace)) {
612
- return {...right, after: {...right.after, whitespace: " "}};
613
- } else if (!spaceAfter && SpacesVisitor.isOnlySpacesAndNotEmpty(right.after.whitespace)) {
614
- return {...right, after: {...right.after, whitespace: ""}};
615
- } else {
616
- return right;
621
+ if (spaceAfter && SpacesVisitor.isNotSingleSpace(draft.after.whitespace)) {
622
+ draft.after.whitespace = " ";
623
+ } else if (!spaceAfter && SpacesVisitor.isOnlySpacesAndNotEmpty(draft.after.whitespace)) {
624
+ draft.after.whitespace = "";
617
625
  }
618
626
  }
619
627
 
620
- private async spaceBeforeLeftPaddedElement<T extends J>(left: J.LeftPadded<T>, spaceBeforePadding: boolean, spaceBeforeElement: boolean): Promise<J.LeftPadded<T>> {
621
- return (await produceAsync(left, async draft => {
622
- if (draft.before.comments.length == 0) {
623
- // Preserve newlines - only modify if no newlines present
624
- if (!draft.before.whitespace.includes("\n")) {
625
- draft.before.whitespace = spaceBeforePadding ? " " : "";
626
- }
628
+ /**
629
+ * Modifies the before space of a LeftPadded draft and the element's prefix in place.
630
+ */
631
+ private spaceBeforeLeftPaddedElementDraft<T extends J>(draft: Draft<J.LeftPadded<T>>, spaceBeforePadding: boolean, spaceBeforeElement: boolean): void {
632
+ if (draft.before.comments.length == 0) {
633
+ // Preserve newlines - only modify if no newlines present
634
+ if (!draft.before.whitespace.includes("\n")) {
635
+ draft.before.whitespace = spaceBeforePadding ? " " : "";
627
636
  }
628
- draft.element = await this.spaceBefore(left.element, spaceBeforeElement) as Draft<T>;
629
- }))!;
637
+ }
638
+ this.spaceBeforeDraft(draft.element, spaceBeforeElement);
630
639
  }
631
640
 
632
- private async spaceBeforeRightPaddedElement<T extends J>(right: J.RightPadded<T>, spaceBefore: boolean): Promise<J.RightPadded<T>> {
633
- return (await produceAsync(right, async draft => {
634
- draft.element = await this.spaceBefore(right.element, spaceBefore) as Draft<T>;
635
- }))!;
641
+ /**
642
+ * Modifies the element's prefix of a RightPadded draft in place.
643
+ */
644
+ private spaceBeforeRightPaddedElementDraft<T extends J>(draft: Draft<J.RightPadded<T>>, spaceBefore: boolean): void {
645
+ this.spaceBeforeDraft(draft.element, spaceBefore);
636
646
  }
637
647
 
638
- private async spaceBefore<T extends J>(j: T, spaceBefore: boolean): Promise<T> {
639
- if (j.prefix.comments.length > 0) {
640
- return j;
648
+ /**
649
+ * Modifies the prefix whitespace of a J draft in place.
650
+ */
651
+ private spaceBeforeDraft<T extends J>(draft: Draft<T>, spaceBefore: boolean): void {
652
+ if (draft.prefix.comments.length > 0) {
653
+ return;
641
654
  }
642
- if (spaceBefore && SpacesVisitor.isNotSingleSpace(j.prefix.whitespace)) {
643
- return produce(j, draft => {
644
- draft.prefix.whitespace = " ";
645
- });
646
- } else if (!spaceBefore && SpacesVisitor.isOnlySpacesAndNotEmpty(j.prefix.whitespace)) {
647
- return produce(j, draft => {
648
- draft.prefix.whitespace = "";
649
- });
650
- } else {
651
- return j;
655
+ if (spaceBefore && SpacesVisitor.isNotSingleSpace(draft.prefix.whitespace)) {
656
+ draft.prefix.whitespace = " ";
657
+ } else if (!spaceBefore && SpacesVisitor.isOnlySpacesAndNotEmpty(draft.prefix.whitespace)) {
658
+ draft.prefix.whitespace = "";
652
659
  }
653
660
  }
654
661
 
655
- private async spaceBeforeContainer<T extends J>(container: J.Container<T>, spaceBefore: boolean): Promise<J.Container<T>> {
656
- if (container.before.comments.length > 0) {
662
+ /**
663
+ * Modifies the before space of a Container draft in place.
664
+ */
665
+ private spaceBeforeContainerDraft<T extends J>(draft: Draft<J.Container<T>>, spaceBefore: boolean): void {
666
+ if (draft.before.comments.length > 0) {
657
667
  // Perform the space rule for the suffix of the last comment only. Same as IntelliJ.
658
- return produce(container, draft => {
659
- draft.before.comments = SpacesVisitor.spaceLastCommentSuffix(container.before.comments, spaceBefore);
660
- });
668
+ SpacesVisitor.spaceLastCommentSuffixDraft(draft.before.comments, spaceBefore);
669
+ return;
661
670
  }
662
671
 
663
- if (spaceBefore && SpacesVisitor.isNotSingleSpace(container.before.whitespace)) {
664
- return produce(container, draft => {
665
- draft.before.whitespace = " ";
666
- });
667
- } else if (!spaceBefore && SpacesVisitor.isOnlySpacesAndNotEmpty(container.before.whitespace)) {
668
- return produce(container, draft => {
669
- draft.before.whitespace = "";
670
- });
671
- } else {
672
- return container;
672
+ if (spaceBefore && SpacesVisitor.isNotSingleSpace(draft.before.whitespace)) {
673
+ draft.before.whitespace = " ";
674
+ } else if (!spaceBefore && SpacesVisitor.isOnlySpacesAndNotEmpty(draft.before.whitespace)) {
675
+ draft.before.whitespace = "";
673
676
  }
674
677
  }
675
678
 
676
- private static spaceLastCommentSuffix(comments: Comment[], spaceSuffix: boolean): Comment[] {
677
- comments[comments.length - 1] = this.spaceSuffix(comments[comments.length - 1], spaceSuffix);
678
- return comments;
679
+ /**
680
+ * Modifies the suffix of the last comment in an array of draft comments in place.
681
+ */
682
+ private static spaceLastCommentSuffixDraft(comments: Draft<Comment>[], spaceSuffix: boolean): void {
683
+ this.spaceSuffixDraft(comments[comments.length - 1], spaceSuffix);
679
684
  }
680
685
 
681
- private static spaceSuffix(comment: Comment, spaceSuffix: boolean): Comment {
682
- if (spaceSuffix && this.isNotSingleSpace(comment.suffix)) {
683
- return produce(comment, draft => {
684
- draft.suffix = " ";
685
- });
686
- } else if (!spaceSuffix && this.isOnlySpacesAndNotEmpty(comment.suffix)) {
687
- return produce(comment, draft => {
688
- draft.suffix = "";
689
- });
690
- } else {
691
- return comment;
686
+ /**
687
+ * Modifies the suffix of a Comment draft in place.
688
+ */
689
+ private static spaceSuffixDraft(draft: Draft<Comment>, spaceSuffix: boolean): void {
690
+ if (spaceSuffix && this.isNotSingleSpace(draft.suffix)) {
691
+ draft.suffix = " ";
692
+ } else if (!spaceSuffix && this.isOnlySpacesAndNotEmpty(draft.suffix)) {
693
+ draft.suffix = "";
692
694
  }
693
695
  }
694
696
 
@@ -17,7 +17,7 @@ import {JavaScriptVisitor} from "../visitor";
17
17
  import {J} from "../../java";
18
18
  import {Cursor, isScope, Tree} from "../../tree";
19
19
  import {JS} from "../tree";
20
- import {Draft, produce} from "immer";
20
+ import {create as produce, Draft} from "mutative";
21
21
  import {findMarker} from "../../markers";
22
22
 
23
23
  /**
@@ -19,14 +19,14 @@ import {Cursor, Tree} from '../../tree';
19
19
  import {TreePrinters} from '../../print';
20
20
  import {JavaScriptParser} from '../parser';
21
21
  import {WhitespaceReconciler} from './whitespace-reconciler';
22
- import {produce} from 'immer';
23
22
  import {randomId} from '../../uuid';
24
23
  import {PrettierStyle, StyleKind} from '../style';
25
24
  import {NamedStyles} from '../../style';
26
- import {findMarker} from '../../markers';
25
+ import {emptyMarkers, findMarker} from '../../markers';
27
26
  import {NormalizeWhitespaceVisitor} from './normalize-whitespace-visitor';
28
27
  import {MinimumViableSpacingVisitor} from './minimum-viable-spacing-visitor';
29
28
  import {loadPrettierVersion} from './prettier-config-loader';
29
+ import {updateIfChanged} from "../../util";
30
30
 
31
31
  /**
32
32
  * Loads Prettier for formatting.
@@ -310,7 +310,7 @@ function createNullPlaceholder(prefix: J.Space): J.Identifier {
310
310
  return {
311
311
  kind: J.Kind.Identifier,
312
312
  id: randomId(),
313
- markers: { kind: "org.openrewrite.marker.Markers", id: randomId(), markers: [] },
313
+ markers: emptyMarkers,
314
314
  prefix: prefix,
315
315
  annotations: [],
316
316
  simpleName: "null",
@@ -388,9 +388,7 @@ function pruneNode(node: any, path: PathSegment[], pathIndex: number, target: an
388
388
  }
389
389
  // Following siblings are omitted
390
390
 
391
- return produce(node, (draft: any) => {
392
- draft.statements = prunedStatements;
393
- });
391
+ return updateIfChanged(node, {statements: prunedStatements});
394
392
  }
395
393
 
396
394
  // For other properties, just recurse without pruning
@@ -399,17 +397,16 @@ function pruneNode(node: any, path: PathSegment[], pathIndex: number, target: an
399
397
  const prunedChild = pruneNode(childNode, path, pathIndex + 1, target);
400
398
 
401
399
  if (prunedChild !== childNode) {
402
- return produce(node, (draft: any) => {
403
- draft[segment.property][segment.index!] = prunedChild;
404
- });
400
+ // Create a copy of the array with the updated element
401
+ const newArray = [...value];
402
+ newArray[segment.index] = prunedChild;
403
+ return { ...node, [segment.property]: newArray };
405
404
  }
406
405
  } else if (!Array.isArray(value)) {
407
406
  const prunedChild = pruneNode(value, path, pathIndex + 1, target);
408
407
 
409
408
  if (prunedChild !== value) {
410
- return produce(node, (draft: any) => {
411
- draft[segment.property] = prunedChild;
412
- });
409
+ return { ...node, [segment.property]: prunedChild };
413
410
  }
414
411
  }
415
412
 
@@ -26,7 +26,7 @@ import {
26
26
  spaceContainsNewline,
27
27
  stripLeadingIndent
28
28
  } from "../../java";
29
- import {produce} from "immer";
29
+ import {create as produce} from "mutative";
30
30
  import {Cursor, isScope, isTree, Tree} from "../../tree";
31
31
  import {mapAsync} from "../../util";
32
32
  import {produceAsync} from "../../visitor";
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import {isIdentifier, isLiteral, isSpace, J, Type} from '../../java';
17
- import {produce} from "immer";
17
+ import {JS} from "../tree";
18
18
 
19
19
  /**
20
20
  * Union type for all tree node types that the reconciler handles.
@@ -234,7 +234,10 @@ export class WhitespaceReconciler {
234
234
  // Skip: kind, id, type properties
235
235
  if (key === 'kind' || key === 'id' ||
236
236
  key === 'type' || key === 'fieldType' || key === 'variableType' ||
237
- key === 'methodType' || key === 'constructorType') {
237
+ key === 'methodType' || key === 'constructorType' ||
238
+ original.kind === JS.Kind.CompilationUnit && key == 'charsetName' ||
239
+ // TODO In Java `null` and `undefined` are both the same
240
+ original.kind === J.Kind.Literal && key === 'value') {
238
241
  continue;
239
242
  }
240
243
 
@@ -244,9 +247,7 @@ export class WhitespaceReconciler {
244
247
  // Space values and markers: copy from formatted when reconciling
245
248
  if ((isSpace(originalValue)) || key === 'markers') {
246
249
  if (this.shouldReconcile() && formattedValue !== originalValue) {
247
- result = produce(result, (draft) => {
248
- (draft as Record<string, unknown>)[key] = formattedValue;
249
- });
250
+ result = { ...result, [key]: formattedValue } as VisitableNode;
250
251
  }
251
252
  continue;
252
253
  }
@@ -254,6 +255,10 @@ export class WhitespaceReconciler {
254
255
  // Handle arrays
255
256
  if (Array.isArray(originalValue)) {
256
257
  if (!Array.isArray(formattedValue) || originalValue.length !== formattedValue.length) {
258
+ if (originalValue.length === 0 && formattedValue === undefined && original.kind == J.Kind.ArrayType) {
259
+ // TODO Somehow J.ArrayType#annotations ends up as `[]`
260
+ continue;
261
+ }
257
262
  return this.structureMismatch(original);
258
263
  }
259
264
 
@@ -269,9 +274,7 @@ export class WhitespaceReconciler {
269
274
  }
270
275
 
271
276
  if (changed) {
272
- result = produce(result, (draft) => {
273
- (draft as Record<string, unknown>)[key] = newArray;
274
- });
277
+ result = { ...result, [key]: newArray } as VisitableNode;
275
278
  }
276
279
  } else {
277
280
  // Visit the property
@@ -279,9 +282,7 @@ export class WhitespaceReconciler {
279
282
  if (!this.compatible) return original;
280
283
 
281
284
  if (visited !== originalValue) {
282
- result = produce(result, (draft) => {
283
- (draft as Record<string, unknown>)[key] = visited;
284
- });
285
+ result = { ...result, [key]: visited } as VisitableNode;
285
286
  }
286
287
  }
287
288
  }
@@ -18,7 +18,6 @@ import {J} from "../java";
18
18
  import {JS} from "./tree";
19
19
  import {RpcCodecs, RpcReceiveQueue, RpcSendQueue} from "../rpc";
20
20
  import {
21
- prettierStyle,
22
21
  PrettierStyle,
23
22
  SpacesStyle,
24
23
  SpacesStyleDetailKind,
@@ -120,11 +119,12 @@ registerPrefixedMarkerCodec<FunctionDeclaration>(JS.Markers.FunctionDeclaration)
120
119
  // Only serialize the variable fields; constant fields are defined in the interface
121
120
  RpcCodecs.registerCodec(StyleKind.PrettierStyle, {
122
121
  async rpcReceive(before: PrettierStyle, q: RpcReceiveQueue): Promise<PrettierStyle> {
123
- const id = await q.receive(before.id);
124
- const config = await q.receive(before.config);
125
- const version = await q.receive(before.prettierVersion);
126
- const ignored = await q.receive(before.ignored);
127
- return prettierStyle(id, config, version, ignored);
122
+ return updateIfChanged(before, {
123
+ id: await q.receive(before.id),
124
+ config: await q.receive(before.config),
125
+ prettierVersion: await q.receive(before.prettierVersion),
126
+ ignored: await q.receive(before.ignored),
127
+ });
128
128
  },
129
129
 
130
130
  async rpcSend(after: PrettierStyle, q: RpcSendQueue): Promise<void> {
@@ -19,7 +19,7 @@ import {TreeVisitor} from "../../../visitor";
19
19
  import {ExecutionContext} from "../../../execution";
20
20
  import {JavaScriptVisitor} from "../../visitor";
21
21
  import {J} from "../../../java";
22
- import {produce} from "immer";
22
+ import {create as produce} from "mutative";
23
23
 
24
24
  export class ModernizeOctalEscapeSequences extends Recipe {
25
25
  name = "org.openrewrite.javascript.migrate.es6.modernize-octal-escape-sequences";
@@ -19,7 +19,7 @@ import {TreeVisitor} from "../../../visitor";
19
19
  import {ExecutionContext} from "../../../execution";
20
20
  import {JavaScriptVisitor} from "../../visitor";
21
21
  import {J} from "../../../java";
22
- import {produce} from "immer";
22
+ import {create as produce} from "mutative";
23
23
 
24
24
  export class ModernizeOctalLiterals extends Recipe {
25
25
  name = "org.openrewrite.javascript.migrate.es6.modernize-octal-literals";
@@ -20,7 +20,7 @@ import {ExecutionContext} from "../../../execution";
20
20
  import {JavaScriptVisitor} from "../../visitor";
21
21
  import {J} from "../../../java";
22
22
  import {JS} from "../../tree";
23
- import {produce} from "immer";
23
+ import {create as produce} from "mutative";
24
24
  import {ElementRemovalFormatter} from "../../../java/formatting-utils";
25
25
 
26
26
  export class RemoveDuplicateObjectKeys extends Recipe {
@@ -19,7 +19,7 @@ import {TreeVisitor} from "../../../visitor";
19
19
  import {ExecutionContext} from "../../../execution";
20
20
  import {JavaScriptVisitor, JS} from "../../../javascript";
21
21
  import {J} from "../../../java";
22
- import {produce} from "immer";
22
+ import {create as produce} from "mutative";
23
23
 
24
24
  export class ExportAssignmentToExportDefault extends Recipe {
25
25
  name = "org.openrewrite.javascript.migrate.typescript.export-assignment-to-export-default";