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

Commit 8ac8033

Browse files
arodionovAndrii Rodionov
andauthored
Updated recipe test, added exp op and make other fixes (#192)
Co-authored-by: Andrii Rodionov <[email protected]>
1 parent de3989b commit 8ac8033

File tree

14 files changed

+177
-16
lines changed

14 files changed

+177
-16
lines changed

openrewrite/src/javascript/parser.ts

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,10 @@ export class JavaScriptParserVisitor {
546546
return this.mapIdentifier(node, 'any');
547547
}
548548

549+
visitIntrinsicKeyword(node: ts.Node) {
550+
return this.mapIdentifier(node, 'intrinsic');
551+
}
552+
549553
visitObjectKeyword(node: ts.Node) {
550554
return this.mapIdentifier(node, 'object');
551555
}
@@ -814,6 +818,13 @@ export class JavaScriptParserVisitor {
814818
annotationType = this.convert(node.expression);
815819
} else if (ts.isPropertyAccessExpression(node.expression)) {
816820
annotationType = this.convert(node.expression);
821+
} else if (ts.isParenthesizedExpression(node.expression)) {
822+
annotationType = new JS.TypeTreeExpression(
823+
randomId(),
824+
this.prefix(node.expression),
825+
Markers.EMPTY,
826+
this.convert(node.expression)
827+
);
817828
} else {
818829
return this.visitUnknown(node);
819830
}
@@ -1045,6 +1056,12 @@ export class JavaScriptParserVisitor {
10451056
);
10461057
}
10471058

1059+
const name: J.Identifier = !node.name
1060+
? this.mapIdentifier(node, "")
1061+
: ts.isStringLiteral(node.name)
1062+
? this.mapIdentifier(node.name, node.name.getText())
1063+
: this.visit(node.name);
1064+
10481065
return new J.MethodDeclaration(
10491066
randomId(),
10501067
this.prefix(node),
@@ -1054,7 +1071,7 @@ export class JavaScriptParserVisitor {
10541071
this.mapTypeParametersAsObject(node),
10551072
this.mapTypeInfo(node),
10561073
new J.MethodDeclaration.IdentifierWithAnnotations(
1057-
node.name ? this.visit(node.name) : this.mapIdentifier(node, ""),
1074+
name,
10581075
[]
10591076
),
10601077
this.mapCommaSeparatedList(this.getParameterListNodes(node)),
@@ -1381,7 +1398,10 @@ export class JavaScriptParserVisitor {
13811398
this.mapTypeParametersAsObject(node),
13821399
new JContainer(
13831400
this.prefix(node.getChildAt(node.getChildren().findIndex(n => n.pos === node.parameters.pos) - 1)),
1384-
node.parameters.map(p => this.rightPadded(this.visit(p), this.suffix(p))),
1401+
node.parameters.length == 0 ?
1402+
[this.rightPadded(this.newJEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!))]
1403+
: node.parameters.map(p => this.rightPadded(this.visit(p), this.suffix(p)))
1404+
.concat(node.parameters.hasTrailingComma ? this.rightPadded(this.newJEmpty(), this.prefix(this.findChildNode(node, ts.SyntaxKind.CloseParenToken)!)) : []),
13851405
Markers.EMPTY),
13861406
this.prefix(this.findChildNode(node, ts.SyntaxKind.EqualsGreaterThanToken)!),
13871407
this.convert(node.type),
@@ -2234,6 +2254,9 @@ export class JavaScriptParserVisitor {
22342254
case ts.SyntaxKind.AsteriskAsteriskToken:
22352255
assignmentOperation = JS.JsAssignmentOperation.Type.Power;
22362256
break;
2257+
case ts.SyntaxKind.AsteriskAsteriskEqualsToken:
2258+
assignmentOperation = JS.JsAssignmentOperation.Type.Exp;
2259+
break;
22372260
}
22382261

22392262
if (assignmentOperation !== undefined) {
@@ -2428,7 +2451,7 @@ export class JavaScriptParserVisitor {
24282451
randomId(),
24292452
this.prefix(node),
24302453
Markers.EMPTY,
2431-
[], //this.mapDecorators(node),
2454+
this.mapDecorators(node),
24322455
[], //this.mapModifiers(node),
24332456
new J.ClassDeclaration.Kind(
24342457
randomId(),
@@ -2558,7 +2581,8 @@ export class JavaScriptParserVisitor {
25582581
}
25592582

25602583
visitVariableStatement(node: ts.VariableStatement) {
2561-
return this.visitVariableDeclarationList(node.declarationList).withModifiers(this.mapModifiers(node)).withPrefix(this.prefix(node));
2584+
const declaration = this.visitVariableDeclarationList(node.declarationList);
2585+
return declaration.withModifiers(this.mapModifiers(node).concat(declaration.modifiers)).withPrefix(this.prefix(node));
25622586
}
25632587

25642588
visitExpressionStatement(node: ts.ExpressionStatement): J.Statement {
@@ -2788,6 +2812,10 @@ export class JavaScriptParserVisitor {
27882812
}
27892813

27902814
visitTryStatement(node: ts.TryStatement) {
2815+
if (node.catchClause?.variableDeclaration?.name && !ts.isIdentifier(node.catchClause?.variableDeclaration?.name)) {
2816+
this.visitUnknown(node);
2817+
}
2818+
27912819
return new J.Try(
27922820
randomId(),
27932821
this.prefix(node),
@@ -2843,14 +2871,28 @@ export class JavaScriptParserVisitor {
28432871
}
28442872

28452873
visitVariableDeclarationList(node: ts.VariableDeclarationList) {
2846-
const kind = node.getFirstToken(this.sourceFile);
2874+
let kind = node.getFirstToken();
2875+
2876+
// to parse the declaration case: await using db = ...
2877+
let modifier;
2878+
if (kind?.kind === ts.SyntaxKind.AwaitKeyword) {
2879+
modifier = new J.Modifier(
2880+
randomId(),
2881+
this.prefix(kind),
2882+
Markers.EMPTY,
2883+
'await',
2884+
J.Modifier.Type.LanguageExtension,
2885+
[]
2886+
);
2887+
kind = node.getChildAt(1);
2888+
}
28472889
return new JS.ScopedVariableDeclarations(
28482890
randomId(),
28492891
Space.EMPTY,
28502892
Markers.EMPTY,
2851-
[],
2893+
modifier ? [modifier] : [],
28522894
this.leftPadded(
2853-
this.prefix(node),
2895+
kind ? this.prefix(kind) : this.prefix(node),
28542896
kind?.kind === ts.SyntaxKind.LetKeyword
28552897
? JS.ScopedVariableDeclarations.Scope.Let
28562898
: kind?.kind === ts.SyntaxKind.ConstKeyword
@@ -3812,7 +3854,7 @@ export class JavaScriptParserVisitor {
38123854
return args;
38133855
}
38143856

3815-
private mapDecorators(node: ts.ClassDeclaration | ts.FunctionDeclaration | ts.MethodDeclaration | ts.ConstructorDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration | ts.SetAccessorDeclaration | ts.GetAccessorDeclaration): J.Annotation[] {
3857+
private mapDecorators(node: ts.ClassDeclaration | ts.FunctionDeclaration | ts.MethodDeclaration | ts.ConstructorDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration | ts.SetAccessorDeclaration | ts.GetAccessorDeclaration | ts.ClassExpression): J.Annotation[] {
38163858
return node.modifiers?.filter(ts.isDecorator)?.map(this.convert<J.Annotation>) ?? [];
38173859
}
38183860

openrewrite/src/javascript/tree/tree.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5747,6 +5747,7 @@ export namespace JsAssignmentOperation {
57475747
And = 1,
57485748
Or = 2,
57495749
Power = 3,
5750+
Exp = 4,
57505751

57515752
}
57525753

openrewrite/test/javascript/parser/binary.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,18 @@ describe('arithmetic operator mapping', () => {
8181
);
8282
});
8383

84-
test('power operation ', () => {
84+
test('power operation', () => {
8585
rewriteRun(
8686
//language=typescript
8787
typeScript('2 ** 3')
8888
);
8989
});
90+
test('exponentiation operation', () => {
91+
rewriteRun(
92+
//language=typescript
93+
typeScript('x **= 1')
94+
);
95+
});
9096
});
9197

9298
describe('bitwise operator mapping', () => {

openrewrite/test/javascript/parser/decorator.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,27 @@ describe('class decorator mapping', () => {
5454
`)
5555
);
5656
});
57+
test('decorator with parenthesized expression', () => {
58+
rewriteRun(
59+
//language=typescript
60+
typeScript(`
61+
class SimpleSpriteAssembler {
62+
@/*a*/(/*b*/Ember.computed('fullName').readOnly()/*c*/)/*d*/
63+
get fullNameReadonly() {
64+
return 'fullName';
65+
}
66+
}
67+
`)
68+
);
69+
});
70+
test('decorator on class expression', () => {
71+
rewriteRun(
72+
//language=typescript
73+
typeScript(`
74+
const Foo = (x => x)(@dec('') class { })
75+
`)
76+
);
77+
});
5778
test('class / method / params / properties decorators', () => {
5879
rewriteRun(
5980
//language=typescript

openrewrite/test/javascript/parser/function.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe('function mapping', () => {
77
test('simple', () => {
88
rewriteRun(
99
//language=typescript
10-
typeScript('function f () { let c = 1; }')
10+
typeScript('function f () /*a*/{/*b*/ let c = 1; }')
1111
);
1212
});
1313
test('single parameter', () => {

openrewrite/test/javascript/parser/method.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,4 +210,15 @@ describe('method mapping', () => {
210210
);
211211
});
212212

213+
test('method name as string literal', () => {
214+
rewriteRun(
215+
//language=typescript
216+
typeScript(`
217+
export interface IEnumerable<T> extends Iterable<T> {
218+
/*a*/"System.Collections.IEnumerable.GetEnumerator"/*b*/(/*c*/): IEnumerator<any>;
219+
}
220+
`)
221+
);
222+
});
223+
213224
});

openrewrite/test/javascript/parser/try-catch.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,22 @@ describe('try-catch mapping', () => {
138138
);
139139
});
140140

141+
test.skip('catch with ObjectBindingPattern as a name', () => {
142+
rewriteRun(
143+
//language=typescript
144+
typeScript(`
145+
class A {
146+
public async connect() {
147+
try {
148+
await new Promise(null);
149+
} catch ({error} : any ) {
150+
throw error;
151+
} finally {
152+
}
153+
}
154+
}
155+
`)
156+
);
157+
});
158+
141159
});

openrewrite/test/javascript/parser/typeAlias.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,4 +270,36 @@ describe('type alias mapping', () => {
270270
);
271271
});
272272

273+
test('type with intrinsic keyword', () => {
274+
rewriteRun(
275+
//language=typescript
276+
typeScript(`
277+
type Uppercase<S extends string> = intrinsic
278+
`)
279+
);
280+
});
281+
282+
test('constructor type with trailing coma', () => {
283+
rewriteRun(
284+
//language=typescript
285+
typeScript(`
286+
type ElementConstructor<P> =
287+
(new(
288+
x: P,
289+
y?: any/*a*/,/*b*/
290+
) => Component<any, any>);
291+
`)
292+
);
293+
});
294+
295+
test('constructor type with empty param', () => {
296+
rewriteRun(
297+
//language=typescript
298+
typeScript(`
299+
type ElementConstructor<P> =
300+
(new(/*a*/) => Component<any, any>);
301+
`)
302+
);
303+
});
304+
273305
});

openrewrite/test/javascript/parser/variableDeclarations.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,21 @@ describe('variable declaration mapping', () => {
187187
`)
188188
);
189189
});
190+
191+
test('variable with await using keyword', () => {
192+
rewriteRun(
193+
//language=typescript
194+
typeScript(`
195+
const getDb = async () => {
196+
return {async createUser(data) {
197+
const user = to<AdapterUser>(data)
198+
/*a*/await /*b*/ using db = await getDb()
199+
await db.U.insertOne(user)
200+
return from<AdapterUser>(user)
201+
}
202+
}
203+
}
204+
`)
205+
);
206+
});
190207
});

rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,13 +467,14 @@ public J visitScopedVariableDeclarations(JS.ScopedVariableDeclarations scopedVar
467467
JS.ScopedVariableDeclarations vd = scopedVariableDeclarations;
468468
vd = vd.withPrefix(visitSpace(vd.getPrefix(), JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_PREFIX, p));
469469
vd = vd.withMarkers(visitMarkers(vd.getMarkers(), p));
470-
vd = vd.getPadding().withScope(visitLeftPadded(vd.getPadding().getScope(), JsLeftPadded.Location.SCOPED_VARIABLE_DECLARATIONS_SCOPE, p));
471470
Statement temp = (Statement) visitStatement(vd, p);
472471
if (!(temp instanceof JS.ScopedVariableDeclarations)) {
473472
return temp;
474473
} else {
475474
vd = (JS.ScopedVariableDeclarations) temp;
476475
}
476+
vd = vd.withModifiers(Objects.requireNonNull(ListUtils.map(vd.getModifiers(), e -> visitAndCast(e, p))));
477+
vd = vd.getPadding().withScope(visitLeftPadded(vd.getPadding().getScope(), JsLeftPadded.Location.SCOPED_VARIABLE_DECLARATIONS_SCOPE, p));
477478
vd = vd.getPadding().withVariables(Objects.requireNonNull(ListUtils.map(vd.getPadding().getVariables(), e -> visitRightPadded(e, JsRightPadded.Location.SCOPED_VARIABLE_DECLARATIONS_VARIABLE, p))));
478479
return vd;
479480
}

0 commit comments

Comments
 (0)