Skip to content

Commit

Permalink
add bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
OlegDokuka committed Nov 27, 2024
1 parent a3d19b8 commit 2ed3070
Show file tree
Hide file tree
Showing 20 changed files with 328 additions and 27 deletions.
26 changes: 17 additions & 9 deletions openrewrite/src/javascript/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
randomId,
SourceFile
} from "../core";
import {binarySearch, compareTextSpans, getNextSibling, TextSpan} from "./parserUtils";
import {binarySearch, compareTextSpans, getNextSibling, getPreviousSibling, TextSpan} from "./parserUtils";
import {JavaScriptTypeMapping} from "./typeMapping";

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

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

Expand Down Expand Up @@ -1309,21 +1309,29 @@ export class JavaScriptParserVisitor {
}

visitUnionType(node: ts.UnionTypeNode) {
const initialBar = getPreviousSibling(node.types[0]);
return new JS.Union(
randomId(),
this.prefix(node),
Markers.EMPTY,
this.rightPaddedList([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.BarToken)(n)),
[
...(initialBar?.kind == ts.SyntaxKind.BarToken ? [this.rightPadded<J.Expression>(this.newJEmpty(), this.prefix(initialBar))] : []),
...this.rightPaddedList<ts.Node, J.Expression>([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.BarToken, getNextSibling)(n))
],
this.mapType(node),
);
}

visitIntersectionType(node: ts.IntersectionTypeNode) {
const initialAmpersand = getPreviousSibling(node.types[0]);
return new JS.Intersection(
randomId(),
this.prefix(node),
Markers.EMPTY,
this.rightPaddedList([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.AmpersandToken)(n)),
[
...(initialAmpersand?.kind == ts.SyntaxKind.AmpersandToken ? [this.rightPadded<J.Expression>(this.newJEmpty(), this.prefix(initialAmpersand))] : []),
...this.rightPaddedList<ts.Node, J.Expression>([...node.types], (n) => this.keywordPrefix(ts.SyntaxKind.AmpersandToken, getNextSibling)(n))
],
this.mapType(node),
);
}
Expand Down Expand Up @@ -2527,8 +2535,8 @@ export class JavaScriptParserVisitor {
randomId(),
this.prefix(node),
Markers.EMPTY,
[],
this.visit(node.name),
this.mapModifiers(node),
this.leftPadded(this.prefix(this.findChildNode(node, ts.SyntaxKind.TypeKeyword)!), this.visit(node.name)),
node.typeParameters ? this.mapTypeParametersAsObject(node) : null,
this.leftPadded(this.prefix(this.findChildNode(node, ts.SyntaxKind.EqualsToken)!), this.convert(node.type)),
this.mapType(node)
Expand Down
4 changes: 2 additions & 2 deletions openrewrite/src/javascript/remote/receiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ class Visitor extends JavaScriptVisitor<ReceiverContext> {
typeDeclaration = typeDeclaration.withPrefix(ctx.receiveNode(typeDeclaration.prefix, receiveSpace)!);
typeDeclaration = typeDeclaration.withMarkers(ctx.receiveNode(typeDeclaration.markers, ctx.receiveMarkers)!);
typeDeclaration = typeDeclaration.withModifiers(ctx.receiveNodes(typeDeclaration.modifiers, ctx.receiveTree)!);
typeDeclaration = typeDeclaration.withName(ctx.receiveNode(typeDeclaration.name, ctx.receiveTree)!);
typeDeclaration = typeDeclaration.padding.withName(ctx.receiveNode(typeDeclaration.padding.name, receiveLeftPaddedTree)!);
typeDeclaration = typeDeclaration.withTypeParameters(ctx.receiveNode(typeDeclaration.typeParameters, ctx.receiveTree));
typeDeclaration = typeDeclaration.padding.withInitializer(ctx.receiveNode(typeDeclaration.padding.initializer, receiveLeftPaddedTree)!);
typeDeclaration = typeDeclaration.withType(ctx.receiveValue(typeDeclaration.type, ValueType.Object));
Expand Down Expand Up @@ -1405,7 +1405,7 @@ class Factory implements ReceiverFactory {
ctx.receiveNode(null, receiveSpace)!,
ctx.receiveNode(null, ctx.receiveMarkers)!,
ctx.receiveNodes<Java.Modifier>(null, ctx.receiveTree)!,
ctx.receiveNode<Java.Identifier>(null, ctx.receiveTree)!,
ctx.receiveNode<JLeftPadded<Java.Identifier>>(null, receiveLeftPaddedTree)!,
ctx.receiveNode<Java.TypeParameters>(null, ctx.receiveTree),
ctx.receiveNode<JLeftPadded<Expression>>(null, receiveLeftPaddedTree)!,
ctx.receiveValue(null, ValueType.Object)
Expand Down
2 changes: 1 addition & 1 deletion openrewrite/src/javascript/remote/sender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ class Visitor extends JavaScriptVisitor<SenderContext> {
ctx.sendNode(typeDeclaration, v => v.prefix, Visitor.sendSpace);
ctx.sendNode(typeDeclaration, v => v.markers, ctx.sendMarkers);
ctx.sendNodes(typeDeclaration, v => v.modifiers, ctx.sendTree, t => t.id);
ctx.sendNode(typeDeclaration, v => v.name, ctx.sendTree);
ctx.sendNode(typeDeclaration, v => v.padding.name, Visitor.sendLeftPadded(ValueType.Tree));
ctx.sendNode(typeDeclaration, v => v.typeParameters, ctx.sendTree);
ctx.sendNode(typeDeclaration, v => v.padding.initializer, Visitor.sendLeftPadded(ValueType.Tree));
ctx.sendTypedValue(typeDeclaration, v => v.type, ValueType.Object);
Expand Down
2 changes: 2 additions & 0 deletions openrewrite/src/javascript/tree/support_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ export namespace JsSpace {
TEMPLATE_EXPRESSION_VALUE_PREFIX,
TUPLE_PREFIX,
TYPE_DECLARATION_PREFIX,
TYPE_DECLARATION_NAME_PREFIX,
TYPE_OF_PREFIX,
TYPE_OPERATOR_PREFIX,
UNARY_PREFIX,
Expand Down Expand Up @@ -253,6 +254,7 @@ export namespace JsLeftPadded {
OBJECT_BINDING_DECLARATIONS_BINDING_DIMENSIONS_AFTER_NAME,
OBJECT_BINDING_DECLARATIONS_BINDING_INITIALIZER,
TYPE_DECLARATION_INITIALIZER,
TYPE_DECLARATION_NAME,
TYPE_OPERATOR_EXPRESSION,
UNARY_OPERATOR,
JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_INITIALIZER,
Expand Down
14 changes: 10 additions & 4 deletions openrewrite/src/javascript/tree/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2021,7 +2021,7 @@ export class Tuple extends JSMixin(Object) implements Expression, TypeTree {

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

private readonly _name: Java.Identifier;
private readonly _name: JLeftPadded<Java.Identifier>;

public get name(): Java.Identifier {
return this._name;
return this._name.element;
}

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

private readonly _typeParameters: Java.TypeParameters | null;
Expand Down Expand Up @@ -2120,6 +2120,12 @@ export class TypeDeclaration extends JSMixin(Object) implements Statement, Typed
get padding() {
const t = this;
return new class {
public get name(): JLeftPadded<Java.Identifier> {
return t._name;
}
public withName(name: JLeftPadded<Java.Identifier>): TypeDeclaration {
return t._name === name ? t : new TypeDeclaration(t._id, t._prefix, t._markers, t._modifiers, name, t._typeParameters, t._initializer, t._type);
}
public get initializer(): JLeftPadded<Expression> {
return t._initializer;
}
Expand Down
2 changes: 1 addition & 1 deletion openrewrite/src/javascript/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
typeDeclaration = tempStatement as TypeDeclaration;
typeDeclaration = typeDeclaration.withMarkers(this.visitMarkers(typeDeclaration.markers, p));
typeDeclaration = typeDeclaration.withModifiers(ListUtils.map(typeDeclaration.modifiers, el => this.visitAndCast(el, p)));
typeDeclaration = typeDeclaration.withName(this.visitAndCast(typeDeclaration.name, p)!);
typeDeclaration = typeDeclaration.padding.withName(this.visitJsLeftPadded(typeDeclaration.padding.name, JsLeftPadded.Location.TYPE_DECLARATION_NAME, p)!);
typeDeclaration = typeDeclaration.withTypeParameters(this.visitAndCast(typeDeclaration.typeParameters, p));
typeDeclaration = typeDeclaration.padding.withInitializer(this.visitJsLeftPadded(typeDeclaration.padding.initializer, JsLeftPadded.Location.TYPE_DECLARATION_INITIALIZER, p)!);
return typeDeclaration;
Expand Down
187 changes: 187 additions & 0 deletions openrewrite/test/javascript/e2e/google-maps-services-js_files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,193 @@ describe('google-maps-services-js files tests', () => {
});
`)
);
})

test('serialize.test.ts', () => {
rewriteRun(
//language=typescript
typeScript(`
/**
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { LatLng, LatLngLiteral } from "./common";
import {
createPremiumPlanQueryString,
latLngArrayToStringMaybeEncoded,
latLngBoundsToString,
latLngToString,
objectToString,
serializer,
toLatLngLiteral,
toTimestamp,
} from "./serialize";
test("latLngToString is correct", () => {
expect(latLngToString("")).toBe("");
expect(latLngToString("10,20")).toBe("10,20");
expect(latLngToString([10, 20])).toBe("10,20");
expect(latLngToString({ lat: 10, lng: 20 })).toBe("10,20");
expect(latLngToString({ latitude: 10, longitude: 20 })).toBe("10,20");
expect(() => {
latLngToString({} as LatLngLiteral);
}).toThrow(TypeError);
});
test("latLngBoundsToString is correct", () => {
expect(latLngBoundsToString("")).toBe("");
expect(
latLngBoundsToString({
southwest: { lat: 1, lng: 2 },
northeast: { lat: 3, lng: 4 },
})
).toBe("1,2|3,4");
});
test("serializer", () => {
expect(
serializer({ quz: (o) => o }, "http://mock.url")({ foo: ["bar"] })
).toBe("foo=bar");
expect(
serializer(
{
foo: (o) => o.map((latLng: LatLng) => latLngToString(latLng)),
},
"http://mock.url"
)({
foo: [
[0, 1],
[2, 3],
],
})
).toBe("foo=0%2C1|2%2C3");
});
test("serializer should not mutate params", () => {
const location = { lat: 0, lng: 1 };
const params = {
location,
};
serializer({ location: latLngToString }, "http://mock.url")(params);
expect(params.location).toBe(location);
});
test("serializer should return pipe joined arrays by default", () => {
expect(serializer({}, "http://mock.url")({ foo: ["b", "a", "r"] })).toBe(
"foo=b|a|r"
);
});
test("serializer creates premium plan query string if premium plan params are included", () => {
const params = {
avoid: "ferries",
destination: {
lat: "38.8977",
lng: "-77.0365",
},
mode: "driving",
origin: {
lat: "33.8121",
lng: "-117.9190",
},
units: "imperial",
client_id: "testClient",
client_secret: "testClientSecret",
};
expect(
serializer(
{
origin: latLngToString,
destination: latLngToString,
},
"https://test.url/maps/api/directions/json"
)(params)
).toEqual(
"avoid=ferries&client=testClient&destination=38.8977%2C-77.0365&mode=driving&origin=33.8121%2C-117.9190&units=imperial&signature=YRJoTd6ohbpsR14WkWv3S7H6MqU="
);
});
test("objectToString", () => {
expect(objectToString("foo")).toBe("foo");
expect(objectToString({ c: "c", a: "a", b: "b" })).toBe("a:a|b:b|c:c");
});
test("latLngArrayToStringMaybeEncoded", () => {
expect(latLngArrayToStringMaybeEncoded("0,0")).toEqual("0,0");
expect(latLngArrayToStringMaybeEncoded([[0, 0]])).toEqual("0,0");
expect(
latLngArrayToStringMaybeEncoded([
[40.714728, -73.998672],
[-34.397, 150.644],
])
).toEqual("enc:abowFtzsbMhgmiMuobzi@");
});
test("toLatLngLiteral", () => {
expect(toLatLngLiteral("0,1")).toEqual({ lat: 0, lng: 1 });
expect(toLatLngLiteral([0, 1])).toEqual({ lat: 0, lng: 1 });
expect(toLatLngLiteral({ lat: 0, lng: 1 })).toEqual({
lat: 0,
lng: 1,
});
expect(toLatLngLiteral({ latitude: 0, longitude: 1 })).toEqual({
lat: 0,
lng: 1,
});
expect(() => {
toLatLngLiteral({} as LatLngLiteral);
}).toThrow(TypeError);
});
test("toTimestamp", () => {
expect(toTimestamp(100)).toEqual(100);
const dt = new Date();
const seconds = Math.round(Number(dt) / 1000);
expect(toTimestamp(dt)).toEqual(seconds);
expect(toTimestamp("now")).toEqual("now");
expect(toTimestamp(new Date("2022-06-22T09:03:33.430Z"))).toEqual(1655888613);
});
test("createPremiumPlanQueryString", () => {
const serializedParams = {
avoid: "ferries",
destination: "38.8977,-77.0365",
mode: "driving",
origin: "33.8121,-117.9190",
units: "imperial",
client_id: "testClient",
client_secret: "testClientSecret",
};
const queryStringOptions = {
arrayFormat: "separator",
arrayFormatSeparator: "|",
};
const baseUrl = "https://test.url/maps/api/directions/json";
expect(
createPremiumPlanQueryString(serializedParams, queryStringOptions, baseUrl)
).toEqual(
"avoid=ferries&client=testClient&destination=38.8977%2C-77.0365&mode=driving&origin=33.8121%2C-117.9190&units=imperial&signature=YRJoTd6ohbpsR14WkWv3S7H6MqU="
);
});
`)
);
});

});
1 change: 1 addition & 0 deletions openrewrite/test/javascript/parser/call.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ describe('call mapping', () => {
const result1 = identity<string>?.("Hello TypeScript");
const result2 = identity?.<string>("Hello TypeScript");
const result3 = identity?.call("Hello TypeScript");
`)
);
});
Expand Down
19 changes: 19 additions & 0 deletions openrewrite/test/javascript/parser/export.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {connect, disconnect, rewriteRun, typeScript} from '../testHarness';

describe('export keyword tests', () => {
beforeAll(() => connect());
afterAll(() => disconnect());

test('module.export', () => {
rewriteRun(
//language=typescript
typeScript(`
const nxPreset = require('@nx/jest/preset').default;
module.exports = { ...nxPreset };
`)
);
});
});


Loading

0 comments on commit 2ed3070

Please sign in to comment.