@lcap/nasl 3.3.0-alpha.3 → 3.4.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,40 +6,42 @@ import generate from '@babel/generator';
6
6
  import * as naslTypes from '../concepts';
7
7
  import { traverse } from '../utils';
8
8
 
9
+ const debug = false;
10
+
9
11
  export function tryParseTS(tsCode: string) {
10
- try {
11
- const root = babel.parseSync(tsCode, {
12
- filename: 'result.ts',
13
- presets: [require('@babel/preset-typescript')],
14
- }) as babelTypes.File;
15
- // console.log((root as any).program.body[0].body.body.map((item) => item.trailingComments));
16
- return root;
17
- } catch (e) {
18
- return null;
19
- }
12
+ try {
13
+ const root = babel.parseSync(tsCode, {
14
+ filename: 'result.ts',
15
+ presets: [require('@babel/preset-typescript')],
16
+ }) as babelTypes.File;
17
+ // console.log((root as any).program.body[0].body.body.map((item) => item.trailingComments));
18
+ return root;
19
+ } catch (e) {
20
+ return null;
21
+ }
20
22
  }
21
23
 
22
24
  function flatMemberExpression(node: babelTypes.Node): Array<babelTypes.Node> {
23
25
  if (node.type === 'MemberExpression')
24
- return [...flatMemberExpression(node.object), node.property];
26
+ return [...flatMemberExpression(node.object), node.property];
25
27
  return [node];
26
28
  }
27
29
  function flatMatchPatternsExpression(node: any): Array<babelTypes.Node> {
28
30
  if (node.concept === 'BinaryExpression') {
29
- if (node.operator === '||') {
30
- return [...flatMatchPatternsExpression(node.left), ...flatMatchPatternsExpression(node.right)];
31
- }
32
- if (node.operator === '==') {
33
- return [node.right];
34
- }
35
- return [node];
31
+ if (node.operator === '||') {
32
+ return [...flatMatchPatternsExpression(node.left), ...flatMatchPatternsExpression(node.right)];
33
+ }
34
+ if (node.operator === '==') {
35
+ return [node.right];
36
+ }
37
+ return [node];
36
38
  }
37
39
  return [node];
38
40
  }
39
41
 
40
42
  function flatIfStatement(node: any): Array<babelTypes.Node> {
41
43
  if (node.alternate.type === 'IfStatement') {
42
- return [...flatIfStatement(node.alternate), node];
44
+ return [...flatIfStatement(node.alternate), node];
43
45
  }
44
46
  return [node];
45
47
  }
@@ -50,631 +52,783 @@ function flatIfStatement(node: any): Array<babelTypes.Node> {
50
52
  * @returns
51
53
  */
52
54
  function fixLogicNode(node: babelTypes.Node): void {
53
- if (node?.type === 'CallExpression') {
54
- const calleeName = generate(node.callee as any).code;
55
- if (calleeName === 'nasl.util.ForEach') {
56
- const callee = flatMemberExpression(node.callee);
57
- node.callee = callee[2] as babelTypes.Identifier;
58
- }
55
+ if (node?.type === 'CallExpression') {
56
+ const calleeName = generate(node.callee as any).code;
57
+ if (calleeName === 'nasl.util.ForEach') {
58
+ const callee = flatMemberExpression(node.callee);
59
+ node.callee = callee[2] as babelTypes.Identifier;
59
60
  }
61
+ }
60
62
  }
61
63
 
64
+
62
65
  export function transformTSCode(tsCode: string, contextLogicName: string, type?: string) {
63
- const logic = new naslTypes.Logic();
64
- logic.body = [];
66
+ const logic = new naslTypes.Logic();
67
+ logic.body = [];
65
68
 
66
- function transformTypeAnnotation(node: babelTypes.TSType): naslTypes.TypeAnnotation {
67
- if (node.type === 'TSTypeReference') {
68
- const typeName = (node.typeName as babelTypes.Identifier).name;
69
- const primitiveType = naslTypes.primitiveTypeList.find((ta) => ta.typeName === typeName);
70
- if ((node as any)?.typeNamespace) {
71
- return naslTypes.TypeAnnotation.createReference(typeName, {
72
- typeNamespace: (node as any).typeNamespace,
73
- });
74
- }
75
- if (primitiveType) {
76
- return naslTypes.TypeAnnotation.createPrimitive(typeName);
77
- }
78
- if (['List', 'Map', 'Current'].includes(typeName) && node.typeParameters) {
79
- return naslTypes.TypeAnnotation.createGeneric(typeName, {
80
- typeArguments: node.typeParameters.params.map(transformTypeAnnotation),
81
- });
82
- }
83
- if (!node.typeParameters) {
84
- return naslTypes.TypeAnnotation.createReference(typeName, {
85
- typeNamespace: 'app.dataSources.defaultDS',
86
- });
87
- }
88
- console.error(node);
89
- throw new Error(`Unhandled node ${node.type}`);
90
- } else if (node.type === 'TSTypeLiteral') {
91
- return naslTypes.TypeAnnotation.createTypeAnonymousStructure(node.members.map((member: babelTypes.TSPropertySignature) => new naslTypes.StructureProperty({
92
- name: (member.key as babelTypes.Identifier).name,
93
- typeAnnotation: transformTypeAnnotation(member.typeAnnotation.typeAnnotation),
94
- })));
95
- } else if (node.type === 'TSBooleanKeyword') {
96
- return naslTypes.TypeAnnotation.createPrimitive('Boolean');
97
- } else if (node.type === 'TSStringKeyword') {
98
- return naslTypes.TypeAnnotation.createPrimitive('String');
99
- } else if (node.type === 'TSNumberKeyword') {
100
- return naslTypes.TypeAnnotation.createPrimitive('Double');
101
- } else if (node.type === 'TSUnionType') {
102
- const union = naslTypes.TypeAnnotation.createPrimitive('Union');
103
- union.typeArguments = [];
104
- node.types.forEach((curType) => {
105
- union.typeArguments.push(transformTypeAnnotation(curType));
106
- });
107
- return union;
108
- } else {
109
- console.error(node);
110
- throw new Error(`Unhandled node ${node.type}`);
111
- }
112
- }
113
- function transformParam(node: babelTypes.Identifier): naslTypes.Param {
114
- const typeAnnotation = (node.typeAnnotation as babelTypes.TSTypeAnnotation)?.typeAnnotation;
115
- return new naslTypes.Param({
116
- name: node.name,
117
- typeAnnotation: typeAnnotation ? transformTypeAnnotation(typeAnnotation) : null,
69
+ function transformTypeAnnotation(node: babelTypes.TSType): naslTypes.TypeAnnotation {
70
+ if (node.type === 'TSTypeReference') {
71
+ const typeName = (node.typeName as babelTypes.Identifier).name;
72
+ const primitiveType = naslTypes.primitiveTypeList.find((ta) => ta.typeName === typeName);
73
+ if ((node as any)?.typeNamespace) {
74
+ return naslTypes.TypeAnnotation.createReference(typeName, {
75
+ typeNamespace: (node as any).typeNamespace,
76
+ });
77
+ }
78
+ if (typeName === 'Integer') {
79
+ return naslTypes.TypeAnnotation.createPrimitive('Long');
80
+ }
81
+ if (primitiveType) {
82
+ return naslTypes.TypeAnnotation.createPrimitive(typeName);
83
+ }
84
+ if (['List', 'Map', 'Current'].includes(typeName) && node.typeParameters) {
85
+ return naslTypes.TypeAnnotation.createGeneric(typeName, {
86
+ typeArguments: node.typeParameters.params.map(transformTypeAnnotation),
87
+ });
88
+ }
89
+ if (!node.typeParameters) {
90
+ return naslTypes.TypeAnnotation.createReference(typeName, {
91
+ typeNamespace: 'app.dataSources.defaultDS',
118
92
  });
93
+ }
94
+ console.error(node);
95
+ if (debug) {
96
+ throw new Error(`Unhandled node ${node.type}`);
97
+ }
98
+ } else if (node.type === 'TSTypeLiteral') {
99
+ return naslTypes.TypeAnnotation.createTypeAnonymousStructure(node.members.map((member: babelTypes.TSPropertySignature) => new naslTypes.StructureProperty({
100
+ name: (member.key as babelTypes.Identifier).name,
101
+ typeAnnotation: transformTypeAnnotation(member.typeAnnotation.typeAnnotation),
102
+ })));
103
+ } else if (node.type === 'TSBooleanKeyword') {
104
+ return naslTypes.TypeAnnotation.createPrimitive('Boolean');
105
+ } else if (node.type === 'TSStringKeyword') {
106
+ return naslTypes.TypeAnnotation.createPrimitive('String');
107
+ } else if (node.type === 'TSNumberKeyword') {
108
+ return naslTypes.TypeAnnotation.createPrimitive('Double');
109
+ } else if (node.type === 'TSUnionType') {
110
+ const union = naslTypes.TypeAnnotation.createPrimitive('Union');
111
+ union.typeArguments = [];
112
+ node.types.forEach((curType) => {
113
+ union.typeArguments.push(transformTypeAnnotation(curType));
114
+ });
115
+ return union;
116
+ } else {
117
+ console.error(node);
118
+ if (debug) {
119
+ throw new Error(`Unhandled node ${node.type}`);
120
+ }
119
121
  }
120
- function pushElseIf(ifNode: babelTypes.IfStatement, switchStatement: naslTypes.SwitchStatement) {
122
+ }
123
+ function transformParam(node: babelTypes.Identifier): naslTypes.Param {
124
+ const typeAnnotation = (node.typeAnnotation as babelTypes.TSTypeAnnotation)?.typeAnnotation;
125
+ return new naslTypes.Param({
126
+ name: node.name,
127
+ typeAnnotation: typeAnnotation ? transformTypeAnnotation(typeAnnotation) : null,
128
+ });
129
+ }
130
+ function pushElseIf(ifNode: babelTypes.IfStatement, switchStatement: naslTypes.SwitchStatement) {
131
+ switchStatement.cases.push(new naslTypes.SwitchCase({
132
+ test: transformLogicNode(ifNode.test),
133
+ consequent: !ifNode.consequent ? [] : (ifNode.consequent as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
134
+ }));
135
+ if (ifNode.alternate && ifNode.alternate.type === 'IfStatement') {
136
+ pushElseIf(ifNode.alternate, switchStatement);
137
+ } else {
121
138
  switchStatement.cases.push(new naslTypes.SwitchCase({
122
- test: transformLogicNode(ifNode.test),
123
- consequent: !ifNode.consequent ? [] : (ifNode.consequent as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
139
+ test: undefined,
140
+ consequent: !ifNode?.alternate ? [] : (ifNode?.alternate as babelTypes.BlockStatement)?.body.map((item) => transformLogicNode(item)).filter((item) => !!item),
124
141
  }));
125
- if (ifNode.alternate && ifNode.alternate.type === 'IfStatement') {
126
- pushElseIf(ifNode.alternate, switchStatement);
127
- } else {
128
- switchStatement.cases.push(new naslTypes.SwitchCase({
129
- test: undefined,
130
- consequent: !ifNode.consequent ? [] : (ifNode.consequent as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
131
- }));
132
- }
142
+ }
133
143
  }
134
144
 
135
- function transformLogicNode(node: babelTypes.Node, typeAnnotation?: naslTypes.TypeAnnotation): naslTypes.LogicItem {
136
- fixLogicNode(node);
137
- // console.log('lemon ~~~ node--1:', node);
138
- if (node.type === 'VariableDeclaration') { // 拆成局部变量和赋值
139
- const declList = node?.declarations || [];
140
- declList?.forEach((decl) => {
141
- const variableName = (decl.id as babelTypes.Identifier).name;
142
- if (!logic.variables.find((variable) => variable.name === variableName)) {
143
- const varTypeAnnotation = ((decl.id as babelTypes.Identifier).typeAnnotation as babelTypes.TSTypeAnnotation)?.typeAnnotation;
144
- logic.variables.push(new naslTypes.Variable({
145
- name: variableName,
146
- typeAnnotation: varTypeAnnotation && transformTypeAnnotation(varTypeAnnotation),
147
- }));
148
- }
149
- if (decl.init) {
150
- if (decl.init.type !== 'ArrayExpression') {
151
- if (type === 'expression') {
152
- return transformLogicNode(decl.init);
153
- }
154
- const item = new naslTypes.Assignment({
155
- left: new naslTypes.Identifier({
156
- name: variableName,
157
- }),
158
- right: transformLogicNode(decl.init),
159
- });
160
- item && logic.body.push(item);
161
- }
162
- }
163
- });
164
- } else if (node.type === 'CallExpression') {
165
- const callee = flatMemberExpression(node.callee);
166
- const calleeName = generate(node.callee as any).code;
167
- // console.log('lemon ~~~ node--2', node, callee, calleeName);
168
- if (/^\$refs\./.test(calleeName)) {
169
- return new naslTypes.CallLogic({
170
- calleeNamespace: `elements.${(callee[1] as babelTypes.Identifier).name}.logics`,
171
- calleeName: (callee[2] as babelTypes.Identifier).name,
172
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
173
- expression: transformLogicNode(arg),
174
- })) as naslTypes.Argument[],
175
- });
176
- }
177
- if (callee.length === 2 && callee[0].type === 'Identifier' && callee[0].name.endsWith('Entity')) {
178
- const entityName = callee[0].name.replace(/Entity$/, '');
179
- return new naslTypes.CallLogic({
180
- calleeNamespace: `app.dataSources.defaultDS.entities.${entityName}.logics`,
181
- calleeName: (callee[1] as babelTypes.Identifier).name,
182
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
183
- expression: transformLogicNode(arg),
184
- })) as naslTypes.Argument[],
185
- });
186
- }
187
- if (calleeName === 'nasl.oql.query') {
188
- return new naslTypes.OqlQueryComponent({
189
- dataSource: 'app.dataSources.defaultDS',
190
- code: generate(node.arguments[0] as any).code.trim().slice(1, -1),
191
- });
192
- }
193
- if (calleeName.startsWith('nasl.util.')) {
194
- const curCalleeName = callee.length === 3 ? (callee[callee.length - 1] as babelTypes.Identifier).name : (callee[0] as any).callee.property.name;
195
- const argument = callee.length === 3 ? node.arguments : (callee[0] as any).arguments as any;
196
- let typeNamespace: string;
197
- if (argument?.[argument.length - 1]?.type === 'ObjectExpression') {
198
- typeNamespace = argument.splice(-1)[0].properties[0].value.value;
199
- }
200
- const nodeElement = new naslTypes.CallFunction({
201
- calleeNamespace: 'nasl.util',
202
- calleeName: curCalleeName,
203
- arguments: argument.map((arg: any, index: number) => new naslTypes.Argument({
204
- expression: transformLogicNode(arg),
205
- keyword: `str${index + 1}`,
206
- })) as naslTypes.Argument[],
207
- typeArguments: node?.typeParameters?.params.map((curType: any) => transformTypeAnnotation({ ...curType, typeNamespace })),
145
+ function handleBinaryExpression(calleeName: String, argument: any) {
146
+ const map: Record<'plus' | 'minus' | 'multiply' | 'divide' | 'remainder', '+' | '-' | '*' | '/' | '%'> = {
147
+ plus: '+',
148
+ minus: '-',
149
+ multiply: '*',
150
+ divide: '/',
151
+ remainder: '%',
152
+ };
153
+ return new naslTypes.BinaryExpression({
154
+ operator: map?.[calleeName as keyof typeof map],
155
+ left: transformLogicNode(argument?.[0]),
156
+ right: transformLogicNode(argument?.[1]),
157
+ });
158
+ }
208
159
 
209
- });
210
- // console.log('lemon ~ callFunction ~ 3:', nodeElement);
211
- return nodeElement;
212
- }
213
- if (callee.length === 3 && calleeName.startsWith('nasl.ui.')) {
214
- return new naslTypes.CallLogic({
215
- calleeNamespace: 'nasl.ui',
216
- calleeName: (callee[2] as babelTypes.Identifier).name,
217
- shortcut: true,
218
- /**
219
- * 这个函数是修复 AI 翻译出错的情况,与正常的 transform 做个区分
220
- * @param node
221
- * @returns
222
- */
223
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
224
- expression: transformLogicNode(arg),
225
- })) as naslTypes.Argument[],
226
- });
227
- }
228
- if (calleeName === 'ForEach') {
229
- const newCallee = node.arguments;
230
- const arrowFunction = node.arguments[3] as babelTypes.ArrowFunctionExpression;
231
- const nodeElement = new naslTypes.ForEachStatement({
232
- each: transformLogicNode(newCallee[0]),
233
- start: transformLogicNode(newCallee[1]),
234
- end: transformLogicNode(newCallee[2]),
235
- item: transformParam(arrowFunction.params[0] as babelTypes.Identifier),
236
- index: transformParam(arrowFunction.params[1] as babelTypes.Identifier),
237
- body: (arrowFunction.body as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
238
- });
239
- return nodeElement;
240
- }
241
- if (callee.length === 2) {
242
- const curCalleeName = (node.callee as any).property.name;
243
- if (curCalleeName === 'forEach') {
244
- const newCallee = (node.callee as any).object;
245
- const arrowFunction = node.arguments[0] as babelTypes.ArrowFunctionExpression;
246
- const nodeElement = new naslTypes.ForEachStatement({
247
- each: transformLogicNode(newCallee.callee.object),
248
- start: transformLogicNode(newCallee?.arguments?.[0]),
249
- end: transformLogicNode(newCallee?.arguments?.[1]),
250
- item: transformParam(arrowFunction.params[0] as babelTypes.Identifier),
251
- index: transformParam(arrowFunction.params[1] as babelTypes.Identifier),
252
- body: (arrowFunction.body as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
253
- });
254
- return nodeElement;
255
- }
256
- } else if (['plus', 'minus', 'multiply', 'divide', 'remainder'].includes(calleeName)) {
257
- const map: Record<'plus' | 'minus' | 'multiply' | 'divide' | 'remainder', '+' | '-' | '*' | '/' | '%'> = {
258
- plus: '+',
259
- minus: '-',
260
- multiply: '*',
261
- divide: '/',
262
- remainder: '%',
263
- };
264
- return new naslTypes.BinaryExpression({
265
- operator: map[calleeName as keyof typeof map],
266
- left: transformLogicNode(node.arguments[0]),
267
- right: transformLogicNode(node.arguments[1]),
268
- });
269
- } else if (calleeName === 'alert') {
270
- return new naslTypes.CallLogic({
271
- calleeNamespace: 'nasl.ui',
272
- calleeName: 'showMessage',
273
- shortcut: true,
274
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
275
- expression: transformLogicNode(arg),
276
- })) as naslTypes.Argument[],
277
- });
278
- } else if (calleeName === 'console.log') {
279
- return new naslTypes.CallLogic({
280
- calleeNamespace: 'nasl.logging',
281
- calleeName: 'INFO',
282
- shortcut: true,
283
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
284
- expression: transformLogicNode(arg),
285
- })) as naslTypes.Argument[],
286
- });
287
- } else if (/^app.dataSources|app.logics|load/.test(calleeName)) {
288
- return new naslTypes.CallLogic({
289
- calleeNamespace: generate((node.callee as any).object).code,
290
- calleeName: (callee[callee.length - 1] as babelTypes.Identifier).name,
291
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
292
- expression: transformLogicNode(arg),
293
- })) as naslTypes.Argument[],
294
- });
295
- } else if (callee.length === 1) {
296
- return new naslTypes.CallLogic({
297
- calleeNamespace: `app.logics`,
298
- calleeName,
299
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
300
- expression: transformLogicNode(arg),
301
- })) as naslTypes.Argument[],
302
- });
303
- } else if (/interfaces/.test(calleeName)) {
304
- return new naslTypes.CallInterface({
305
- calleeNamespace: generate((node.callee as any).object).code,
306
- calleeName: (callee[callee.length - 1] as babelTypes.Identifier).name,
307
- arguments: node.arguments.map((arg: any) => new naslTypes.Argument({
308
- keyword: arg.properties[0].key.name,
309
- expression: transformLogicNode(arg.properties[0].value),
310
- })) as naslTypes.Argument[],
311
- });
312
- } else if (/destination/.test(calleeName)) {
313
- const newCallee = flatMemberExpression((node.callee as any).object);
314
- return new naslTypes.Destination({
315
- viewNamespace: generate((node.callee as any).object.object).code,
316
- viewName: (newCallee[newCallee.length - 1] as babelTypes.Identifier).name,
317
- target: (node.arguments[0] as any).properties[1].value.value,
318
- anchor: new naslTypes.Anchor({
319
- expression: transformLogicNode((node.arguments[0] as any).properties[0].value),
320
- }),
321
- });
322
- } else if (node.callee.type === 'ArrowFunctionExpression') {
323
- // NOTE: 适用于 if else
324
- const newCallee = (node.callee.body as any).body;
325
- if (newCallee[newCallee.length - 1].argument?.callee?.name === '__MatchExpressionFuntion') {
326
- const match = new naslTypes.Match({
327
- expression: transformLogicNode(newCallee[0]),
328
- isExpression: type === 'expression',
329
- cases: flatIfStatement(newCallee[1].body.body[0]).map((_case: any) => new naslTypes.MatchCase({
330
- patterns: !_case.test ? [] : flatMatchPatternsExpression(transformLogicNode(_case.test)) as any,
331
- body: _case.consequent.body.filter((item: any) => item.type !== 'BreakStatement').map((item: any) => transformLogicNode(item)).filter((item: any) => !!item),
332
- })),
333
- });
334
- if (!match.cases.length || match.cases[match.cases.length - 1].patterns.length) {
335
- match.cases.push(new naslTypes.MatchCase({
336
- patterns: [],
337
- body: [],
338
- }));
339
- }
340
- match.cases.forEach((case_: any) => {
341
- if (case_.body.length && (case_.body[0].concept === 'BooleanLiteral' || case_.body[0].concept === 'StringLiteral')) {
342
- case_.isMatchedTypeEnumable = true;
343
- }
344
- if (case_.patterns.length && case_.patterns[0].concept === 'MemberExpression') {
345
- case_.isMatchedTypeEnumable = true;
346
- case_.patterns[0] = new naslTypes.MemberExpression({
347
- object: { concept: 'Identifier',
348
- name: case_.patterns[0].object.property.name,
349
- folded: false,
350
- namespace: 'app.enums' } as any,
351
- property: {
352
- concept: 'Identifier',
353
- name: case_.patterns[0].property.value,
354
- folded: false,
355
- } as any,
356
- });
357
- }
358
- });
359
- return match;
360
- }
361
- if (newCallee[newCallee.length - 1].argument?.callee?.name === '__SwitchExpressionFuntion') {
362
- const switchStatement = transformLogicNode(newCallee[0].body.body[0]);
363
- return switchStatement;
364
- }
365
- console.error(node);
366
- throw new Error(`Unhandled ArrowFunctionExpression node ${node.type}`);
367
- } else {
368
- console.error(node);
369
- throw new Error(`Unhandled node ${callee.map((item: babelTypes.Identifier) => item.name).join('.')} ${node.type}`);
370
- }
371
- } else if (node.type === 'IfStatement') {
372
- if (node.alternate && node.alternate.type === 'IfStatement') {
373
- const switchStatement = new naslTypes.SwitchStatement({
374
- cases: [],
375
- });
376
- pushElseIf(node, switchStatement);
377
- return switchStatement;
378
- }
379
- return new naslTypes.IfStatement({
380
- test: transformLogicNode(node.test),
381
- consequent: !node.consequent ? [] : (node.consequent as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
382
- alternate: !node.alternate ? [] : (node.alternate as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
383
- });
384
- } else if (node.type === 'WhileStatement') {
385
- return new naslTypes.WhileStatement({
386
- test: transformLogicNode(node.test),
387
- body: (node.body as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
388
- });
389
- } else if (node.type === 'SwitchStatement') {
390
- const match = new naslTypes.Match({
391
- expression: transformLogicNode(node.discriminant),
392
- isExpression: type === 'expression',
393
- cases: node.cases.map((_case) => new naslTypes.MatchCase({
394
- patterns: !_case.test ? [] : [transformLogicNode(_case.test)],
395
- body: _case.consequent.filter((item) => item.type !== 'BreakStatement').map((item) => transformLogicNode(item)).filter((item) => !!item),
396
- })),
397
- });
398
- if (!match.cases.length || match.cases[match.cases.length - 1].patterns.length) {
399
- match.cases.push(new naslTypes.MatchCase({
400
- patterns: [],
401
- body: [],
402
- }));
403
- }
404
- match.cases.forEach((case_: any) => {
405
- if (case_.body.length && (case_.body[0].concept === 'BooleanLiteral' || case_.body[0].concept === 'StringLiteral')) {
406
- case_.isMatchedTypeEnumable = true;
407
- }
408
- if (case_.patterns.length && case_.patterns[0].concept === 'MemberExpression') {
409
- case_.isMatchedTypeEnumable = true;
410
- case_.patterns[0].object.namespace = 'app.enums';
411
- }
412
- });
413
- return match;
414
- } else if (node.type === 'MemberExpression') {
415
- if (node.property.type === 'NumericLiteral') {
416
- return new naslTypes.CallFunction({
417
- calleeNamespace: 'nasl.util',
418
- calleeName: 'Get',
419
- arguments: [
420
- new naslTypes.Argument({
421
- expression: transformLogicNode(node.object),
422
- }),
423
- new naslTypes.Argument({
424
- expression: transformLogicNode(node.property),
425
- }),
426
- ],
427
- });
428
- }
429
- return new naslTypes.MemberExpression({
430
- object: transformLogicNode(node.object),
431
- property: transformLogicNode(node.property),
432
- });
433
- } else if (node.type === 'Identifier') {
434
- return new naslTypes.Identifier({
435
- name: node.name,
436
- });
437
- } else if (node.type === 'ExpressionStatement') {
438
- return transformLogicNode(node.expression);
439
- } else if (node.type === 'AssignmentExpression') {
440
- if (node.operator === '+=' || node.operator === '-=') {
441
- if (type === 'expression') {
442
- return new naslTypes.BinaryExpression({
443
- operator: node.operator[0] as '+' | '-',
444
- left: transformLogicNode(node.left),
445
- right: transformLogicNode(node.right),
446
- });
447
- }
448
- return new naslTypes.Assignment({
449
- left: transformLogicNode(node.left),
450
- right: new naslTypes.BinaryExpression({
451
- operator: node.operator[0] as '+' | '-',
452
- left: transformLogicNode(node.left),
453
- right: transformLogicNode(node.right),
454
- }),
455
- });
456
- }
160
+ function handleNewExpression(calleeName: String, node: any) {
161
+ if (calleeName === 'NewList') {
162
+ return new naslTypes.NewList({
163
+ typeAnnotation: naslTypes.TypeAnnotation.createGeneric('List', {
164
+ typeArguments: node?.typeParameters?.params.map(transformTypeAnnotation),
165
+ }),
166
+ items: node?.arguments?.[0]?.elements?.map((arg: any) => transformLogicNode(arg)),
167
+ });
168
+ }
169
+ if (calleeName === 'NewMap') {
170
+ const keys: any = [];
171
+ const values: any = [];
172
+ node?.arguments?.[0]?.properties.forEach((arg: any) => {
173
+ keys.push(transformLogicNode(arg.key));
174
+ values.push(transformLogicNode(arg.value));
175
+ });
176
+ return new naslTypes.NewMap({
177
+ typeAnnotation: naslTypes.TypeAnnotation.createGeneric('Map', {
178
+ typeArguments: node?.typeParameters?.params.map(transformTypeAnnotation),
179
+ }),
180
+ keys,
181
+ values,
182
+ });
183
+ }
184
+ if (calleeName === 'NewEntity') {
185
+ const properties: any = [];
186
+ const rights: any = [];
187
+ node?.arguments?.[0]?.properties.forEach((arg: any) => {
188
+ properties.push(transformLogicNode(arg.key));
189
+ rights.push(new naslTypes.SelectMembers({
190
+ expression: transformLogicNode(arg.value)
191
+ }));
192
+ });
193
+ const typeName = node?.typeParameters?.params?.[0]?.typeName?.name;
194
+ return new naslTypes.NewComposite({
195
+ typeAnnotation: naslTypes.TypeAnnotation.createReference(typeName, {
196
+ typeNamespace: 'app.dataSources.defaultDS.entities',
197
+ typeName
198
+ }),
199
+ properties,
200
+ rights,
201
+ });
202
+ }
203
+ if (calleeName === 'NewAnonymityStructure') {
204
+ const properties: any = [];
205
+ const rights: any = [];
206
+ const structureProperties: any = [];
207
+ node?.arguments?.[0]?.properties?.forEach((arg: any) => {
208
+ properties.push(transformLogicNode(arg.key));
209
+ rights.push(new naslTypes.SelectMembers({
210
+ expression: transformLogicNode(arg.value)
211
+ }));
212
+ structureProperties.push(new naslTypes.StructureProperty({
213
+ name: arg?.key?.name,
214
+ typeAnnotation: null
215
+ }));
216
+ });
217
+ return new naslTypes.NewComposite({
218
+ typeAnnotation: naslTypes.TypeAnnotation.createTypeAnonymousStructure(structureProperties),
219
+ properties,
220
+ rights,
221
+ });
222
+ }
223
+ return node;
224
+ }
225
+
226
+ function transformLogicNode(node: babelTypes.Node, typeAnnotation?: naslTypes.TypeAnnotation): naslTypes.LogicItem {
227
+ fixLogicNode(node);
228
+ // console.log('lemon ~~~ node--1:', node);
229
+ if (node.type === 'VariableDeclaration') { // 拆成局部变量和赋值
230
+ const declList = node?.declarations || [];
231
+ declList?.forEach((decl) => {
232
+ const variableName = (decl.id as babelTypes.Identifier).name;
233
+ if (!logic.variables.find((variable) => variable.name === variableName)) {
234
+ const varTypeAnnotation = ((decl.id as babelTypes.Identifier).typeAnnotation as babelTypes.TSTypeAnnotation)?.typeAnnotation;
235
+ logic.variables.push(new naslTypes.Variable({
236
+ name: variableName,
237
+ typeAnnotation: varTypeAnnotation && transformTypeAnnotation(varTypeAnnotation),
238
+ }));
239
+ }
240
+ if (decl.init) {
241
+ if (decl.init.type !== 'ArrayExpression' && decl.init.type !== 'ObjectExpression') {
457
242
  if (type === 'expression') {
458
- return transformLogicNode(node.right);
243
+ return transformLogicNode(decl.init);
459
244
  }
460
- return new naslTypes.Assignment({
461
- left: transformLogicNode(node.left),
462
- right: transformLogicNode(node.right),
245
+ const item = new naslTypes.Assignment({
246
+ left: new naslTypes.Identifier({
247
+ name: variableName,
248
+ }),
249
+ right: transformLogicNode(decl.init),
463
250
  });
464
- } else if (node.type === 'NewExpression') {
465
- const calleeName = generate(node.callee as any).code;
466
- if (['Boolean', 'Integer', 'Double', 'Decimal', 'Long'].includes(calleeName)) {
467
- return transformLogicNode(node.arguments[0], naslTypes.TypeAnnotation.createPrimitive(calleeName));
468
- }
469
- console.error(node);
470
- throw new Error(`Unhandled node ${node.type}`);
471
- } else if (node.type === 'ArrowFunctionExpression') {
472
- return new naslTypes.AnonymousFunction({
473
- params: node.params.map((param: babelTypes.Identifier) => transformParam(param)),
474
- body: transformLogicNode(node.body),
475
- }) as any as naslTypes.LogicItem;
476
- } else if (node.type === 'BooleanLiteral') {
477
- return new naslTypes.BooleanLiteral({
478
- value: String(node.value),
479
- });
480
- } else if (node.type === 'StringLiteral') {
481
- return new naslTypes.StringLiteral({
482
- value: node.value,
483
- });
484
- } else if (node.type === 'NumericLiteral') {
485
- const literal = new naslTypes.NumericLiteral({
486
- value: String(node.value),
487
- typeAnnotation: typeAnnotation || naslTypes.TypeAnnotation.createPrimitive('Integer'),
488
- });
489
- literal.typeAnnotation.typeName = literal.changeType(String(node.value));
490
- return literal;
491
- } else if (node.type === 'NullLiteral') {
492
- return new naslTypes.NullLiteral();
493
- } else if (node.type === 'TemplateLiteral') {
494
- const expressions = [...node.expressions as babelTypes.Expression[], ...node.quasis.map((element) => ({
495
- type: 'StringLiteral',
496
- value: element.value.raw,
497
- start: element.start,
498
- end: element.end,
499
- })) as babelTypes.StringLiteral[]];
500
- expressions.sort((a, b) => a.start - b.start);
251
+ item && logic.body.push(item);
252
+ }
253
+ }
254
+ });
255
+ } else if (node.type === 'CallExpression') {
256
+ const callee = flatMemberExpression(node.callee);
257
+ const calleeName = generate(node.callee as any).code;
258
+ // console.log('lemon ~~~ node--2', node, callee, calleeName);
259
+ if (/^\$refs\./.test(calleeName)) {
260
+ return new naslTypes.CallLogic({
261
+ calleeNamespace: `elements.${(callee[1] as babelTypes.Identifier).name}.logics`,
262
+ calleeName: (callee[2] as babelTypes.Identifier).name,
263
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
264
+ expression: transformLogicNode(arg),
265
+ })) as naslTypes.Argument[],
266
+ });
267
+ }
268
+ if (callee.length === 2 && callee[0].type === 'Identifier' && callee[0].name.endsWith('Entity')) {
269
+ const entityName = callee[0].name.replace(/Entity$/, '');
270
+ return new naslTypes.CallLogic({
271
+ calleeNamespace: `app.dataSources.defaultDS.entities.${entityName}.logics`,
272
+ calleeName: (callee[1] as babelTypes.Identifier).name,
273
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
274
+ expression: transformLogicNode(arg),
275
+ })) as naslTypes.Argument[],
276
+ });
277
+ }
278
+ if (calleeName === 'nasl.oql.query') {
279
+ return new naslTypes.OqlQueryComponent({
280
+ dataSource: 'app.dataSources.defaultDS',
281
+ code: generate(node.arguments[0] as any).code.trim().slice(1, -1),
282
+ });
283
+ }
284
+ if (calleeName === 'nasl.util.consoleLog' || calleeName === 'console.log') {
285
+ if (contextLogicName.includes('on_') || contextLogicName.includes('viewLogic_')) {
286
+ return new naslTypes.CallLogic({
287
+ calleeNamespace: 'nasl.util',
288
+ calleeName: 'consoleLog',
289
+ shortcut: true,
290
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
291
+ expression: transformLogicNode(arg),
292
+ })) as naslTypes.Argument[],
293
+ });
294
+ }
295
+ return new naslTypes.CallLogic({
296
+ calleeNamespace: 'nasl.logging',
297
+ calleeName: 'INFO',
298
+ shortcut: true,
299
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
300
+ expression: transformLogicNode(arg),
301
+ })) as naslTypes.Argument[],
302
+ });
303
+ }
304
+ if (calleeName === 'nasl.util.jsonSerialize' || calleeName === 'nasl.util.jsonDeserialize') {
305
+ const curCalleeName = (node.callee as any).property.name;
306
+ return new naslTypes.CallLogic({
307
+ calleeNamespace: 'nasl.util',
308
+ calleeName: curCalleeName,
309
+ shortcut: true,
310
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
311
+ expression: transformLogicNode(arg),
312
+ })) as naslTypes.Argument[],
313
+ typeArguments: node?.typeParameters?.params.map((curType: any) => transformTypeAnnotation({ ...curType })),
314
+ });
315
+ };
316
+ if (calleeName.startsWith('nasl.util.')) {
317
+ const curCalleeName = callee.length === 3 ? (callee[callee.length - 1] as babelTypes.Identifier).name : (callee[0] as any).callee.property.name;
318
+ const argument = callee.length === 3 ? node.arguments : (callee[0] as any).arguments as any;
501
319
 
502
- return new naslTypes.StringInterpolation({
503
- expressions: expressions.map((item) => transformLogicNode(item)),
504
- });
505
- } else if (node.type === 'BinaryExpression' || node.type === 'LogicalExpression') {
506
- if (node.operator === '===')
507
- node.operator = '==';
508
- if (node.operator === '!==')
509
- node.operator = '!=';
510
- if (['+', '-', '*', '/', '%', '==', '!=', '>', '<', '>=', '<=', '&&', '||', 'startwith', 'endwith', 'like', 'in'].includes(node.operator)) {
511
- return new naslTypes.BinaryExpression({
512
- operator: node.operator as any,
513
- left: transformLogicNode(node.left),
514
- right: transformLogicNode(node.right),
515
- });
516
- }
517
- console.error(node);
518
- throw new Error(`Unhandled node ${node.type}`);
519
- } else if (node.type === 'UnaryExpression') {
520
- if (['!'].includes(node.operator)) {
521
- return new naslTypes.UnaryExpression({
522
- operator: node.operator as any,
523
- argument: transformLogicNode(node.argument),
524
- });
525
- }
526
- if (['-'].includes(node.operator) && node.argument.type === 'NumericLiteral') {
527
- return transformLogicNode({
528
- type: 'NumericLiteral',
529
- value: -node.argument.value,
530
- } as babelTypes.NumericLiteral);
531
- }
532
- console.error(node);
533
- throw new Error(`Unhandled node ${node.type}`);
534
- } else if (node.type === 'UpdateExpression') {
535
- if (node.operator === '++' || node.operator === '--') {
536
- return new naslTypes.Assignment({
537
- left: transformLogicNode(node.argument),
538
- right: new naslTypes.BinaryExpression({
539
- operator: node.operator[0] as '+' | '-',
540
- left: transformLogicNode(node.argument),
541
- right: new naslTypes.NumericLiteral({
542
- value: '1',
543
- typeAnnotation: naslTypes.TypeAnnotation.createPrimitive('Integer'),
544
- }),
545
- }),
546
- });
320
+ if (['plus', 'minus', 'multiply', 'divide', 'remainder'].includes(curCalleeName)) {
321
+ return handleBinaryExpression(curCalleeName, argument);
322
+ };
323
+
324
+ if (['NewList', 'NewMap', 'NewEntity', 'NewAnonymityStructure'].includes(curCalleeName)) {
325
+ return handleNewExpression(curCalleeName, node);
326
+ }
327
+
328
+ let typeNamespace: string;
329
+ if (argument?.[argument.length - 1]?.type === 'ObjectExpression') {
330
+ typeNamespace = argument.splice(-1)[0].properties[0].value.value;
331
+ }
332
+ const nodeElement = new naslTypes.CallFunction({
333
+ calleeNamespace: 'nasl.util',
334
+ calleeName: curCalleeName,
335
+ arguments: argument.map((arg: any, index: number) => new naslTypes.Argument({
336
+ expression: transformLogicNode(arg),
337
+ keyword: `str${index + 1}`,
338
+ })) as naslTypes.Argument[],
339
+ typeArguments: node?.typeParameters?.params.map((curType: any) => transformTypeAnnotation({ ...curType, typeNamespace })),
340
+
341
+ });
342
+ // console.log('lemon ~ callFunction ~ 3:', nodeElement);
343
+ return nodeElement;
344
+ }
345
+ if (callee.length === 3 && calleeName.startsWith('nasl.ui.')) {
346
+ if ((callee[2] as babelTypes.Identifier).name === 'destination') {
347
+ const namespace = (node.arguments[0] as babelTypes.StringLiteral).value;
348
+ const nsArr = namespace.split('.').map((item) => item.replace(/_view$/, ''));
349
+ const viewName = nsArr.pop();
350
+
351
+ return new naslTypes.Destination({
352
+ viewNamespace: `app.frontends.pc.views${nsArr.map((item) => `.${item}.views`).join('')}`, // viewNamespace
353
+ viewName, // viewName
354
+ arguments: node.arguments.slice(1).map((arg) => new naslTypes.Argument({
355
+ expression: transformLogicNode(arg),
356
+ })) as naslTypes.Argument[],
357
+ });
358
+ }
359
+ return new naslTypes.CallLogic({
360
+ calleeNamespace: 'nasl.ui',
361
+ calleeName: (callee[2] as babelTypes.Identifier).name,
362
+ shortcut: true,
363
+ /**
364
+ * 这个函数是修复 AI 翻译出错的情况,与正常的 transform 做个区分
365
+ * @param node
366
+ * @returns
367
+ */
368
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
369
+ expression: transformLogicNode(arg),
370
+ })) as naslTypes.Argument[],
371
+ });
372
+ }
373
+ if (calleeName === 'ForEach') {
374
+ const newCallee = node.arguments;
375
+ const arrowFunction = node.arguments[3] as babelTypes.ArrowFunctionExpression;
376
+ const nodeElement = new naslTypes.ForEachStatement({
377
+ each: transformLogicNode(newCallee[0]),
378
+ start: transformLogicNode(newCallee[1]),
379
+ end: transformLogicNode(newCallee[2]),
380
+ item: transformParam(arrowFunction.params[0] as babelTypes.Identifier),
381
+ index: transformParam(arrowFunction.params[1] as babelTypes.Identifier),
382
+ body: (arrowFunction.body as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
383
+ });
384
+ return nodeElement;
385
+ }
386
+ if (callee.length === 2) {
387
+ const curCalleeName = (node.callee as any).property.name;
388
+ if (curCalleeName === 'forEach') {
389
+ const newCallee = (node.callee as any).object;
390
+ const arrowFunction = node.arguments[0] as babelTypes.ArrowFunctionExpression;
391
+ const nodeElement = new naslTypes.ForEachStatement({
392
+ each: transformLogicNode(newCallee.callee.object),
393
+ start: transformLogicNode(newCallee?.arguments?.[0]),
394
+ end: transformLogicNode(newCallee?.arguments?.[1]),
395
+ item: transformParam(arrowFunction.params[0] as babelTypes.Identifier),
396
+ index: transformParam(arrowFunction.params[1] as babelTypes.Identifier),
397
+ body: (arrowFunction.body as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
398
+ });
399
+ return nodeElement;
400
+ }
401
+ } else if (['plus', 'minus', 'multiply', 'divide', 'remainder'].includes(calleeName)) {
402
+ return handleBinaryExpression(calleeName, node?.arguments);
403
+ } else if (calleeName === 'alert') {
404
+ return new naslTypes.CallLogic({
405
+ calleeNamespace: 'nasl.ui',
406
+ calleeName: 'showMessage',
407
+ shortcut: true,
408
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
409
+ expression: transformLogicNode(arg),
410
+ })) as naslTypes.Argument[],
411
+ });
412
+ } else if (/^app.dataSources|app.logics|load/.test(calleeName)) {
413
+ return new naslTypes.CallLogic({
414
+ calleeNamespace: generate((node.callee as any).object).code,
415
+ calleeName: (callee[callee.length - 1] as babelTypes.Identifier).name,
416
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
417
+ expression: transformLogicNode(arg),
418
+ })) as naslTypes.Argument[],
419
+ });
420
+ } else if (callee.length === 1) {
421
+ if (calleeName.startsWith('viewLogic_')) {
422
+ return new naslTypes.CallLogic({
423
+ calleeNamespace: '',
424
+ calleeName: calleeName.slice('viewLogic_'.length),
425
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
426
+ expression: transformLogicNode(arg),
427
+ })) as naslTypes.Argument[],
428
+ });
429
+ }
430
+ return new naslTypes.CallLogic({
431
+ calleeNamespace: `app.logics`,
432
+ calleeName,
433
+ arguments: node.arguments.map((arg) => new naslTypes.Argument({
434
+ expression: transformLogicNode(arg),
435
+ })) as naslTypes.Argument[],
436
+ });
437
+ } else if (/interfaces/.test(calleeName)) {
438
+ return new naslTypes.CallInterface({
439
+ calleeNamespace: generate((node.callee as any).object).code,
440
+ calleeName: (callee[callee.length - 1] as babelTypes.Identifier).name,
441
+ arguments: node.arguments.map((arg: any) => new naslTypes.Argument({
442
+ keyword: arg.properties[0].key.name,
443
+ expression: transformLogicNode(arg.properties[0].value),
444
+ })) as naslTypes.Argument[],
445
+ });
446
+ }
447
+ // else if (/destination/.test(calleeName)) {
448
+ // const newCallee = flatMemberExpression((node.callee as any).object);
449
+ // return new naslTypes.Destination({
450
+ // viewNamespace: generate((node.callee as any).object.object).code,
451
+ // viewName: (newCallee[newCallee.length - 1] as babelTypes.Identifier).name,
452
+ // target: (node.arguments[0] as any).properties[1].value.value,
453
+ // anchor: new naslTypes.Anchor({
454
+ // expression: transformLogicNode((node.arguments[0] as any).properties[0].value),
455
+ // }),
456
+ // });
457
+ // }
458
+ else if (node.callee.type === 'ArrowFunctionExpression') {
459
+ // NOTE: 适用于 if else
460
+ const newCallee = (node.callee.body as any).body;
461
+ if (newCallee[newCallee.length - 1].argument?.callee?.name === '__MatchExpressionFuntion') {
462
+ const match = new naslTypes.Match({
463
+ expression: transformLogicNode(newCallee[0]),
464
+ isExpression: type === 'expression',
465
+ cases: flatIfStatement(newCallee[1].body.body[0]).map((_case: any) => new naslTypes.MatchCase({
466
+ patterns: !_case.test ? [] : flatMatchPatternsExpression(transformLogicNode(_case.test)) as any,
467
+ body: _case.consequent.body.filter((item: any) => item.type !== 'BreakStatement').map((item: any) => transformLogicNode(item)).filter((item: any) => !!item),
468
+ })),
469
+ });
470
+ if (!match.cases.length || match.cases[match.cases.length - 1].patterns.length) {
471
+ match.cases.push(new naslTypes.MatchCase({
472
+ patterns: [],
473
+ body: [],
474
+ }));
475
+ }
476
+ match.cases.forEach((case_: any) => {
477
+ if (case_.body.length && (case_.body[0].concept === 'BooleanLiteral' || case_.body[0].concept === 'StringLiteral')) {
478
+ case_.isMatchedTypeEnumable = true;
547
479
  }
548
- } else if (node.type === 'ReturnStatement') {
549
- if (node.argument) {
550
- if (type === 'expression') {
551
- return transformLogicNode(node.argument);
552
- }
553
- if (!logic.returns.length) {
554
- logic.returns.push(new naslTypes.Return({
555
- name: 'result',
556
- }));
557
- }
558
- return new naslTypes.Assignment({
559
- left: new naslTypes.Identifier({
560
- name: logic.returns[0].name,
561
- }),
562
- right: transformLogicNode(node.argument),
563
- });
480
+ if (case_.patterns.length && case_.patterns[0].concept === 'MemberExpression') {
481
+ case_.isMatchedTypeEnumable = true;
482
+ case_.patterns[0] = new naslTypes.MemberExpression({
483
+ object: {
484
+ concept: 'Identifier',
485
+ name: case_.patterns[0].object.property.name,
486
+ folded: false,
487
+ namespace: 'app.enums'
488
+ } as any,
489
+ property: {
490
+ concept: 'Identifier',
491
+ name: case_.patterns[0].property.value,
492
+ folded: false,
493
+ } as any,
494
+ });
564
495
  }
565
- } else if (node.type === 'EmptyStatement') {
566
- return node.leadingComments && new naslTypes.Comment({
567
- value: String(node.leadingComments[0].value),
568
- });
569
- } else if (node.type === 'BlockStatement') {
570
- return transformLogicNode(node?.body?.[0]);
571
- } else {
572
- console.error(node);
573
- throw new Error(`Unhandled node ${node.type}`);
496
+ });
497
+ return match;
498
+ }
499
+ if (newCallee[newCallee.length - 1].argument?.callee?.name === '__SwitchExpressionFuntion') {
500
+ const switchStatement = transformLogicNode(newCallee[0].body.body[0]);
501
+ return switchStatement;
502
+ }
503
+ console.error(node);
504
+ if (debug) {
505
+ throw new Error(`Unhandled ArrowFunctionExpression node ${node.type}`);
506
+ }
507
+ } else {
508
+ console.error(node);
509
+ if (debug) {
510
+ throw new Error(`Unhandled node ${callee.map((item: babelTypes.Identifier) => item.name).join('.')} ${node.type}`);
511
+ }
512
+ }
513
+ } else if (node.type === 'IfStatement') {
514
+ if (node.alternate && node.alternate.type === 'IfStatement') {
515
+ const switchStatement = new naslTypes.SwitchStatement({
516
+ cases: [],
517
+ });
518
+ pushElseIf(node, switchStatement);
519
+ return switchStatement;
520
+ }
521
+ return new naslTypes.IfStatement({
522
+ test: transformLogicNode(node.test),
523
+ consequent: !node.consequent ? [] : (node.consequent as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
524
+ alternate: !node.alternate ? [] : (node.alternate as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
525
+ });
526
+ } else if (node.type === 'WhileStatement') {
527
+ return new naslTypes.WhileStatement({
528
+ test: transformLogicNode(node.test),
529
+ body: (node.body as babelTypes.BlockStatement).body.map((item) => transformLogicNode(item)).filter((item) => !!item),
530
+ });
531
+ } else if (node.type === 'SwitchStatement') {
532
+ const match = new naslTypes.Match({
533
+ expression: transformLogicNode(node.discriminant),
534
+ isExpression: type === 'expression',
535
+ cases: node.cases.map((_case) => new naslTypes.MatchCase({
536
+ patterns: !_case.test ? [] : [transformLogicNode(_case.test)],
537
+ body: _case.consequent.filter((item) => item.type !== 'BreakStatement').map((item) => transformLogicNode(item)).filter((item) => !!item),
538
+ })),
539
+ });
540
+ if (!match.cases.length || match.cases[match.cases.length - 1].patterns.length) {
541
+ match.cases.push(new naslTypes.MatchCase({
542
+ patterns: [],
543
+ body: [],
544
+ }));
545
+ }
546
+ match.cases.forEach((case_: any) => {
547
+ if (case_.body.length && (case_.body[0].concept === 'BooleanLiteral' || case_.body[0].concept === 'StringLiteral')) {
548
+ case_.isMatchedTypeEnumable = true;
549
+ }
550
+ if (case_.patterns.length && case_.patterns[0].concept === 'MemberExpression') {
551
+ case_.isMatchedTypeEnumable = true;
552
+ case_.patterns[0].object.namespace = 'app.enums';
553
+ }
554
+ });
555
+ return match;
556
+ } else if (node.type === 'MemberExpression') {
557
+ if (node.property.type === 'NumericLiteral') {
558
+ return new naslTypes.CallFunction({
559
+ calleeNamespace: 'nasl.util',
560
+ calleeName: 'Get',
561
+ arguments: [
562
+ new naslTypes.Argument({
563
+ expression: transformLogicNode(node.object),
564
+ }),
565
+ new naslTypes.Argument({
566
+ expression: transformLogicNode(node.property),
567
+ }),
568
+ ],
569
+ });
570
+ }
571
+ return new naslTypes.MemberExpression({
572
+ object: transformLogicNode(node.object),
573
+ property: transformLogicNode(node.property),
574
+ });
575
+ } else if (node.type === 'Identifier') {
576
+ return new naslTypes.Identifier({
577
+ name: node.name,
578
+ });
579
+ } else if (node.type === 'ExpressionStatement') {
580
+ return transformLogicNode(node.expression);
581
+ } else if (node.type === 'AssignmentExpression') {
582
+ if (node.operator === '+=' || node.operator === '-=') {
583
+ if (type === 'expression') {
584
+ return new naslTypes.BinaryExpression({
585
+ operator: node.operator[0] as '+' | '-',
586
+ left: transformLogicNode(node.left),
587
+ right: transformLogicNode(node.right),
588
+ });
589
+ }
590
+ return new naslTypes.Assignment({
591
+ left: transformLogicNode(node.left),
592
+ right: new naslTypes.BinaryExpression({
593
+ operator: node.operator[0] as '+' | '-',
594
+ left: transformLogicNode(node.left),
595
+ right: transformLogicNode(node.right),
596
+ }),
597
+ });
598
+ }
599
+ if (type === 'expression') {
600
+ return transformLogicNode(node.right);
601
+ }
602
+ return new naslTypes.Assignment({
603
+ left: transformLogicNode(node.left),
604
+ right: transformLogicNode(node.right),
605
+ });
606
+ } else if (node.type === 'NewExpression') {
607
+ const calleeName = generate(node.callee as any).code;
608
+ if (['Boolean', 'Integer', 'Double', 'Decimal', 'Long'].includes(calleeName)) {
609
+ return transformLogicNode(node.arguments[0], naslTypes.TypeAnnotation.createPrimitive(calleeName));
610
+ }
611
+ console.error(node);
612
+ if (debug) {
613
+ throw new Error(`Unhandled node ${node.type}`);
614
+ }
615
+ } else if (node.type === 'ArrowFunctionExpression') {
616
+ return new naslTypes.AnonymousFunction({
617
+ params: node.params.map((param: babelTypes.Identifier) => transformParam(param)),
618
+ body: transformLogicNode(node.body),
619
+ }) as any as naslTypes.LogicItem;
620
+ } else if (node.type === 'BooleanLiteral') {
621
+ return new naslTypes.BooleanLiteral({
622
+ value: String(node.value),
623
+ });
624
+ } else if (node.type === 'StringLiteral') {
625
+ return new naslTypes.StringLiteral({
626
+ value: node.value,
627
+ });
628
+ } else if (node.type === 'NumericLiteral') {
629
+ const literal = new naslTypes.NumericLiteral({
630
+ value: String(node.value),
631
+ typeAnnotation: typeAnnotation || naslTypes.TypeAnnotation.createPrimitive('Integer'),
632
+ });
633
+ literal.typeAnnotation.typeName = literal.changeType(String(node.value));
634
+ return literal;
635
+ } else if (node.type === 'NullLiteral') {
636
+ return new naslTypes.NullLiteral();
637
+ } else if (node.type === 'TemplateLiteral') {
638
+ const expressions = [...node.expressions as babelTypes.Expression[], ...node.quasis.map((element) => ({
639
+ type: 'StringLiteral',
640
+ value: element.value.raw,
641
+ start: element.start,
642
+ end: element.end,
643
+ })) as babelTypes.StringLiteral[]];
644
+ expressions.sort((a, b) => a.start - b.start);
645
+
646
+ return new naslTypes.StringInterpolation({
647
+ expressions: expressions.map((item) => transformLogicNode(item)),
648
+ });
649
+ } else if (node.type === 'BinaryExpression' || node.type === 'LogicalExpression') {
650
+ if (node.operator === '===')
651
+ node.operator = '==';
652
+ if (node.operator === '!==')
653
+ node.operator = '!=';
654
+ if (['+', '-', '*', '/', '%', '==', '!=', '>', '<', '>=', '<=', '&&', '||', 'startwith', 'endwith', 'like', 'in'].includes(node.operator)) {
655
+ return new naslTypes.BinaryExpression({
656
+ operator: node.operator as any,
657
+ left: transformLogicNode(node.left),
658
+ right: transformLogicNode(node.right),
659
+ });
660
+ }
661
+ console.error(node);
662
+ if (debug) {
663
+ throw new Error(`Unhandled node ${node.type}`);
664
+ }
665
+ } else if (node.type === 'UnaryExpression') {
666
+ if (['!'].includes(node.operator)) {
667
+ return new naslTypes.UnaryExpression({
668
+ operator: node.operator as any,
669
+ argument: transformLogicNode(node.argument),
670
+ });
671
+ }
672
+ if (['-'].includes(node.operator) && node.argument.type === 'NumericLiteral') {
673
+ return transformLogicNode({
674
+ type: 'NumericLiteral',
675
+ value: -node.argument.value,
676
+ } as babelTypes.NumericLiteral);
677
+ }
678
+ console.error(node);
679
+ if (debug) {
680
+ throw new Error(`Unhandled node ${node.type}`);
681
+ }
682
+ } else if (node.type === 'UpdateExpression') {
683
+ if (node.operator === '++' || node.operator === '--') {
684
+ return new naslTypes.Assignment({
685
+ left: transformLogicNode(node.argument),
686
+ right: new naslTypes.BinaryExpression({
687
+ operator: node.operator[0] as '+' | '-',
688
+ left: transformLogicNode(node.argument),
689
+ right: new naslTypes.NumericLiteral({
690
+ value: '1',
691
+ typeAnnotation: naslTypes.TypeAnnotation.createPrimitive('Integer'),
692
+ }),
693
+ }),
694
+ });
695
+ }
696
+ } else if (node.type === 'ReturnStatement') {
697
+ if (node.argument) {
698
+ if (type === 'expression') {
699
+ return transformLogicNode(node.argument);
700
+ }
701
+ if (!logic.returns.length) {
702
+ logic.returns.push(new naslTypes.Return({
703
+ name: 'result',
704
+ }));
574
705
  }
706
+ return new naslTypes.Assignment({
707
+ left: new naslTypes.Identifier({
708
+ name: logic.returns[0].name,
709
+ }),
710
+ right: transformLogicNode(node.argument),
711
+ });
712
+ }
713
+ } else if (node.type === 'EmptyStatement') {
714
+ return node.leadingComments && new naslTypes.Comment({
715
+ value: String(node.leadingComments[0].value),
716
+ });
717
+ } else if (node.type === 'BlockStatement') {
718
+ return transformLogicNode(node?.body?.[0]);
719
+ } else {
720
+ console.error(node);
721
+ if (debug) {
722
+ throw new Error(`Unhandled node ${node.type}`);
723
+ }
575
724
  }
725
+ }
576
726
 
577
- const root = babel.parseSync(tsCode, {
578
- filename: 'result.ts',
579
- presets: [require('@babel/preset-typescript')],
580
- }) as babelTypes.File;
727
+ const root = babel.parseSync(tsCode, {
728
+ filename: 'result.ts',
729
+ presets: [require('@babel/preset-typescript')],
730
+ }) as babelTypes.File;
581
731
 
582
- let parameters: babelTypes.Identifier[] = [];
583
- let statements: babelTypes.Statement[] = root.program.body;
732
+ let parameters: babelTypes.Identifier[] = [];
733
+ let statements: babelTypes.Statement[] = [];
584
734
 
585
- traverse<babelTypes.Node>((current) => {
586
- if (current.node.type === 'FunctionDeclaration' && (current.node.id.name === contextLogicName || type === 'expression')) {
587
- parameters = current.node.params as babelTypes.Identifier[];
588
- statements = current.node.body.body;
589
- return true;
590
- }
591
- }, { node: root.program }, { mode: 'anyObject' });
735
+ let func: babelTypes.FunctionDeclaration;
736
+ if (root.program.body[0].type === 'ExportNamedDeclaration') {
737
+ func = root.program.body[0].declaration as babelTypes.FunctionDeclaration;
738
+ }
739
+ parameters = func.params as babelTypes.Identifier[];
740
+ statements = func.body.body;
741
+ // traverse<babelTypes.Node>((current) => {
742
+ // if (current.node.type === 'FunctionDeclaration' && (current.node.id.name === contextLogicName || type === 'expression')) {
743
+ // return true;
744
+ // }
745
+ // }, { node: root.program }, { mode: 'anyObject' });
592
746
 
593
- const currentPositionComment = root.comments.find((comment) => comment.type === 'CommentLine' && comment.value === ' 当前位置');
594
- if (currentPositionComment) {
595
- statements = statements.filter((stat) => stat.start > currentPositionComment.start);
596
- }
747
+ const currentPositionComment = root.comments.find((comment) => comment.type === 'CommentLine' && comment.value === ' 当前位置');
748
+ if (currentPositionComment) {
749
+ statements = statements.filter((stat) => stat.start > currentPositionComment.start);
750
+ }
597
751
 
598
- // traverse<babelTypes.Node>((current) => {
599
- // if (!current.node.type)
600
- // console.log(current.key, current.node);
601
- // // console.log(current.node.type);
602
- // }, { node: {
603
- // type: 'BlockStatement',
604
- // body: statements,
605
- // } as babelTypes.BlockStatement }, {
606
- // mode: 'anyObject',
607
- // depthFirst: true,
608
- // excludedKeySet: new Set(['loc']),
609
- // });
752
+ // traverse<babelTypes.Node>((current) => {
753
+ // if (!current.node.type)
754
+ // console.log(current.key, current.node);
755
+ // // console.log(current.node.type);
756
+ // }, { node: {
757
+ // type: 'BlockStatement',
758
+ // body: statements,
759
+ // } as babelTypes.BlockStatement }, {
760
+ // mode: 'anyObject',
761
+ // depthFirst: true,
762
+ // excludedKeySet: new Set(['loc']),
763
+ // });
610
764
 
611
- parameters.forEach((node) => {
612
- const param = transformParam(node);
613
- param && logic.params.push(param);
614
- });
615
- statements.forEach((node) => {
616
- const item = transformLogicNode(node);
617
- item && logic.body.push(item);
618
- });
765
+ parameters.forEach((node) => {
766
+ const param = transformParam(node);
767
+ param && logic.params.push(param);
768
+ });
769
+ statements.forEach((node) => {
770
+ const item = transformLogicNode(node);
771
+ item && logic.body.push(item);
772
+ });
619
773
 
620
- // console.log(JSON.stringify(logic));
621
- // try {
622
- // console.log(logic.toNaturalTS());
623
- // } catch (e) {
624
- // console.error(e);
625
- // }
774
+ // console.log(JSON.stringify(logic));
775
+ // try {
776
+ // console.log(logic.toNaturalTS());
777
+ // } catch (e) {
778
+ // console.error(e);
779
+ // }
626
780
 
627
- return logic;
781
+ return logic;
628
782
  }
629
783
 
630
784
  export function tryTransformTSCode(tsCode: string, contextLogicName: string, type?: string): naslTypes.Logic {
631
- if (tsCode.includes('```')) {
632
- const cap = tsCode.match(/```.*\n([\s\S]+?)```/);
633
- if (cap)
634
- tsCode = cap[1].trim();
635
- }
785
+ if (tsCode.includes('```')) {
786
+ const cap = tsCode.match(/```.*\n([\s\S]+?)```/);
787
+ if (cap)
788
+ tsCode = cap[1].trim();
789
+ }
636
790
 
637
- return transformTSCode(tsCode, contextLogicName, type);
791
+ return transformTSCode(tsCode, contextLogicName, type);
638
792
  }
639
793
 
640
794
  export function transformTSCodeEx(answer: any, activeLogic: any, context: any) {
641
- let logicName = activeLogic.name;
642
- const { app, nasl } = context;
643
- if (activeLogic.parentNode instanceof nasl.BindEvent && activeLogic.parentNode.parentNode instanceof nasl.View) {
644
- logicName = `on_view_${activeLogic.name}`;
645
- } else if (activeLogic.parentNode instanceof nasl.BindEvent && activeLogic.parentNode.parentNode instanceof nasl.ViewElement) {
646
- logicName = `on_${(activeLogic.parentNode).element.name}_${activeLogic.name}`;
647
- } else {
648
- logicName = activeLogic.name;
649
- }
795
+ let logicName = activeLogic.name;
796
+ const { app, nasl } = context;
797
+ if (activeLogic.parentNode instanceof nasl.BindEvent && activeLogic.parentNode.parentNode instanceof nasl.View) {
798
+ logicName = `viewLogic_${activeLogic.name}`;
799
+ } else if (activeLogic.parentNode instanceof nasl.BindEvent && activeLogic.parentNode.parentNode instanceof nasl.ViewElement) {
800
+ logicName = `on_${(activeLogic.parentNode).element.name}_${activeLogic.name}`;
801
+ } else {
802
+ logicName = activeLogic.name;
803
+ }
650
804
 
651
- const logic = tryTransformTSCode(answer, logicName);
652
- app.emit('collect:start', { actionMsg: '自然语言生成代码' });
653
- logic.params.forEach((param: any) => {
654
- if (!activeLogic.params.find((_: any) => _.name === param.name))
655
- activeLogic.addParam(param.toJSON());
656
- });
657
- logic.variables.forEach((variable: any) => {
658
- if (!activeLogic.variables.find((_: any) => _.name === variable.name))
659
- activeLogic.addVariable(variable.toJSON());
660
- });
661
- if (logic.returns.length && !activeLogic.returns.length) {
662
- activeLogic.addReturn(logic.returns[0].toJSON());
663
- }
664
- logic.body.forEach((item: any) => activeLogic.insertItemInBodyAt(item.toJSON(), activeLogic.body.length - 1));
665
- app.emit('collect:end');
805
+ const logic = tryTransformTSCode(answer, logicName);
806
+ app.emit('collect:start', { actionMsg: '自然语言生成代码' });
807
+ logic.params.forEach((param: any) => {
808
+ if (!activeLogic.params.find((_: any) => _.name === param.name))
809
+ activeLogic.addParam(param.toJSON());
810
+ });
811
+ logic.variables.forEach((variable: any) => {
812
+ if (!activeLogic.variables.find((_: any) => _.name === variable.name))
813
+ activeLogic.addVariable(variable.toJSON());
814
+ });
815
+ if (logic.returns.length && !activeLogic.returns.length) {
816
+ activeLogic.addReturn(logic.returns[0].toJSON());
817
+ }
818
+ logic.body.forEach((item: any) => activeLogic.insertItemInBodyAt(item.toJSON(), activeLogic.body.length - 1));
819
+ app.emit('collect:end');
666
820
  }
667
821
 
668
822
  export function transformTSCodeToExpression(answer: any, context: any) {
669
- let logic;
670
- try {
671
- logic = tryTransformTSCode(answer, '', 'expression');
672
- } catch (error) {
673
- throw new Error(error);
674
- }
675
- const { app } = context;
676
- app.emit('collect:start', { actionMsg: '自然语言生成代码' });
677
- const { body } = logic;
678
- app.emit('collect:end');
679
- return body;
823
+ let logic;
824
+ try {
825
+ logic = tryTransformTSCode(answer, '', 'expression');
826
+ } catch (error) {
827
+ throw new Error(error);
828
+ }
829
+ const { app } = context;
830
+ app.emit('collect:start', { actionMsg: '自然语言生成代码' });
831
+ const { body } = logic;
832
+ app.emit('collect:end');
833
+ return body;
680
834
  }