forked from alibaba/lowcode-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjsExpression.ts
More file actions
128 lines (111 loc) · 3.44 KB
/
jsExpression.ts
File metadata and controls
128 lines (111 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import * as parser from '@babel/parser';
import generate from '@babel/generator';
import traverse from '@babel/traverse';
import * as t from '@babel/types';
import { JSExpression, JSFunction, isJSExpression, isJSFunction } from '@alilc/lowcode-types';
import { CodeGeneratorError, IScope } from '../types';
import { transformExpressionLocalRef, ParseError } from './expressionParser';
function parseFunction(content: string): t.FunctionExpression | null {
try {
const ast = parser.parse(`(${content});`);
let resultNode: t.FunctionExpression | null = null;
traverse(ast, {
FunctionExpression(path) {
resultNode = path.node;
path.stop();
},
});
return resultNode;
} catch (e) {
throw new ParseError(content, e);
}
}
function transformFuncExpr2MethodMember(methodName: string, content: string): string {
const funcNode = parseFunction(content);
if (funcNode) {
const targetNode = t.classMethod(
'method',
(methodName && t.identifier(methodName)) || funcNode.id || t.identifier('notDefineName'),
funcNode.params,
funcNode.body,
undefined,
undefined,
undefined,
funcNode.async || undefined,
);
const { code: resultCode } = generate(targetNode, { sourceMaps: false });
return resultCode;
}
throw new Error('Can not find Function Statement');
}
function getArrowFunction(content: string) {
const funcNode = parseFunction(content);
if (funcNode) {
const targetNode = t.arrowFunctionExpression(
funcNode.params,
funcNode.body,
funcNode.async || undefined,
);
const { code: resultCode } = generate(targetNode, { sourceMaps: false });
return resultCode;
}
throw new Error('Can not find Function Statement');
}
function getBodyStatements(content: string) {
const funcNode = parseFunction(content);
if (funcNode) {
const statements: t.Statement[] = funcNode.body.body;
const targetNode = t.program(statements, undefined, 'module', undefined);
const { code: resultCode } = generate(targetNode, { sourceMaps: false });
return resultCode;
}
throw new Error('Can not find Function Statement');
}
export function isJsCode(value: unknown): boolean {
return isJSExpression(value) || isJSFunction(value);
}
export function generateExpression(value: any, scope: IScope): string {
if (isJSExpression(value)) {
const exprVal = (value as JSExpression).value.trim();
if (!exprVal) {
return 'null';
}
const afterProcessWithLocals = transformExpressionLocalRef(exprVal, scope);
return afterProcessWithLocals;
}
throw new CodeGeneratorError('Not a JSExpression');
}
export function generateFunction(
value: any,
config: {
name?: string;
isMember?: boolean;
isBlock?: boolean;
isArrow?: boolean;
isBindExpr?: boolean;
} = {
name: undefined,
isMember: false,
isBlock: false,
isArrow: false,
isBindExpr: false,
},
) {
if (isJsCode(value)) {
const functionCfg = value as JSFunction;
if (config.isMember) {
return transformFuncExpr2MethodMember(config.name || '', functionCfg.value);
}
if (config.isBlock) {
return getBodyStatements(functionCfg.value);
}
if (config.isArrow) {
return getArrowFunction(functionCfg.value);
}
if (config.isBindExpr) {
return `(${functionCfg.value}).bind(this)`;
}
return functionCfg.value;
}
throw new CodeGeneratorError('Not a JSFunction or JSExpression');
}