@openrewrite/rewrite 8.53.0 → 8.53.1

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 (48) hide show
  1. package/dist/src/java/visitor.d.ts.map +1 -1
  2. package/dist/src/java/visitor.js +10 -0
  3. package/dist/src/java/visitor.js.map +1 -1
  4. package/dist/src/javascript/assertions.d.ts +2 -0
  5. package/dist/src/javascript/assertions.d.ts.map +1 -1
  6. package/dist/src/javascript/assertions.js +20 -0
  7. package/dist/src/javascript/assertions.js.map +1 -1
  8. package/dist/src/javascript/format.d.ts +62 -44
  9. package/dist/src/javascript/format.d.ts.map +1 -1
  10. package/dist/src/javascript/format.js +244 -12
  11. package/dist/src/javascript/format.js.map +1 -1
  12. package/dist/src/javascript/parser.d.ts +11 -15
  13. package/dist/src/javascript/parser.d.ts.map +1 -1
  14. package/dist/src/javascript/parser.js +136 -56
  15. package/dist/src/javascript/parser.js.map +1 -1
  16. package/dist/src/javascript/print.d.ts +7 -3
  17. package/dist/src/javascript/print.d.ts.map +1 -1
  18. package/dist/src/javascript/print.js +93 -35
  19. package/dist/src/javascript/print.js.map +1 -1
  20. package/dist/src/javascript/rpc.js +83 -0
  21. package/dist/src/javascript/rpc.js.map +1 -1
  22. package/dist/src/javascript/style.d.ts +19 -6
  23. package/dist/src/javascript/style.d.ts.map +1 -1
  24. package/dist/src/javascript/style.js +31 -4
  25. package/dist/src/javascript/style.js.map +1 -1
  26. package/dist/src/javascript/tree.d.ts +48 -4
  27. package/dist/src/javascript/tree.d.ts.map +1 -1
  28. package/dist/src/javascript/tree.js +1 -1
  29. package/dist/src/javascript/tree.js.map +1 -1
  30. package/dist/src/javascript/visitor.d.ts +6 -1
  31. package/dist/src/javascript/visitor.d.ts.map +1 -1
  32. package/dist/src/javascript/visitor.js +59 -0
  33. package/dist/src/javascript/visitor.js.map +1 -1
  34. package/dist/src/tree.d.ts +1 -0
  35. package/dist/src/tree.d.ts.map +1 -1
  36. package/dist/src/tree.js +4 -0
  37. package/dist/src/tree.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/java/visitor.ts +12 -0
  40. package/src/javascript/assertions.ts +20 -0
  41. package/src/javascript/format.ts +254 -71
  42. package/src/javascript/parser.ts +195 -76
  43. package/src/javascript/print.ts +90 -39
  44. package/src/javascript/rpc.ts +78 -1
  45. package/src/javascript/style.ts +47 -9
  46. package/src/javascript/tree.ts +75 -4
  47. package/src/javascript/visitor.ts +56 -1
  48. package/src/tree.ts +5 -0
@@ -28,7 +28,7 @@ import {
28
28
  TypeTree,
29
29
  VariableDeclarator,
30
30
  } from '../java';
31
- import {Asterisk, DelegatedYield, FunctionDeclaration, JS, NonNullAssertion, Optional, Spread} from '.';
31
+ import {Asterisk, DelegatedYield, FunctionDeclaration, JS, JSX, NonNullAssertion, Optional, Spread} from '.';
32
32
  import {
33
33
  emptyMarkers,
34
34
  markers,
@@ -61,6 +61,8 @@ import {JavaScriptTypeMapping} from "./type-mapping";
61
61
  import {produce} from "immer";
62
62
  import Kind = JS.Kind;
63
63
  import ComputedPropertyName = JS.ComputedPropertyName;
64
+ import Attribute = JSX.Attribute;
65
+ import SpreadAttribute = JSX.SpreadAttribute;
64
66
 
65
67
  export interface JavaScriptParserOptions extends ParserOptions {
66
68
  styles?: NamedStyles[]
@@ -72,13 +74,14 @@ export class JavaScriptParser extends Parser {
72
74
  private readonly styles?: NamedStyles[];
73
75
  private oldProgram?: ts.Program;
74
76
 
75
- constructor({
76
- ctx,
77
- relativeTo,
78
- styles
79
- }: JavaScriptParserOptions = {},
80
- private readonly sourceFileCache: Map<String, ts.SourceFile> = new Map()
81
- ) {
77
+ constructor(
78
+ {
79
+ ctx,
80
+ relativeTo,
81
+ styles
82
+ }: JavaScriptParserOptions = {},
83
+ private readonly sourceFileCache: Map<String, ts.SourceFile> = new Map()
84
+ ) {
82
85
  super({ctx, relativeTo});
83
86
  this.compilerOptions = {
84
87
  target: ts.ScriptTarget.Latest,
@@ -86,7 +89,8 @@ export class JavaScriptParser extends Parser {
86
89
  allowJs: true,
87
90
  esModuleInterop: true,
88
91
  experimentalDecorators: true,
89
- emitDecoratorMetadata: true
92
+ emitDecoratorMetadata: true,
93
+ jsx: ts.JsxEmit.Preserve
90
94
  };
91
95
  this.styles = styles;
92
96
  }
@@ -634,7 +638,7 @@ export class JavaScriptParserVisitor {
634
638
  }
635
639
 
636
640
  private mapLiteral(node: ts.LiteralExpression | ts.TrueLiteral | ts.FalseLiteral | ts.NullLiteral | ts.Identifier
637
- | ts.TemplateHead | ts.TemplateMiddle | ts.TemplateTail, value: any): J.Literal {
641
+ | ts.TemplateHead | ts.TemplateMiddle | ts.TemplateTail | ts.JsxText, value: any): J.Literal {
638
642
 
639
643
  let valueSource = node.getText();
640
644
  if (!isValidSurrogateRange(valueSource)) {
@@ -661,10 +665,6 @@ export class JavaScriptParserVisitor {
661
665
  return this.mapLiteral(node, node.text); // FIXME value not in AST
662
666
  }
663
667
 
664
- visitJsxText(node: ts.JsxText): J.Unknown {
665
- return this.visitUnknown(node);
666
- }
667
-
668
668
  visitRegularExpressionLiteral(node: ts.RegularExpressionLiteral): J.Literal {
669
669
  return this.mapLiteral(node, node.text); // FIXME value not in AST
670
670
  }
@@ -746,8 +746,8 @@ export class JavaScriptParserVisitor {
746
746
  kind: J.Kind.JContainer,
747
747
  before: this.prefix(this.findChildNode(node, ts.SyntaxKind.ExtendsKeyword) ?? this.findChildNode(node, ts.SyntaxKind.EqualsToken)!),
748
748
  elements: [
749
- node.constraint ? this.rightPadded(this.visit(node.constraint), this.suffix(node.constraint)) : this.rightPadded(this.newJEmpty(), emptySpace),
750
- node.default ? this.rightPadded(this.visit(node.default), this.suffix(node.default)) : this.rightPadded(this.newJEmpty(), emptySpace)
749
+ node.constraint ? this.rightPadded(this.visit(node.constraint), this.suffix(node.constraint)) : this.rightPadded(this.newEmpty(), emptySpace),
750
+ node.default ? this.rightPadded(this.visit(node.default), this.suffix(node.default)) : this.rightPadded(this.newEmpty(), emptySpace)
751
751
  ],
752
752
  markers: emptyMarkers
753
753
  }
@@ -1207,9 +1207,9 @@ export class JavaScriptParserVisitor {
1207
1207
  kind: J.Kind.JContainer,
1208
1208
  before: this.prefix(node.getChildAt(node.getChildren().findIndex(n => n.pos === node.parameters.pos) - 1)),
1209
1209
  elements: node.parameters.length == 0 ?
1210
- [this.rightPadded(this.newJEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!))]
1210
+ [this.rightPadded(this.newEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!))]
1211
1211
  : node.parameters.map(p => this.rightPadded(this.visit(p), this.suffix(p)))
1212
- .concat(node.parameters.hasTrailingComma ? this.rightPadded(this.newJEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!)) : []),
1212
+ .concat(node.parameters.hasTrailingComma ? this.rightPadded(this.newEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!)) : []),
1213
1213
  markers: emptyMarkers
1214
1214
  },
1215
1215
  returnType: this.leftPadded(this.prefix(this.findChildNode(node, ts.SyntaxKind.EqualsGreaterThanToken)!), this.convert(node.type))
@@ -1229,9 +1229,9 @@ export class JavaScriptParserVisitor {
1229
1229
  kind: J.Kind.JContainer,
1230
1230
  before: this.prefix(node.getChildAt(node.getChildren().findIndex(n => n.pos === node.parameters.pos) - 1)),
1231
1231
  elements: node.parameters.length == 0 ?
1232
- [this.rightPadded(this.newJEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!))]
1232
+ [this.rightPadded(this.newEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!))]
1233
1233
  : node.parameters.map(p => this.rightPadded(this.visit(p), this.suffix(p)))
1234
- .concat(node.parameters.hasTrailingComma ? this.rightPadded(this.newJEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!)) : []),
1234
+ .concat(node.parameters.hasTrailingComma ? this.rightPadded(this.newEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!)) : []),
1235
1235
  markers: emptyMarkers
1236
1236
  },
1237
1237
  returnType: this.leftPadded(this.prefix(this.findChildNode(node, ts.SyntaxKind.EqualsGreaterThanToken)!), this.convert(node.type))
@@ -1297,8 +1297,8 @@ export class JavaScriptParserVisitor {
1297
1297
  before: emptySpace,
1298
1298
  elements: node.elements.length > 0 ?
1299
1299
  node.elements.map(p => this.rightPadded(this.convert(p), this.suffix(p)))
1300
- .concat(node.elements.hasTrailingComma ? this.rightPadded(this.newJEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseBracketToken)!)) : [])
1301
- : [this.rightPadded(this.newJEmpty(this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseBracketToken)!)), emptySpace)],
1300
+ .concat(node.elements.hasTrailingComma ? this.rightPadded(this.newEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseBracketToken)!)) : [])
1301
+ : [this.rightPadded(this.newEmpty(this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseBracketToken)!)), emptySpace)],
1302
1302
  markers: emptyMarkers
1303
1303
  },
1304
1304
  type: this.mapType(node)
@@ -1339,7 +1339,7 @@ export class JavaScriptParserVisitor {
1339
1339
  prefix: this.prefix(node),
1340
1340
  markers: emptyMarkers,
1341
1341
  types: [
1342
- ...(initialBar?.kind === ts.SyntaxKind.BarToken ? [this.rightPadded<Expression>(this.newJEmpty(), this.prefix(initialBar))] : []),
1342
+ ...(initialBar?.kind === ts.SyntaxKind.BarToken ? [this.rightPadded<Expression>(this.newEmpty(), this.prefix(initialBar))] : []),
1343
1343
  ...this.rightPaddedList<ts.Node, Expression>([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.BarToken, getNextSibling)(n))
1344
1344
  ],
1345
1345
  type: this.mapType(node)
@@ -1354,7 +1354,7 @@ export class JavaScriptParserVisitor {
1354
1354
  prefix: this.prefix(node),
1355
1355
  markers: emptyMarkers,
1356
1356
  types: [
1357
- ...(initialAmpersand?.kind === ts.SyntaxKind.AmpersandToken ? [this.rightPadded<Expression>(this.newJEmpty(), this.prefix(initialAmpersand))] : []),
1357
+ ...(initialAmpersand?.kind === ts.SyntaxKind.AmpersandToken ? [this.rightPadded<Expression>(this.newEmpty(), this.prefix(initialAmpersand))] : []),
1358
1358
  ...this.rightPaddedList<ts.Node, Expression>([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.AmpersandToken, getNextSibling)(n))
1359
1359
  ],
1360
1360
  type: this.mapType(node)
@@ -1522,22 +1522,22 @@ export class JavaScriptParserVisitor {
1522
1522
  before: this.prefix(this.findChildNode(node, ts.SyntaxKind.ColonToken)!),
1523
1523
  elements: [this.rightPadded(this.visit(node.type), this.suffix(node.type)),
1524
1524
  this.findChildNode(node, ts.SyntaxKind.SemicolonToken) ?
1525
- this.rightPadded(this.newJEmpty(emptySpace, markers({
1525
+ this.rightPadded(this.newEmpty(emptySpace, markers({
1526
1526
  kind: J.Markers.Semicolon,
1527
1527
  id: randomId()
1528
1528
  })), this.prefix(node.getLastToken()!))
1529
- : this.rightPadded(this.newJEmpty(), this.prefix(node.getLastToken()!))
1529
+ : this.rightPadded(this.newEmpty(), this.prefix(node.getLastToken()!))
1530
1530
  ],
1531
1531
  markers: emptyMarkers
1532
1532
  } : {
1533
1533
  kind: J.Kind.JContainer,
1534
1534
  before: emptySpace,
1535
1535
  elements: [this.findChildNode(node, ts.SyntaxKind.SemicolonToken) ?
1536
- this.rightPadded(this.newJEmpty(this.prefix(this.findChildNode(node, ts.SyntaxKind.SemicolonToken)!), markers({
1536
+ this.rightPadded(this.newEmpty(this.prefix(this.findChildNode(node, ts.SyntaxKind.SemicolonToken)!), markers({
1537
1537
  kind: J.Markers.Semicolon,
1538
1538
  id: randomId()
1539
1539
  })), this.prefix(node.getLastToken()!))
1540
- : this.rightPadded(this.newJEmpty(), this.prefix(node.getLastToken()!))
1540
+ : this.rightPadded(this.newEmpty(), this.prefix(node.getLastToken()!))
1541
1541
  ],
1542
1542
  markers: emptyMarkers
1543
1543
  },
@@ -1947,8 +1947,8 @@ export class JavaScriptParserVisitor {
1947
1947
  parenthesized: isParenthesized,
1948
1948
  parameters: node.parameters.length > 0 ?
1949
1949
  node.parameters.map(p => this.rightPadded(this.convert(p), this.suffix(p)))
1950
- .concat(node.parameters.hasTrailingComma ? this.rightPadded(this.newJEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!)) : []) :
1951
- isParenthesized ? [this.rightPadded(this.newJEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!))] : [],
1950
+ .concat(node.parameters.hasTrailingComma ? this.rightPadded(this.newEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!)) : []) :
1951
+ isParenthesized ? [this.rightPadded(this.newEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!))] : [],
1952
1952
  },
1953
1953
  arrow: this.prefix(node.equalsGreaterThanToken),
1954
1954
  body: this.convert(node.body),
@@ -2385,7 +2385,7 @@ export class JavaScriptParserVisitor {
2385
2385
  }
2386
2386
 
2387
2387
  visitOmittedExpression(node: ts.OmittedExpression) {
2388
- return this.newJEmpty(this.prefix(node));
2388
+ return this.newEmpty(this.prefix(node));
2389
2389
  }
2390
2390
 
2391
2391
  visitExpressionWithTypeArguments(node: ts.ExpressionWithTypeArguments) {
@@ -2467,7 +2467,7 @@ export class JavaScriptParserVisitor {
2467
2467
  }
2468
2468
 
2469
2469
  visitSemicolonClassElement(node: ts.SemicolonClassElement): J.Empty {
2470
- return this.newJEmpty(this.semicolonPrefix(node));
2470
+ return this.newEmpty(this.semicolonPrefix(node));
2471
2471
  }
2472
2472
 
2473
2473
  visitBlock(node: ts.Block): J.Block {
@@ -2483,7 +2483,7 @@ export class JavaScriptParserVisitor {
2483
2483
  }
2484
2484
 
2485
2485
  visitEmptyStatement(node: ts.EmptyStatement): J.Empty {
2486
- return this.newJEmpty(this.prefix(node));
2486
+ return this.newEmpty(this.prefix(node));
2487
2487
  }
2488
2488
 
2489
2489
  visitVariableStatement(node: ts.VariableStatement) {
@@ -2610,9 +2610,9 @@ export class JavaScriptParserVisitor {
2610
2610
  markers: emptyMarkers,
2611
2611
  expression: this.visit(node.initializer)
2612
2612
  }, this.suffix(node.initializer))) :
2613
- this.rightPadded(this.newJEmpty(), this.suffix(this.findChildNode(node, ts.SyntaxKind.OpenParenToken)!))],
2613
+ this.rightPadded(this.newEmpty(), this.suffix(this.findChildNode(node, ts.SyntaxKind.OpenParenToken)!))],
2614
2614
  condition: node.condition ? this.rightPadded(this.visit(node.condition), this.suffix(node.condition)) :
2615
- this.rightPadded(this.newJEmpty(), this.suffix(this.findChildNode(node, ts.SyntaxKind.SemicolonToken)!)),
2615
+ this.rightPadded(this.newEmpty(), this.suffix(this.findChildNode(node, ts.SyntaxKind.SemicolonToken)!)),
2616
2616
  update: [node.incrementor ? this.rightPadded(ts.isStatement(node.incrementor) ? this.visit(node.incrementor) : {
2617
2617
  kind: JS.Kind.ExpressionStatement,
2618
2618
  id: randomId(),
@@ -2620,7 +2620,7 @@ export class JavaScriptParserVisitor {
2620
2620
  markers: emptyMarkers,
2621
2621
  expression: this.visit(node.incrementor)
2622
2622
  }, this.suffix(node.incrementor)) :
2623
- this.rightPadded(this.newJEmpty(this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!)), emptySpace)]
2623
+ this.rightPadded(this.newEmpty(this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!)), emptySpace)]
2624
2624
  },
2625
2625
  body: this.rightPadded(
2626
2626
  this.convert(node.statement),
@@ -3413,52 +3413,148 @@ export class JavaScriptParserVisitor {
3413
3413
  }
3414
3414
  }
3415
3415
 
3416
- visitJsxElement(node: ts.JsxElement) {
3417
- return this.visitUnknown(node);
3418
- }
3419
-
3420
- visitJsxSelfClosingElement(node: ts.JsxSelfClosingElement) {
3421
- return this.visitUnknown(node);
3422
- }
3423
-
3424
- visitJsxOpeningElement(node: ts.JsxOpeningElement) {
3425
- return this.visitUnknown(node);
3426
- }
3427
-
3428
- visitJsxClosingElement(node: ts.JsxClosingElement) {
3429
- return this.visitUnknown(node);
3430
- }
3431
-
3432
- visitJsxFragment(node: ts.JsxFragment) {
3433
- return this.visitUnknown(node);
3416
+ visitJsxText(node: ts.JsxText): J.Literal {
3417
+ return this.mapLiteral(node, node.text);
3434
3418
  }
3435
3419
 
3436
- visitJsxOpeningFragment(node: ts.JsxOpeningFragment) {
3437
- return this.visitUnknown(node);
3420
+ visitJsxElement(node: ts.JsxElement): JSX.Tag {
3421
+ const attrs = node.openingElement.attributes.properties;
3422
+ return {
3423
+ kind: JS.Kind.JsxTag,
3424
+ id: randomId(),
3425
+ prefix: this.prefix(node),
3426
+ markers: emptyMarkers,
3427
+ openName: this.leftPadded(this.prefix(node.openingElement), this.visit(node.openingElement.tagName)),
3428
+ afterName: attrs.length === 0 ?
3429
+ this.prefix(this.findChildNode(node.openingElement, ts.SyntaxKind.GreaterThanToken)!) :
3430
+ emptySpace,
3431
+ attributes: attrs.length === 0 ?
3432
+ [] :
3433
+ this.mapJsxChildren<Attribute | SpreadAttribute>(
3434
+ attrs,
3435
+ this.prefix(this.findChildNode(node.openingElement, ts.SyntaxKind.GreaterThanToken)!),
3436
+ () => emptyMarkers
3437
+ ),
3438
+ children: node.children.length > 0 ?
3439
+ this.mapJsxChildren<JSX.EmbeddedExpression | JSX.Tag | J.Identifier | J.Literal>(
3440
+ node.children,
3441
+ this.prefix(this.findChildNode(node.closingElement, ts.SyntaxKind.LessThanToken)!),
3442
+ () => emptyMarkers
3443
+ ) :
3444
+ [
3445
+ this.rightPadded(
3446
+ this.newEmpty(),
3447
+ this.prefix(this.findChildNode(node.closingElement, ts.SyntaxKind.LessThanToken)!)
3448
+ )
3449
+ ],
3450
+ closingName: this.leftPadded(this.prefix(node.closingElement.tagName), this.visit(node.closingElement.tagName)),
3451
+ afterClosingName: this.suffix(node.closingElement.tagName)
3452
+ };
3438
3453
  }
3439
3454
 
3440
- visitJsxClosingFragment(node: ts.JsxClosingFragment) {
3441
- return this.visitUnknown(node);
3455
+ visitJsxSelfClosingElement(node: ts.JsxSelfClosingElement): JSX.Tag {
3456
+ const attrs = node.attributes.properties;
3457
+ return {
3458
+ kind: JS.Kind.JsxTag,
3459
+ id: randomId(),
3460
+ prefix: this.prefix(node),
3461
+ markers: emptyMarkers,
3462
+ openName: this.leftPadded(this.prefix(node.tagName), this.visit(node.tagName)),
3463
+ afterName: attrs.length === 0 ?
3464
+ this.prefix(this.findChildNode(node, ts.SyntaxKind.GreaterThanToken)!) :
3465
+ emptySpace,
3466
+ attributes: attrs.length === 0 ?
3467
+ [] :
3468
+ this.mapJsxChildren<Attribute | SpreadAttribute>(
3469
+ attrs,
3470
+ this.prefix(this.findChildNode(node, ts.SyntaxKind.GreaterThanToken)!),
3471
+ () => emptyMarkers
3472
+ ),
3473
+ selfClosing: this.prefix(this.findChildNode(node, ts.SyntaxKind.SlashToken)!),
3474
+ };
3442
3475
  }
3443
3476
 
3444
- visitJsxAttribute(node: ts.JsxAttribute) {
3445
- return this.visitUnknown(node);
3477
+ visitJsxFragment(node: ts.JsxFragment): JSX.Tag {
3478
+ return {
3479
+ kind: JS.Kind.JsxTag,
3480
+ id: randomId(),
3481
+ prefix: this.prefix(node),
3482
+ markers: emptyMarkers,
3483
+ openName: this.leftPadded(this.prefix(node.openingFragment), this.newEmpty()),
3484
+ afterName: this.prefix(this.findChildNode(node.openingFragment, ts.SyntaxKind.GreaterThanToken)!),
3485
+ attributes: [],
3486
+ children: node.children.length > 0 ?
3487
+ this.mapJsxChildren<JSX.EmbeddedExpression | JSX.Tag | J.Identifier | J.Literal>(
3488
+ node.children,
3489
+ this.prefix(this.findChildNode(node.closingFragment, ts.SyntaxKind.LessThanToken)!),
3490
+ () => emptyMarkers
3491
+ ) :
3492
+ [
3493
+ this.rightPadded(
3494
+ this.newEmpty(),
3495
+ this.prefix(this.findChildNode(node.closingFragment, ts.SyntaxKind.LessThanToken)!)
3496
+ )
3497
+ ],
3498
+ closingName: this.leftPadded(emptySpace, this.newEmpty()),
3499
+ afterClosingName: emptySpace
3500
+ };
3446
3501
  }
3447
3502
 
3448
- visitJsxAttributes(node: ts.JsxAttributes) {
3449
- return this.visitUnknown(node);
3503
+ visitJsxAttribute(node: ts.JsxAttribute): JSX.Attribute {
3504
+ return {
3505
+ kind: JS.Kind.JsxAttribute,
3506
+ id: randomId(),
3507
+ prefix: this.prefix(node),
3508
+ markers: emptyMarkers,
3509
+ key: this.visit(node.name),
3510
+ value: node.initializer
3511
+ ? this.leftPadded(
3512
+ this.prefix(this.findChildNode(node, ts.SyntaxKind.EqualsToken)!),
3513
+ this.visit(node.initializer)
3514
+ )
3515
+ : undefined
3516
+ };
3450
3517
  }
3451
3518
 
3452
- visitJsxSpreadAttribute(node: ts.JsxSpreadAttribute) {
3453
- return this.visitUnknown(node);
3519
+ visitJsxSpreadAttribute(node: ts.JsxSpreadAttribute): JSX.SpreadAttribute {
3520
+ return {
3521
+ kind: JS.Kind.JsxSpreadAttribute,
3522
+ id: randomId(),
3523
+ prefix: this.prefix(node),
3524
+ markers: emptyMarkers,
3525
+ dots: this.prefix(this.findChildNode(node, ts.SyntaxKind.DotDotDotToken)!),
3526
+ expression: this.rightPadded(this.visit(node.expression),
3527
+ this.suffix(node.expression))
3528
+ };
3454
3529
  }
3455
3530
 
3456
- visitJsxExpression(node: ts.JsxExpression) {
3457
- return this.visitUnknown(node);
3531
+ visitJsxExpression(node: ts.JsxExpression): JSX.EmbeddedExpression {
3532
+ return {
3533
+ kind: JS.Kind.JsxEmbeddedExpression,
3534
+ id: randomId(),
3535
+ prefix: this.prefix(node),
3536
+ markers: emptyMarkers,
3537
+ expression: this.rightPadded(
3538
+ node.expression ?
3539
+ this.convert<Expression>(node.expression) :
3540
+ this.newEmpty(),
3541
+ this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseBraceToken)!)
3542
+ )
3543
+ };
3458
3544
  }
3459
3545
 
3460
- visitJsxNamespacedName(node: ts.JsxNamespacedName) {
3461
- return this.visitUnknown(node);
3546
+ visitJsxNamespacedName(node: ts.JsxNamespacedName): JSX.NamespacedName {
3547
+ return {
3548
+ kind: JS.Kind.JsxNamespacedName,
3549
+ id: randomId(),
3550
+ prefix: this.prefix(node),
3551
+ markers: emptyMarkers,
3552
+ namespace: this.mapIdentifier(node.namespace, node.namespace.getText()),
3553
+ name: this.leftPadded(
3554
+ this.prefix(this.findChildNode(node, ts.SyntaxKind.ColonToken)!),
3555
+ this.mapIdentifier(node.name, node.name.getText())
3556
+ )
3557
+ };
3462
3558
  }
3463
3559
 
3464
3560
  visitCaseClause(node: ts.CaseClause): J.Case {
@@ -3928,7 +4024,7 @@ export class JavaScriptParserVisitor {
3928
4024
  return emptyContainer();
3929
4025
  }
3930
4026
  const prefix = this.prefix(nodes[0]);
3931
- const args: J.RightPadded<T>[] = this.mapToRightPaddedList(nodes[1] as ts.SyntaxList, this.prefix(nodes[2]), markers);
4027
+ const args: J.RightPadded<T>[] = this.mapToRightPaddedList(nodes[1].getChildren(this.sourceFile), this.prefix(nodes[2]), markers);
3932
4028
  return {
3933
4029
  kind: J.Kind.JContainer,
3934
4030
  before: prefix,
@@ -3937,14 +4033,13 @@ export class JavaScriptParserVisitor {
3937
4033
  };
3938
4034
  }
3939
4035
 
3940
- private mapToRightPaddedList<T extends J>(node: ts.SyntaxList, lastAfter: J.Space, markers?: (ns: readonly ts.Node[], i: number) => Markers): J.RightPadded<T>[] {
3941
- let elementList = node.getChildren(this.sourceFile);
4036
+ private mapToRightPaddedList<T extends J>(elementList: readonly ts.Node[], lastAfter: J.Space, markers?: (ns: readonly ts.Node[], i: number) => Markers): J.RightPadded<T>[] {
3942
4037
  let childCount = elementList.length;
3943
4038
 
3944
4039
  const args: J.RightPadded<T>[] = [];
3945
4040
  if (childCount === 0) {
3946
4041
  args.push(this.rightPadded(
3947
- this.newJEmpty() as T,
4042
+ this.newEmpty() as T,
3948
4043
  lastAfter,
3949
4044
  emptyMarkers
3950
4045
  ));
@@ -3965,6 +4060,30 @@ export class JavaScriptParserVisitor {
3965
4060
  return args;
3966
4061
  }
3967
4062
 
4063
+ private mapJsxChildren<T extends J>(elementList: readonly ts.Node[], lastAfter: J.Space, markers?: (ns: readonly ts.Node[], i: number) => Markers): J.RightPadded<T>[] {
4064
+ let childCount = elementList.length;
4065
+
4066
+ const args: J.RightPadded<T>[] = [];
4067
+ if (childCount === 0) {
4068
+ args.push(this.rightPadded(
4069
+ this.newEmpty() as T,
4070
+ lastAfter,
4071
+ emptyMarkers
4072
+ ));
4073
+ } else {
4074
+ for (let i = 0; i < childCount; i++) {
4075
+ const node = elementList[i];
4076
+ const isLast = i === childCount - 1;
4077
+ args.push(this.rightPadded(
4078
+ this.visit(node),
4079
+ isLast ? lastAfter : emptySpace,
4080
+ markers ? markers(elementList, i) : emptyMarkers
4081
+ ));
4082
+ }
4083
+ }
4084
+ return args;
4085
+ }
4086
+
3968
4087
  private mapDecorators(node: ts.ClassDeclaration | ts.FunctionDeclaration | ts.MethodDeclaration | ts.ConstructorDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration | ts.SetAccessorDeclaration | ts.GetAccessorDeclaration | ts.ClassExpression): J.Annotation[] {
3969
4088
  return node.modifiers?.filter(ts.isDecorator)?.map(this.convert<J.Annotation>) ?? [];
3970
4089
  }
@@ -3983,7 +4102,7 @@ export class JavaScriptParserVisitor {
3983
4102
  markers: emptyMarkers,
3984
4103
  annotations: [],
3985
4104
  modifiers: [],
3986
- name: this.newJEmpty(),
4105
+ name: this.newEmpty(),
3987
4106
  },
3988
4107
  this.prefix(this.findChildNode(node, ts.SyntaxKind.GreaterThanToken)!)) : []),
3989
4108
  markers: emptyMarkers
@@ -4009,7 +4128,7 @@ export class JavaScriptParserVisitor {
4009
4128
  markers: emptyMarkers,
4010
4129
  annotations: [],
4011
4130
  modifiers: [],
4012
- name: this.newJEmpty(),
4131
+ name: this.newEmpty(),
4013
4132
  }, this.prefix(this.findChildNode(node, ts.SyntaxKind.GreaterThanToken)!))]
4014
4133
  : typeParameters.map(tp => this.rightPadded(this.visit(tp), this.suffix(tp)))
4015
4134
  .concat(typeParameters.hasTrailingComma ? this.rightPadded(
@@ -4020,7 +4139,7 @@ export class JavaScriptParserVisitor {
4020
4139
  markers: emptyMarkers,
4021
4140
  annotations: [],
4022
4141
  modifiers: [],
4023
- name: this.newJEmpty(),
4142
+ name: this.newEmpty(),
4024
4143
  },
4025
4144
  this.prefix(this.findChildNode(node, ts.SyntaxKind.GreaterThanToken)!)) : []),
4026
4145
  };
@@ -4051,7 +4170,7 @@ export class JavaScriptParserVisitor {
4051
4170
  return undefined;
4052
4171
  }
4053
4172
 
4054
- private newJEmpty(prefix: J.Space = emptySpace, markers?: Markers): J.Empty {
4173
+ private newEmpty(prefix: J.Space = emptySpace, markers?: Markers): J.Empty {
4055
4174
  return {kind: J.Kind.Empty, id: randomId(), prefix: prefix, markers: markers ?? emptyMarkers};
4056
4175
  }
4057
4176