@lcap/nasl 3.12.0-rc.5 → 3.13.0-alpha.microapp-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.
Files changed (55) hide show
  1. package/out/common/Messager.d.ts.map +1 -1
  2. package/out/common/Messager.js +12 -5
  3. package/out/common/Messager.js.map +1 -1
  4. package/out/generator/annotation/utils.js +1 -1
  5. package/out/generator/annotation/utils.js.map +1 -1
  6. package/out/generator/genBundleFiles.d.ts.map +1 -1
  7. package/out/generator/genBundleFiles.js +26 -18
  8. package/out/generator/genBundleFiles.js.map +1 -1
  9. package/out/generator/microApp.d.ts.map +1 -1
  10. package/out/generator/microApp.js +2 -2
  11. package/out/generator/microApp.js.map +1 -1
  12. package/out/generator/qiankun.d.ts +1 -1
  13. package/out/generator/qiankun.d.ts.map +1 -1
  14. package/out/generator/qiankun.js +6 -0
  15. package/out/generator/qiankun.js.map +1 -1
  16. package/out/generator/release-body/body.d.ts +3 -1
  17. package/out/generator/release-body/body.d.ts.map +1 -1
  18. package/out/generator/release-body/body.js +61 -9
  19. package/out/generator/release-body/body.js.map +1 -1
  20. package/out/generator/release-body/data.d.ts +5 -3
  21. package/out/generator/release-body/data.d.ts.map +1 -1
  22. package/out/generator/release-body/data.js +12 -7
  23. package/out/generator/release-body/data.js.map +1 -1
  24. package/out/generator/release-body/internal.d.ts +2 -0
  25. package/out/generator/release-body/internal.d.ts.map +1 -1
  26. package/out/generator/release-body/internal.js.map +1 -1
  27. package/out/generator/release-body/utils.js +4 -4
  28. package/out/generator/release-body/utils.js.map +1 -1
  29. package/out/generator/ui-library-declaration/dependency.d.ts.map +1 -1
  30. package/out/generator/ui-library-declaration/dependency.js +1 -0
  31. package/out/generator/ui-library-declaration/dependency.js.map +1 -1
  32. package/out/generator/wujie.d.ts +3 -0
  33. package/out/generator/wujie.d.ts.map +1 -0
  34. package/out/generator/wujie.js +38 -0
  35. package/out/generator/wujie.js.map +1 -0
  36. package/out/manager/diagnostic.d.ts +1 -1
  37. package/out/manager/diagnostic.d.ts.map +1 -1
  38. package/out/manager/diagnostic.js.map +1 -1
  39. package/out/server/OQL/oql-cache.d.ts +5 -2
  40. package/out/server/OQL/oql-cache.d.ts.map +1 -1
  41. package/out/server/OQL/oql-cache.js +43 -25
  42. package/out/server/OQL/oql-cache.js.map +1 -1
  43. package/out/server/naslServer.d.ts +15 -13
  44. package/out/server/naslServer.d.ts.map +1 -1
  45. package/out/server/naslServer.js +428 -395
  46. package/out/server/naslServer.js.map +1 -1
  47. package/out/server/translator.d.ts.map +1 -1
  48. package/out/server/translator.js +24 -0
  49. package/out/server/translator.js.map +1 -1
  50. package/package.json +15 -14
  51. package/sandbox/stdlib/nasl.langUtil.ts +2 -0
  52. package/sandbox/stdlib/nasl.util.ts +28 -11
  53. package/ts-worker/bundle.js +8 -8
  54. package/ts-worker/lib/Messager.js +19 -4
  55. package/ts-worker/src/index.js +33 -3
@@ -34,15 +34,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
34
34
  var NaslServer_1;
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.NaslServer = exports.getDisplayString2Type = void 0;
37
- /// #if process.env.BUILD_TARGET === 'node'
38
- const fs = __importStar(require("fs-extra"));
39
- const path = __importStar(require("path"));
40
- const worker_threads_1 = require("worker_threads");
41
37
  const decimal_js_1 = require("decimal.js");
42
38
  const config_1 = require("../config");
43
39
  const nasl_sentry_1 = require("@lcap/nasl-sentry");
44
40
  const Messager_1 = __importDefault(require("../common/Messager"));
45
41
  const oql_cache_1 = require("./OQL/oql-cache");
42
+ /// #if process.env.BUILD_TARGET === 'node'
43
+ const fs = __importStar(require("fs-extra"));
44
+ const path = __importStar(require("path"));
45
+ const worker_threads_1 = require("worker_threads");
46
+ /// #endif
46
47
  const concepts_1 = require("../concepts");
47
48
  const asserts_1 = require("@lcap/nasl-concepts/asserts");
48
49
  const service_1 = require("@lcap/nasl-concepts/service");
@@ -175,7 +176,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
175
176
  this.changeStackList = [];
176
177
  // 包含组件逻辑调用的逻辑map
177
178
  this.logicSetWithComponentLogic = new Set();
178
- this.isFirstScreen = true;
179
+ this.isFirstScreen = true; // 优化首屏 getAncestor 热点代码
179
180
  /// #if process.env.BUILD_TARGET === 'node'
180
181
  if (globalThis.process)
181
182
  // For TS build
@@ -208,13 +209,16 @@ let NaslServer = NaslServer_1 = class NaslServer {
208
209
  getSender: () => this.worker,
209
210
  handleMessage: async ({ data }) => {
210
211
  if (data && data.event === 'publishDiagnostics') {
211
- const records = await this._resolveDiagnosticRecords(data.records, data.versions);
212
- if (this.isFirstScreen) {
213
- await this.diagnosticManager.setInitialDiagData(records);
214
- this.isFirstScreen = false;
215
- }
216
- else {
217
- await this.diagnosticManager.pushAll(records);
212
+ if (!this.isAnnotationMode) {
213
+ const records = await this._resolveDiagnosticRecords(data.records, data.versions);
214
+ if (this.isFirstScreen) {
215
+ this.isFirstScreen = false;
216
+ await this.diagnosticManager.setInitialDiagData(records);
217
+ this.semData.calcAndSaveIndRetDepAndRevMap(this.tempApp.logics.map(this.toRaw));
218
+ }
219
+ else {
220
+ await this.diagnosticManager.pushAll(records);
221
+ }
218
222
  }
219
223
  try {
220
224
  // 结束诊断和标注
@@ -285,7 +289,8 @@ let NaslServer = NaslServer_1 = class NaslServer {
285
289
  return this.messager.requestCommand('start');
286
290
  }
287
291
  terminate() {
288
- return this.worker.terminate();
292
+ this.worker.terminate();
293
+ this.worker = null;
289
294
  }
290
295
  async createUiTs(components, optinos) {
291
296
  const { standardUIComponents, // 标准组件(带有ts类型定义文件的组件)
@@ -307,7 +312,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
307
312
  code = code.replace(extendsStringReg, ($0, $1, $2) => `extends nasl.core.StringLiteral<\`${$2}\`>`);
308
313
  return code;
309
314
  };
310
- /// process.env.BUILD_TARGET !== 'node'
315
+ /// #if process.env.BUILD_TARGET !== 'node'
311
316
  if (!utils.isNode) {
312
317
  await this.addFile({
313
318
  file: 'nasl.ui.definition.ts',
@@ -352,7 +357,9 @@ let NaslServer = NaslServer_1 = class NaslServer {
352
357
  });
353
358
  this.elementsLogic = elementsLogic;
354
359
  }
355
- *contentToFile(module) {
360
+ *contentToFile(module1) {
361
+ // @ts-ignore
362
+ const module = module1.__v_raw ?? module1;
356
363
  if (!module) {
357
364
  return [];
358
365
  }
@@ -465,100 +472,92 @@ let NaslServer = NaslServer_1 = class NaslServer {
465
472
  }
466
473
  return results;
467
474
  }
468
- redirectSlowGetters(app, varScopeCtx) {
469
- Object.defineProperty(concepts_1.BaseNode.prototype, 'app', {
470
- get() { return app; },
471
- configurable: true,
472
- });
473
- Object.defineProperties(concepts_1.Identifier.prototype, {
474
- isFrontendVariables: {
475
- get() { return varScopeCtx.frontendGlobalVars.has(`${this.namespace}.${this.name}`); },
476
- configurable: true,
477
- },
478
- view: {
479
- get() { return varScopeCtx.idToView.get(this); },
480
- configurable: true,
481
- },
482
- viewElement: {
483
- get() { return varScopeCtx.idToViewElem.get(this); },
484
- configurable: true,
485
- },
486
- businessComponent: {
487
- get() { return varScopeCtx.idToBsComponent.get(this); },
488
- configurable: true,
489
- },
490
- callLogic: {
491
- get() { return varScopeCtx.idToCallLogic.get(this); },
492
- configurable: true,
493
- },
494
- frontendType: {
495
- get() { return varScopeCtx.idToFrontendType.get(this); },
496
- configurable: true,
497
- },
498
- callQueryComponent: {
499
- get() { return varScopeCtx.idToCallQueryComponent.get(this); },
500
- configurable: true,
501
- },
502
- });
475
+ async requestDatabaseConfigs(http, app) {
476
+ const res = await http.get('/api/v1/app/config/list?category=sql');
477
+ const data = res.data?.result || [];
478
+ const map = data.filter((item) => item.category === 'sql' && item.available)
479
+ ?.reduce((acc, item) => ({
480
+ ...acc,
481
+ [item.configId]: item.configs?.type,
482
+ }), ({}));
483
+ app.saveDatabaseConfigIdToTypeMap(map);
503
484
  }
504
- recoverSlowGetters() {
505
- Object.defineProperty(concepts_1.BaseNode.prototype, 'app', {
506
- get() { return this.getAncestor('App'); },
507
- configurable: true,
485
+ async requestSqlFunctions(http, appName) {
486
+ const res = await http.get('/api/v1/app/config/database/functions');
487
+ const data = res.data?.result?.result || [];
488
+ const files = data
489
+ .filter((item) => !!item.signature)
490
+ .map((item) => {
491
+ return {
492
+ file: `/embedded/${appName}/sqlFunctions/${item.dbType}.ts`,
493
+ fileContent: item.signature.replace('declare namespace nasl.util', `declare namespace nasl.sqlFunction.${item.dbType}`),
494
+ };
508
495
  });
509
- Object.defineProperties(concepts_1.Identifier.prototype, {
510
- isFrontendVariables: {
511
- get() {
512
- const self = this.__v_raw ?? this;
513
- const frontendType = self.getAncestor('FrontendType');
514
- return (self.namespace?.startsWith(`app.frontendTypes.${frontendType?.kind}.frontends`) &&
515
- self.namespace?.endsWith('variables'));
516
- },
517
- configurable: true,
518
- },
519
- view: {
520
- get() { return this.getAncestor('View'); },
521
- configurable: true,
522
- },
523
- viewElement: {
524
- get() { return this.getAncestor('ViewElement'); },
525
- configurable: true,
526
- },
527
- businessComponent: {
528
- get() { return this.getAncestor('BusinessComponent'); },
529
- configurable: true,
530
- },
531
- callLogic: {
532
- get() { return this.getAncestor('CallLogic'); },
533
- configurable: true,
534
- },
535
- frontendType: {
536
- get() { return this.getAncestor('FrontendType'); },
537
- configurable: true,
538
- },
539
- callQueryComponent: {
540
- get() { return this.getAncestor('CallQueryComponent'); },
541
- configurable: true,
542
- },
496
+ data.forEach((item) => {
497
+ delete item.signature;
543
498
  });
499
+ this._sqlFunctions = data;
500
+ return files;
501
+ }
502
+ getSqlFunctions(dbType) {
503
+ const res = this._sqlFunctions.find((f) => f.dbType === dbType);
504
+ if (res) {
505
+ res.functions.forEach((func) => {
506
+ func.expanded = true;
507
+ });
508
+ }
509
+ return res;
510
+ }
511
+ getSqlFunction(dbType, functionName) {
512
+ if (!functionName)
513
+ return null;
514
+ const sqlFunction = this.getSqlFunctions(dbType);
515
+ if (!sqlFunction)
516
+ return null;
517
+ const upperFunctionName = functionName.toUpperCase();
518
+ for (const category of sqlFunction.functions) {
519
+ for (const func of category.children) {
520
+ if (func.name === upperFunctionName) {
521
+ return func;
522
+ }
523
+ }
524
+ }
525
+ return null;
544
526
  }
545
527
  async openApp(app, performance = false, needRegisterCommand = true) {
546
528
  app.naslServer = this;
529
+ this.tempApp = app; // IDE 加载临时使用,诊断信息处理完回设置为 undefined,不要在其他地方使用了,避免循环引用。
547
530
  if (utils.isAutoTestEnv) {
548
531
  this.logger.info('运行在自动化测试模式下...');
549
532
  }
550
533
  this.logger.time('全量生成并写入 TS 文件——总计');
534
+ const toEmbeddedTSStartTime = new Date().getTime();
551
535
  this.logger.time('全量生成 TS——翻译');
552
536
  this.logger.time('全量生成 TS——翻译——简单语义分析');
553
537
  this.semData = new nasl_concepts_1.SemanticData();
554
538
  // 除此之外,好像没什么简单的方法可以让 __xxx.ts 文件快速拿到 app.naslServer 的引用了……
555
- this.redirectSlowGetters(app, this.semData.varScopeCtx);
556
- this.semData.collectAllSemanticCtx(app);
539
+ // @ts-ignore
540
+ this.semData.redirectSlowGetters(app.__v_raw ?? app, this.semData.varScopeCtx);
541
+ // @ts-ignore
542
+ this.semData.collectAllSemanticCtx(app.__v_raw ?? app);
557
543
  // semantics.printSemanticDataInfo();
558
544
  this.logger.timeEnd('全量生成 TS——翻译——简单语义分析');
559
545
  (0, common_1.invokeCommand)('naslServer:startWork');
560
546
  const self = this;
561
547
  this.performance = performance;
548
+ try {
549
+ await this.requestDatabaseConfigs(this.http, app);
550
+ }
551
+ catch (err) {
552
+ this.logger.error('请求数据库配置列表失败', err);
553
+ }
554
+ let sqlSignatureFiles = [];
555
+ try {
556
+ sqlSignatureFiles = await this.requestSqlFunctions(this.http, app.name);
557
+ }
558
+ catch (err) {
559
+ this.logger.error('请求sql函数列表失败', err);
560
+ }
562
561
  const results = await utils.runGeneratorAsync(getAllTsFiles());
563
562
  const files = results.map((result) => ({
564
563
  file: result.filePath,
@@ -570,6 +569,10 @@ let NaslServer = NaslServer_1 = class NaslServer {
570
569
  files.forEach((f) => {
571
570
  this.diagnosticManager.deleteVersionByFilePath(f.file);
572
571
  });
572
+ // 添加 sql 函数签名文件
573
+ sqlSignatureFiles.forEach((sqlFunction) => {
574
+ files.push(sqlFunction);
575
+ });
573
576
  await this.writeFiles(files);
574
577
  this._debugInFileStorage(app, files);
575
578
  if (needRegisterCommand) {
@@ -585,9 +588,13 @@ let NaslServer = NaslServer_1 = class NaslServer {
585
588
  });
586
589
  }
587
590
  this.logger.timeEnd('全量生成 TS——写入文件');
588
- this.recoverSlowGetters();
591
+ this.semData.recoverSlowGetters();
589
592
  this.semData.clearSemanticData();
590
593
  this.logger.timeEnd('全量生成并写入 TS 文件——总计');
594
+ const toEmbeddedTSEndTime = new Date().getTime();
595
+ const toEmbeddedTSUsedTime = toEmbeddedTSEndTime - toEmbeddedTSStartTime;
596
+ app.naslServer.appPerfermenceData = app.naslServer.appPerfermenceData || {};
597
+ app.naslServer.appPerfermenceData.toEmbeddedTSUsedTime = toEmbeddedTSUsedTime;
591
598
  function* getAllTsFiles() {
592
599
  const files = yield* self.contentToFile(app);
593
600
  const otherModules = [
@@ -606,7 +613,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
606
613
  return files;
607
614
  }
608
615
  }
609
- async refreshApp(app) {
616
+ async refreshApp(app, performance) {
610
617
  // 清除所有问题
611
618
  this.diagnosticManager.clear();
612
619
  // 刷新要清除文件列表
@@ -614,8 +621,12 @@ let NaslServer = NaslServer_1 = class NaslServer {
614
621
  await this.deleteDirectoryFiles({ directoryName: '/embedded' });
615
622
  // 清楚check count的数量
616
623
  await this.messager.requestCommand('_clearTimeout');
624
+ // 如果没传就用当前this的
625
+ if (performance === undefined) {
626
+ performance = this.performance;
627
+ }
617
628
  // 重新加载app下内容
618
- await this.openApp(app, this.performance);
629
+ await this.openApp(app, performance);
619
630
  // 重新check一遍所有内容
620
631
  await this.getDiagnosticRecordsAndPushAll();
621
632
  // check内容后,会自动走增量类型标注完善全部类型
@@ -990,13 +1001,14 @@ let NaslServer = NaslServer_1 = class NaslServer {
990
1001
  });
991
1002
  record.semanticDiagnostics = (yield* utils.wrapMapToGenerator(record.semanticDiagnostics, diag => self._resolveSingleDiagnostic(diag, node, record))).filter((diag) => !!diag);
992
1003
  record.semanticDiagnostics.push(...(yield* self._attachDiagnosticsWithGenerator(node)));
1004
+ let sugDiag = [];
993
1005
  // 报错降级逻辑
994
1006
  record.semanticDiagnostics = (yield* utils.wrapMapToGenerator(record.semanticDiagnostics, (diag) => {
995
1007
  // 错误降级如果属于草稿态的就降级
996
1008
  if (diag?.node) {
997
1009
  let currentNode = diag.node;
998
1010
  if (diag.severity === 'warning') {
999
- record.suggestionDiagnostics.push(diag);
1011
+ sugDiag.push(diag);
1000
1012
  return null;
1001
1013
  }
1002
1014
  if (concepts_1.asserts.isStrictOqlQueryComponent(currentNode)) {
@@ -1008,7 +1020,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
1008
1020
  // 重置组件节点上的错误信息
1009
1021
  diag.node.tsErrorDetail.severity = 'warning';
1010
1022
  }
1011
- record.suggestionDiagnostics.push(diag);
1023
+ sugDiag.push(diag);
1012
1024
  return null;
1013
1025
  }
1014
1026
  }
@@ -1027,7 +1039,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
1027
1039
  // 重置组件节点上的错误信息
1028
1040
  diag.node.tsErrorDetail.severity = 'warning';
1029
1041
  }
1030
- record.suggestionDiagnostics.push(diag);
1042
+ sugDiag.push(diag);
1031
1043
  return null;
1032
1044
  }
1033
1045
  }
@@ -1040,7 +1052,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
1040
1052
  // 重置组件节点上的错误信息
1041
1053
  diag.node.tsErrorDetail.severity = 'warning';
1042
1054
  }
1043
- record.suggestionDiagnostics.push(diag);
1055
+ sugDiag.push(diag);
1044
1056
  return null;
1045
1057
  }
1046
1058
  currentNode = currentNode.parentNode;
@@ -1054,7 +1066,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
1054
1066
  return diag;
1055
1067
  })).filter((diag) => !!diag);
1056
1068
  // 处理后的警告异常提示信息
1057
- record.suggestionDiagnostics = (yield* utils.wrapMapToGenerator(record.suggestionDiagnostics, function* resolveSuggestionDiagnostic(diag) {
1069
+ sugDiag = (yield* utils.wrapMapToGenerator(sugDiag, function* resolveSuggestionDiagnostic(diag) {
1058
1070
  // 上面错误降级下来的
1059
1071
  if (diag?.node) {
1060
1072
  return diag;
@@ -1112,7 +1124,8 @@ let NaslServer = NaslServer_1 = class NaslServer {
1112
1124
  return null;
1113
1125
  }))
1114
1126
  .filter((diag) => !!diag);
1115
- record.suggestionDiagnostics.push(...yield* self._attachSuggestionDiagnosticsWithGenerator(node));
1127
+ sugDiag.push(...yield* self._attachSuggestionDiagnosticsWithGenerator(node));
1128
+ record.suggestionDiagnostics = sugDiag;
1116
1129
  });
1117
1130
  this.logger.timeEnd('处理诊断数据');
1118
1131
  this.logger.timeEnd('语言服务变更');
@@ -1669,6 +1682,14 @@ let NaslServer = NaslServer_1 = class NaslServer {
1669
1682
  }
1670
1683
  });
1671
1684
  }
1685
+ if (node._foldInView) {
1686
+ const diagnostic = {
1687
+ node,
1688
+ severity: 'error',
1689
+ message: `组件${node.name}已经极速折叠`,
1690
+ };
1691
+ diagnostics.push(diagnostic);
1692
+ }
1672
1693
  }
1673
1694
  else if ((node instanceof concepts_1.Variable || node instanceof concepts_1.Return) && cmpFileNode(fileNode, fileNodeRaw, likeComponent)) {
1674
1695
  if (!node.typeAnnotation && !node.__TypeAnnotation) {
@@ -4581,6 +4602,23 @@ let NaslServer = NaslServer_1 = class NaslServer {
4581
4602
  });
4582
4603
  }
4583
4604
  }
4605
+ getSlotCurrentCompletion(node) {
4606
+ const { currentSource, fileNode } = this.getCurrentSource(node);
4607
+ if (currentSource && fileNode) {
4608
+ const range = {
4609
+ line: (0, translator_1.lsp2tspNumber)(currentSource.start.line),
4610
+ offset: (0, translator_1.lsp2tspNumber)(currentSource.start.character),
4611
+ };
4612
+ if (['BindAttribute', 'BindDirective', 'BindStyle'].includes(node.concept)) {
4613
+ range.line = (0, translator_1.lsp2tspNumber)(currentSource.end.line);
4614
+ range.offset = 1;
4615
+ }
4616
+ return this.messager.requestCommand('getSlotCurrentCompletion', {
4617
+ file: fileNode.getEmbeddedFilePath(),
4618
+ range
4619
+ });
4620
+ }
4621
+ }
4584
4622
  _getFieldKeySelectCompletion(args) {
4585
4623
  return this.messager.requestCommand('getFieldKeySelectCompletion', args);
4586
4624
  }
@@ -4729,7 +4767,8 @@ let NaslServer = NaslServer_1 = class NaslServer {
4729
4767
  }
4730
4768
  // 如果 入参不是虚拟节点的,就不去请求类型
4731
4769
  // 只有虚拟节点的入参,才没有类型
4732
- if (node.concept === 'Param' && (node.parentKey !== 'virtualParams' && node.parentKey !== 'item' && node.parentNode.concept !== 'AnonymousFunction')) {
4770
+ if (node.concept === 'Param' &&
4771
+ (node.parentKey !== 'virtualParams' && node.parentKey !== 'item' && node.parentNode.concept !== 'AnonymousFunction')) {
4733
4772
  return;
4734
4773
  }
4735
4774
  if (![
@@ -4831,7 +4870,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
4831
4870
  }
4832
4871
  else if (node instanceof concepts_1.Argument) {
4833
4872
  // 如果Argument,但是没可以用的类型,就用原来logic的参数类型
4834
- const argType = yield* self.getArgumentTypeAnnotationWithGenerator(node, newQuickInfoNodes, types);
4873
+ const argType = yield* self.getArgumentTypeAnnotationWithGenerator(node, types);
4835
4874
  types.set(node, argType);
4836
4875
  }
4837
4876
  else if (node instanceof concepts_1.MatchCase) {
@@ -4845,14 +4884,14 @@ let NaslServer = NaslServer_1 = class NaslServer {
4845
4884
  }
4846
4885
  }
4847
4886
  });
4848
- yield* utils.wrapIteratorToGenerator(types.entries(), ([node, value]) => {
4887
+ yield* utils.wrapIteratorToGenerator(types.entries(), ([node, ty]) => {
4849
4888
  try {
4850
4889
  // 因为node可能是经过处理的TypeAnnotation
4851
4890
  node.__isCorrectTypeAnnotation = true;
4852
- if (value) {
4891
+ if (ty) {
4853
4892
  if (node instanceof concepts_1.OqlQueryComponent) {
4854
4893
  // 自动推导情况
4855
- const typeAnnotation = value;
4894
+ const typeAnnotation = ty;
4856
4895
  if (!node.typeAnnotation && typeAnnotation) {
4857
4896
  if (typeAnnotation.typeName === 'List' && typeAnnotation.typeKind === 'generic') {
4858
4897
  const { typeArguments } = typeAnnotation;
@@ -4863,11 +4902,11 @@ let NaslServer = NaslServer_1 = class NaslServer {
4863
4902
  }
4864
4903
  }
4865
4904
  }
4866
- if (value instanceof concepts_1.TypeAnnotation) {
4867
- node.__TypeAnnotation = value;
4905
+ if (ty instanceof concepts_1.TypeAnnotation) {
4906
+ node.__TypeAnnotation = ty;
4868
4907
  }
4869
- else if (value.typeAnnotation) {
4870
- node.__TypeAnnotation = value.typeAnnotation;
4908
+ else if (ty.typeAnnotation) {
4909
+ node.__TypeAnnotation = ty.typeAnnotation;
4871
4910
  }
4872
4911
  // 节点有函数返回时候 返回类型作为typeAnnotation
4873
4912
  const nodeType = node.__nodeType;
@@ -4909,9 +4948,6 @@ let NaslServer = NaslServer_1 = class NaslServer {
4909
4948
  }
4910
4949
  }
4911
4950
  catch (err) {
4912
- // if (globalThis.window) {
4913
- // this.logger.info(err);
4914
- // }
4915
4951
  }
4916
4952
  });
4917
4953
  // 预留时间做 minor gc,减少峰值内存占用
@@ -4996,11 +5032,11 @@ let NaslServer = NaslServer_1 = class NaslServer {
4996
5032
  const typesMap = await this.getQuickInfoNodesTypeMap(nodes, true);
4997
5033
  this.logger.time('app to AnnotatedJSON');
4998
5034
  const jsonMap = new Map();
4999
- const json = naslNode._toJSON((source, instance) => {
5035
+ const json = naslNode._toJSON((newJson, oldNode) => {
5000
5036
  // 删除多余属性,降低全量数据
5001
- delete source._aiUID;
5002
- jsonMap.set(instance, source);
5003
- return source;
5037
+ delete newJson._aiUID;
5038
+ jsonMap.set(oldNode, newJson);
5039
+ return newJson;
5004
5040
  });
5005
5041
  this.logger.timeEnd('app to AnnotatedJSON');
5006
5042
  this.logger.timeEnd(`${isApp ? '全量' : '单文件'}标注`);
@@ -5011,66 +5047,215 @@ let NaslServer = NaslServer_1 = class NaslServer {
5011
5047
  if (releaseFlag) {
5012
5048
  this.logger.time('annotationToJson');
5013
5049
  // 全量标注后对json进行一些修改,为了服务端翻译处理
5014
- this.annotationToJson(typesMap, json, jsonMap);
5050
+ this.annotationToJson(typesMap, jsonMap); // 把 typesMap 里的类型写入 jsonMap 的 node.typeAnnotation 里
5015
5051
  this.logger.timeEnd('annotationToJson');
5016
5052
  }
5017
5053
  return json;
5018
5054
  }
5019
- // 全量标注并且返回json,用 generator
5020
- *getNaslAnnotatedJSONWithGenerator(naslNode, releaseFlag) {
5055
+ // 不用 TS LS 的最新类型,用现有类型直接写入 NASL json
5056
+ async fastGetNaslAnnotatedJSON(naslNode) {
5021
5057
  // eslint-disable-next-line @typescript-eslint/no-shadow
5022
5058
  const isApp = concepts_1.asserts.isApp(naslNode);
5023
5059
  if (this.changeStackList?.length) {
5024
5060
  throw new Error(`当前还有${this.changeStackList.length}个文件还在执行更新操作`);
5025
5061
  }
5026
- this.logger.time(`${isApp ? '全量' : '单文件'}标注`);
5027
- const nodes = [];
5028
- if (!isApp) {
5029
- const filePath = naslNode?.getEmbeddedFilePath();
5030
- naslNode.sourceMap?.forEach?.((item, node) => {
5031
- nodes.push({
5032
- filePath,
5033
- node,
5034
- item,
5035
- });
5036
- });
5037
- }
5038
- else {
5039
- this.file2NodeMap.forEach((fileNode, filePath) => {
5040
- // 先不排除view,传递给后端的时候,去除views下的标注
5041
- if (!(0, service_1.isIgnoreFullAnnotationFileNode)(fileNode)) {
5042
- fileNode.sourceMap.forEach((item, node) => {
5043
- nodes.push({
5044
- filePath,
5045
- node,
5046
- item,
5047
- });
5048
- });
5049
- }
5050
- });
5051
- }
5052
- const typesMap = yield* this._getQuickInfoNodesTypeMapWithGenerator(nodes);
5053
5062
  this.logger.time('app to AnnotatedJSON');
5054
- const jsonMap = new Map();
5055
- // @ts-ignore
5056
- const json = yield* naslNode._toJSONWithGenerator((source, instance) => {
5063
+ const timeZoneArgumentIndexMap = new Map([
5064
+ ['ToString', 1],
5065
+ ['CurrDateTime', 0],
5066
+ ['CurrDate', 0],
5067
+ ['CurrTime', 0],
5068
+ ['FormatDateTime', 2],
5069
+ ['jsonSerialize', 1],
5070
+ ['GetDateCount', 2],
5071
+ ['GetSpecificDaysOfWeek', 3]
5072
+ ]);
5073
+ const tyAnnToJSON = (nd) => nd ? (nd.toJSON?.() ?? nd) : null;
5074
+ const longTyAnn = concepts_1.TypeAnnotation.createPrimitive('Long').toJSON();
5075
+ const json = this.toRaw(naslNode)._toJSON((newJson, oldNd) => {
5057
5076
  // 删除多余属性,降低全量数据
5058
- delete source._aiUID;
5059
- jsonMap.set(instance, source);
5060
- return source;
5077
+ delete newJson._aiUID; // @ts-ignore
5078
+ let tyAnn = tyAnnToJSON(oldNd.__TypeAnnotation);
5079
+ // 原来的标注环节复制粘贴过来改写的
5080
+ {
5081
+ // 如果节点本身有类型就不去在塞一遍了
5082
+ // 有值而且没有类型再去设置
5083
+ // 但是Identifier 和 MemberExpression 都用标注出来的因为本身是变量,有类型也需要覆盖一下
5084
+ if (tyAnn && (oldNd instanceof concepts_1.Argument) && oldNd.getAncestor('Connector')?.concept === 'Connector') { // @ts-ignore
5085
+ newJson.typeAnnotation = tyAnn;
5086
+ }
5087
+ if (tyAnn && (!oldNd.typeAnnotation || oldNd instanceof concepts_1.Identifier || oldNd instanceof concepts_1.MemberExpression)) { // @ts-ignore
5088
+ newJson.typeAnnotation = tyAnn;
5089
+ }
5090
+ // 旧版本数据查询需要确认是匿名数据结构的 ListTotal 类型
5091
+ if (oldNd instanceof concepts_1.CallQueryComponent && !oldNd.isAutoInfer()) { // @ts-ignore
5092
+ newJson.typeAnnotation = {
5093
+ concept: 'TypeAnnotation',
5094
+ typeKind: 'anonymousStructure',
5095
+ typeNamespace: null,
5096
+ typeName: null,
5097
+ typeArguments: [],
5098
+ inferred: false,
5099
+ ruleMap: null,
5100
+ properties: [
5101
+ {
5102
+ concept: 'StructureProperty',
5103
+ name: 'list',
5104
+ label: null,
5105
+ description: null,
5106
+ typeAnnotation: {
5107
+ concept: 'TypeAnnotation',
5108
+ typeKind: 'generic',
5109
+ typeNamespace: 'nasl.collection',
5110
+ typeName: 'List', // @ts-ignore
5111
+ typeArguments: [newJson.typeAnnotation],
5112
+ inferred: null,
5113
+ },
5114
+ required: null,
5115
+ defaultValue: null,
5116
+ },
5117
+ {
5118
+ concept: 'StructureProperty',
5119
+ name: 'total',
5120
+ label: null,
5121
+ description: null,
5122
+ typeAnnotation: {
5123
+ concept: 'TypeAnnotation',
5124
+ typeKind: 'primitive',
5125
+ typeNamespace: 'nasl.core',
5126
+ typeName: 'Long',
5127
+ typeArguments: null,
5128
+ inferred: null,
5129
+ },
5130
+ required: null,
5131
+ defaultValue: null,
5132
+ },
5133
+ ],
5134
+ };
5135
+ }
5136
+ // 特殊处理param有类型错误的
5137
+ if (tyAnn && oldNd instanceof concepts_1.Param) {
5138
+ // index在nasl foreach上有脏数据
5139
+ if (oldNd.parentKey === 'index' && oldNd.parentNode instanceof concepts_1.ForEachStatement) { // @ts-ignore
5140
+ newJson.typeAnnotation = longTyAnn;
5141
+ }
5142
+ }
5143
+ if (oldNd instanceof concepts_1.Match) {
5144
+ const matchExpression = oldNd.expression;
5145
+ if (matchExpression?.__TypeAnnotation?.typeKind === 'union' &&
5146
+ (matchExpression instanceof concepts_1.Identifier || matchExpression instanceof concepts_1.MemberExpression)) {
5147
+ const { currentSource, fileNode } = matchExpression?.getCurrentSource();
5148
+ const currentCode = this.getNodeCode(fileNode, currentSource);
5149
+ fileNode.sourceMap.forEach((item, itemNode) => {
5150
+ const itemCode = this.getNodeCode(fileNode, item);
5151
+ if (itemNode.concept === matchExpression.concept && itemCode === currentCode) { // @ts-ignore
5152
+ newJson.typeAnnotation = matchExpression.__TypeAnnotation;
5153
+ }
5154
+ });
5155
+ }
5156
+ }
5157
+ // 特殊处理param有类型错误的
5158
+ if (tyAnn && (oldNd instanceof concepts_1.Param)) {
5159
+ // index在nasl foreach上有脏数据
5160
+ if (oldNd.parentKey === 'index' && oldNd.parentNode instanceof concepts_1.ForEachStatement) { // @ts-ignore
5161
+ newJson.typeAnnotation = tyAnn;
5162
+ }
5163
+ }
5164
+ if (tyAnn && (oldNd instanceof concepts_1.NewComposite) &&
5165
+ (oldNd.typeAnnotation?.typeKind === 'anonymousStructure' || oldNd.typeAnnotation?.typeKind === 'generic')) { // @ts-ignore
5166
+ newJson.typeAnnotation = tyAnn;
5167
+ }
5168
+ // jsonSerializer 是 CallLogic,其余是 CallFunction
5169
+ if (oldNd instanceof concepts_1.CallFunction || oldNd instanceof concepts_1.CallLogic) {
5170
+ const tzArgIdx = timeZoneArgumentIndexMap.get(oldNd.calleeName);
5171
+ const args = oldNd.arguments;
5172
+ const tzArg = args ? args[tzArgIdx] : undefined;
5173
+ if (tzArgIdx && tzArg?.keyword === '时区' && !isCoreDateTimeType(oldNd.arguments[0])) {
5174
+ if (!isFunctionWithFixedTimeZoneParam(oldNd.calleeName)) {
5175
+ oldNd.arguments.pop();
5176
+ }
5177
+ }
5178
+ /**
5179
+ * 特殊处理,不想去查两次类型, 因为是从函数签名上拿类型,所以直接合并在一起,先这样
5180
+ */
5181
+ if (oldNd instanceof concepts_1.CallLogic && oldNd.__TypeArguments?.length) { // @ts-ignore
5182
+ newJson.typeArguments = oldNd.__TypeArguments.map(tyAnnToJSON); // @ts-ignore
5183
+ newJson.typeAnnotation = tyAnn;
5184
+ }
5185
+ // 根据 https://projectmanage.netease-official.lcap.163yun.com/dashboard/FeatureDetail?id=2737356895760128&id1=null&iterationId=null&versionid=null&tab=info
5186
+ // 对CallFunction节点,若其callee为部分List/Map内置函数,则修改其argument类型标注以让服务端据此插入显式的类型转换。规则如下:
5187
+ // - 对argument.expression.typeAnnotation 无需做修改,保持为其实际类型
5188
+ // - 对argument.typeAnnotation,为根据对应Collection的泛型参数的类型填写其类型
5189
+ if (newJson.concept === 'CallFunction') {
5190
+ if (oldNd.calleeNamespace === 'nasl.util') {
5191
+ const calleeName = oldNd.calleeName;
5192
+ const listFunctionParamIndexMaps = new Map(Object.entries({
5193
+ Add: { collection: 0, item: 1 },
5194
+ Insert: { collection: 0, item: 2 },
5195
+ Remove: { collection: 0, item: 1 },
5196
+ Contains: { collection: 0, item: 1 },
5197
+ }));
5198
+ const mapFunctionParamIndexMaps = new Map(Object.entries({
5199
+ MapPut: { collection: 0, key: 1, value: 2 },
5200
+ MapGet: { collection: 0, key: 1, },
5201
+ MapRemove: { collection: 0, key: 1 },
5202
+ MapContains: { collection: 0, key: 1 },
5203
+ }));
5204
+ const listParamIndex = listFunctionParamIndexMaps.get(calleeName);
5205
+ if (listParamIndex) {
5206
+ const list = newJson.arguments[listParamIndex.collection];
5207
+ const item = newJson.arguments[listParamIndex.item];
5208
+ const itemExpression = item?.expression;
5209
+ if (itemExpression) {
5210
+ const listTypeArgument = tyAnnToJSON(list.__TypeAnnotation?.typeArguments?.[0]);
5211
+ if (listTypeArgument) {
5212
+ newJson.typeAnnotation = listTypeArgument;
5213
+ }
5214
+ }
5215
+ }
5216
+ else {
5217
+ const mapParamIndex = mapFunctionParamIndexMaps.get(calleeName);
5218
+ if (mapParamIndex) {
5219
+ const map = newJson.arguments[mapParamIndex.collection];
5220
+ const key = newJson.arguments[mapParamIndex.key];
5221
+ const value = newJson.arguments[mapParamIndex.value];
5222
+ const keyExpression = key?.expression;
5223
+ const valueExpression = value?.expression;
5224
+ if (keyExpression) {
5225
+ const mapKeyTypeArgument = tyAnnToJSON(map.__TypeAnnotation?.typeArguments?.[0]);
5226
+ if (mapKeyTypeArgument) {
5227
+ const kJson = newJson.arguments[mapParamIndex.key];
5228
+ kJson.typeAnnotation = mapKeyTypeArgument;
5229
+ }
5230
+ }
5231
+ if (valueExpression) {
5232
+ const mapValueTypeArgument = tyAnnToJSON(map.__TypeAnnotation?.typeArguments?.[1]);
5233
+ if (mapValueTypeArgument) {
5234
+ const vJson = newJson.arguments[mapParamIndex.value];
5235
+ vJson.typeAnnotation = mapValueTypeArgument;
5236
+ }
5237
+ }
5238
+ }
5239
+ }
5240
+ }
5241
+ }
5242
+ }
5243
+ // 服务端需要默认值节点有类型来判断父节点是否是日期类型
5244
+ if (newJson.concept === 'DefaultValue' && !tyAnn) {
5245
+ const parentNodeType = oldNd.parentNode?.typeAnnotation || oldNd.parentNode?.__TypeAnnotation;
5246
+ if (parentNodeType) { // @ts-ignore
5247
+ newJson.typeAnnotation = tyAnnToJSON(parentNodeType);
5248
+ }
5249
+ }
5250
+ }
5251
+ ;
5252
+ return newJson;
5061
5253
  });
5062
5254
  this.logger.timeEnd('app to AnnotatedJSON');
5063
- this.logger.timeEnd(`${isApp ? '全量' : '单文件'}标注`);
5064
5255
  // 测试环境或者是调试模式打印数据
5065
5256
  if (utils.isDebugMode || utils.isTestBrowser) {
5066
5257
  this.logger.info(`${isApp ? '全量' : '单文件'}标注数据`, json);
5067
5258
  }
5068
- if (releaseFlag) {
5069
- this.logger.time('annotationToJsonWithGenerator');
5070
- // 全量标注后对json进行一些修改,为了服务端翻译处理
5071
- yield* this.annotationToJsonWithGenerator(typesMap, json, jsonMap);
5072
- this.logger.timeEnd('annotationToJsonWithGenerator');
5073
- }
5074
5259
  return json;
5075
5260
  }
5076
5261
  /**
@@ -5124,7 +5309,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
5124
5309
  yield* this._getQuickInfoNodesTypeMapWithGenerator(nodes);
5125
5310
  this.logger.timeEnd('增量标注');
5126
5311
  }
5127
- annotationToJson(typesMap, json, jsonMap) {
5312
+ annotationToJson(typesMap, jsonMap) {
5128
5313
  const timeZoneArgumentIndexMap = new Map([
5129
5314
  ['ToString', 1],
5130
5315
  ['CurrDateTime', 0],
@@ -5135,26 +5320,26 @@ let NaslServer = NaslServer_1 = class NaslServer {
5135
5320
  ['GetDateCount', 2],
5136
5321
  ['GetSpecificDaysOfWeek', 3]
5137
5322
  ]);
5138
- typesMap.forEach((value, node) => {
5323
+ typesMap.forEach((typ, node) => {
5139
5324
  // 如果节点本身有类型就不去在塞一遍了
5140
5325
  // 有值而且没有类型再去设置
5141
5326
  // 但是Identifier 和 MemberExpression 都用标注出来的因为本身是变量,有类型也需要覆盖一下
5142
- if (value && (node instanceof concepts_1.Argument) && node.getAncestor('Connector')?.concept === 'Connector') {
5143
- const jsonNode = jsonMap.get(node);
5144
- if (jsonNode) {
5145
- jsonNode.typeAnnotation = value?.toJSON?.() ?? value;
5327
+ if (typ && (node instanceof concepts_1.Argument) && node.getAncestor('Connector')?.concept === 'Connector') {
5328
+ const newJson = jsonMap.get(node);
5329
+ if (newJson) {
5330
+ newJson.typeAnnotation = typ?.toJSON?.() ?? typ;
5146
5331
  }
5147
5332
  }
5148
- if (value && (!node.typeAnnotation || node instanceof concepts_1.Identifier || node instanceof concepts_1.MemberExpression)) {
5149
- const jsonNode = jsonMap.get(node);
5150
- if (jsonNode) {
5151
- jsonNode.typeAnnotation = value?.toJSON?.() ?? value;
5333
+ if (typ && (!node.typeAnnotation || node instanceof concepts_1.Identifier || node instanceof concepts_1.MemberExpression)) {
5334
+ const newJson = jsonMap.get(node);
5335
+ if (newJson) {
5336
+ newJson.typeAnnotation = typ?.toJSON?.() ?? typ;
5152
5337
  }
5153
5338
  }
5154
5339
  // 旧版本数据查询需要确认是匿名数据结构的 ListTotal 类型
5155
5340
  if (node instanceof concepts_1.CallQueryComponent && !node.isAutoInfer()) {
5156
- const jsonNode = jsonMap.get(node);
5157
- jsonNode.typeAnnotation = {
5341
+ const newJson = jsonMap.get(node);
5342
+ newJson.typeAnnotation = {
5158
5343
  concept: 'TypeAnnotation',
5159
5344
  typeKind: 'anonymousStructure',
5160
5345
  typeNamespace: null,
@@ -5173,7 +5358,7 @@ let NaslServer = NaslServer_1 = class NaslServer {
5173
5358
  typeKind: 'generic',
5174
5359
  typeNamespace: 'nasl.collection',
5175
5360
  typeName: 'List',
5176
- typeArguments: [jsonNode.typeAnnotation],
5361
+ typeArguments: [newJson.typeAnnotation],
5177
5362
  inferred: null,
5178
5363
  },
5179
5364
  required: null,
@@ -5202,8 +5387,8 @@ let NaslServer = NaslServer_1 = class NaslServer {
5202
5387
  if (node instanceof concepts_1.Param) {
5203
5388
  // index在nasl foreach上有脏数据
5204
5389
  if (node.parentKey === 'index' && node.parentNode instanceof concepts_1.ForEachStatement) {
5205
- const jsonNode = jsonMap.get(node);
5206
- jsonNode.typeAnnotation = concepts_1.TypeAnnotation.createPrimitive('Long').toJSON();
5390
+ const newJson = jsonMap.get(node);
5391
+ newJson.typeAnnotation = concepts_1.TypeAnnotation.createPrimitive('Long').toJSON();
5207
5392
  }
5208
5393
  }
5209
5394
  if (node instanceof concepts_1.Match) {
@@ -5215,23 +5400,23 @@ let NaslServer = NaslServer_1 = class NaslServer {
5215
5400
  fileNode.sourceMap.forEach((item, itemNode) => {
5216
5401
  const itemCode = this.getNodeCode(fileNode, item);
5217
5402
  if (itemNode.concept === matchExpression.concept && itemCode === currentCode) {
5218
- const jsonNode = jsonMap.get(itemNode);
5219
- jsonNode.typeAnnotation = matchExpression.__TypeAnnotation;
5403
+ const newJson = jsonMap.get(itemNode);
5404
+ newJson.typeAnnotation = matchExpression.__TypeAnnotation;
5220
5405
  }
5221
5406
  });
5222
5407
  }
5223
5408
  }
5224
5409
  // 特殊处理param有类型错误的
5225
- if (value && (node instanceof concepts_1.Param)) {
5410
+ if (typ && (node instanceof concepts_1.Param)) {
5226
5411
  // index在nasl foreach上有脏数据
5227
5412
  if (node.parentKey === 'index' && node.parentNode instanceof concepts_1.ForEachStatement) {
5228
- const jsonNode = jsonMap.get(node);
5229
- jsonNode.typeAnnotation = value?.toJSON?.() ?? value;
5413
+ const newJson = jsonMap.get(node);
5414
+ newJson.typeAnnotation = typ?.toJSON?.() ?? typ;
5230
5415
  }
5231
5416
  }
5232
- if (value && (node instanceof concepts_1.NewComposite) && (node.typeAnnotation?.typeKind === 'anonymousStructure' || node.typeAnnotation?.typeKind === 'generic')) {
5233
- const jsonNode = jsonMap.get(node);
5234
- jsonNode.typeAnnotation = value?.toJSON?.() ?? value;
5417
+ if (typ && (node instanceof concepts_1.NewComposite) && (node.typeAnnotation?.typeKind === 'anonymousStructure' || node.typeAnnotation?.typeKind === 'generic')) {
5418
+ const newJson = jsonMap.get(node);
5419
+ newJson.typeAnnotation = typ?.toJSON?.() ?? typ;
5235
5420
  }
5236
5421
  // jsonSerializer 是 CallLogic,其余是 CallFunction
5237
5422
  if (node instanceof concepts_1.CallFunction || node instanceof concepts_1.CallLogic) {
@@ -5247,9 +5432,9 @@ let NaslServer = NaslServer_1 = class NaslServer {
5247
5432
  * 特殊处理,不想去查两次类型, 因为是从函数签名上拿类型,所以直接合并在一起,先这样
5248
5433
  */
5249
5434
  if (node instanceof concepts_1.CallLogic && node.__TypeArguments?.length) {
5250
- const jsonNode = jsonMap.get(node);
5251
- jsonNode.typeArguments = node.__TypeArguments.map((type) => type?.toJSON?.() ?? type);
5252
- jsonNode.typeAnnotation = node.__TypeAnnotation?.toJSON?.() ?? node.__TypeAnnotation;
5435
+ const newJson = jsonMap.get(node);
5436
+ newJson.typeArguments = node.__TypeArguments.map((type) => type?.toJSON?.() ?? type);
5437
+ newJson.typeAnnotation = node.__TypeAnnotation?.toJSON?.() ?? node.__TypeAnnotation;
5253
5438
  }
5254
5439
  // 根据 https://projectmanage.netease-official.lcap.163yun.com/dashboard/FeatureDetail?id=2737356895760128&id1=null&iterationId=null&versionid=null&tab=info
5255
5440
  // 对CallFunction节点,若其callee为部分List/Map内置函数,则修改其argument类型标注以让服务端据此插入显式的类型转换。规则如下:
@@ -5278,8 +5463,8 @@ let NaslServer = NaslServer_1 = class NaslServer {
5278
5463
  if (itemExpression) {
5279
5464
  const listTypeArgument = list.__TypeAnnotation?.typeArguments?.[0]?.toJSON?.() ?? list.__TypeAnnotation?.typeArguments?.[0];
5280
5465
  if (listTypeArgument) {
5281
- const jsonNode = jsonMap.get(item);
5282
- jsonNode.typeAnnotation = listTypeArgument;
5466
+ const newJson = jsonMap.get(item);
5467
+ newJson.typeAnnotation = listTypeArgument;
5283
5468
  }
5284
5469
  }
5285
5470
  }
@@ -5294,15 +5479,15 @@ let NaslServer = NaslServer_1 = class NaslServer {
5294
5479
  if (keyExpression) {
5295
5480
  const mapKeyTypeArgument = map.__TypeAnnotation?.typeArguments?.[0]?.toJSON?.() ?? map.__TypeAnnotation?.typeArguments?.[0];
5296
5481
  if (mapKeyTypeArgument) {
5297
- const jsonNode = jsonMap.get(key);
5298
- jsonNode.typeAnnotation = mapKeyTypeArgument;
5482
+ const newJson = jsonMap.get(key);
5483
+ newJson.typeAnnotation = mapKeyTypeArgument;
5299
5484
  }
5300
5485
  }
5301
5486
  if (valueExpression) {
5302
5487
  const mapValueTypeArgument = map.__TypeAnnotation?.typeArguments?.[1]?.toJSON?.() ?? map.__TypeAnnotation?.typeArguments?.[1];
5303
5488
  if (mapValueTypeArgument) {
5304
- const jsonNode = jsonMap.get(value);
5305
- jsonNode.typeAnnotation = mapValueTypeArgument;
5489
+ const newJson = jsonMap.get(value);
5490
+ newJson.typeAnnotation = mapValueTypeArgument;
5306
5491
  }
5307
5492
  }
5308
5493
  }
@@ -5311,218 +5496,21 @@ let NaslServer = NaslServer_1 = class NaslServer {
5311
5496
  }
5312
5497
  }
5313
5498
  // 服务端需要默认值节点有类型来判断父节点是否是日期类型
5314
- if (node instanceof concepts_1.DefaultValue && !value) {
5315
- const jsonNode = jsonMap.get(node);
5499
+ if (node instanceof concepts_1.DefaultValue && !typ) {
5500
+ const newJson = jsonMap.get(node);
5316
5501
  const parentNodeType = node.parentNode?.typeAnnotation || node.parentNode?.__TypeAnnotation;
5317
- if (parentNodeType && jsonNode) {
5318
- jsonNode.typeAnnotation = parentNodeType?.toJSON?.() ?? parentNodeType;
5502
+ if (parentNodeType && newJson) {
5503
+ newJson.typeAnnotation = parentNodeType?.toJSON?.() ?? parentNodeType;
5319
5504
  }
5320
5505
  }
5321
5506
  });
5322
5507
  }
5323
- *annotationToJsonWithGenerator(typesMap, json, jsonMap) {
5324
- const timeZoneArgumentIndexMap = new Map([
5325
- ['ToString', 1],
5326
- ['CurrDateTime', 0],
5327
- ['CurrDate', 0],
5328
- ['CurrTime', 0],
5329
- ['FormatDateTime', 2],
5330
- ['jsonSerialize', 1],
5331
- ['GetDateCount', 2],
5332
- ['GetSpecificDaysOfWeek', 3]
5333
- ]);
5334
- for (const [node, value] of typesMap) {
5335
- // 如果节点本身有类型就不去在塞一遍了
5336
- // 有值而且没有类型再去设置
5337
- // 但是Identifier 和 MemberExpression 都用标注出来的因为本身是变量,有类型也需要覆盖一下
5338
- if (value && (node instanceof concepts_1.Argument) && node.getAncestor('Connector')?.concept === 'Connector') {
5339
- const jsonNode = jsonMap.get(node);
5340
- if (jsonNode) {
5341
- jsonNode.typeAnnotation = value?.toJSON?.() ?? value;
5342
- }
5343
- }
5344
- if (value && (!node.typeAnnotation || node instanceof concepts_1.Identifier || node instanceof concepts_1.MemberExpression)) {
5345
- const jsonNode = jsonMap.get(node);
5346
- if (jsonNode) {
5347
- jsonNode.typeAnnotation = value?.toJSON?.() ?? value;
5348
- }
5349
- }
5350
- // 旧版本数据查询需要确认是匿名数据结构的 ListTotal 类型
5351
- if (node instanceof concepts_1.CallQueryComponent && !node.isAutoInfer()) {
5352
- const jsonNode = jsonMap.get(node);
5353
- jsonNode.typeAnnotation = {
5354
- concept: 'TypeAnnotation',
5355
- typeKind: 'anonymousStructure',
5356
- typeNamespace: null,
5357
- typeName: null,
5358
- typeArguments: [],
5359
- inferred: false,
5360
- ruleMap: null,
5361
- properties: [
5362
- {
5363
- concept: 'StructureProperty',
5364
- name: 'list',
5365
- label: null,
5366
- description: null,
5367
- typeAnnotation: {
5368
- concept: 'TypeAnnotation',
5369
- typeKind: 'generic',
5370
- typeNamespace: 'nasl.collection',
5371
- typeName: 'List',
5372
- typeArguments: [jsonNode.typeAnnotation],
5373
- inferred: null,
5374
- },
5375
- required: null,
5376
- defaultValue: null,
5377
- },
5378
- {
5379
- concept: 'StructureProperty',
5380
- name: 'total',
5381
- label: null,
5382
- description: null,
5383
- typeAnnotation: {
5384
- concept: 'TypeAnnotation',
5385
- typeKind: 'primitive',
5386
- typeNamespace: 'nasl.core',
5387
- typeName: 'Long',
5388
- typeArguments: null,
5389
- inferred: null,
5390
- },
5391
- required: null,
5392
- defaultValue: null,
5393
- },
5394
- ],
5395
- };
5396
- }
5397
- // 特殊处理param有类型错误的
5398
- if (node instanceof concepts_1.Param) {
5399
- // index在nasl foreach上有脏数据
5400
- if (node.parentKey === 'index' && node.parentNode instanceof concepts_1.ForEachStatement) {
5401
- const jsonNode = jsonMap.get(node);
5402
- jsonNode.typeAnnotation = concepts_1.TypeAnnotation.createPrimitive('Long').toJSON();
5403
- }
5404
- }
5405
- if (node instanceof concepts_1.Match) {
5406
- const matchExpression = node.expression;
5407
- if (matchExpression?.__TypeAnnotation?.typeKind === 'union' &&
5408
- (matchExpression instanceof concepts_1.Identifier || matchExpression instanceof concepts_1.MemberExpression)) {
5409
- const { currentSource, fileNode } = matchExpression?.getCurrentSource();
5410
- const currentCode = this.getNodeCode(fileNode, currentSource);
5411
- fileNode.sourceMap.forEach((item, itemNode) => {
5412
- const itemCode = this.getNodeCode(fileNode, item);
5413
- if (itemNode.concept === matchExpression.concept && itemCode === currentCode) {
5414
- const jsonNode = jsonMap.get(itemNode);
5415
- jsonNode.typeAnnotation = matchExpression.__TypeAnnotation;
5416
- }
5417
- });
5418
- }
5419
- }
5420
- // 特殊处理param有类型错误的
5421
- if (value && (node instanceof concepts_1.Param)) {
5422
- // index在nasl foreach上有脏数据
5423
- if (node.parentKey === 'index' && node.parentNode instanceof concepts_1.ForEachStatement) {
5424
- const jsonNode = jsonMap.get(node);
5425
- jsonNode.typeAnnotation = value?.toJSON?.() ?? value;
5426
- }
5427
- }
5428
- if (value && (node instanceof concepts_1.NewComposite) && (node.typeAnnotation?.typeKind === 'anonymousStructure' || node.typeAnnotation?.typeKind === 'generic')) {
5429
- const jsonNode = jsonMap.get(node);
5430
- jsonNode.typeAnnotation = value?.toJSON?.() ?? value;
5431
- }
5432
- // jsonSerializer 是 CallLogic,其余是 CallFunction
5433
- if (node instanceof concepts_1.CallFunction || node instanceof concepts_1.CallLogic) {
5434
- const tzArgIdx = timeZoneArgumentIndexMap.get(node.calleeName);
5435
- const args = node.arguments;
5436
- const tzArg = args ? args[tzArgIdx] : undefined;
5437
- if (tzArgIdx && tzArg?.keyword === '时区' && !isCoreDateTimeType(node.arguments[0])) {
5438
- if (!isFunctionWithFixedTimeZoneParam(node.calleeName)) {
5439
- node.arguments.pop();
5440
- }
5441
- }
5442
- /**
5443
- * 特殊处理,不想去查两次类型, 因为是从函数签名上拿类型,所以直接合并在一起,先这样
5444
- */
5445
- if (node instanceof concepts_1.CallLogic && node.__TypeArguments?.length) {
5446
- const jsonNode = jsonMap.get(node);
5447
- jsonNode.typeArguments = node.__TypeArguments.map((type) => type?.toJSON?.() ?? type);
5448
- jsonNode.typeAnnotation = node.__TypeAnnotation?.toJSON?.() ?? node.__TypeAnnotation;
5449
- }
5450
- // 根据 https://projectmanage.netease-official.lcap.163yun.com/dashboard/FeatureDetail?id=2737356895760128&id1=null&iterationId=null&versionid=null&tab=info
5451
- // 对CallFunction节点,若其callee为部分List/Map内置函数,则修改其argument类型标注以让服务端据此插入显式的类型转换。规则如下:
5452
- // - 对argument.expression.typeAnnotation 无需做修改,保持为其实际类型
5453
- // - 对argument.typeAnnotation,为根据对应Collection的泛型参数的类型填写其类型
5454
- if (node instanceof concepts_1.CallFunction) {
5455
- if (node.calleeNamespace === 'nasl.util') {
5456
- const calleeName = node.calleeName;
5457
- const listFunctionParamIndexMaps = new Map(Object.entries({
5458
- Add: { collection: 0, item: 1 },
5459
- Insert: { collection: 0, item: 2 },
5460
- Remove: { collection: 0, item: 1 },
5461
- Contains: { collection: 0, item: 1 },
5462
- }));
5463
- const mapFunctionParamIndexMaps = new Map(Object.entries({
5464
- MapPut: { collection: 0, key: 1, value: 2 },
5465
- MapGet: { collection: 0, key: 1, },
5466
- MapRemove: { collection: 0, key: 1 },
5467
- MapContains: { collection: 0, key: 1 },
5468
- }));
5469
- const listParamIndex = listFunctionParamIndexMaps.get(calleeName);
5470
- if (listParamIndex) {
5471
- const list = node.arguments[listParamIndex.collection];
5472
- const item = node.arguments[listParamIndex.item];
5473
- const itemExpression = item?.expression;
5474
- if (itemExpression) {
5475
- const listTypeArgument = list.__TypeAnnotation?.typeArguments?.[0]?.toJSON?.() ?? list.__TypeAnnotation?.typeArguments?.[0];
5476
- if (listTypeArgument) {
5477
- const jsonNode = jsonMap.get(item);
5478
- jsonNode.typeAnnotation = listTypeArgument;
5479
- }
5480
- }
5481
- }
5482
- else {
5483
- const mapParamIndex = mapFunctionParamIndexMaps.get(calleeName);
5484
- if (mapParamIndex) {
5485
- const map = node.arguments[mapParamIndex.collection];
5486
- const key = node.arguments[mapParamIndex.key];
5487
- const value = node.arguments[mapParamIndex.value];
5488
- const keyExpression = key?.expression;
5489
- const valueExpression = value?.expression;
5490
- if (keyExpression) {
5491
- const mapKeyTypeArgument = map.__TypeAnnotation?.typeArguments?.[0]?.toJSON?.() ?? map.__TypeAnnotation?.typeArguments?.[0];
5492
- if (mapKeyTypeArgument) {
5493
- const jsonNode = jsonMap.get(key);
5494
- jsonNode.typeAnnotation = mapKeyTypeArgument;
5495
- }
5496
- }
5497
- if (valueExpression) {
5498
- const mapValueTypeArgument = map.__TypeAnnotation?.typeArguments?.[1]?.toJSON?.() ?? map.__TypeAnnotation?.typeArguments?.[1];
5499
- if (mapValueTypeArgument) {
5500
- const jsonNode = jsonMap.get(value);
5501
- jsonNode.typeAnnotation = mapValueTypeArgument;
5502
- }
5503
- }
5504
- }
5505
- }
5506
- }
5507
- }
5508
- }
5509
- // 服务端需要默认值节点有类型来判断父节点是否是日期类型
5510
- if (node instanceof concepts_1.DefaultValue && !value) {
5511
- const jsonNode = jsonMap.get(node);
5512
- const parentNodeType = node.parentNode?.typeAnnotation || node.parentNode?.__TypeAnnotation;
5513
- if (parentNodeType && jsonNode) {
5514
- jsonNode.typeAnnotation = parentNodeType?.toJSON?.() ?? parentNodeType;
5515
- }
5516
- }
5517
- yield;
5518
- }
5519
- }
5520
5508
  /**
5521
5509
  * 获取getArgument的参数位的类型
5522
5510
  * 如果内部表达式的,就用表达式的,如果没有就试试用默认值的
5523
5511
  * 获取logic的默认值和原来Arg的类型和默认值对应
5524
5512
  */
5525
- *getArgumentTypeAnnotationWithGenerator(node, QuickInfoNodes, types) {
5513
+ *getArgumentTypeAnnotationWithGenerator(node, types) {
5526
5514
  // 直接复用内部expression的type类型
5527
5515
  if (node.parentNode instanceof concepts_1.CallLogic &&
5528
5516
  node.parentNode.calleeNamespace?.includes('entities') &&
@@ -6093,7 +6081,6 @@ let NaslServer = NaslServer_1 = class NaslServer {
6093
6081
  }
6094
6082
  return;
6095
6083
  }
6096
- this.logger.time('TS 文件变更');
6097
6084
  const fileTsPath = fileNode.getEmbeddedFilePath();
6098
6085
  /**
6099
6086
  * 由于业务组件的声明位置会动态变更
@@ -6106,9 +6093,48 @@ let NaslServer = NaslServer_1 = class NaslServer {
6106
6093
  }
6107
6094
  // 递增ts文件版本号
6108
6095
  this.diagnosticManager.incrementVersionByFilePath(fileTsPath);
6109
- const result = await utils.timeSlicingWithGenerator(fileNode.toEmbeddedTSFile());
6096
+ // @ts-ignore
6097
+ const fileNodeRaw = this.toRaw(fileNode);
6098
+ // @ts-ignore
6099
+ const targetNodeRaw = this.toRaw(targetNode);
6100
+ if (targetNodeRaw) {
6101
+ if (['BindAttribute', 'BindDirective', 'BindStyle'].includes(targetNodeRaw.concept)) {
6102
+ if (!targetNodeRaw.expression) {
6103
+ utils.isDebugMode && console.time('remove dirty records');
6104
+ const usefulRecords = this.diagnosticManager.records.filter(r => this.semData.dirtyViewId === r.id);
6105
+ usefulRecords.forEach((r, idx) => {
6106
+ const thisNodePath = targetNodeRaw.nodePath;
6107
+ r.semanticDiagnostics.forEach((diag, idx) => {
6108
+ // @ts-ignore
6109
+ if (this.toRaw(diag.node)?.nodePath.includes(thisNodePath)) {
6110
+ r.semanticDiagnostics.splice(idx, 1);
6111
+ }
6112
+ });
6113
+ });
6114
+ utils.isDebugMode && console.timeEnd('remove dirty records');
6115
+ // 跳过 ts 和错误诊断
6116
+ return;
6117
+ }
6118
+ }
6119
+ }
6120
+ const viewId = targetNodeRaw.getAncestorRaw('View')?.id;
6121
+ if (viewId) {
6122
+ this.semData.dirtyViewId = viewId;
6123
+ }
6124
+ this.logger.time('TS 文件变更');
6125
+ this.isFirstScreen = true; // getter 会看 naslServer.isFirstScreen
6126
+ this.semData.redirectSlowGetters(fileNodeRaw.getAncestorRaw('App'), this.semData.varScopeCtx);
6127
+ utils.isDebugMode && console.time('Update Semantic Context');
6128
+ await utils.timeSlicingWithGenerator(this.semData.updateSemanticCtxAsPer(fileNodeRaw));
6129
+ utils.isDebugMode && console.timeEnd('Update Semantic Context');
6130
+ utils.isDebugMode && console.time('TS File Update Core Time');
6131
+ const result = await utils.timeSlicingWithGenerator(fileNodeRaw.toEmbeddedTSFile());
6132
+ utils.isDebugMode && console.timeEnd('TS File Update Core Time');
6133
+ this.isFirstScreen = false;
6134
+ this.semData.recoverSlowGetters();
6135
+ fileNodeRaw.concept === 'Logic' && this.semData.updateDirtyIndRetDeps(fileNodeRaw);
6110
6136
  this.logger.timeEnd('TS 文件变更');
6111
- this.logger.info('TS 文件变更', fileTsPath);
6137
+ utils.isDebugMode && this.logger.info('TS 文件变更', fileTsPath);
6112
6138
  // 当前操作的节点
6113
6139
  // 如果当前没有生成tsFile
6114
6140
  if (!result.sourceMap) {
@@ -6220,6 +6246,10 @@ let NaslServer = NaslServer_1 = class NaslServer {
6220
6246
  })));
6221
6247
  await this.getDiagnosticRecordsAndPushAll();
6222
6248
  }
6249
+ toRaw(nd) {
6250
+ // @ts-ignore
6251
+ return nd.__v_raw ?? nd;
6252
+ }
6223
6253
  };
6224
6254
  exports.NaslServer = NaslServer;
6225
6255
  __decorate([
@@ -6228,6 +6258,9 @@ __decorate([
6228
6258
  __decorate([
6229
6259
  (0, decorators_1.withQueueExecute)('annotation')
6230
6260
  ], NaslServer.prototype, "getNaslAnnotatedJSON", null);
6261
+ __decorate([
6262
+ (0, decorators_1.withQueueExecute)('annotation')
6263
+ ], NaslServer.prototype, "fastGetNaslAnnotatedJSON", null);
6231
6264
  exports.NaslServer = NaslServer = NaslServer_1 = __decorate([
6232
6265
  nasl_sentry_1.sentryMonitorNaslServer
6233
6266
  ], NaslServer);