@lcap/nasl 3.8.3-beta.4 → 3.8.3-beta.5

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.
Files changed (88) hide show
  1. package/out/common/BaseNode.d.ts +9 -4
  2. package/out/common/BaseNode.js +73 -18
  3. package/out/common/BaseNode.js.map +1 -1
  4. package/out/concepts/App__.js +17 -13
  5. package/out/concepts/App__.js.map +1 -1
  6. package/out/concepts/AuthLogicForCallInterface__.js +2 -50
  7. package/out/concepts/AuthLogicForCallInterface__.js.map +1 -1
  8. package/out/concepts/BusinessComponent__.js +2 -42
  9. package/out/concepts/BusinessComponent__.js.map +1 -1
  10. package/out/concepts/BusinessLogic__.js +2 -50
  11. package/out/concepts/BusinessLogic__.js.map +1 -1
  12. package/out/concepts/CallFunction__.d.ts +1 -1
  13. package/out/concepts/CallFunction__.js +1 -1
  14. package/out/concepts/CallLogic__.js +2 -2
  15. package/out/concepts/CallLogic__.js.map +1 -1
  16. package/out/concepts/Identifier__.d.ts +2 -0
  17. package/out/concepts/Identifier__.js +51 -5
  18. package/out/concepts/Identifier__.js.map +1 -1
  19. package/out/concepts/Logic__.js +6 -101
  20. package/out/concepts/Logic__.js.map +1 -1
  21. package/out/concepts/MemberExpression__.d.ts +1 -1
  22. package/out/concepts/MemberExpression__.js +15 -3
  23. package/out/concepts/MemberExpression__.js.map +1 -1
  24. package/out/concepts/OverriddenLogic__.js +2 -50
  25. package/out/concepts/OverriddenLogic__.js.map +1 -1
  26. package/out/concepts/ProcessElementV2__.js +4 -0
  27. package/out/concepts/ProcessElementV2__.js.map +1 -1
  28. package/out/concepts/ProcessElement__.js +4 -0
  29. package/out/concepts/ProcessElement__.js.map +1 -1
  30. package/out/concepts/ProcessV2__.js +4 -0
  31. package/out/concepts/ProcessV2__.js.map +1 -1
  32. package/out/concepts/Process__.js +4 -0
  33. package/out/concepts/Process__.js.map +1 -1
  34. package/out/concepts/SubLogic__.js +5 -50
  35. package/out/concepts/SubLogic__.js.map +1 -1
  36. package/out/concepts/TypeAnnotation__.js +1 -1
  37. package/out/concepts/TypeAnnotation__.js.map +1 -1
  38. package/out/concepts/View__.js +10 -49
  39. package/out/concepts/View__.js.map +1 -1
  40. package/out/generator/genBundleFiles.js +5 -5
  41. package/out/generator/permission.js +21 -5
  42. package/out/generator/permission.js.map +1 -1
  43. package/out/generator/release-body/body.js.map +1 -1
  44. package/out/natural/transformTS2UI.js +5 -5
  45. package/out/natural/transformTS2UI.js.map +1 -1
  46. package/out/natural/transforms/transform2LogicItem.js +4 -4
  47. package/out/natural/transforms/transform2LogicItem.js.map +1 -1
  48. package/out/server/naslServer.js +17 -2
  49. package/out/server/naslServer.js.map +1 -1
  50. package/out/server/semanticData.d.ts +32 -0
  51. package/out/server/semanticData.js +371 -0
  52. package/out/server/semanticData.js.map +1 -0
  53. package/out/templator/block2nasl/viewMergeBlock.js +2 -1
  54. package/out/templator/block2nasl/viewMergeBlock.js.map +1 -1
  55. package/package.json +1 -1
  56. package/src/common/BaseNode.ts +106 -36
  57. package/src/concepts/App__.ts +17 -13
  58. package/src/concepts/AuthLogicForCallInterface__.ts +3 -56
  59. package/src/concepts/BusinessComponent__.ts +6 -51
  60. package/src/concepts/BusinessLogic__.ts +4 -56
  61. package/src/concepts/CallFunction__.ts +1 -1
  62. package/src/concepts/CallLogic__.ts +8 -4
  63. package/src/concepts/Identifier__.ts +57 -6
  64. package/src/concepts/Logic__.ts +9 -111
  65. package/src/concepts/MemberExpression__.ts +21 -7
  66. package/src/concepts/OverriddenLogic__.ts +4 -56
  67. package/src/concepts/ProcessElementV2__.ts +4 -0
  68. package/src/concepts/ProcessElement__.ts +4 -0
  69. package/src/concepts/ProcessV2__.ts +5 -0
  70. package/src/concepts/Process__.ts +4 -0
  71. package/src/concepts/SubLogic__.ts +6 -56
  72. package/src/concepts/TypeAnnotation__.ts +1 -1
  73. package/src/concepts/View__.ts +14 -54
  74. package/src/generator/genBundleFiles.ts +5 -5
  75. package/src/generator/permission.ts +23 -5
  76. package/src/generator/release-body/body.ts +0 -1
  77. package/src/natural/transformTS2UI.ts +5 -5
  78. package/src/natural/transforms/transform2LogicItem.ts +4 -4
  79. package/src/server/naslServer.ts +22 -2
  80. package/src/server/semanticData.ts +447 -0
  81. package/src/templator/block2nasl/viewMergeBlock.ts +2 -1
  82. package/src/translator/utils.ts +1 -1
  83. package/test/concepts/logic/__snapshots__/toEmbeddedTS.spec.ts.snap +182 -0
  84. package/test/concepts/logic/constant.ts +5 -0
  85. package/test/concepts/logic/fixtures/variable-host-call-logic-member-expression.json +267 -0
  86. package/test/concepts/logic/fixtures/variable-host-call-logic-nested-member-expression copy.json +457 -0
  87. package/test/concepts/logic/fixtures/variable-host-call-logic-with-handle-error-member-expression.json +267 -0
  88. package/test/concepts/logic/toEmbeddedTS.spec.ts +15 -0
@@ -124,6 +124,8 @@ import { withQueueExecute } from '../decorators';
124
124
  import { getNodeByNodeCallee } from '../automate/engine/utils';
125
125
  import { isApp, isConnection, isConnector, isMsgTriggerEvent, isProcess, isProcessV2, isStrictLogic } from '../concepts/utils/asserts';
126
126
 
127
+ import { collectAllSemanticCtx, clearSemanticData, printSemanticDataInfo } from './semanticData';
128
+
127
129
  const EmbeddedTSFileLineMap: { [name: string]: number } = {
128
130
  Entity: 3,
129
131
  };
@@ -649,6 +651,10 @@ class NaslServer {
649
651
 
650
652
  async openApp(app: App, performance = false, needRegisterCommand = true) {
651
653
  this.logger.time('生成 TS 文件');
654
+ this.logger.time('简单语义分析');
655
+ await utils.runGeneratorSync(collectAllSemanticCtx(app));
656
+ this.logger.timeEnd('简单语义分析');
657
+ // printSemanticDataInfo();
652
658
  invokeCommand('naslServer:startWork');
653
659
 
654
660
  app.naslServer = this;
@@ -677,6 +683,7 @@ class NaslServer {
677
683
  callback();
678
684
  });
679
685
  }
686
+ clearSemanticData();
680
687
  this.logger.timeEnd('生成 TS 文件');
681
688
 
682
689
  function* getAllTsFiles() {
@@ -1121,7 +1128,9 @@ class NaslServer {
1121
1128
  return;
1122
1129
  }
1123
1130
 
1124
- const { node } = record;
1131
+ let { node } = record;
1132
+ // @ts-ignore
1133
+ node = node.__v_raw || node; // 暂时先这样提速
1125
1134
 
1126
1135
  // 先获取原来的节点先清除一下之前有异常的节点,下面重新赋值
1127
1136
  const oldRecord = self.diagnosticManager.getRecord?.(record.id);
@@ -1815,6 +1824,8 @@ class NaslServer {
1815
1824
  */
1816
1825
  private *_attachDiagnosticsWithGenerator(fileNode: BaseNode) {
1817
1826
  // 每次诊断前先清空这个Set
1827
+ // @ts-ignore
1828
+ fileNode = fileNode.__v_raw || fileNode; // 暂时先这样提速
1818
1829
  this.logicSetWithComponentLogic = new Set<string>();
1819
1830
 
1820
1831
  const self = this;
@@ -3197,11 +3208,15 @@ class NaslServer {
3197
3208
  fileNode: FileNode
3198
3209
  ): Generator<void, MinRange> {
3199
3210
  let minRange: MinRange;
3211
+ // @ts-ignore
3212
+ fileNode = fileNode.__v_raw || fileNode; // 暂时先这样提速
3200
3213
  const { sourceMap } = fileNode;
3201
3214
  // 是否找到了行内准确的,是的话,就不走多行的
3202
3215
  let haveLineNode = false;
3203
3216
 
3204
- for (const [node, item] of sourceMap.entries()) {
3217
+ for (let [node, item] of sourceMap.entries()) {
3218
+ // @ts-ignore
3219
+ node = node.__v_raw || node; // 暂时先这样提速
3205
3220
  /**
3206
3221
  * 当前内容的开始行 <= 诊断开始的行 &&
3207
3222
  * 当前内容的结束行 >= 诊断结束的行
@@ -4663,6 +4678,7 @@ class NaslServer {
4663
4678
  }
4664
4679
  if (
4665
4680
  ![
4681
+
4666
4682
  'Identifier',
4667
4683
  'BinaryExpression',
4668
4684
  'CallLogic',
@@ -4775,8 +4791,10 @@ class NaslServer {
4775
4791
  }
4776
4792
  }
4777
4793
  });
4794
+
4778
4795
  yield* utils.wrapIteratorToGenerator(types.entries(), ([node, value]) => {
4779
4796
  try {
4797
+
4780
4798
  // 因为node可能是经过处理的TypeAnnotation
4781
4799
  node.__isCorrectTypeAnnotation = true;
4782
4800
  if (value) {
@@ -5492,6 +5510,7 @@ class NaslServer {
5492
5510
  */
5493
5511
  async handleRename(fileNode: BaseNode, targetNode: BaseNode, result: utils.EmbeddedTSFileResult, oldFilePath?: string) {
5494
5512
  // rename 场景
5513
+
5495
5514
  const outputFiles = [{ file: result.filePath, fileContent: result.code }];
5496
5515
  // 如果是要修改顶级文件名
5497
5516
  // file节点和当前改得是同一节点
@@ -5798,6 +5817,7 @@ class NaslServer {
5798
5817
 
5799
5818
  changeFileNext() {
5800
5819
  if (!this.singleFileChangeIng) {
5820
+ // SHIFT IS O(n) AND SLOW
5801
5821
  const item = this.changeStackList.shift();
5802
5822
  this.receiveHandleChange(item)
5803
5823
  .catch((err) => {
@@ -0,0 +1,447 @@
1
+ import { App, Identifier, MemberExpression, View, ViewElement, BaseNode, Return, Variable,
2
+ Assignment, BatchAssignment, CallFunction, AuthLogicForCallInterface, BusinessComponent, BusinessLogic,
3
+ Logic, OverriddenLogic, SubLogic,
4
+ Process,
5
+ ProcessV2,
6
+ ProcessElement,
7
+ ProcessElementV2,
8
+ } from '..';
9
+
10
+ import { SyntaxNode } from '../concepts/utils/types';
11
+
12
+ import { createCompilerState, shiftState } from '../translator';
13
+ import { runGeneratorAsync, runGeneratorSync, wrapForEachToGenerator, returnOrigin } from '../utils';
14
+
15
+ type VarScopeCtx = {
16
+ // 优化首屏 getAncestor 热点代码
17
+ app: App;
18
+ isFirstScreen: boolean;
19
+ frontendGlobalVars: Set<string>;
20
+ varInViewOrComponent: Set<string>;
21
+ logicInViewOrComponent: Set<string>;
22
+ idToView: Map<Identifier, View>;
23
+ ctxViewElement: Array<ViewElement>;
24
+ ctxView: Array<View>;
25
+ isInViewOrComponent: boolean;
26
+ memExprToViewElem: Map<MemberExpression, ViewElement>;
27
+ }
28
+
29
+ type TyInferCtx = {
30
+ // 优化首屏 类型推导,变量提升
31
+ inferViaAsgnMap: Map<Return | Variable , Assignment | BatchAssignment | CallFunction>,
32
+ inferViaFnCallMap: Map<Return | Variable , CallFunction>,
33
+ scope: Array<AuthLogicForCallInterface | BusinessComponent | BusinessLogic | Logic | OverriddenLogic | SubLogic | View>,
34
+ // key 用 name 是不精确的,应该用地址。 暂时用 name,后面比较的时候简单点,暂时应该没 bug
35
+ // 全局变量暂不支持推导
36
+ capturedVars: Map<string, Variable | Return>,
37
+ }
38
+
39
+ type SubLogicCtx = {
40
+ // naslNodesCount: number;
41
+ ctx: Logic | Process | ProcessV2 | ProcessElement | ProcessElementV2 | null;
42
+ // 我也不知道为啥 view 这么特殊
43
+ viewSubLogics: Set<SubLogic>;
44
+ }
45
+
46
+ // 前端全局变量很少,一般就十个以内,所以 map 大小可以忽略不计
47
+ export const varScopeCtx : VarScopeCtx = {
48
+ app: null,
49
+ isFirstScreen: false,
50
+ frontendGlobalVars: new Set<string>(),
51
+ // Collect all params, (local) variables, and logic names under business component
52
+ // Note that within a business component, one can only refer to the above variables, and cannot refer to
53
+ // frontend global variables and any other variables under Views; therefore, checking the Name already suffices.
54
+ // 收集业务组件下的所有参数、(局部)变量和逻辑名称,请注意,在业务组件中,只能引用上述变量,
55
+ // 而不能引用前端全局变量和其他任何 “视图 ”下的变量;因此,检查 “Name” 已经足够了。
56
+ varInViewOrComponent: new Set<string>(),
57
+
58
+ logicInViewOrComponent: new Set<string>(),
59
+
60
+ // Collect all params, (local) variables, and logic names under views
61
+ // Actually, frontendGlobalVars U idInView U idInComponent should be the complete set of accessible variables
62
+ // 事实上,frontendGlobalVars 并上 idInView 并上 idInComponent 应该是前端所有能访问到的变量(名的集合)
63
+
64
+ // 赫基 27w 应用,前端 View 下有 2000 个变量名字;56176 个变量引用,内存占用约 1M。
65
+ idToView: new Map<Identifier, View>(),
66
+
67
+ // 路径上的 ViewElement 节点
68
+ ctxViewElement: [],
69
+
70
+ // 路径上的 View 节点
71
+ ctxView: [],
72
+
73
+ isInViewOrComponent: false,
74
+
75
+ memExprToViewElem: new Map<MemberExpression, ViewElement>(),
76
+ };
77
+
78
+ export const tyInferCtx : TyInferCtx = {
79
+ inferViaAsgnMap: new Map(),
80
+ inferViaFnCallMap: new Map(),
81
+ scope: [],
82
+ capturedVars: new Map(),
83
+ }
84
+
85
+ export const subLogicCtx : SubLogicCtx = {
86
+ // naslNodesCount: 0,
87
+ ctx: null, // 当前逻辑
88
+ viewSubLogics : new Set<SubLogic>(), // 隶属于 view 的 SubLogic,需要排除掉隶属于 Logic 的 SubLogic。
89
+ }
90
+
91
+ const last = <T>(arr: Array<T>) => arr[arr.length - 1];
92
+
93
+
94
+ export function *collectAllSemanticCtx(app: App) {
95
+ varScopeCtx.app = app;
96
+ varScopeCtx.isFirstScreen = true;
97
+ const tasks = [
98
+ // collectFrontendVariablesTask, 这样不值得,能快一点还是快一点吧,
99
+ collectVarInViewOrComponentCtxTask,
100
+ collectLogicInViewOrComponentTask,
101
+ // collectMemExprToViewElemCtxTask, // 因为 $ce 的原因,暂时用不了
102
+ collectIdToViewCtxTask,
103
+ collectSubLogicCtxTask,
104
+ collectTyInferCtxTask
105
+ ];
106
+
107
+ const cleanups = [
108
+ collectVarInViewOrComponentCtxCleanup,
109
+ // collectLogicInViewOrComponentCleanup,
110
+ // collectMemExprToViewElemCtxCleanup, // 因为 $ce 的原因,暂时用不了
111
+ collectIdToViewCtxCleanup,
112
+ collectSubLogicCtxCleanup,
113
+ collectTyInferCtxCleanup
114
+ ];
115
+
116
+ runGeneratorSync(collectFrontendVariablesTask(app));
117
+ runGeneratorSync(app.traverseStrictChildrenDoMultiTasks(tasks, cleanups));
118
+ }
119
+
120
+
121
+ function *collectFrontendVariablesTask(app: App) {
122
+ app.frontendTypes.forEach(ft => {
123
+ ft.frontends.forEach(f => {
124
+ f.variables.forEach(v => {
125
+ varScopeCtx.frontendGlobalVars.add(v.name);
126
+ });
127
+ });
128
+ })
129
+ }
130
+
131
+ function *collectVarInViewOrComponentCtxTask(nd: SyntaxNode) {
132
+ switch (nd.concept) {
133
+ case 'Variable': /* FALL THROUGH */
134
+ case 'Param': /* FALL THROUGH */
135
+ case 'Return': {
136
+ if (varScopeCtx.isInViewOrComponent) {
137
+ varScopeCtx.varInViewOrComponent.add(nd.name);
138
+ }
139
+ break;
140
+ }
141
+ case 'View': /* FALL THROUGH */
142
+ case 'BusinessComponent': varScopeCtx.isInViewOrComponent = true; break;
143
+ default: break;
144
+ }
145
+ }
146
+
147
+ function *collectVarInViewOrComponentCtxCleanup(nd: SyntaxNode) {
148
+ if (nd.concept === 'View' || nd.concept === 'BusinessComponent') {
149
+ varScopeCtx.isInViewOrComponent = false;
150
+ }
151
+ }
152
+
153
+
154
+ // component-like:业务组件下的变量引用
155
+ function *collectLogicInViewOrComponentTask(nd: SyntaxNode) {
156
+ if (nd.concept === 'Logic' || nd.concept === 'BusinessComponent') {
157
+ if (varScopeCtx.isInViewOrComponent) {
158
+ varScopeCtx.logicInViewOrComponent.add(nd.name);
159
+ }
160
+ }
161
+ }
162
+ // collectLogicInViewOrComponentCleanup 的事情被 collectVarInViewOrComponentCtxPost 做了
163
+
164
+
165
+ function *collectMemExprToViewElemCtxTask(nd: SyntaxNode) {
166
+ // view 下的 identifier 的 getAncestor 必定有 view
167
+ switch (nd.concept) {
168
+ case 'ViewElement': {
169
+ varScopeCtx.ctxViewElement.push(nd as ViewElement);
170
+ break;
171
+ }
172
+ case 'MemberExpression': {
173
+ if (varScopeCtx.ctxViewElement) {
174
+ varScopeCtx.memExprToViewElem.set(nd as MemberExpression, last(varScopeCtx.ctxViewElement));
175
+ }
176
+ break;
177
+ }
178
+ default: break;
179
+ }
180
+ }
181
+
182
+ function *collectMemExprToViewElemCtxCleanup(nd: SyntaxNode) {
183
+ if (nd.concept === 'ViewElement') {
184
+ varScopeCtx.ctxViewElement.pop();
185
+ }
186
+ }
187
+
188
+
189
+ function *collectIdToViewCtxTask(nd: SyntaxNode) {
190
+ // view 下的 identifier 的 getAncestor 必定有 view
191
+ switch (nd.concept) {
192
+ case 'View': varScopeCtx.ctxView.push(nd); break;
193
+ case 'Identifier': {
194
+ if (varScopeCtx.ctxView.length > 0) {
195
+ varScopeCtx.idToView.set(nd as Identifier, last(varScopeCtx.ctxView));
196
+ }
197
+ break;
198
+ }
199
+ default: break;
200
+ }
201
+ }
202
+
203
+ function *collectIdToViewCtxCleanup(nd: SyntaxNode) {
204
+ switch (nd.concept) {
205
+ case 'View': varScopeCtx.ctxView.pop(); break;
206
+ default: break;
207
+ }
208
+ }
209
+
210
+
211
+ function *collectSubLogicCtxTask(nd : SyntaxNode) {
212
+ switch (nd.concept) {
213
+ case 'Logic': /* FALL THROUGH */
214
+ /* 流程支持子逻辑 */
215
+ /* 流程变量不支持类型推导 */
216
+ case 'Process': /* FALL THROUGH */
217
+ case 'ProcessV2': /* FALL THROUGH */
218
+ case 'ProcessElement': /* FALL THROUGH */
219
+ case 'ProcessElementV2': /* FALL THROUGH */
220
+ case 'BusinessLogic': subLogicCtx.ctx = nd; break;
221
+ case 'SubLogic': {
222
+ // 收集子逻辑
223
+ if (subLogicCtx.ctx) {
224
+ subLogicCtx.ctx.subLogics.push(nd as SubLogic);
225
+ // console.log('逻辑或流程的子逻辑:', subLogicCtx.ctx)
226
+ } else {
227
+ subLogicCtx.viewSubLogics.add(nd as SubLogic);
228
+ }
229
+ break;
230
+ }
231
+ default: break;
232
+ }
233
+ }
234
+
235
+ function *collectSubLogicCtxCleanup(nd : SyntaxNode) {
236
+ switch (nd.concept) {
237
+ /* 流程支持子逻辑 */
238
+ /* 流程变量不支持类型推导 */
239
+ case 'Logic': /* FALL THROUGH */
240
+ case 'Process': /* FALL THROUGH */
241
+ case 'ProcessV2': /* FALL THROUGH */
242
+ case 'ProcessElement': /* FALL THROUGH */
243
+ case 'ProcessElementV2': subLogicCtx.ctx = null; break;
244
+ // 可能是有人忘了给业务组件加 subLogics?
245
+ case 'View': {
246
+ subLogicCtx.viewSubLogics.forEach(sl => { nd.subLogics.push(sl); });
247
+ // console.log('View 的子逻辑:', nd.subLogics)
248
+ subLogicCtx.viewSubLogics.clear();
249
+ break;
250
+ }
251
+ default: break;
252
+ }
253
+ }
254
+
255
+
256
+ const addVars = (nd : Array<Variable> | Array<Return>, s : Map<string, Variable | Return>) => {
257
+ nd.forEach(v => {
258
+ if (!v.typeAnnotation) {
259
+ s.set(v.name, v);
260
+ }
261
+ })
262
+ }
263
+
264
+ const removeVars = (nd : Array<Variable> | Array<Return>, s : Map<string, Variable | Return>) => {
265
+ nd.forEach(v => s.delete(v.name))
266
+ }
267
+
268
+
269
+ // OQL 批量优化优化完成前请勿移除
270
+ // const oqlSet = new Set<string>();
271
+
272
+ function *collectTyInferCtxTask(nd : SyntaxNode) {
273
+ // ++subLogicCtx.naslNodesCount;
274
+ // if (nd.concept === 'OqlQueryComponent') {
275
+ // oqlSet.add(nd.code);
276
+ // }
277
+ switch (nd.concept) {
278
+ case 'Logic': /* FALL THROUGH */
279
+ case 'AuthLogicForCallInterface': /* FALL THROUGH */
280
+ case 'BusinessLogic': /* FALL THROUGH */
281
+ case 'OverriddenLogic': /* FALL THROUGH */
282
+ case 'SubLogic': {
283
+ // 全局变量不支持类型推导;逻辑的变量也不支持跨子逻辑推导
284
+ // addVars(nd.variables, tyInferCtx.capturedVars);
285
+ // addVars(nd.returns, tyInferCtx.capturedVars);
286
+ tyInferCtx.scope.push(nd);
287
+ break;
288
+ }
289
+ case 'View': /* FALL THROUGH */
290
+ case 'BusinessComponent': {
291
+ addVars(nd.variables, tyInferCtx.capturedVars);
292
+ tyInferCtx.scope.push(nd);
293
+ break;
294
+ }
295
+ default: {
296
+ runGeneratorAsync(
297
+ collectAsgn(tyInferCtx.inferViaAsgnMap, tyInferCtx.inferViaFnCallMap, nd));
298
+ break;
299
+ }
300
+ }
301
+ }
302
+
303
+ function *collectTyInferCtxCleanup(nd : SyntaxNode) {
304
+ switch (nd.concept) {
305
+ case 'Logic': /* FALL THROUGH */
306
+ case 'AuthLogicForCallInterface': /* FALL THROUGH */
307
+ case 'BusinessLogic': /* FALL THROUGH */
308
+ case 'OverriddenLogic': /* FALL THROUGH */
309
+ case 'SubLogic': {
310
+ // removeVars(nd.variables, tyInferCtx.capturedVars);
311
+ // removeVars(nd.returns, tyInferCtx.capturedVars);
312
+ tyInferCtx.scope.pop();
313
+ break;
314
+ }
315
+
316
+ case 'View': /* FALL THROUGH */
317
+ case 'BusinessComponent': {
318
+ removeVars(nd.variables, tyInferCtx.capturedVars);
319
+ tyInferCtx.scope.pop();
320
+ break;
321
+ }
322
+ default: break;
323
+ }
324
+ }
325
+
326
+
327
+ type LogicContainer = AuthLogicForCallInterface | BusinessComponent | BusinessLogic | Logic | OverriddenLogic | SubLogic | View;
328
+
329
+ export function *reCollectTyInferCtx(
330
+ inferViaAsgn: Map<Return | Variable, Assignment | BatchAssignment | CallFunction>,
331
+ inferViaFnCall: Map<Return | Variable, CallFunction>,
332
+ self: LogicContainer) {
333
+
334
+ // No (types of) variables to be inferred
335
+ // @ts-ignore
336
+ const preTest = self.variables?.some((v : Variable) => !v.typeAnnotation) || self.returns?.some((v : Variable) => !v.typeAnnotation)
337
+ if (!preTest) {
338
+ return;
339
+ }
340
+
341
+ // 非首次则清空脏 map,重新收集所需上下文
342
+ if (!varScopeCtx.isFirstScreen) {
343
+ tyInferCtx.inferViaAsgnMap.clear();
344
+ tyInferCtx.inferViaFnCallMap.clear();
345
+ yield* self.traverseChildrenGenerator(collectTyInferCtxTask);
346
+ }
347
+
348
+ self.variables.forEach((locVar : Variable) => {
349
+ if (tyInferCtx.inferViaAsgnMap.has(locVar)){
350
+ inferViaAsgn.set(locVar, tyInferCtx.inferViaAsgnMap.get(locVar))
351
+ } else if (tyInferCtx.inferViaFnCallMap.has(locVar)){
352
+ inferViaFnCall.set(locVar, tyInferCtx.inferViaFnCallMap.get(locVar))
353
+ }
354
+ });
355
+ // @ts-ignore
356
+ self.returns?.forEach((locRet : Return) => {
357
+ if (tyInferCtx.inferViaAsgnMap.has(locRet)){
358
+ inferViaAsgn.set(locRet, tyInferCtx.inferViaAsgnMap.get(locRet))
359
+ } else if (tyInferCtx.inferViaFnCallMap.has(locRet)){
360
+ inferViaFnCall.set(locRet, tyInferCtx.inferViaFnCallMap.get(locRet))
361
+ }
362
+ });
363
+ }
364
+
365
+ function *collectAsgn(
366
+ inferViaAsgnMap: Map<Return | Variable, Assignment | BatchAssignment | CallFunction>,
367
+ inferViaBuiltinFnMap: Map<Return | Variable, CallFunction>,
368
+ nd: SyntaxNode) {
369
+ const self = last(tyInferCtx.scope); // 可能是 undefined
370
+ if (!nd || !self) {
371
+ return;
372
+ }
373
+
374
+ if (nd.concept === 'Assignment' && nd.left?.name) {
375
+ if (!self) {
376
+ console.log('nd', nd)
377
+ }
378
+ const hoistVar = self.variables?.find(v => nd.left?.name === v.name && !v.typeAnnotation)
379
+ // View 和 BusinessComponent 没有 returns
380
+ // @ts-ignore
381
+ ?? self.returns?.find(ret => nd.left?.name === ret.name && !ret.typeAnnotation)
382
+ ?? tyInferCtx.capturedVars.get(nd.left.name);
383
+ if (hoistVar && !inferViaAsgnMap.has(hoistVar)) {
384
+ inferViaAsgnMap.set(hoistVar, nd);
385
+ }
386
+ } else if (nd.concept === 'BatchAssignment') {
387
+ yield* wrapForEachToGenerator(nd.assignmentLines, function* warpForEachGenerator({ leftIndex }) {
388
+ const leftCode =
389
+ leftIndex.length === 1
390
+ ? yield* nd.left.expression.toEmbeddedTS(shiftState(createCompilerState(), '', { inline: true }))
391
+ : yield* nd.left.members[leftIndex[1]]?.toEmbeddedTS(shiftState(createCompilerState(), '', { inline: true })) ??
392
+ returnOrigin('');
393
+ const hoistVar = self.variables?.find((v : Variable) => leftCode === v.name && !v.typeAnnotation)
394
+ // View 和 BusinessComponent 没有 returns
395
+ // @ts-ignore
396
+ ?? self.returns?.find(ret => leftCode === ret.name && !ret.typeAnnotation)
397
+ ?? tyInferCtx.capturedVars.get(leftCode);
398
+ if (hoistVar && !inferViaAsgnMap.has(hoistVar)) {
399
+ inferViaAsgnMap.set(hoistVar, nd);
400
+ }
401
+ });
402
+ } else if (nd.concept === 'CallFunction' && nd.derivableCollection?.name) {
403
+ // 需要被推导的集合
404
+ const expr = nd.derivableCollection;
405
+ // 宽泛意义上的变量(变量+出参),View 和 BusinessComponent 没有 returns
406
+ const hoistVar = self.variables.find((v) => expr?.name === v.name && !v.typeAnnotation)
407
+ // @ts-ignore
408
+ ?? self.returns?.find(ret => expr?.name === ret.name && !ret.typeAnnotation)
409
+ ?? tyInferCtx.capturedVars.get(expr.name);
410
+ if (hoistVar && !inferViaBuiltinFnMap.has(hoistVar)) {
411
+ inferViaBuiltinFnMap.set(hoistVar, nd);
412
+ }
413
+ }
414
+ }
415
+
416
+ export const clearSemanticData = () => {
417
+ varScopeCtx.isFirstScreen = false;
418
+ varScopeCtx.frontendGlobalVars.clear();
419
+ varScopeCtx.varInViewOrComponent.clear();
420
+ varScopeCtx.logicInViewOrComponent.clear();
421
+ varScopeCtx.idToView.clear();
422
+ varScopeCtx.ctxViewElement = [];
423
+ varScopeCtx.memExprToViewElem.clear();
424
+ tyInferCtx.inferViaAsgnMap.clear();
425
+ tyInferCtx.inferViaFnCallMap.clear();
426
+ tyInferCtx.scope = [];
427
+ tyInferCtx.capturedVars.clear();
428
+ subLogicCtx.viewSubLogics.clear();
429
+ subLogicCtx.ctx = null;
430
+ }
431
+
432
+ export function printSemanticDataInfo() {
433
+ console.log('frontendGlobalVars', varScopeCtx.frontendGlobalVars)
434
+ console.log('varInViewOrComponent', varScopeCtx.varInViewOrComponent)
435
+ console.log('logicInViewOrComponent', varScopeCtx.logicInViewOrComponent)
436
+ console.log('idToView', varScopeCtx.idToView)
437
+ console.log('memExprToViewElem', varScopeCtx.memExprToViewElem)
438
+ console.log('inferViaAsgnMap', tyInferCtx.inferViaAsgnMap)
439
+ console.log('inferViaFnCallMap', tyInferCtx.inferViaFnCallMap)
440
+ // console.log(oqlSet)
441
+ // console.log('capturedVars', tyInferCtx.capturedVars)
442
+ // console.log('viewSubLogics', subLogicCtx.viewSubLogics)
443
+ // console.log('naslNodesCount', subLogicCtx.naslNodesCount)
444
+ // console.log('ctx', subLogicCtx.ctx)
445
+ // console.log('scope', tyInferCtx.scope)
446
+ // console.log('isFirstScreen', varScopeCtx.isFirstScreen)
447
+ }
@@ -37,7 +37,8 @@ export function viewMergeBlock({
37
37
  const naslCode = tryTransformBlock2Nasl(code);
38
38
  const blockView = naslCode.view;
39
39
  // vue2需要对tag进行转换 kebab-case
40
- if(((((view as any)?.parentNode as Frontend))?.parentNode as FrontendType)?.frameworkKind === 'vue2') {
40
+ const frontendType = (view as any)?.getAncestor('FrontendType');
41
+ if((frontendType as any)?.frameworkKind === 'vue2') {
41
42
  traverse(({ node }) => {
42
43
  if (node.concept === 'ViewElement') {
43
44
  node.tag = Camel2kebab(node.tag);
@@ -314,4 +314,4 @@ export function createIdentifierCode(name: string) {
314
314
 
315
315
  export function textualNamespace(name: string) {
316
316
  return name.replace(/\./g, '::');
317
- }
317
+ }