Skip to content
This repository was archived by the owner on May 12, 2025. It is now read-only.

Commit a3d19b8

Browse files
arodionovAndrii Rodionov
andauthored
Implemented template expression and conditional type (#160)
* fix parsing errors * Implemented template expression - added JS.TemplateExpression and JS.TaggedTemplateExpression to support templates - added JS.ExpressionWithTypeArguments * implemented visitTemplateLiteralType * introduce JS.ConditionalType --------- Co-authored-by: Andrii Rodionov <andriih@moderne.io>
1 parent 9e9c427 commit a3d19b8

File tree

20 files changed

+1333
-225
lines changed

20 files changed

+1333
-225
lines changed

openrewrite/src/javascript/parser.ts

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,8 @@ export class JavaScriptParserVisitor {
534534
return this.mapLiteral(node, null);
535535
}
536536

537-
private mapLiteral(node: ts.LiteralExpression | ts.TrueLiteral | ts.FalseLiteral | ts.NullLiteral | ts.Identifier, value: any): J.Literal {
537+
private mapLiteral(node: ts.LiteralExpression | ts.TrueLiteral | ts.FalseLiteral | ts.NullLiteral | ts.Identifier
538+
| ts.TemplateHead | ts.TemplateMiddle | ts.TemplateTail, value: any): J.Literal {
538539
return new J.Literal(
539540
randomId(),
540541
this.prefix(node),
@@ -567,15 +568,15 @@ export class JavaScriptParserVisitor {
567568
}
568569

569570
visitTemplateHead(node: ts.TemplateHead) {
570-
return this.visitUnknown(node);
571+
return this.mapLiteral(node, node.text);
571572
}
572573

573574
visitTemplateMiddle(node: ts.TemplateMiddle) {
574-
return this.visitUnknown(node);
575+
return this.mapLiteral(node, node.text);
575576
}
576577

577578
visitTemplateTail(node: ts.TemplateTail) {
578-
return this.visitUnknown(node);
579+
return this.mapLiteral(node, node.text);
579580
}
580581

581582
visitIdentifier(node: ts.Identifier) {
@@ -1328,7 +1329,28 @@ export class JavaScriptParserVisitor {
13281329
}
13291330

13301331
visitConditionalType(node: ts.ConditionalTypeNode) {
1331-
return this.visitUnknown(node);
1332+
return new JS.ConditionalType(
1333+
randomId(),
1334+
this.prefix(node),
1335+
Markers.EMPTY,
1336+
this.visit(node.checkType),
1337+
new JContainer(
1338+
this.prefix(this.findChildNode(node, ts.SyntaxKind.ExtendsKeyword)!),
1339+
[this.rightPadded(
1340+
new J.Ternary(
1341+
randomId(),
1342+
Space.EMPTY,
1343+
Markers.EMPTY,
1344+
this.convert(node.extendsType),
1345+
this.leftPadded(this.suffix(node.extendsType), this.convert(node.trueType)),
1346+
this.leftPadded(this.suffix(node.trueType), this.convert(node.falseType)),
1347+
this.mapType(node)),
1348+
Space.EMPTY
1349+
)],
1350+
Markers.EMPTY
1351+
),
1352+
this.mapType(node)
1353+
);
13321354
}
13331355

13341356
visitInferType(node: ts.InferTypeNode) {
@@ -1379,11 +1401,24 @@ export class JavaScriptParserVisitor {
13791401
}
13801402

13811403
visitTemplateLiteralType(node: ts.TemplateLiteralTypeNode) {
1382-
return this.visitUnknown(node);
1404+
return new JS.TemplateExpression(
1405+
randomId(),
1406+
this.prefix(node),
1407+
Markers.EMPTY,
1408+
this.visit(node.head),
1409+
node.templateSpans.map(s => this.rightPadded(this.visit(s), this.suffix(s))),
1410+
this.mapType(node)
1411+
)
13831412
}
13841413

13851414
visitTemplateLiteralTypeSpan(node: ts.TemplateLiteralTypeSpan) {
1386-
return this.visitUnknown(node);
1415+
return new JS.TemplateExpression.TemplateSpan(
1416+
randomId(),
1417+
this.prefix(node),
1418+
Markers.EMPTY,
1419+
this.convert(node.type),
1420+
this.visit(node.literal)
1421+
)
13871422
}
13881423

13891424
visitImportType(node: ts.ImportTypeNode) {
@@ -1591,7 +1626,15 @@ export class JavaScriptParserVisitor {
15911626
}
15921627

15931628
visitTaggedTemplateExpression(node: ts.TaggedTemplateExpression) {
1594-
return this.visitUnknown(node);
1629+
return new JS.TaggedTemplateExpression(
1630+
randomId(),
1631+
this.prefix(node),
1632+
Markers.EMPTY,
1633+
this.rightPadded(this.visit(node.tag), this.suffix(node.tag)),
1634+
node.typeArguments ? this.mapTypeArguments(Space.EMPTY, node.typeArguments) : null,
1635+
this.visit(node.template),
1636+
this.mapType(node)
1637+
)
15951638
}
15961639

15971640
visitTypeAssertionExpression(node: ts.TypeAssertion) {
@@ -1959,7 +2002,14 @@ export class JavaScriptParserVisitor {
19592002
}
19602003

19612004
visitTemplateExpression(node: ts.TemplateExpression) {
1962-
return this.visitUnknown(node);
2005+
return new JS.TemplateExpression(
2006+
randomId(),
2007+
this.prefix(node),
2008+
Markers.EMPTY,
2009+
this.visit(node.head),
2010+
node.templateSpans.map(s => this.rightPadded(this.visit(s), this.suffix(s))),
2011+
this.mapType(node)
2012+
)
19632013
}
19642014

19652015
visitYieldExpression(node: ts.YieldExpression) {
@@ -2029,16 +2079,14 @@ export class JavaScriptParserVisitor {
20292079

20302080
visitExpressionWithTypeArguments(node: ts.ExpressionWithTypeArguments) {
20312081
if (node.typeArguments) {
2032-
if (node.typeArguments) {
2033-
return new J.ParameterizedType(
2034-
randomId(),
2035-
this.prefix(node),
2036-
Markers.EMPTY,
2037-
this.visit(node.expression),
2038-
this.mapTypeArguments(this.suffix(node.expression), node.typeArguments),
2039-
this.mapType(node)
2040-
)
2041-
}
2082+
return new JS.ExpressionWithTypeArguments(
2083+
randomId(),
2084+
this.prefix(node),
2085+
Markers.EMPTY,
2086+
this.visit(node.expression),
2087+
this.mapTypeArguments(this.suffix(node.expression), node.typeArguments),
2088+
this.mapType(node)
2089+
)
20422090
}
20432091
return this.visit(node.expression);
20442092
}
@@ -2079,7 +2127,13 @@ export class JavaScriptParserVisitor {
20792127
}
20802128

20812129
visitTemplateSpan(node: ts.TemplateSpan) {
2082-
return this.visitUnknown(node);
2130+
return new JS.TemplateExpression.TemplateSpan(
2131+
randomId(),
2132+
this.prefix(node),
2133+
Markers.EMPTY,
2134+
this.convert(node.expression),
2135+
this.visit(node.literal)
2136+
)
20832137
}
20842138

20852139
visitSemicolonClassElement(node: ts.SemicolonClassElement) {

openrewrite/src/javascript/remote/receiver.ts

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as extensions from "./remote_extensions";
22
import {Checksum, Cursor, FileAttributes, ListUtils, Tree} from '../../core';
33
import {DetailsReceiver, Receiver, ReceiverContext, ReceiverFactory, ValueType} from '@openrewrite/rewrite-remote';
44
import {JavaScriptVisitor} from '..';
5-
import {JS, JsLeftPadded, JsRightPadded, JsContainer, JsSpace, CompilationUnit, Alias, ArrowFunction, Await, DefaultType, Delete, Export, ExpressionStatement, FunctionType, JsImport, JsImportSpecifier, JsBinary, ObjectBindingDeclarations, PropertyAssignment, ScopedVariableDeclarations, StatementExpression, TemplateExpression, Tuple, TypeDeclaration, TypeOf, TypeQuery, TypeOperator, Unary, Union, Intersection, Void, Yield, TypeInfo, JSVariableDeclarations, JSMethodDeclaration, JSForOfLoop, JSForInLoop, JSForInOfLoopControl, NamespaceDeclaration, FunctionDeclaration, TypeLiteral, IndexSignatureDeclaration, ArrayBindingPattern, BindingElement} from '../tree';
5+
import {JS, JsLeftPadded, JsRightPadded, JsContainer, JsSpace, CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, JsImport, JsImportSpecifier, JsBinary, ObjectBindingDeclarations, PropertyAssignment, ScopedVariableDeclarations, StatementExpression, TaggedTemplateExpression, TemplateExpression, Tuple, TypeDeclaration, TypeOf, TypeQuery, TypeOperator, Unary, Union, Intersection, Void, Yield, TypeInfo, JSVariableDeclarations, JSMethodDeclaration, JSForOfLoop, JSForInLoop, JSForInOfLoopControl, NamespaceDeclaration, FunctionDeclaration, TypeLiteral, IndexSignatureDeclaration, ArrayBindingPattern, BindingElement} from '../tree';
66
import {Expression, J, JContainer, JLeftPadded, JRightPadded, NameTree, Space, Statement, TypeTree, TypedTree} from "../../java";
77
import * as Java from "../../java/tree";
88

@@ -75,6 +75,16 @@ class Visitor extends JavaScriptVisitor<ReceiverContext> {
7575
return await;
7676
}
7777

78+
public visitConditionalType(conditionalType: ConditionalType, ctx: ReceiverContext): J {
79+
conditionalType = conditionalType.withId(ctx.receiveValue(conditionalType.id, ValueType.UUID)!);
80+
conditionalType = conditionalType.withPrefix(ctx.receiveNode(conditionalType.prefix, receiveSpace)!);
81+
conditionalType = conditionalType.withMarkers(ctx.receiveNode(conditionalType.markers, ctx.receiveMarkers)!);
82+
conditionalType = conditionalType.withCheckType(ctx.receiveNode(conditionalType.checkType, ctx.receiveTree)!);
83+
conditionalType = conditionalType.padding.withCondition(ctx.receiveNode(conditionalType.padding.condition, receiveContainer)!);
84+
conditionalType = conditionalType.withType(ctx.receiveValue(conditionalType.type, ValueType.Object));
85+
return conditionalType;
86+
}
87+
7888
public visitDefaultType(defaultType: DefaultType, ctx: ReceiverContext): J {
7989
defaultType = defaultType.withId(ctx.receiveValue(defaultType.id, ValueType.UUID)!);
8090
defaultType = defaultType.withPrefix(ctx.receiveNode(defaultType.prefix, receiveSpace)!);
@@ -112,6 +122,16 @@ class Visitor extends JavaScriptVisitor<ReceiverContext> {
112122
return expressionStatement;
113123
}
114124

125+
public visitExpressionWithTypeArguments(expressionWithTypeArguments: ExpressionWithTypeArguments, ctx: ReceiverContext): J {
126+
expressionWithTypeArguments = expressionWithTypeArguments.withId(ctx.receiveValue(expressionWithTypeArguments.id, ValueType.UUID)!);
127+
expressionWithTypeArguments = expressionWithTypeArguments.withPrefix(ctx.receiveNode(expressionWithTypeArguments.prefix, receiveSpace)!);
128+
expressionWithTypeArguments = expressionWithTypeArguments.withMarkers(ctx.receiveNode(expressionWithTypeArguments.markers, ctx.receiveMarkers)!);
129+
expressionWithTypeArguments = expressionWithTypeArguments.withClazz(ctx.receiveNode(expressionWithTypeArguments.clazz, ctx.receiveTree)!);
130+
expressionWithTypeArguments = expressionWithTypeArguments.padding.withTypeArguments(ctx.receiveNode(expressionWithTypeArguments.padding.typeArguments, receiveContainer));
131+
expressionWithTypeArguments = expressionWithTypeArguments.withType(ctx.receiveValue(expressionWithTypeArguments.type, ValueType.Object));
132+
return expressionWithTypeArguments;
133+
}
134+
115135
public visitFunctionType(functionType: FunctionType, ctx: ReceiverContext): J {
116136
functionType = functionType.withId(ctx.receiveValue(functionType.id, ValueType.UUID)!);
117137
functionType = functionType.withPrefix(ctx.receiveNode(functionType.prefix, receiveSpace)!);
@@ -195,25 +215,34 @@ class Visitor extends JavaScriptVisitor<ReceiverContext> {
195215
return statementExpression;
196216
}
197217

218+
public visitTaggedTemplateExpression(taggedTemplateExpression: TaggedTemplateExpression, ctx: ReceiverContext): J {
219+
taggedTemplateExpression = taggedTemplateExpression.withId(ctx.receiveValue(taggedTemplateExpression.id, ValueType.UUID)!);
220+
taggedTemplateExpression = taggedTemplateExpression.withPrefix(ctx.receiveNode(taggedTemplateExpression.prefix, receiveSpace)!);
221+
taggedTemplateExpression = taggedTemplateExpression.withMarkers(ctx.receiveNode(taggedTemplateExpression.markers, ctx.receiveMarkers)!);
222+
taggedTemplateExpression = taggedTemplateExpression.padding.withTag(ctx.receiveNode(taggedTemplateExpression.padding.tag, receiveRightPaddedTree));
223+
taggedTemplateExpression = taggedTemplateExpression.padding.withTypeArguments(ctx.receiveNode(taggedTemplateExpression.padding.typeArguments, receiveContainer));
224+
taggedTemplateExpression = taggedTemplateExpression.withTemplateExpression(ctx.receiveNode(taggedTemplateExpression.templateExpression, ctx.receiveTree)!);
225+
taggedTemplateExpression = taggedTemplateExpression.withType(ctx.receiveValue(taggedTemplateExpression.type, ValueType.Object));
226+
return taggedTemplateExpression;
227+
}
228+
198229
public visitTemplateExpression(templateExpression: TemplateExpression, ctx: ReceiverContext): J {
199230
templateExpression = templateExpression.withId(ctx.receiveValue(templateExpression.id, ValueType.UUID)!);
200231
templateExpression = templateExpression.withPrefix(ctx.receiveNode(templateExpression.prefix, receiveSpace)!);
201232
templateExpression = templateExpression.withMarkers(ctx.receiveNode(templateExpression.markers, ctx.receiveMarkers)!);
202-
templateExpression = templateExpression.withDelimiter(ctx.receiveValue(templateExpression.delimiter, ValueType.Primitive)!);
203-
templateExpression = templateExpression.padding.withTag(ctx.receiveNode(templateExpression.padding.tag, receiveRightPaddedTree));
204-
templateExpression = templateExpression.withStrings(ctx.receiveNodes(templateExpression.strings, ctx.receiveTree)!);
233+
templateExpression = templateExpression.withHead(ctx.receiveNode(templateExpression.head, ctx.receiveTree)!);
234+
templateExpression = templateExpression.padding.withTemplateSpans(ctx.receiveNodes(templateExpression.padding.templateSpans, receiveRightPaddedTree)!);
205235
templateExpression = templateExpression.withType(ctx.receiveValue(templateExpression.type, ValueType.Object));
206236
return templateExpression;
207237
}
208238

209-
public visitTemplateExpressionValue(value: TemplateExpression.Value, ctx: ReceiverContext): J {
210-
value = value.withId(ctx.receiveValue(value.id, ValueType.UUID)!);
211-
value = value.withPrefix(ctx.receiveNode(value.prefix, receiveSpace)!);
212-
value = value.withMarkers(ctx.receiveNode(value.markers, ctx.receiveMarkers)!);
213-
value = value.withTree(ctx.receiveNode(value.tree, ctx.receiveTree)!);
214-
value = value.withAfter(ctx.receiveNode(value.after, receiveSpace)!);
215-
value = value.withEnclosedInBraces(ctx.receiveValue(value.enclosedInBraces, ValueType.Primitive)!);
216-
return value;
239+
public visitTemplateExpressionTemplateSpan(templateSpan: TemplateExpression.TemplateSpan, ctx: ReceiverContext): J {
240+
templateSpan = templateSpan.withId(ctx.receiveValue(templateSpan.id, ValueType.UUID)!);
241+
templateSpan = templateSpan.withPrefix(ctx.receiveNode(templateSpan.prefix, receiveSpace)!);
242+
templateSpan = templateSpan.withMarkers(ctx.receiveNode(templateSpan.markers, ctx.receiveMarkers)!);
243+
templateSpan = templateSpan.withExpression(ctx.receiveNode(templateSpan.expression, ctx.receiveTree)!);
244+
templateSpan = templateSpan.withTail(ctx.receiveNode(templateSpan.tail, ctx.receiveTree)!);
245+
return templateSpan;
217246
}
218247

219248
public visitTuple(tuple: Tuple, ctx: ReceiverContext): J {
@@ -1173,6 +1202,17 @@ class Factory implements ReceiverFactory {
11731202
);
11741203
}
11751204

1205+
if (type === "org.openrewrite.javascript.tree.JS$ConditionalType") {
1206+
return new ConditionalType(
1207+
ctx.receiveValue(null, ValueType.UUID)!,
1208+
ctx.receiveNode(null, receiveSpace)!,
1209+
ctx.receiveNode(null, ctx.receiveMarkers)!,
1210+
ctx.receiveNode<Expression>(null, ctx.receiveTree)!,
1211+
ctx.receiveNode<JContainer<TypedTree>>(null, receiveContainer)!,
1212+
ctx.receiveValue(null, ValueType.Object)
1213+
);
1214+
}
1215+
11761216
if (type === "org.openrewrite.javascript.tree.JS$DefaultType") {
11771217
return new DefaultType(
11781218
ctx.receiveValue(null, ValueType.UUID)!,
@@ -1214,6 +1254,17 @@ class Factory implements ReceiverFactory {
12141254
);
12151255
}
12161256

1257+
if (type === "org.openrewrite.javascript.tree.JS$ExpressionWithTypeArguments") {
1258+
return new ExpressionWithTypeArguments(
1259+
ctx.receiveValue(null, ValueType.UUID)!,
1260+
ctx.receiveNode(null, receiveSpace)!,
1261+
ctx.receiveNode(null, ctx.receiveMarkers)!,
1262+
ctx.receiveNode<NameTree>(null, ctx.receiveTree)!,
1263+
ctx.receiveNode<JContainer<Expression>>(null, receiveContainer),
1264+
ctx.receiveValue(null, ValueType.Object)
1265+
);
1266+
}
1267+
12171268
if (type === "org.openrewrite.javascript.tree.JS$FunctionType") {
12181269
return new FunctionType(
12191270
ctx.receiveValue(null, ValueType.UUID)!,
@@ -1305,26 +1356,36 @@ class Factory implements ReceiverFactory {
13051356
);
13061357
}
13071358

1359+
if (type === "org.openrewrite.javascript.tree.JS$TaggedTemplateExpression") {
1360+
return new TaggedTemplateExpression(
1361+
ctx.receiveValue(null, ValueType.UUID)!,
1362+
ctx.receiveNode(null, receiveSpace)!,
1363+
ctx.receiveNode(null, ctx.receiveMarkers)!,
1364+
ctx.receiveNode<JRightPadded<Expression>>(null, receiveRightPaddedTree),
1365+
ctx.receiveNode<JContainer<Expression>>(null, receiveContainer),
1366+
ctx.receiveNode<TemplateExpression>(null, ctx.receiveTree)!,
1367+
ctx.receiveValue(null, ValueType.Object)
1368+
);
1369+
}
1370+
13081371
if (type === "org.openrewrite.javascript.tree.JS$TemplateExpression") {
13091372
return new TemplateExpression(
13101373
ctx.receiveValue(null, ValueType.UUID)!,
13111374
ctx.receiveNode(null, receiveSpace)!,
13121375
ctx.receiveNode(null, ctx.receiveMarkers)!,
1313-
ctx.receiveValue(null, ValueType.Primitive)!,
1314-
ctx.receiveNode<JRightPadded<Expression>>(null, receiveRightPaddedTree),
1315-
ctx.receiveNodes<J>(null, ctx.receiveTree)!,
1376+
ctx.receiveNode<Java.Literal>(null, ctx.receiveTree)!,
1377+
ctx.receiveNodes(null, receiveRightPaddedTree)!,
13161378
ctx.receiveValue(null, ValueType.Object)
13171379
);
13181380
}
13191381

1320-
if (type === "org.openrewrite.javascript.tree.JS$TemplateExpression$Value") {
1321-
return new TemplateExpression.Value(
1382+
if (type === "org.openrewrite.javascript.tree.JS$TemplateExpression$TemplateSpan") {
1383+
return new TemplateExpression.TemplateSpan(
13221384
ctx.receiveValue(null, ValueType.UUID)!,
13231385
ctx.receiveNode(null, receiveSpace)!,
13241386
ctx.receiveNode(null, ctx.receiveMarkers)!,
13251387
ctx.receiveNode<J>(null, ctx.receiveTree)!,
1326-
ctx.receiveNode(null, receiveSpace)!,
1327-
ctx.receiveValue(null, ValueType.Primitive)!
1388+
ctx.receiveNode<Java.Literal>(null, ctx.receiveTree)!
13281389
);
13291390
}
13301391

0 commit comments

Comments
 (0)