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

Commit 2ed3070

Browse files
committed
add bug fixes
1 parent a3d19b8 commit 2ed3070

File tree

20 files changed

+328
-27
lines changed

20 files changed

+328
-27
lines changed

openrewrite/src/javascript/parser.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
randomId,
2424
SourceFile
2525
} from "../core";
26-
import {binarySearch, compareTextSpans, getNextSibling, TextSpan} from "./parserUtils";
26+
import {binarySearch, compareTextSpans, getNextSibling, getPreviousSibling, TextSpan} from "./parserUtils";
2727
import {JavaScriptTypeMapping} from "./typeMapping";
2828

2929
export class JavaScriptParser extends Parser {
@@ -260,10 +260,10 @@ export class JavaScriptParserVisitor {
260260
private mapModifiers(node: ts.VariableDeclarationList | ts.VariableStatement | ts.ClassDeclaration | ts.PropertyDeclaration
261261
| ts.FunctionDeclaration | ts.ParameterDeclaration | ts.MethodDeclaration | ts.EnumDeclaration | ts.InterfaceDeclaration
262262
| ts.PropertySignature | ts.ConstructorDeclaration | ts.ModuleDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration
263-
| ts.ArrowFunction | ts.IndexSignatureDeclaration) {
263+
| ts.ArrowFunction | ts.IndexSignatureDeclaration | ts.TypeAliasDeclaration) {
264264
if (ts.isVariableStatement(node) || ts.isModuleDeclaration(node) || ts.isClassDeclaration(node) || ts.isEnumDeclaration(node)
265265
|| ts.isInterfaceDeclaration(node) || ts.isPropertyDeclaration(node) || ts.isPropertySignature(node) || ts.isParameter(node)
266-
|| ts.isMethodDeclaration(node) || ts.isConstructorDeclaration(node) || ts.isArrowFunction(node) || ts.isIndexSignatureDeclaration(node)) {
266+
|| ts.isMethodDeclaration(node) || ts.isConstructorDeclaration(node) || ts.isArrowFunction(node) || ts.isIndexSignatureDeclaration(node) || ts.isTypeAliasDeclaration(node)) {
267267
return node.modifiers ? node.modifiers?.filter(ts.isModifier).map(this.mapModifier) : [];
268268
} else if (ts.isFunctionDeclaration(node)) {
269269
return [...node.modifiers ? node.modifiers?.filter(ts.isModifier).map(this.mapModifier) : [],
@@ -393,8 +393,8 @@ export class JavaScriptParserVisitor {
393393
return last?.kind == ts.SyntaxKind.SemicolonToken ? this.prefix(last) : Space.EMPTY;
394394
}
395395

396-
private keywordPrefix = (token: ts.PunctuationSyntaxKind) => (node: ts.Node): Space => {
397-
const last = getNextSibling(node);
396+
private keywordPrefix = (token: ts.PunctuationSyntaxKind, findSibling : (node: ts.Node) => ts.Node | null) => (node: ts.Node): Space => {
397+
const last = findSibling(node);
398398
return last?.kind == token ? this.prefix(last) : Space.EMPTY;
399399
}
400400

@@ -1309,21 +1309,29 @@ export class JavaScriptParserVisitor {
13091309
}
13101310

13111311
visitUnionType(node: ts.UnionTypeNode) {
1312+
const initialBar = getPreviousSibling(node.types[0]);
13121313
return new JS.Union(
13131314
randomId(),
13141315
this.prefix(node),
13151316
Markers.EMPTY,
1316-
this.rightPaddedList([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.BarToken)(n)),
1317+
[
1318+
...(initialBar?.kind == ts.SyntaxKind.BarToken ? [this.rightPadded<J.Expression>(this.newJEmpty(), this.prefix(initialBar))] : []),
1319+
...this.rightPaddedList<ts.Node, J.Expression>([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.BarToken, getNextSibling)(n))
1320+
],
13171321
this.mapType(node),
13181322
);
13191323
}
13201324

13211325
visitIntersectionType(node: ts.IntersectionTypeNode) {
1326+
const initialAmpersand = getPreviousSibling(node.types[0]);
13221327
return new JS.Intersection(
13231328
randomId(),
13241329
this.prefix(node),
13251330
Markers.EMPTY,
1326-
this.rightPaddedList([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.AmpersandToken)(n)),
1331+
[
1332+
...(initialAmpersand?.kind == ts.SyntaxKind.AmpersandToken ? [this.rightPadded<J.Expression>(this.newJEmpty(), this.prefix(initialAmpersand))] : []),
1333+
...this.rightPaddedList<ts.Node, J.Expression>([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.AmpersandToken, getNextSibling)(n))
1334+
],
13271335
this.mapType(node),
13281336
);
13291337
}
@@ -2527,8 +2535,8 @@ export class JavaScriptParserVisitor {
25272535
randomId(),
25282536
this.prefix(node),
25292537
Markers.EMPTY,
2530-
[],
2531-
this.visit(node.name),
2538+
this.mapModifiers(node),
2539+
this.leftPadded(this.prefix(this.findChildNode(node, ts.SyntaxKind.TypeKeyword)!), this.visit(node.name)),
25322540
node.typeParameters ? this.mapTypeParametersAsObject(node) : null,
25332541
this.leftPadded(this.prefix(this.findChildNode(node, ts.SyntaxKind.EqualsToken)!), this.convert(node.type)),
25342542
this.mapType(node)

openrewrite/src/javascript/remote/receiver.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ class Visitor extends JavaScriptVisitor<ReceiverContext> {
259259
typeDeclaration = typeDeclaration.withPrefix(ctx.receiveNode(typeDeclaration.prefix, receiveSpace)!);
260260
typeDeclaration = typeDeclaration.withMarkers(ctx.receiveNode(typeDeclaration.markers, ctx.receiveMarkers)!);
261261
typeDeclaration = typeDeclaration.withModifiers(ctx.receiveNodes(typeDeclaration.modifiers, ctx.receiveTree)!);
262-
typeDeclaration = typeDeclaration.withName(ctx.receiveNode(typeDeclaration.name, ctx.receiveTree)!);
262+
typeDeclaration = typeDeclaration.padding.withName(ctx.receiveNode(typeDeclaration.padding.name, receiveLeftPaddedTree)!);
263263
typeDeclaration = typeDeclaration.withTypeParameters(ctx.receiveNode(typeDeclaration.typeParameters, ctx.receiveTree));
264264
typeDeclaration = typeDeclaration.padding.withInitializer(ctx.receiveNode(typeDeclaration.padding.initializer, receiveLeftPaddedTree)!);
265265
typeDeclaration = typeDeclaration.withType(ctx.receiveValue(typeDeclaration.type, ValueType.Object));
@@ -1405,7 +1405,7 @@ class Factory implements ReceiverFactory {
14051405
ctx.receiveNode(null, receiveSpace)!,
14061406
ctx.receiveNode(null, ctx.receiveMarkers)!,
14071407
ctx.receiveNodes<Java.Modifier>(null, ctx.receiveTree)!,
1408-
ctx.receiveNode<Java.Identifier>(null, ctx.receiveTree)!,
1408+
ctx.receiveNode<JLeftPadded<Java.Identifier>>(null, receiveLeftPaddedTree)!,
14091409
ctx.receiveNode<Java.TypeParameters>(null, ctx.receiveTree),
14101410
ctx.receiveNode<JLeftPadded<Expression>>(null, receiveLeftPaddedTree)!,
14111411
ctx.receiveValue(null, ValueType.Object)

openrewrite/src/javascript/remote/sender.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ class Visitor extends JavaScriptVisitor<SenderContext> {
254254
ctx.sendNode(typeDeclaration, v => v.prefix, Visitor.sendSpace);
255255
ctx.sendNode(typeDeclaration, v => v.markers, ctx.sendMarkers);
256256
ctx.sendNodes(typeDeclaration, v => v.modifiers, ctx.sendTree, t => t.id);
257-
ctx.sendNode(typeDeclaration, v => v.name, ctx.sendTree);
257+
ctx.sendNode(typeDeclaration, v => v.padding.name, Visitor.sendLeftPadded(ValueType.Tree));
258258
ctx.sendNode(typeDeclaration, v => v.typeParameters, ctx.sendTree);
259259
ctx.sendNode(typeDeclaration, v => v.padding.initializer, Visitor.sendLeftPadded(ValueType.Tree));
260260
ctx.sendTypedValue(typeDeclaration, v => v.type, ValueType.Object);

openrewrite/src/javascript/tree/support_types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ export namespace JsSpace {
210210
TEMPLATE_EXPRESSION_VALUE_PREFIX,
211211
TUPLE_PREFIX,
212212
TYPE_DECLARATION_PREFIX,
213+
TYPE_DECLARATION_NAME_PREFIX,
213214
TYPE_OF_PREFIX,
214215
TYPE_OPERATOR_PREFIX,
215216
UNARY_PREFIX,
@@ -253,6 +254,7 @@ export namespace JsLeftPadded {
253254
OBJECT_BINDING_DECLARATIONS_BINDING_DIMENSIONS_AFTER_NAME,
254255
OBJECT_BINDING_DECLARATIONS_BINDING_INITIALIZER,
255256
TYPE_DECLARATION_INITIALIZER,
257+
TYPE_DECLARATION_NAME,
256258
TYPE_OPERATOR_EXPRESSION,
257259
UNARY_OPERATOR,
258260
JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_INITIALIZER,

openrewrite/src/javascript/tree/tree.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,7 +2021,7 @@ export class Tuple extends JSMixin(Object) implements Expression, TypeTree {
20212021

20222022
@LstType("org.openrewrite.javascript.tree.JS$TypeDeclaration")
20232023
export class TypeDeclaration extends JSMixin(Object) implements Statement, TypedTree {
2024-
public constructor(id: UUID, prefix: Space, markers: Markers, modifiers: Java.Modifier[], name: Java.Identifier, typeParameters: Java.TypeParameters | null, initializer: JLeftPadded<Expression>, _type: JavaType | null) {
2024+
public constructor(id: UUID, prefix: Space, markers: Markers, modifiers: Java.Modifier[], name: JLeftPadded<Java.Identifier>, typeParameters: Java.TypeParameters | null, initializer: JLeftPadded<Expression>, _type: JavaType | null) {
20252025
super();
20262026
this._id = id;
20272027
this._prefix = prefix;
@@ -2073,14 +2073,14 @@ export class TypeDeclaration extends JSMixin(Object) implements Statement, Typed
20732073
return modifiers === this._modifiers ? this : new TypeDeclaration(this._id, this._prefix, this._markers, modifiers, this._name, this._typeParameters, this._initializer, this._type);
20742074
}
20752075

2076-
private readonly _name: Java.Identifier;
2076+
private readonly _name: JLeftPadded<Java.Identifier>;
20772077

20782078
public get name(): Java.Identifier {
2079-
return this._name;
2079+
return this._name.element;
20802080
}
20812081

20822082
public withName(name: Java.Identifier): TypeDeclaration {
2083-
return name === this._name ? this : new TypeDeclaration(this._id, this._prefix, this._markers, this._modifiers, name, this._typeParameters, this._initializer, this._type);
2083+
return this.padding.withName(this._name.withElement(name));
20842084
}
20852085

20862086
private readonly _typeParameters: Java.TypeParameters | null;
@@ -2120,6 +2120,12 @@ export class TypeDeclaration extends JSMixin(Object) implements Statement, Typed
21202120
get padding() {
21212121
const t = this;
21222122
return new class {
2123+
public get name(): JLeftPadded<Java.Identifier> {
2124+
return t._name;
2125+
}
2126+
public withName(name: JLeftPadded<Java.Identifier>): TypeDeclaration {
2127+
return t._name === name ? t : new TypeDeclaration(t._id, t._prefix, t._markers, t._modifiers, name, t._typeParameters, t._initializer, t._type);
2128+
}
21232129
public get initializer(): JLeftPadded<Expression> {
21242130
return t._initializer;
21252131
}

openrewrite/src/javascript/visitor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
341341
typeDeclaration = tempStatement as TypeDeclaration;
342342
typeDeclaration = typeDeclaration.withMarkers(this.visitMarkers(typeDeclaration.markers, p));
343343
typeDeclaration = typeDeclaration.withModifiers(ListUtils.map(typeDeclaration.modifiers, el => this.visitAndCast(el, p)));
344-
typeDeclaration = typeDeclaration.withName(this.visitAndCast(typeDeclaration.name, p)!);
344+
typeDeclaration = typeDeclaration.padding.withName(this.visitJsLeftPadded(typeDeclaration.padding.name, JsLeftPadded.Location.TYPE_DECLARATION_NAME, p)!);
345345
typeDeclaration = typeDeclaration.withTypeParameters(this.visitAndCast(typeDeclaration.typeParameters, p));
346346
typeDeclaration = typeDeclaration.padding.withInitializer(this.visitJsLeftPadded(typeDeclaration.padding.initializer, JsLeftPadded.Location.TYPE_DECLARATION_INITIALIZER, p)!);
347347
return typeDeclaration;

openrewrite/test/javascript/e2e/google-maps-services-js_files.test.ts

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,193 @@ describe('google-maps-services-js files tests', () => {
363363
});
364364
`)
365365
);
366+
})
367+
368+
test('serialize.test.ts', () => {
369+
rewriteRun(
370+
//language=typescript
371+
typeScript(`
372+
/**
373+
* Copyright 2020 Google LLC
374+
*
375+
* Licensed under the Apache License, Version 2.0 (the "License");
376+
* you may not use this file except in compliance with the License.
377+
* You may obtain a copy of the License at
378+
*
379+
* http://www.apache.org/licenses/LICENSE-2.0
380+
*
381+
* Unless required by applicable law or agreed to in writing, software
382+
* distributed under the License is distributed on an "AS IS" BASIS,
383+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
384+
* See the License for the specific language governing permissions and
385+
* limitations under the License.
386+
*/
387+
388+
import { LatLng, LatLngLiteral } from "./common";
389+
import {
390+
createPremiumPlanQueryString,
391+
latLngArrayToStringMaybeEncoded,
392+
latLngBoundsToString,
393+
latLngToString,
394+
objectToString,
395+
serializer,
396+
toLatLngLiteral,
397+
toTimestamp,
398+
} from "./serialize";
399+
400+
test("latLngToString is correct", () => {
401+
expect(latLngToString("")).toBe("");
402+
expect(latLngToString("10,20")).toBe("10,20");
403+
expect(latLngToString([10, 20])).toBe("10,20");
404+
expect(latLngToString({ lat: 10, lng: 20 })).toBe("10,20");
405+
expect(latLngToString({ latitude: 10, longitude: 20 })).toBe("10,20");
406+
expect(() => {
407+
latLngToString({} as LatLngLiteral);
408+
}).toThrow(TypeError);
409+
});
410+
411+
test("latLngBoundsToString is correct", () => {
412+
expect(latLngBoundsToString("")).toBe("");
413+
expect(
414+
latLngBoundsToString({
415+
southwest: { lat: 1, lng: 2 },
416+
northeast: { lat: 3, lng: 4 },
417+
})
418+
).toBe("1,2|3,4");
419+
});
420+
421+
test("serializer", () => {
422+
expect(
423+
serializer({ quz: (o) => o }, "http://mock.url")({ foo: ["bar"] })
424+
).toBe("foo=bar");
425+
expect(
426+
serializer(
427+
{
428+
foo: (o) => o.map((latLng: LatLng) => latLngToString(latLng)),
429+
},
430+
"http://mock.url"
431+
)({
432+
foo: [
433+
[0, 1],
434+
[2, 3],
435+
],
436+
})
437+
).toBe("foo=0%2C1|2%2C3");
438+
});
439+
440+
test("serializer should not mutate params", () => {
441+
const location = { lat: 0, lng: 1 };
442+
const params = {
443+
location,
444+
};
445+
446+
serializer({ location: latLngToString }, "http://mock.url")(params);
447+
expect(params.location).toBe(location);
448+
});
449+
450+
test("serializer should return pipe joined arrays by default", () => {
451+
expect(serializer({}, "http://mock.url")({ foo: ["b", "a", "r"] })).toBe(
452+
"foo=b|a|r"
453+
);
454+
});
455+
456+
test("serializer creates premium plan query string if premium plan params are included", () => {
457+
const params = {
458+
avoid: "ferries",
459+
destination: {
460+
lat: "38.8977",
461+
lng: "-77.0365",
462+
},
463+
mode: "driving",
464+
origin: {
465+
lat: "33.8121",
466+
lng: "-117.9190",
467+
},
468+
units: "imperial",
469+
client_id: "testClient",
470+
client_secret: "testClientSecret",
471+
};
472+
473+
expect(
474+
serializer(
475+
{
476+
origin: latLngToString,
477+
destination: latLngToString,
478+
},
479+
"https://test.url/maps/api/directions/json"
480+
)(params)
481+
).toEqual(
482+
"avoid=ferries&client=testClient&destination=38.8977%2C-77.0365&mode=driving&origin=33.8121%2C-117.9190&units=imperial&signature=YRJoTd6ohbpsR14WkWv3S7H6MqU="
483+
);
484+
});
485+
486+
test("objectToString", () => {
487+
expect(objectToString("foo")).toBe("foo");
488+
expect(objectToString({ c: "c", a: "a", b: "b" })).toBe("a:a|b:b|c:c");
489+
});
490+
491+
test("latLngArrayToStringMaybeEncoded", () => {
492+
expect(latLngArrayToStringMaybeEncoded("0,0")).toEqual("0,0");
493+
expect(latLngArrayToStringMaybeEncoded([[0, 0]])).toEqual("0,0");
494+
expect(
495+
latLngArrayToStringMaybeEncoded([
496+
[40.714728, -73.998672],
497+
[-34.397, 150.644],
498+
])
499+
).toEqual("enc:abowFtzsbMhgmiMuobzi@");
500+
});
501+
502+
test("toLatLngLiteral", () => {
503+
expect(toLatLngLiteral("0,1")).toEqual({ lat: 0, lng: 1 });
504+
expect(toLatLngLiteral([0, 1])).toEqual({ lat: 0, lng: 1 });
505+
expect(toLatLngLiteral({ lat: 0, lng: 1 })).toEqual({
506+
lat: 0,
507+
lng: 1,
508+
});
509+
expect(toLatLngLiteral({ latitude: 0, longitude: 1 })).toEqual({
510+
lat: 0,
511+
lng: 1,
512+
});
513+
expect(() => {
514+
toLatLngLiteral({} as LatLngLiteral);
515+
}).toThrow(TypeError);
516+
});
517+
518+
test("toTimestamp", () => {
519+
expect(toTimestamp(100)).toEqual(100);
520+
521+
const dt = new Date();
522+
const seconds = Math.round(Number(dt) / 1000);
523+
expect(toTimestamp(dt)).toEqual(seconds);
524+
expect(toTimestamp("now")).toEqual("now");
525+
526+
expect(toTimestamp(new Date("2022-06-22T09:03:33.430Z"))).toEqual(1655888613);
527+
});
528+
529+
test("createPremiumPlanQueryString", () => {
530+
const serializedParams = {
531+
avoid: "ferries",
532+
destination: "38.8977,-77.0365",
533+
mode: "driving",
534+
origin: "33.8121,-117.9190",
535+
units: "imperial",
536+
client_id: "testClient",
537+
client_secret: "testClientSecret",
538+
};
539+
const queryStringOptions = {
540+
arrayFormat: "separator",
541+
arrayFormatSeparator: "|",
542+
};
543+
const baseUrl = "https://test.url/maps/api/directions/json";
544+
545+
expect(
546+
createPremiumPlanQueryString(serializedParams, queryStringOptions, baseUrl)
547+
).toEqual(
548+
"avoid=ferries&client=testClient&destination=38.8977%2C-77.0365&mode=driving&origin=33.8121%2C-117.9190&units=imperial&signature=YRJoTd6ohbpsR14WkWv3S7H6MqU="
549+
);
550+
});
551+
`)
552+
);
366553
});
367554

368555
});

openrewrite/test/javascript/parser/call.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ describe('call mapping', () => {
8686
8787
const result1 = identity<string>?.("Hello TypeScript");
8888
const result2 = identity?.<string>("Hello TypeScript");
89+
const result3 = identity?.call("Hello TypeScript");
8990
`)
9091
);
9192
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {connect, disconnect, rewriteRun, typeScript} from '../testHarness';
2+
3+
describe('export keyword tests', () => {
4+
beforeAll(() => connect());
5+
afterAll(() => disconnect());
6+
7+
test('module.export', () => {
8+
rewriteRun(
9+
//language=typescript
10+
typeScript(`
11+
const nxPreset = require('@nx/jest/preset').default;
12+
13+
module.exports = { ...nxPreset };
14+
`)
15+
);
16+
});
17+
});
18+
19+

0 commit comments

Comments
 (0)