Skip to content

Commit cf5ad6d

Browse files
committed
feat: support builder.newExpression
1 parent 4983f47 commit cf5ad6d

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed

src/builders.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as recast from "recast";
22
import { proxifyFunctionCall } from "./proxy/function-call";
3+
import { proxifyNewExpression } from "./proxy/new-expression";
34
import { literalToAst } from "./proxy/_utils";
45
import { Proxified } from "./types";
56
import { parseExpression } from "./code";
@@ -17,6 +18,16 @@ export const builders = {
1718
);
1819
return proxifyFunctionCall(node as any);
1920
},
21+
/**
22+
* Create a new expression node.
23+
*/
24+
newExpression(callee: string, ...args: any[]): Proxified {
25+
const node = b.newExpression(
26+
b.identifier(callee),
27+
args.map((i) => literalToAst(i) as any)
28+
);
29+
return proxifyNewExpression(node as any);
30+
},
2031
/**
2132
* Create a proxified version of a literal value.
2233
*/

src/proxy/new-expression.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { ASTNode } from "../types";
2+
import { MagicastError } from "../error";
3+
import { createProxy } from "./_utils";
4+
import { proxifyArrayElements } from "./array";
5+
import { ProxifiedModule, ProxifiedNewExpression } from "./types";
6+
7+
export function proxifyNewExpression<T extends []>(
8+
node: ASTNode,
9+
mod?: ProxifiedModule
10+
): ProxifiedNewExpression<T> {
11+
if (node.type !== "NewExpression") {
12+
throw new MagicastError("Not a new expression");
13+
}
14+
15+
function stringifyExpression(node: ASTNode): string {
16+
if (node.type === "Identifier") {
17+
return node.name;
18+
}
19+
if (node.type === "MemberExpression") {
20+
return `${stringifyExpression(node.object)}.${stringifyExpression(
21+
node.property
22+
)}`;
23+
}
24+
throw new MagicastError("Not implemented");
25+
}
26+
27+
const argumentsProxy = proxifyArrayElements<T>(node, node.arguments, mod);
28+
29+
return createProxy(
30+
node,
31+
{
32+
$type: "new-expression",
33+
$callee: stringifyExpression(node.callee as any),
34+
$args: argumentsProxy,
35+
},
36+
{}
37+
) as ProxifiedNewExpression<T>;
38+
}

src/proxy/proxify.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ASTNode } from "../types";
33
import { proxifyArray } from "./array";
44
import { proxifyFunctionCall } from "./function-call";
55
import { proxifyObject } from "./object";
6+
import { proxifyNewExpression } from "./new-expression";
67
import { Proxified, ProxifiedModule, ProxifiedValue } from "./types";
78
import { LITERALS_AST, LITERALS_TYPEOF } from "./_utils";
89

@@ -34,6 +35,10 @@ export function proxify<T>(node: ASTNode, mod?: ProxifiedModule): Proxified<T> {
3435
proxy = proxifyFunctionCall(node, mod);
3536
break;
3637
}
38+
case "NewExpression": {
39+
proxy = proxifyNewExpression(node, mod);
40+
break;
41+
}
3742
default:
3843
throw new MagicastError(`Casting "${node.type}" is not supported`, {
3944
ast: node,

src/proxy/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ export type ProxifiedFunctionCall<Args extends any[] = unknown[]> =
2323
$callee: string;
2424
};
2525

26+
export type ProxifiedNewExpression<Args extends any[] = unknown[]> =
27+
ProxyBase & {
28+
$type: "new-expression";
29+
$args: ProxifiedArray<Args>;
30+
$callee: string;
31+
};
32+
2633
export type ProxifiedObject<T extends object = object> = {
2734
[K in keyof T]: Proxified<T[K]>;
2835
} & ProxyBase & {
@@ -86,6 +93,7 @@ export interface ImportItemInput {
8693
export type ProxifiedValue =
8794
| ProxifiedArray
8895
| ProxifiedFunctionCall
96+
| ProxifiedNewExpression
8997
| ProxifiedObject
9098
| ProxifiedModule
9199
| ProxifiedImportsMap

test/builders.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,32 @@ describe("builders", () => {
2929
`);
3030
});
3131

32+
it("new expression", () => {
33+
const call = builders.newExpression("Foo", 1, "bar", {
34+
foo: "bar",
35+
});
36+
expect(call.$type).toBe("new-expression");
37+
expect(call.$callee).toBe("Foo");
38+
expect(call.$args).toMatchInlineSnapshot(`
39+
[
40+
1,
41+
"bar",
42+
{
43+
"foo": "bar",
44+
},
45+
]
46+
`);
47+
48+
const mod = parseModule("");
49+
mod.exports.a = call;
50+
51+
expect(generate(mod)).toMatchInlineSnapshot(`
52+
"export const a = new Foo(1, \\"bar\\", {
53+
foo: \\"bar\\",
54+
});"
55+
`);
56+
});
57+
3258
it("raw", () => {
3359
const expression = builders.raw("{ foo: 1 }");
3460
expect(expression.$type).toBe("object");

0 commit comments

Comments
 (0)