@openrewrite/rewrite 8.66.0 → 8.66.2

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 (113) hide show
  1. package/dist/java/tree.d.ts +10 -1
  2. package/dist/java/tree.d.ts.map +1 -1
  3. package/dist/java/tree.js +21 -5
  4. package/dist/java/tree.js.map +1 -1
  5. package/dist/java/type-visitor.d.ts +1 -1
  6. package/dist/java/type-visitor.d.ts.map +1 -1
  7. package/dist/java/visitor.d.ts +2 -2
  8. package/dist/java/visitor.d.ts.map +1 -1
  9. package/dist/java/visitor.js +8 -2
  10. package/dist/java/visitor.js.map +1 -1
  11. package/dist/javascript/assertions.d.ts +6 -0
  12. package/dist/javascript/assertions.d.ts.map +1 -1
  13. package/dist/javascript/assertions.js +14 -6
  14. package/dist/javascript/assertions.js.map +1 -1
  15. package/dist/javascript/comparator.d.ts +217 -7
  16. package/dist/javascript/comparator.d.ts.map +1 -1
  17. package/dist/javascript/comparator.js +1020 -2848
  18. package/dist/javascript/comparator.js.map +1 -1
  19. package/dist/javascript/format.d.ts +5 -3
  20. package/dist/javascript/format.d.ts.map +1 -1
  21. package/dist/javascript/format.js +87 -44
  22. package/dist/javascript/format.js.map +1 -1
  23. package/dist/javascript/index.d.ts +2 -1
  24. package/dist/javascript/index.d.ts.map +1 -1
  25. package/dist/javascript/index.js +2 -1
  26. package/dist/javascript/index.js.map +1 -1
  27. package/dist/javascript/parser.d.ts +2 -1
  28. package/dist/javascript/parser.d.ts.map +1 -1
  29. package/dist/javascript/parser.js +54 -43
  30. package/dist/javascript/parser.js.map +1 -1
  31. package/dist/javascript/templating/capture.d.ts +293 -0
  32. package/dist/javascript/templating/capture.d.ts.map +1 -0
  33. package/dist/javascript/templating/capture.js +461 -0
  34. package/dist/javascript/templating/capture.js.map +1 -0
  35. package/dist/javascript/templating/comparator.d.ts +171 -0
  36. package/dist/javascript/templating/comparator.d.ts.map +1 -0
  37. package/dist/javascript/templating/comparator.js +1221 -0
  38. package/dist/javascript/templating/comparator.js.map +1 -0
  39. package/dist/javascript/templating/engine.d.ts +108 -0
  40. package/dist/javascript/templating/engine.d.ts.map +1 -0
  41. package/dist/javascript/templating/engine.js +661 -0
  42. package/dist/javascript/templating/engine.js.map +1 -0
  43. package/dist/javascript/templating/index.d.ts +6 -0
  44. package/dist/javascript/templating/index.d.ts.map +1 -0
  45. package/dist/javascript/templating/index.js +44 -0
  46. package/dist/javascript/templating/index.js.map +1 -0
  47. package/dist/javascript/templating/pattern.d.ts +276 -0
  48. package/dist/javascript/templating/pattern.d.ts.map +1 -0
  49. package/dist/javascript/templating/pattern.js +952 -0
  50. package/dist/javascript/templating/pattern.js.map +1 -0
  51. package/dist/javascript/templating/placeholder-replacement.d.ts +83 -0
  52. package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -0
  53. package/dist/javascript/templating/placeholder-replacement.js +467 -0
  54. package/dist/javascript/templating/placeholder-replacement.js.map +1 -0
  55. package/dist/javascript/templating/rewrite.d.ts +84 -0
  56. package/dist/javascript/templating/rewrite.d.ts.map +1 -0
  57. package/dist/javascript/templating/rewrite.js +208 -0
  58. package/dist/javascript/templating/rewrite.js.map +1 -0
  59. package/dist/javascript/templating/template.d.ts +230 -0
  60. package/dist/javascript/templating/template.d.ts.map +1 -0
  61. package/dist/javascript/templating/template.js +367 -0
  62. package/dist/javascript/templating/template.js.map +1 -0
  63. package/dist/javascript/templating/types.d.ts +610 -0
  64. package/dist/javascript/templating/types.d.ts.map +1 -0
  65. package/dist/javascript/templating/types.js +3 -0
  66. package/dist/javascript/templating/types.js.map +1 -0
  67. package/dist/javascript/templating/utils.d.ts +135 -0
  68. package/dist/javascript/templating/utils.d.ts.map +1 -0
  69. package/dist/javascript/templating/utils.js +251 -0
  70. package/dist/javascript/templating/utils.js.map +1 -0
  71. package/dist/javascript/type-mapping.d.ts.map +1 -1
  72. package/dist/javascript/type-mapping.js +21 -11
  73. package/dist/javascript/type-mapping.js.map +1 -1
  74. package/dist/json/rpc.js +2 -2
  75. package/dist/json/rpc.js.map +1 -1
  76. package/dist/recipe/order-imports.js.map +1 -1
  77. package/dist/test/rewrite-test.d.ts.map +1 -1
  78. package/dist/test/rewrite-test.js +10 -6
  79. package/dist/test/rewrite-test.js.map +1 -1
  80. package/dist/version.txt +1 -1
  81. package/dist/visitor.d.ts +4 -4
  82. package/dist/visitor.d.ts.map +1 -1
  83. package/dist/visitor.js +8 -3
  84. package/dist/visitor.js.map +1 -1
  85. package/package.json +5 -2
  86. package/src/java/tree.ts +10 -3
  87. package/src/java/type-visitor.ts +1 -1
  88. package/src/java/visitor.ts +11 -5
  89. package/src/javascript/assertions.ts +9 -3
  90. package/src/javascript/comparator.ts +1095 -3373
  91. package/src/javascript/format.ts +72 -33
  92. package/src/javascript/index.ts +2 -1
  93. package/src/javascript/parser.ts +67 -45
  94. package/src/javascript/templating/capture.ts +595 -0
  95. package/src/javascript/templating/comparator.ts +1383 -0
  96. package/src/javascript/templating/engine.ts +750 -0
  97. package/src/javascript/templating/index.ts +67 -0
  98. package/src/javascript/templating/pattern.ts +1101 -0
  99. package/src/javascript/templating/placeholder-replacement.ts +475 -0
  100. package/src/javascript/templating/rewrite.ts +229 -0
  101. package/src/javascript/templating/template.ts +414 -0
  102. package/src/javascript/templating/types.ts +674 -0
  103. package/src/javascript/templating/utils.ts +298 -0
  104. package/src/javascript/type-mapping.ts +20 -11
  105. package/src/json/rpc.ts +2 -2
  106. package/src/recipe/order-imports.ts +1 -1
  107. package/src/test/rewrite-test.ts +12 -7
  108. package/src/visitor.ts +14 -6
  109. package/dist/javascript/templating.d.ts +0 -265
  110. package/dist/javascript/templating.d.ts.map +0 -1
  111. package/dist/javascript/templating.js +0 -1027
  112. package/dist/javascript/templating.js.map +0 -1
  113. package/src/javascript/templating.ts +0 -1226
@@ -13,9 +13,9 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import {JS} from "./tree";
16
+ import {isJavaScript, JS} from "./tree";
17
17
  import {JavaScriptVisitor} from "./visitor";
18
- import {Comment, J, Statement} from "../java";
18
+ import {Comment, isJava, J, Statement} from "../java";
19
19
  import {Draft, produce} from "immer";
20
20
  import {Cursor, isScope, Tree} from "../tree";
21
21
  import {
@@ -28,16 +28,15 @@ import {
28
28
  } from "./style";
29
29
  import {produceAsync} from "../visitor";
30
30
 
31
- export async function maybeAutoFormat<J2 extends J, P>(before: J2, after: J2, p: P, stopAfter?: J, parent?: Cursor): Promise<J2> {
31
+ export const maybeAutoFormat = async <J2 extends J, P>(before: J2, after: J2, p: P, stopAfter?: J, parent?: Cursor): Promise<J2> => {
32
32
  if (before !== after) {
33
33
  return autoFormat(after, p, stopAfter, parent);
34
34
  }
35
35
  return after;
36
36
  }
37
37
 
38
- export async function autoFormat<J2 extends J, P>(j: J2, p: P, stopAfter?: J, parent?: Cursor): Promise<J2> {
39
- return await new AutoformatVisitor(stopAfter).visit(j, p, parent) as J2;
40
- }
38
+ export const autoFormat = async <J2 extends J, P>(j: J2, p: P, stopAfter?: J, parent?: Cursor): Promise<J2> =>
39
+ (await new AutoformatVisitor(stopAfter).visit(j, p, parent) as J2);
41
40
 
42
41
  export class AutoformatVisitor<P> extends JavaScriptVisitor<P> {
43
42
  constructor(private stopAfter?: Tree) {
@@ -336,6 +335,13 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
336
335
  });
337
336
  }
338
337
 
338
+ protected async visitPropertyAssignment(propertyAssignment: JS.PropertyAssignment, p: P): Promise<J | undefined> {
339
+ const pa = await super.visitPropertyAssignment(propertyAssignment, p) as JS.PropertyAssignment;
340
+ return produceAsync(pa, draft => {
341
+ draft.name.after.whitespace = this.style.other.beforePropertyNameValueSeparator ? " " : "";
342
+ });
343
+ }
344
+
339
345
  protected async visitSwitch(switchNode: J.Switch, p: P): Promise<J | undefined> {
340
346
  const ret = await super.visitSwitch(switchNode, p) as J.Switch;
341
347
  return produceAsync(ret, async draft => {
@@ -406,11 +412,13 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
406
412
  const spacing = this.style.aroundOperators.unary;
407
413
 
408
414
  switch (draft.operator.element) {
415
+ case J.Unary.Type.Not:
416
+ draft.expression.prefix.whitespace = this.style.aroundOperators.afterUnaryNotAndNotNull ? " " : "";
417
+ break;
409
418
  case J.Unary.Type.PreIncrement:
410
419
  case J.Unary.Type.PreDecrement:
411
420
  case J.Unary.Type.Negative:
412
421
  case J.Unary.Type.Positive:
413
- case J.Unary.Type.Not:
414
422
  case J.Unary.Type.Complement:
415
423
  draft.expression.prefix.whitespace = spacing ? " " : "";
416
424
  break;
@@ -462,18 +470,18 @@ export class SpacesVisitor<P> extends JavaScriptVisitor<P> {
462
470
  }
463
471
 
464
472
  private async spaceBeforeLeftPaddedElement<T extends J>(left: J.LeftPadded<T>, spaceBeforePadding: boolean, spaceBeforeElement: boolean): Promise<J.LeftPadded<T>> {
465
- return produceAsync(left, async draft => {
473
+ return (await produceAsync(left, async draft => {
466
474
  if (draft.before.comments.length == 0) {
467
475
  draft.before.whitespace = spaceBeforePadding ? " " : "";
468
476
  }
469
477
  draft.element = await this.spaceBefore(left.element, spaceBeforeElement) as Draft<T>;
470
- });
478
+ }))!;
471
479
  }
472
480
 
473
481
  private async spaceBeforeRightPaddedElement<T extends J>(right: J.RightPadded<T>, spaceBefore: boolean): Promise<J.RightPadded<T>> {
474
- return produceAsync(right, async draft => {
482
+ return (await produceAsync(right, async draft => {
475
483
  draft.element = await this.spaceBefore(right.element, spaceBefore) as Draft<T>;
476
- });
484
+ }))!;
477
485
  }
478
486
 
479
487
  private async spaceBefore<T extends J>(j: T, spaceBefore: boolean): Promise<T> {
@@ -639,7 +647,9 @@ export class WrappingAndBracesVisitor<P> extends JavaScriptVisitor<P> {
639
647
  const b = await super.visitBlock(block, p) as J.Block;
640
648
  return produce(b, draft => {
641
649
  if (!draft.end.whitespace.includes("\n") && (draft.statements.length == 0 || !draft.statements[draft.statements.length - 1].after.whitespace.includes("\n"))) {
642
- draft.end = this.withNewlineSpace(draft.end);
650
+ if (this.cursor.parent?.value.kind !== J.Kind.NewClass) {
651
+ draft.end = this.withNewlineSpace(draft.end);
652
+ }
643
653
  }
644
654
  });
645
655
  }
@@ -825,8 +835,8 @@ export class MinimumViableSpacingVisitor<P> extends JavaScriptVisitor<P> {
825
835
  const ret = await super.visitNewClass(newClass, p) as J.NewClass;
826
836
  return produce(ret, draft => {
827
837
  if (draft.class) {
828
- if (draft.class.kind == JS.Kind.TypeTreeExpression) {
829
- this.ensureSpace((draft.class as Draft<JS.TypeTreeExpression>).expression.prefix);
838
+ if (draft.class.kind == J.Kind.Identifier) {
839
+ this.ensureSpace((draft.class as Draft<J.Identifier>).prefix);
830
840
  }
831
841
  }
832
842
  });
@@ -925,27 +935,30 @@ export class BlankLinesVisitor<P> extends JavaScriptVisitor<P> {
925
935
  super();
926
936
  }
927
937
 
928
- override async visit<R extends J>(tree: Tree, p: P, cursor?: Cursor): Promise<R | undefined> {
929
- if (this.cursor?.getNearestMessage("stop") != null) {
930
- return tree as R;
931
- }
932
- if (tree.kind === JS.Kind.CompilationUnit) {
933
- const cu = produce(tree as JS.CompilationUnit, draft => {
938
+ protected async preVisit(tree: J, p: P): Promise<J | undefined> {
939
+ let ret = await super.preVisit(tree, p) as J;
940
+
941
+ if (ret.kind === JS.Kind.CompilationUnit) {
942
+ ret = produce(ret as JS.CompilationUnit, draft => {
934
943
  if (draft.prefix.comments.length == 0) {
935
944
  draft.prefix.whitespace = "";
936
945
  }
937
946
  });
938
- return super.visit(cu, p, cursor);
939
947
  }
940
- if (tree.kind === JS.Kind.StatementExpression && (tree as JS.StatementExpression).statement.kind == J.Kind.MethodDeclaration) {
941
- tree = produce(tree as JS.StatementExpression, draft => {
942
- this.ensurePrefixHasNewLine(draft);
943
- });
944
- } else if (tree.kind === J.Kind.MethodDeclaration && this.cursor.value.kind != JS.Kind.StatementExpression) {
945
- tree = produce(tree as J.MethodDeclaration, draft => {
948
+ if (ret.kind === J.Kind.MethodDeclaration
949
+ && this.cursor.parent?.parent?.parent?.value.kind === J.Kind.ClassDeclaration) {
950
+ ret = produce(ret as JS.StatementExpression, draft => {
946
951
  this.ensurePrefixHasNewLine(draft);
947
952
  });
948
953
  }
954
+
955
+ return ret;
956
+ }
957
+
958
+ override async visit<R extends J>(tree: Tree, p: P, cursor?: Cursor): Promise<R | undefined> {
959
+ if (this.cursor?.getNearestMessage("stop") != null) {
960
+ return tree as R;
961
+ }
949
962
  return super.visit(tree, p, cursor);
950
963
  }
951
964
 
@@ -1017,7 +1030,7 @@ export class BlankLinesVisitor<P> extends JavaScriptVisitor<P> {
1017
1030
  }
1018
1031
  this.keepMaximumBlankLines(draft, this.style.keepMaximum.inCode);
1019
1032
  }
1020
- } else if (parent?.kind === J.Kind.Block ||
1033
+ } else if (parent?.kind === J.Kind.Block && grandparent?.kind !== J.Kind.NewClass ||
1021
1034
  (parent?.kind === JS.Kind.CompilationUnit && (parent! as JS.CompilationUnit).statements[0].element.id != draft.id) ||
1022
1035
  (parent?.kind === J.Kind.Case)) {
1023
1036
  if (draft.kind != J.Kind.Case) {
@@ -1030,8 +1043,10 @@ export class BlankLinesVisitor<P> extends JavaScriptVisitor<P> {
1030
1043
  protected async visitBlock(block: J.Block, p: P): Promise<J.Block> {
1031
1044
  const b = await super.visitBlock(block, p) as J.Block;
1032
1045
  return produce(b, draft => {
1033
- if (!draft.end.whitespace.includes("\n")) {
1034
- draft.end.whitespace = draft.end.whitespace + "\n";
1046
+ if (this.cursor.parent?.value.kind != J.Kind.NewClass) {
1047
+ if (!draft.end.whitespace.includes("\n")) {
1048
+ draft.end.whitespace = draft.end.whitespace.replace(/[ \t]+$/, '') + "\n";
1049
+ }
1035
1050
  }
1036
1051
  });
1037
1052
  }
@@ -1107,7 +1122,7 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
1107
1122
  let indentShouldIncrease =
1108
1123
  tree.kind === J.Kind.Block
1109
1124
  || this.cursor.parent?.parent?.parent?.value.kind == J.Kind.Case
1110
- || (tree.kind === JS.Kind.StatementExpression && (tree as JS.StatementExpression).statement.kind == J.Kind.MethodDeclaration);
1125
+ || (tree.kind === JS.Kind.StatementExpression && (tree as JS.StatementExpression).statement.kind == J.Kind.MethodDeclaration && tree.prefix.whitespace.includes("\n"));
1111
1126
 
1112
1127
  const previousIndent = this.currentIndent;
1113
1128
 
@@ -1167,10 +1182,34 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
1167
1182
  if (this.cursor?.getNearestMessage("stop") != null) {
1168
1183
  return tree as R;
1169
1184
  }
1170
- return await super.visit(tree, p, parent) as R;
1185
+
1186
+ if (parent) {
1187
+ this.cursor = new Cursor(tree, parent);
1188
+ for (let c: Cursor | undefined = this.cursor; c != null; c = c.parent) {
1189
+ let space: J.Space;
1190
+ const v = c.value;
1191
+ if (v.kind == J.Kind.RightPadded) {
1192
+ space = v.after;
1193
+ } else if (v.kind == J.Kind.LeftPadded || v.kind == J.Kind.Container) {
1194
+ space = v.before;
1195
+ } else if (isJava(v) || isJavaScript(v)) {
1196
+ space = v.prefix;
1197
+ } else {
1198
+ continue;
1199
+ }
1200
+
1201
+ const lastWhitespace = space.comments.length > 0 ? space.comments[space.comments.length - 1].suffix : space.whitespace;
1202
+ const idx = lastWhitespace.lastIndexOf('\n');
1203
+ if (idx !== -1) {
1204
+ c.messages.set("indentToUse", lastWhitespace.substring(idx + 1));
1205
+ break;
1206
+ }
1207
+ }
1208
+ }
1209
+ return await super.visit(tree, p) as R;
1171
1210
  }
1172
1211
 
1173
- public async visitLeftPadded<T extends J | J.Space | number | string | boolean>(left: J.LeftPadded<T>, p: P): Promise<J.LeftPadded<T>> {
1212
+ public async visitLeftPadded<T extends J | J.Space | number | string | boolean>(left: J.LeftPadded<T>, p: P): Promise<J.LeftPadded<T> | undefined> {
1174
1213
  const ret = await super.visitLeftPadded(left, p);
1175
1214
  if (ret == undefined) {
1176
1215
  return ret;
@@ -20,8 +20,9 @@ export * from "./parser";
20
20
  export * from "./style";
21
21
  export * from "./markers";
22
22
  export * from "./preconditions";
23
- export * from "./templating";
23
+ export * from "./templating/index";
24
24
  export * from "./method-matcher";
25
+ export * from "./format";
25
26
 
26
27
  export * from "./add-import";
27
28
  export * from "./remove-import";
@@ -76,7 +76,7 @@ export class JavaScriptParser extends Parser {
76
76
  private readonly compilerOptions: ts.CompilerOptions;
77
77
  private readonly styles?: NamedStyles[];
78
78
  private oldProgram?: ts.Program;
79
- private sourceFileCache?: Map<string, ts.SourceFile>;
79
+ private readonly sourceFileCache?: Map<string, ts.SourceFile>;
80
80
 
81
81
  constructor(
82
82
  {
@@ -612,14 +612,10 @@ export class JavaScriptParserVisitor {
612
612
  }
613
613
  for (let heritageClause of node.heritageClauses) {
614
614
  if (heritageClause.token == ts.SyntaxKind.ExtendsKeyword) {
615
- const expression = this.visit(heritageClause.types[0]);
616
- return this.leftPadded<TypeTree>(this.prefix(heritageClause.getFirstToken()!), {
617
- kind: JS.Kind.TypeTreeExpression,
618
- id: randomId(),
619
- prefix: emptySpace,
620
- markers: emptyMarkers,
621
- expression: expression
622
- } satisfies JS.TypeTreeExpression as JS.TypeTreeExpression);
615
+ return this.leftPadded<TypeTree>(
616
+ this.prefix(heritageClause.getFirstToken()!),
617
+ this.mapTypeTree(heritageClause.types[0])
618
+ );
623
619
  }
624
620
  }
625
621
  return undefined;
@@ -667,6 +663,33 @@ export class JavaScriptParserVisitor {
667
663
  return undefined;
668
664
  }
669
665
 
666
+ private mapTypeTree(node: ts.LeftHandSideExpression | ts.ExpressionWithTypeArguments | ts.Expression): TypeTree {
667
+ const expression = this.visit(node);
668
+
669
+ // Check if the expression is already a TypeTree
670
+ // J.Identifier, J.FieldAccess, J.ArrayType, and J.ParameterizedType all implement TypeTree
671
+ if (expression.kind === J.Kind.Identifier ||
672
+ expression.kind === J.Kind.FieldAccess ||
673
+ expression.kind === J.Kind.ArrayType ||
674
+ expression.kind === J.Kind.ParameterizedType) {
675
+ return expression as TypeTree;
676
+ }
677
+
678
+ // For expressions that don't implement TypeTree, wrap them in JS.TypeTreeExpression
679
+ // Transfer the prefix from the expression to the wrapper
680
+ const prefix = expression.prefix;
681
+ return {
682
+ kind: JS.Kind.TypeTreeExpression,
683
+ id: randomId(),
684
+ prefix: prefix,
685
+ markers: emptyMarkers,
686
+ expression: {
687
+ ...expression,
688
+ prefix: emptySpace
689
+ },
690
+ } satisfies JS.TypeTreeExpression as JS.TypeTreeExpression;
691
+ }
692
+
670
693
  visitNumericLiteral(node: ts.NumericLiteral): J.Literal {
671
694
  // Parse the numeric value from the text
672
695
  const text = node.text;
@@ -907,28 +930,25 @@ export class JavaScriptParserVisitor {
907
930
  let annotationType: NameTree | TypeTree;
908
931
  let _arguments: J.Container<Expression> | undefined = undefined;
909
932
 
910
- if (ts.isCallExpression(node.expression)) {
933
+ if (ts.isCallExpression(node.expression) && node.expression.typeArguments) {
911
934
  annotationType = {
912
935
  kind: JS.Kind.ExpressionWithTypeArguments,
913
936
  id: randomId(),
914
937
  prefix: emptySpace,
915
938
  markers: emptyMarkers,
916
939
  clazz: this.convert<J>(node.expression.expression) as Expression,
917
- typeArguments: node.expression.typeArguments && this.mapTypeArguments(this.suffix(node.expression.expression), node.expression.typeArguments)
940
+ typeArguments: this.mapTypeArguments(this.suffix(node.expression.expression), node.expression.typeArguments)
918
941
  } satisfies JS.ExpressionWithTypeArguments as JS.ExpressionWithTypeArguments;
919
942
  _arguments = this.mapCommaSeparatedList(node.expression.getChildren(this.sourceFile).slice(-3))
943
+ } else if (ts.isCallExpression(node.expression)) {
944
+ annotationType = this.convert<J>(node.expression.expression) as Expression;
945
+ _arguments = this.mapCommaSeparatedList(node.expression.getChildren(this.sourceFile).slice(-3))
920
946
  } else if (ts.isIdentifier(node.expression)) {
921
947
  annotationType = this.convert(node.expression);
922
948
  } else if (ts.isPropertyAccessExpression(node.expression)) {
923
949
  annotationType = this.convert(node.expression);
924
950
  } else if (ts.isParenthesizedExpression(node.expression)) {
925
- annotationType = {
926
- kind: JS.Kind.TypeTreeExpression,
927
- id: randomId(),
928
- prefix: this.prefix(node.expression),
929
- markers: emptyMarkers,
930
- expression: this.convert(node.expression) as Expression
931
- } satisfies JS.TypeTreeExpression as JS.TypeTreeExpression;
951
+ annotationType = this.mapTypeTree(node.expression);
932
952
  } else {
933
953
  return this.visitUnknown(node);
934
954
  }
@@ -1493,7 +1513,7 @@ export class JavaScriptParserVisitor {
1493
1513
  element: {
1494
1514
  kind: J.Kind.Ternary,
1495
1515
  id: randomId(),
1496
- prefix: emptySpace,
1516
+ prefix: this.prefix(node.extendsType),
1497
1517
  markers: emptyMarkers,
1498
1518
  condition: this.convert(node.extendsType),
1499
1519
  truePart: this.leftPadded(this.suffix(node.extendsType), this.convert(node.trueType)),
@@ -1998,24 +2018,23 @@ export class JavaScriptParserVisitor {
1998
2018
  class: node.typeArguments ? {
1999
2019
  kind: J.Kind.ParameterizedType,
2000
2020
  id: randomId(),
2001
- prefix: emptySpace,
2021
+ prefix: this.prefix(node.expression),
2002
2022
  markers: emptyMarkers,
2003
- class: {
2004
- kind: JS.Kind.TypeTreeExpression,
2005
- id: randomId(),
2006
- prefix: emptySpace,
2007
- markers: emptyMarkers,
2008
- expression: this.visit(node.expression),
2009
- } satisfies JS.TypeTreeExpression as JS.TypeTreeExpression,
2023
+ class: (() => {
2024
+ // For parameterized types, we need to handle the prefix differently
2025
+ const typeTree = this.mapTypeTree(node.expression);
2026
+ // If it's a TypeTreeExpression, clear the prefix since it was already set on the ParameterizedType
2027
+ if (typeTree.kind === JS.Kind.TypeTreeExpression) {
2028
+ return {
2029
+ ...typeTree,
2030
+ prefix: emptySpace
2031
+ };
2032
+ }
2033
+ return typeTree;
2034
+ })(),
2010
2035
  typeParameters: this.mapTypeArguments(this.prefix(this.findChildNode(node, ts.SyntaxKind.LessThanToken)!), node.typeArguments),
2011
2036
  type: undefined
2012
- } satisfies J.ParameterizedType as J.ParameterizedType : {
2013
- kind: JS.Kind.TypeTreeExpression,
2014
- id: randomId(),
2015
- prefix: emptySpace,
2016
- markers: emptyMarkers,
2017
- expression: this.visit(node.expression),
2018
- } satisfies JS.TypeTreeExpression as JS.TypeTreeExpression,
2037
+ } satisfies J.ParameterizedType as J.ParameterizedType : this.mapTypeTree(node.expression),
2019
2038
  arguments: node.arguments ?
2020
2039
  this.mapCommaSeparatedList(this.getParameterListNodes(node)) : {
2021
2040
  ...emptyContainer<Expression>(),
@@ -2460,12 +2479,12 @@ export class JavaScriptParserVisitor {
2460
2479
  return {
2461
2480
  kind: JS.Kind.StatementExpression,
2462
2481
  id: randomId(),
2463
- prefix: emptySpace,
2482
+ prefix: this.prefix(node),
2464
2483
  markers: emptyMarkers,
2465
2484
  statement: {
2466
2485
  kind: J.Kind.Yield,
2467
2486
  id: randomId(),
2468
- prefix: this.prefix(node),
2487
+ prefix: emptySpace,
2469
2488
  markers: node.asteriskToken ?
2470
2489
  markers({
2471
2490
  kind: JS.Markers.DelegatedYield,
@@ -2492,12 +2511,12 @@ export class JavaScriptParserVisitor {
2492
2511
  return {
2493
2512
  kind: JS.Kind.StatementExpression,
2494
2513
  id: randomId(),
2495
- prefix: emptySpace,
2514
+ prefix: this.prefix(node),
2496
2515
  markers: emptyMarkers,
2497
2516
  statement: {
2498
2517
  kind: J.Kind.ClassDeclaration,
2499
2518
  id: randomId(),
2500
- prefix: this.prefix(node),
2519
+ prefix: emptySpace,
2501
2520
  markers: emptyMarkers,
2502
2521
  leadingAnnotations: this.mapDecorators(node),
2503
2522
  modifiers: [],
@@ -2645,16 +2664,19 @@ export class JavaScriptParserVisitor {
2645
2664
  }
2646
2665
 
2647
2666
  visitExpressionStatement(node: ts.ExpressionStatement): Statement {
2648
- const expression = this.visit(node.expression) as Expression;
2667
+ const expression: Expression = this.visit(node.expression) as Expression;
2649
2668
  if (isStatement(expression)) {
2650
2669
  return expression as Statement;
2651
2670
  }
2671
+ const e: Expression = expression;
2652
2672
  return {
2653
2673
  kind: JS.Kind.ExpressionStatement,
2654
2674
  id: randomId(),
2655
- prefix: emptySpace,
2675
+ prefix: e.prefix,
2656
2676
  markers: emptyMarkers,
2657
- expression: expression
2677
+ expression: produce(e, draft => {
2678
+ draft.prefix = emptySpace
2679
+ })
2658
2680
  } satisfies JS.ExpressionStatement as JS.ExpressionStatement;
2659
2681
  }
2660
2682
 
@@ -2767,7 +2789,7 @@ export class JavaScriptParserVisitor {
2767
2789
  update: [node.incrementor ? this.rightPadded(ts.isStatement(node.incrementor) ? this.visit(node.incrementor) : {
2768
2790
  kind: JS.Kind.ExpressionStatement,
2769
2791
  id: randomId(),
2770
- prefix: emptySpace,
2792
+ prefix: this.prefix(node.incrementor),
2771
2793
  markers: emptyMarkers,
2772
2794
  expression: this.visit(node.incrementor)
2773
2795
  }, this.suffix(node.incrementor)) :
@@ -3262,7 +3284,7 @@ export class JavaScriptParserVisitor {
3262
3284
  {
3263
3285
  kind: J.Kind.EnumValueSet,
3264
3286
  id: randomId(),
3265
- prefix: emptySpace,
3287
+ prefix: node.members[0] ? this.prefix(node.members[0]) : emptySpace,
3266
3288
  markers: emptyMarkers,
3267
3289
  enums: node.members.map(em => this.rightPadded(this.visit(em), this.suffix(em))),
3268
3290
  terminatedWithSemicolon: node.members.hasTrailingComma
@@ -3322,7 +3344,7 @@ export class JavaScriptParserVisitor {
3322
3344
  return {
3323
3345
  kind: JS.Kind.NamespaceDeclaration,
3324
3346
  id: randomId(),
3325
- prefix: node.parent.kind === ts.SyntaxKind.ModuleBlock ? this.prefix(node) : emptySpace,
3347
+ prefix: this.prefix(node),
3326
3348
  markers: emptyMarkers,
3327
3349
  modifiers: this.mapModifiers(node),
3328
3350
  keywordType: this.leftPadded(
@@ -3456,7 +3478,7 @@ export class JavaScriptParserVisitor {
3456
3478
  const typeKeyword = node.getChildren().find(n => n.kind === ts.SyntaxKind.TypeKeyword);
3457
3479
  return this.prefix(typeKeyword!);
3458
3480
  } else {
3459
- return emptySpace;
3481
+ return this.prefix(node.name);
3460
3482
  }
3461
3483
  })(),
3462
3484
  markers: emptyMarkers,