@lcap/nasl-language-server-core 4.1.0-rc.7 → 4.1.0-rc.9

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 (107) hide show
  1. package/out/checker.d.ts +1 -1
  2. package/out/checker.d.ts.map +1 -1
  3. package/out/checker.js +87 -121
  4. package/out/checker.js.map +1 -1
  5. package/out/index.d.ts +2 -2
  6. package/out/index.d.ts.map +1 -1
  7. package/out/index.js +4 -3
  8. package/out/index.js.map +1 -1
  9. package/out/reference-manager/builtin-q-name.d.ts +1 -2
  10. package/out/reference-manager/builtin-q-name.d.ts.map +1 -1
  11. package/out/reference-manager/builtin-q-name.js +1 -5
  12. package/out/reference-manager/builtin-q-name.js.map +1 -1
  13. package/out/reference-manager/collect-q-name.d.ts.map +1 -1
  14. package/out/reference-manager/collect-q-name.js +8 -7
  15. package/out/reference-manager/collect-q-name.js.map +1 -1
  16. package/out/reference-manager/helper.d.ts +1 -1
  17. package/out/reference-manager/helper.d.ts.map +1 -1
  18. package/out/reference-manager/helper.js +11 -1
  19. package/out/reference-manager/helper.js.map +1 -1
  20. package/out/reference-manager/reference-manager.d.ts +64 -7
  21. package/out/reference-manager/reference-manager.d.ts.map +1 -1
  22. package/out/reference-manager/reference-manager.js +198 -56
  23. package/out/reference-manager/reference-manager.js.map +1 -1
  24. package/out/reference-manager/remove-q-name.js +8 -8
  25. package/out/reference-manager/remove-q-name.js.map +1 -1
  26. package/out/reference-manager/rename-q-name.d.ts.map +1 -1
  27. package/out/reference-manager/rename-q-name.js +6 -6
  28. package/out/reference-manager/rename-q-name.js.map +1 -1
  29. package/out/reference-manager/update-nasl-fragment.d.ts +0 -1
  30. package/out/reference-manager/update-nasl-fragment.d.ts.map +1 -1
  31. package/out/reference-manager/update-nasl-fragment.js +2 -33
  32. package/out/reference-manager/update-nasl-fragment.js.map +1 -1
  33. package/out/typer/component-def-manager/utils.js +1 -1
  34. package/out/typer/component-def-manager/utils.js.map +1 -1
  35. package/out/typer/dispatch-all.d.ts +10 -3
  36. package/out/typer/dispatch-all.d.ts.map +1 -1
  37. package/out/typer/dispatch-all.js +44 -7
  38. package/out/typer/dispatch-all.js.map +1 -1
  39. package/out/typer/dispatch-call.d.ts +14 -0
  40. package/out/typer/dispatch-call.d.ts.map +1 -0
  41. package/out/typer/dispatch-call.js +637 -0
  42. package/out/typer/dispatch-call.js.map +1 -0
  43. package/out/typer/dispatch-def.d.ts +9 -3
  44. package/out/typer/dispatch-def.d.ts.map +1 -1
  45. package/out/typer/dispatch-def.js +101 -91
  46. package/out/typer/dispatch-def.js.map +1 -1
  47. package/out/typer/dispatch-expr.d.ts +3 -15
  48. package/out/typer/dispatch-expr.d.ts.map +1 -1
  49. package/out/typer/dispatch-expr.js +94 -677
  50. package/out/typer/dispatch-expr.js.map +1 -1
  51. package/out/typer/dispatch-process.d.ts.map +1 -1
  52. package/out/typer/dispatch-process.js +28 -11
  53. package/out/typer/dispatch-process.js.map +1 -1
  54. package/out/typer/dispatch-stmt.d.ts.map +1 -1
  55. package/out/typer/dispatch-stmt.js +39 -38
  56. package/out/typer/dispatch-stmt.js.map +1 -1
  57. package/out/typer/dispatch-view.d.ts.map +1 -1
  58. package/out/typer/dispatch-view.js +22 -16
  59. package/out/typer/dispatch-view.js.map +1 -1
  60. package/out/typer/get-oql-files.d.ts +13 -0
  61. package/out/typer/get-oql-files.d.ts.map +1 -0
  62. package/out/typer/get-oql-files.js +136 -0
  63. package/out/typer/get-oql-files.js.map +1 -0
  64. package/out/typer/helper.d.ts +2 -2
  65. package/out/typer/helper.d.ts.map +1 -1
  66. package/out/typer/helper.js +5 -5
  67. package/out/typer/helper.js.map +1 -1
  68. package/out/typer/incremental-update.d.ts +0 -12
  69. package/out/typer/incremental-update.d.ts.map +1 -1
  70. package/out/typer/incremental-update.js +99 -193
  71. package/out/typer/incremental-update.js.map +1 -1
  72. package/out/typer/index.d.ts +6 -4
  73. package/out/typer/index.d.ts.map +1 -1
  74. package/out/typer/index.js +9 -10
  75. package/out/typer/index.js.map +1 -1
  76. package/out/typer/subster.d.ts +0 -1
  77. package/out/typer/subster.d.ts.map +1 -1
  78. package/out/typer/subster.js +3 -23
  79. package/out/typer/subster.js.map +1 -1
  80. package/out/typer/topo-sort.d.ts +4 -4
  81. package/out/typer/topo-sort.d.ts.map +1 -1
  82. package/out/typer/topo-sort.js +5 -1
  83. package/out/typer/topo-sort.js.map +1 -1
  84. package/out/typer/type-manager.d.ts +2 -2
  85. package/out/typer/type-manager.d.ts.map +1 -1
  86. package/out/typer/type-manager.js +32 -9
  87. package/out/typer/type-manager.js.map +1 -1
  88. package/out/typer/type-predicate.d.ts +6 -1
  89. package/out/typer/type-predicate.d.ts.map +1 -1
  90. package/out/typer/type-predicate.js +22 -4
  91. package/out/typer/type-predicate.js.map +1 -1
  92. package/out/typer/typer.d.ts +27 -6
  93. package/out/typer/typer.d.ts.map +1 -1
  94. package/out/typer/typer.js +69 -18
  95. package/out/typer/typer.js.map +1 -1
  96. package/out/typer/unifier.d.ts +1 -1
  97. package/out/typer/unifier.d.ts.map +1 -1
  98. package/out/typer/unifier.js +48 -69
  99. package/out/typer/unifier.js.map +1 -1
  100. package/out/utils/string.d.ts.map +1 -1
  101. package/out/utils/string.js +1 -0
  102. package/out/utils/string.js.map +1 -1
  103. package/package.json +5 -5
  104. package/out/typer/nasl-predicate.d.ts +0 -8
  105. package/out/typer/nasl-predicate.d.ts.map +0 -1
  106. package/out/typer/nasl-predicate.js +0 -25
  107. package/out/typer/nasl-predicate.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRightByLine = exports.removeErrTys = exports.tpEntityLogic = exports.tpMatch = exports.tpSolvingExpr = exports.extractNameTyPair = exports.tpCallConnector = exports.tpCallMicroserviceInterface = exports.tpCallAuthInterface = exports.tpCallInterface = exports.tpCallFunction = exports.changeArgTyToParamTy = exports.determineCallLogicFnTy = exports.tpCallLogic = exports.dispatchExpr = void 0;
3
+ exports.getRightByLine = exports.tpMatch = exports.tpSolvingExpr = exports.extractNameTyPair = exports.tpSubLogic = exports.tpAnonymousFunction = exports.dispatchExpr = void 0;
4
4
  const nasl_concepts_1 = require("@lcap/nasl-concepts");
5
5
  const fp_macros_1 = require("../utils/fp-macros");
6
6
  const sem_diag_1 = require("./sem-diag");
@@ -11,7 +11,6 @@ const dispatch_stmt_2 = require("./dispatch-stmt");
11
11
  const dispatch_def_1 = require("./dispatch-def");
12
12
  const get_q_name_1 = require("../reference-manager/get-q-name");
13
13
  const reference_manager_1 = require("../reference-manager/reference-manager");
14
- const symbol_type_1 = require("../reference-manager/symbol-type");
15
14
  const string_1 = require("../utils/string");
16
15
  const assertion_1 = require("../utils/assertion");
17
16
  const service_1 = require("@lcap/nasl-concepts/service");
@@ -19,15 +18,13 @@ const asserts_1 = require("@lcap/nasl-concepts/asserts");
19
18
  const type_manager_1 = require("./type-manager");
20
19
  const type_predicate_1 = require("./type-predicate");
21
20
  const type_predicate_2 = require("./type-predicate");
22
- const dispatch_process_1 = require("./dispatch-process");
23
21
  const dispatch_view_1 = require("./dispatch-view");
24
22
  const subster_2 = require("./subster");
25
- const parseTsClassType_1 = require("../utils/parseTsClassType");
26
23
  const error_boundary_1 = require("../utils/error-boundary");
27
24
  const types_1 = require("../utils/types");
28
25
  const type_operator_1 = require("../utils/type-operator");
29
26
  const nasl_type_manipulation_1 = require("../utils/nasl-type-manipulation");
30
- const overload_helper_1 = require("./overload-helper");
27
+ const dispatch_call_1 = require("./dispatch-call");
31
28
  // speed consideration
32
29
  function dispatchExpr(env, nd, tgtTy) {
33
30
  if (!nd) {
@@ -46,15 +43,16 @@ function dispatchExpr(env, nd, tgtTy) {
46
43
  case 'NullLiteral': return tpNullLiteral(env, nd, tgtTy);
47
44
  case 'Function': return tpFunction(env, nd, tgtTy); // 历史兼容
48
45
  case 'DefaultValue': return tpDefaultValue(env, nd, tgtTy);
49
- case 'CallLogic': return tpCallLogic(env, nd, tgtTy);
50
- case 'CallFunction': return tpCallFunction(env, nd, tgtTy);
46
+ case 'CallLogic': return (0, dispatch_call_1.tpCallLogic)(env, nd, tgtTy);
47
+ case 'CallFunction': return (0, dispatch_call_1.tpCallFunction)(env, nd, tgtTy);
51
48
  case 'CallEvent': return (0, dispatch_view_1.tpCallEvent)(env, nd, tgtTy);
52
- case 'CallInterface': return tpCallInterface(env, nd, tgtTy);
53
- case 'CallMicroserviceInterface': return (0, exports.tpCallMicroserviceInterface)(env, nd, tgtTy);
54
- case 'CallAuthInterface': return (0, exports.tpCallAuthInterface)(env, nd, tgtTy);
49
+ case 'CallInterface':
50
+ case 'CallAuthInterface':
51
+ case 'CallMicroserviceInterface':
52
+ case 'CallGatewayInterface': return (0, dispatch_call_1.tpCallInterface)(env, nd, tgtTy);
55
53
  case 'CallQueryComponent': return tpCallQueryComponent(env, nd, tgtTy);
56
54
  // @ts-ignore
57
- case 'CallConnector': return (0, exports.tpCallConnector)(env, nd, tgtTy);
55
+ case 'CallConnector': return (0, dispatch_call_1.tpCallLogic)(env, nd, tgtTy);
58
56
  case 'Argument': return tpArgument(env, nd, tgtTy);
59
57
  case 'ValidationRule': return (0, dispatch_view_1.tpViewValidationRule)(env, nd);
60
58
  case 'NewComposite': return tpNewComposite(env, nd, tgtTy);
@@ -62,8 +60,8 @@ function dispatchExpr(env, nd, tgtTy) {
62
60
  case 'NewMap': return tpNewMap(env, nd, tgtTy);
63
61
  case 'Match': return tpMatch(env, nd, tgtTy);
64
62
  case 'StringInterpolation': return tpStringInterpolation(env, nd, tgtTy);
65
- case 'AnonymousFunction': return tpAnonymousFunction(env, nd, tgtTy);
66
- case 'SubLogic': return tpSubLogic(env, nd, tgtTy);
63
+ case 'AnonymousFunction': return (0, exports.tpAnonymousFunction)(env, nd, tgtTy);
64
+ case 'SubLogic': return (0, exports.tpSubLogic)(env, nd, tgtTy);
67
65
  case 'Unparsed': return tpUnparsed(env, nd, tgtTy);
68
66
  case 'QueryFieldExpression': return fakeTpQueryFieldExpression(env, nd, tgtTy);
69
67
  case 'Paginate': return tpPaginate(env, nd, tgtTy);
@@ -155,7 +153,7 @@ function tpNumericLiteral(env, nd, tgtTy) {
155
153
  function tpStringInterpolation(env, nd, tgtTy) {
156
154
  nd.expressions.forEach((expr) => {
157
155
  // HACK: 动态拖入一个表达式的时候,在 expressions 数组中是 proxied
158
- return dispatchExpr(env, toRaw(expr), undefined);
156
+ return dispatchExpr(env, (0, dispatch_stmt_1.toRaw)(expr), undefined);
159
157
  });
160
158
  env.setType(nd, type_manager_1.naslStringTy);
161
159
  env.unifier.unify(type_manager_1.naslStringTy, tgtTy);
@@ -637,7 +635,7 @@ const tpBinaryOrderExpr = (env, nd, tgtTy) => {
637
635
  if (!ty) {
638
636
  return false;
639
637
  }
640
- if ((0, type_predicate_2.isPrimitiveTy)(ty) && orderableTyNames.includes(ty.typeName)) {
638
+ if ((0, type_predicate_2.isPrimitiveTy)(ty) && orderableTyNames.includes(ty.typeName) || (0, type_predicate_2.isNullTy)(ty) || (0, type_predicate_2.isAnyTy)(ty)) {
641
639
  return true;
642
640
  }
643
641
  // 支持Union类型:如果所有成员都是可排序类型,则Union类型也是可排序的
@@ -688,453 +686,7 @@ function tpUnaryExpression(env, nd, tgtTy) {
688
686
  return env.getRawType(nd);
689
687
  }
690
688
  }
691
- function isEntityLogic(nsp) {
692
- return nsp.startsWith('app.dataSources.') && nsp.endsWith('logics') && /\.entities\./.test(nsp);
693
- }
694
- function isLoggingLogic(nsp) {
695
- return nsp === 'nasl.logging';
696
- }
697
- function tpCallLogic(env, nd, tgtTy) {
698
- if (!nd.calleeName) {
699
- return undefined;
700
- }
701
- // 特殊处理咯 ad hoc treatment for entity logics
702
- if (isEntityLogic(nd.calleeNamespace)) {
703
- return tpEntityLogic(env, nd, tgtTy);
704
- }
705
- // 特殊处理咯,你自己看看你的 Call 的 NASL 和定义能对得上一毫米吗?
706
- if (isLoggingLogic(nd.calleeNamespace)) {
707
- // Use a different approach to avoid the parameter issues
708
- for (const arg of nd.arguments) {
709
- dispatchExpr(env, arg, type_manager_1.naslAnyTy);
710
- }
711
- env.setType(nd, type_manager_1.naslVoidTy);
712
- return env.getRawType(nd);
713
- }
714
- let def;
715
- if (nd.calleeNamespace !== 'nasl.util') {
716
- def = env.resolveRef(nd);
717
- }
718
- else {
719
- // 'nasl.util' 时 是 json 序列化
720
- def = env.quickGetLibDef(nd, nd.calleeName, undefined);
721
- }
722
- // 处理调用处的验证规则
723
- if (nd.validation?.rules && nd.validation.rules.length > 0 && def) {
724
- def.params.forEach(param => (0, dispatch_def_1.dispatchDef)(env, param));
725
- nd.validation?.rules?.forEach(rule => (0, dispatch_stmt_1.dispatchStmt)(env, rule));
726
- def.params.forEach(env.removeVar);
727
- }
728
- if ((0, symbol_type_1.isProcessLogicCall)(nd.calleeNamespace) && (0, symbol_type_1.isSpecialProcessLogic)(nd.calleeName)) {
729
- return (0, dispatch_process_1.tpSpecialProcessLogicCall)(env, nd, tgtTy);
730
- }
731
- // 余下的流程逻辑比较正常,就走正常的 CallLogic 处理流程好了
732
- let fnTy = determineCallLogicFnTy(env, nd, def);
733
- if (!fnTy) {
734
- // TODO fnTy 可能为undefined 或 typeKind!=function, 需要考虑
735
- env.addError(`无法找到逻辑 ${nd.calleeName}`);
736
- return;
737
- }
738
- if (fnTy.typeParams?.length) {
739
- fnTy = renameAndMakePartialTyApp(env, fnTy, nd);
740
- }
741
- // typing arguments
742
- for (const [idx, parTy] of fnTy.typeArguments.entries()) {
743
- let param = def ? def.params?.[idx] : undefined;
744
- // TODO: json序列化等没有 def,导致 param 直接 undefined
745
- const arg = nd.arguments[idx];
746
- if (!arg) {
747
- env.setType(nd, type_manager_1.naslAnyTy);
748
- continue;
749
- }
750
- if (arg?.expression) {
751
- dispatchExpr(env, arg, parTy);
752
- changeArgTyToParamTy(env, arg, parTy);
753
- }
754
- else if (param) {
755
- if (param.optional || parTy.optional) { // 组件逻辑等现在没有 def,用 type 判断
756
- env.setType(arg, parTy);
757
- }
758
- else if (param.defaultValue?.expression) {
759
- env.setType(arg, parTy);
760
- }
761
- else {
762
- // 报错:泛型逻辑调用,最后的 callInfo 里有 type variables,会被判定为 unresolved,目前不检查 arg 会缺少报错
763
- // env.addError(`调用逻辑:参数不能为空`, env.getCurFileNode(), arg);
764
- env.setType(arg, type_manager_1.naslAnyTy);
765
- }
766
- }
767
- else {
768
- // 报错
769
- env.setType(arg, type_manager_1.naslAnyTy);
770
- }
771
- }
772
- let finalRetTy = fnTy.returnType?.[0];
773
- // CallConnector 不支持 handleError 错误处理参数
774
- if (nd.concept !== 'CallConnector') {
775
- if (nd.handleError === true) {
776
- dispatchExpr(env, nd.errorMessage, undefined);
777
- }
778
- else {
779
- // 做了手动处理 Error 需求后,需要 remove Error types from return types
780
- finalRetTy = (0, exports.removeErrTys)(env, nd, fnTy?.returnType?.[0]);
781
- }
782
- }
783
- env.unifier.unify(finalRetTy, tgtTy);
784
- env.setType(nd, finalRetTy);
785
- // 给 checker 报错用,都给吧,CallLogic 也有要处理 Error | T 返回类型的复杂情形,checker 直接拿结果就行不用重复处理
786
- // TODO: 前端的部分组件逻辑好像指飞了(env.resoleRef 和 env.resolvedCallInfo 结果不一样)……先用 !env.isView 判断一下
787
- if (!env.isView || nd.calleeNamespace === 'nasl.util') { // json 序列化 - similarly add param info for nasl.util
788
- const callInfo = (0, type_manager_1.createFunctionDef)(fnTy.typeArguments, finalRetTy, def, fnTy.typeParams);
789
- env.resolvedCallInfo.set(nd, callInfo);
790
- }
791
- if (fnTy.typeParams?.length) {
792
- env.addPostCheckTask(nd, (e, pSubst) => {
793
- // 写入 __TypeArguments 字段,调用泛型依赖库时,代码生成要用。
794
- const typeArgs = fnTy.typeParams
795
- ?.map((x) => {
796
- return e.getType(pSubst(x));
797
- })
798
- .filter(types_1.isNotNil) ?? [];
799
- // 写入来自:_getQuickInfoNodesTypeMapWithGenerator
800
- nd.__TypeArguments = typeArgs;
801
- });
802
- }
803
- return finalRetTy;
804
- }
805
- exports.tpCallLogic = tpCallLogic;
806
- function determineCallLogicFnTy(env, nd, def) {
807
- if (def && (0, service_1.isCallableNaslLogic)(def)) {
808
- // TODO zzr 需要用个 cache 加快速度吗
809
- return env.getRawType(def);
810
- }
811
- else {
812
- const qName = (0, get_q_name_1.getTokenQualifiedName)(nd);
813
- if (!qName) {
814
- return undefined;
815
- }
816
- const placeholderFnTy = createAndSetForwardReferencePlaceholder(env, nd);
817
- // @ts-expect-error
818
- if (def?.concept === 'TypeAnnotation') {
819
- // 令根据根据本次 Call 计算得出的类型为 placeholderFnTy
820
- // 所有出现 placeholderFnTy 的地方,都可以被 def 替换,因此 def 为 placeholderFnTy 的子类型
821
- env.unifier.unify(def, placeholderFnTy);
822
- }
823
- else {
824
- if (env.isDebugMode) {
825
- // FIXME wudengke 修复use before def的问题,debug模式下先报出来。
826
- env.addDiagnosticsFor(`[DEBUG] determineCallLogicFnTy: 可能出现了use before def。 ${qName}`, nd);
827
- }
828
- }
829
- return placeholderFnTy;
830
- }
831
- }
832
- exports.determineCallLogicFnTy = determineCallLogicFnTy;
833
- function changeArgTyToParamTy(env, nd, parTy) {
834
- // 初始时, nd.type === nd.expression.type
835
- // FIXME: 例如后端需要 argument.type 与 argument.expression.type 不一样做 long -> decimal 的强制转换
836
- // 这里有个问题,JSON 序列化不是 CallFunction 是 CallLogic,所以会走到这里
837
- // 但是它 的 paramTy 是 NASL 不存在的类型 Any,炸裂还是得用 argTy
838
- if (!(0, type_predicate_2.isAnyTy)(parTy)) {
839
- env.setType(nd, parTy);
840
- }
841
- // Magic!
842
- nd.paramTypeAnnotation = parTy;
843
- }
844
- exports.changeArgTyToParamTy = changeArgTyToParamTy;
845
- function renameAndMakePartialTyApp(env, fnTy, nd) {
846
- // 先 rename bound type variables
847
- if ((0, type_predicate_1.isUnResolvedTy)(fnTy)) {
848
- fnTy = (0, type_manager_1.copyTyAnn)(fnTy);
849
- env.unifier.inPlaceRenameTy(fnTy);
850
- }
851
- // 再做 type arguments partial application
852
- // 用户选定部分 type params,这一块 Java 依赖库好像还有特殊处理,估计之后要大改
853
- // 事实证明 Add 这种函数 nd.typeArguments 是 null 不是空数组 []
854
- if (nd.typeArguments && nd.typeArguments.length > 0) {
855
- if (fnTy.typeParams) {
856
- const subst = new Map();
857
- nd.typeArguments.forEach((ty, idx) => {
858
- if (ty.typeName && ty.typeKind) {
859
- fnTy.typeParams[idx] && subst.set(fnTy.typeParams[idx].typeName, ty);
860
- }
861
- });
862
- fnTy.typeParams = fnTy.typeParams.map((0, subster_1.substTyAnn)(env, subst));
863
- fnTy = (0, subster_1.substTyAnn)(env, subst)(fnTy);
864
- }
865
- }
866
- return fnTy;
867
- }
868
- function tpCallFunction(env, nd, tgtTy) {
869
- let calleeName = nd.calleeName;
870
- if (!calleeName) {
871
- env.addError('没有函数名,无法进行调用');
872
- return undefined;
873
- }
874
- // 处理 enum 函数
875
- if (parseTsClassType_1.enumBuiltinFns.includes(calleeName)) {
876
- return handleEnumFn(env, nd, tgtTy);
877
- }
878
- // 前端全局类型推导 + 重载函数几乎无法做任何类型推导,只能做后置验证。后端可以推导,但简单起见,不区分前后端了。
879
- // 总结:全局类型推导 + 重载 = 灾难
880
- if (parseTsClassType_1.overloadedFns.includes(calleeName)) {
881
- return handleOverloadedFunction(env, nd, tgtTy, calleeName);
882
- }
883
- const fnDef = env.quickGetLibDef(nd, calleeName, env.ctxCQC?.dataSourceSqlType);
884
- let fnTy = fnDef?.__TypeAnnotation;
885
- if (!fnTy) {
886
- env.addError('无法找到函数定义(类型)');
887
- return;
888
- }
889
- if (fnTy.typeParams?.length) {
890
- fnTy = renameAndMakePartialTyApp(env, fnTy, nd);
891
- }
892
- for (const [idx, parTy] of fnTy.typeArguments.entries()) {
893
- if (parTy.spread) { // 抽取 Array<T> 中的 T
894
- const elemTy = parTy.typeArguments[0];
895
- // 余下的一并处理
896
- for (let i = idx; i < nd.arguments.length; ++i) {
897
- /**
898
- * ListSort 只能特殊处理了。
899
- * nasl.util 里定义为 { asc: Boolean, by: Long | Decimal | ... } 的话会有匿名数据类型不匹配报错(invariance)
900
- * 如果定义为泛型 T2 extends Long | Decimal | ... 且 { asc: Boolean, by: T2 } 的话 T2 不支持实例化成 Union
901
- * (页面是全局求解,暂时不好区分 T2 的约束是来自多个赋值还是一个赋值,如果是多个则报错,如果是一个则使用 Union 作为解这种复杂的机制
902
- */
903
- if (calleeName === 'ListSort' || calleeName === 'ListSortAsync') {
904
- const expr = nd.arguments[i].expression;
905
- // 抠出函数类型的参数和返回类型
906
- if (!(0, type_predicate_2.isFuncTy)(elemTy)) {
907
- continue; // 干不了了
908
- }
909
- const parTy = elemTy.typeArguments?.[0];
910
- const retTy = elemTy.returnType?.[0];
911
- // 留给 checker.ts 去做后置检查吧
912
- if (expr?.concept === 'AnonymousFunction') {
913
- tpAnonymousFunction(env, expr, (0, type_manager_1.createFnTyFromTyAnns)([parTy], undefined), true);
914
- // dispatchExpr(env, expr.params[0], parTy);
915
- // dispatchExpr(env, expr.body, retTy);
916
- }
917
- else if (expr?.concept === 'SubLogic') {
918
- tpSubLogic(env, expr, (0, type_manager_1.createFnTyFromTyAnns)([parTy], undefined), true);
919
- }
920
- }
921
- else {
922
- // 正常处理
923
- dispatchExpr(env, nd.arguments[i], elemTy);
924
- }
925
- }
926
- }
927
- else {
928
- dispatchExpr(env, nd.arguments[idx], parTy);
929
- }
930
- }
931
- const finalRetTy = fnTy.returnType?.[0] ?? tgtTy;
932
- env.unifier.unify(finalRetTy, tgtTy);
933
- // TODO:处理可选参数必填选填问题
934
- env.setType(nd, finalRetTy); // 似乎不可能为空
935
- const callInfo = (0, type_manager_1.createFunctionDef)(fnTy.typeArguments, finalRetTy, fnDef, // 内置函数
936
- fnTy.typeParams);
937
- env.resolvedCallInfo.set(nd, callInfo);
938
- return finalRetTy;
939
- function handleEnumFn(env, nd, tgtTy) {
940
- const createAnonymousRetTy = (ty) => (0, type_manager_1.createAnonymousTyAnn)(['text', 'value'], [type_manager_1.naslStringTy, ty]);
941
- let res = undefined;
942
- let tyParam = undefined; // <T>. 但是是实例化后的
943
- let paramTy = undefined; // (T)
944
- let def = env.resolveRef(nd);
945
- switch (nd.calleeName) {
946
- // 暂时不合并代码了,也不是特别长
947
- case 'EnumToList': {
948
- if (!nd.typeArguments?.[0]) {
949
- // 报错 缺参数
950
- return;
951
- }
952
- tyParam = nd.typeArguments[0];
953
- const enumDef = env.resolveRef(nd.typeArguments[0]);
954
- if (enumDef?.concept === 'Enum') {
955
- const ty = enumDef.valueType ?? type_manager_1.naslStringTy; // FIXME:还能是空的,服了
956
- res = (0, type_manager_1.createListTyAnn)(createAnonymousRetTy(ty));
957
- }
958
- else {
959
- env.addError((0, sem_diag_1.mkIncompatibleTyErr)(env, tyParam || type_manager_1.naslAnyTy, '枚举'), env.getCurFileNode(), nd);
960
- }
961
- break;
962
- }
963
- case 'ToEnumItem': {
964
- if (!nd.typeArguments?.[0]) {
965
- // 报错 缺参数
966
- return;
967
- }
968
- tyParam = nd.typeArguments[0];
969
- const enumDef = env.resolveRef(tyParam);
970
- if (enumDef?.concept === 'Enum') {
971
- const exprTy = dispatchExpr(env, nd.arguments[0], enumDef.valueType ?? type_manager_1.naslStringTy);
972
- res = env.getRawType(enumDef);
973
- paramTy = exprTy;
974
- }
975
- else {
976
- env.addError((0, sem_diag_1.mkIncompatibleTyErr)(env, tyParam || type_manager_1.naslAnyTy, '枚举'), env.getCurFileNode(), nd);
977
- }
978
- break;
979
- }
980
- case 'EnumItemToStructure': {
981
- if (!nd.arguments?.[0]) {
982
- // 报错 缺参数
983
- return;
984
- }
985
- const exprTy = dispatchExpr(env, nd.arguments[0], undefined);
986
- if (!exprTy) {
987
- return;
988
- }
989
- paramTy = exprTy;
990
- const enumValueTy = (0, type_operator_1.createValueTypeForAssumedEnumTy)(exprTy);
991
- const postChk = (fileNode, severity, exprTy) => (env, pSubst) => {
992
- const ty = (0, subster_1.normalizeWithSubst)(env, pSubst, exprTy);
993
- // 断言: 它是枚举类型
994
- if (!(0, type_predicate_1.isEnumTy)(ty)) {
995
- const errMsg = (0, sem_diag_1.mkIncompatibleTyErr)(env, ty || type_manager_1.naslAnyTy, '枚举');
996
- env.addError(errMsg, fileNode, nd, severity);
997
- }
998
- };
999
- env.addPostCheckTask(env.errBoundary, postChk(env.getCurFileNode(), env.errSeverity, exprTy));
1000
- res = createAnonymousRetTy(enumValueTy);
1001
- break;
1002
- }
1003
- case 'EnumItemToText': {
1004
- const exprTy = dispatchExpr(env, nd.arguments[0], undefined);
1005
- // 如果不是枚举类型就报错,稍后建立 List、Map、Enums 等通用检测机制
1006
- // FIXME zzr exprTy可能包含类型变元,此时无法立刻判断求解
1007
- paramTy = exprTy;
1008
- res = type_manager_1.naslStringTy;
1009
- const postChk = (fileNode, severity, exprTy) => (env, pSubst) => {
1010
- const ty = (0, subster_1.normalizeWithSubst)(env, pSubst, exprTy);
1011
- if (!(0, type_predicate_1.isEnumTy)(ty)) {
1012
- const errMsg = (0, sem_diag_1.mkIncompatibleTyErr)(env, ty || type_manager_1.naslAnyTy, '枚举');
1013
- env.addError(errMsg, fileNode, nd, severity);
1014
- }
1015
- };
1016
- env.addPostCheckTask(env.errBoundary, postChk(env.getCurFileNode(), env.errSeverity, exprTy));
1017
- break;
1018
- }
1019
- default: {
1020
- throw new Error(`未实现的 enum 枚举内置函数,函数名 ${nd.calleeName}`);
1021
- }
1022
- }
1023
- env.unifier.unify(res, tgtTy);
1024
- const retTy = res ?? tgtTy;
1025
- env.setType(nd, retTy);
1026
- const callInfo = (0, type_manager_1.createFunctionDef)(paramTy ? [paramTy] : [], type_manager_1.naslBooleanTy, def, tyParam ? [tyParam] : []);
1027
- env.resolvedCallInfo.set(nd, callInfo);
1028
- return retTy;
1029
- }
1030
- }
1031
- exports.tpCallFunction = tpCallFunction;
1032
- /**
1033
- * 处理重载函数的调用
1034
- * @param env 语义环境
1035
- * @param nd 函数调用节点
1036
- * @param tgtTy 目标类型
1037
- * @param calleeName 被调用函数名
1038
- * @returns 处理后的类型注解
1039
- */
1040
- const handleOverloadedFunction = (env, nd, tgtTy, calleeName) => {
1041
- const ovParamIdx = (0, overload_helper_1.getOvParamIdx)(calleeName);
1042
- const argTys = [];
1043
- for (const arg of nd.arguments) {
1044
- argTys.push(dispatchExpr(env, arg, undefined) ?? type_manager_1.naslAnyTy);
1045
- }
1046
- if (calleeName === 'CAST') {
1047
- argTys[ovParamIdx] = (0, overload_helper_1.createCastLiteralType)(nd.arguments?.[ovParamIdx]?.expression?.value ?? '');
1048
- }
1049
- // Convert, Length, CAST 的返回类型可以从用户选择的类型(通过 type picker)拿到
1050
- // 其他重载函数都在 SQL 里,都在服务端逻辑里,可以立即从参数类型获得,没有页面全局类型推导的问题
1051
- let retTy = (0, overload_helper_1.getOverloadFuncRetTy)(nd, argTys[ovParamIdx]);
1052
- if (!retTy) {
1053
- if (!env.isView) {
1054
- const mangledCalleeName = (0, overload_helper_1.mangleOvFnName)(calleeName, argTys[ovParamIdx]);
1055
- const fnDef = env.quickGetLibDef(nd, mangledCalleeName, env.ctxCQC?.dataSourceSqlType);
1056
- const fnTy = fnDef?.__TypeAnnotation;
1057
- retTy = fnTy?.returnType?.[0];
1058
- }
1059
- else {
1060
- retTy = type_manager_1.naslAnyTy;
1061
- }
1062
- }
1063
- env.unifier.unify(retTy, tgtTy);
1064
- const callInfo = (0, type_manager_1.createFunctionDef)(argTys, retTy, undefined, undefined);
1065
- env.resolvedCallInfo.set(nd, callInfo);
1066
- const capturedDbSqlType = env.ctxCQC?.dataSourceSqlType;
1067
- // 剩下的需要后置处理
1068
- const postChk = (fileNode, errBoundary, severity) => (env) => {
1069
- const argTys = nd.arguments.map((arg) => env.getType(arg.expression));
1070
- if (calleeName === 'CAST') {
1071
- argTys[ovParamIdx] = (0, overload_helper_1.createCastLiteralType)(nd.arguments?.[ovParamIdx]?.expression?.value ?? '');
1072
- }
1073
- const ovArgTy = argTys[ovParamIdx];
1074
- const mangledCalleeName = (0, overload_helper_1.mangleOvFnName)(calleeName, ovArgTy);
1075
- let fnDef = mangledCalleeName ? env.quickGetLibDef(nd, mangledCalleeName, capturedDbSqlType) : undefined;
1076
- let fnTy = fnDef?.__TypeAnnotation;
1077
- // If no matching overload found, validate and report error
1078
- if (!fnDef || !fnTy) {
1079
- // Create fallback definition to prevent further errors
1080
- const fallbackDef = (0, overload_helper_1.createFallbackOverloadDef)(calleeName, nd.calleeNamespace, nd.arguments.length);
1081
- fnDef = fallbackDef;
1082
- fnTy = fallbackDef.__TypeAnnotation;
1083
- // Convert 允许接收任何类型,跳过报错(mangled name convertList convertMap 等查不到定义会产生额外错误)
1084
- if (calleeName !== 'Convert') {
1085
- const possibleTypes = (0, overload_helper_1.getOverloadParameterTypes)(env, nd, capturedDbSqlType);
1086
- if (possibleTypes.length > 0) {
1087
- const errorMsg = (0, sem_diag_1.createOverloadTypeError)(calleeName, ovArgTy, possibleTypes);
1088
- // precise error boundary nd.arguments[i]! is not working here, why?
1089
- env.addError(errorMsg, fileNode, errBoundary, severity);
1090
- }
1091
- }
1092
- }
1093
- // 后置类型校验,暂时都不需要,不可能报错
1094
- // for (let i = 0; i < argTys.length && i < (fnTy?.typeArguments?.length ?? 0); ++i) {
1095
- // const sub = argTys[i];
1096
- // const sup = fnTy!.typeArguments![i];
1097
- // if (!isSubTy(env, sub, sup)) { // precise error boundary nd.arguments[i]! is not working here, why?
1098
- // env.addError(mkIncompatibleTyErr(env, sub, sup), fileNode, errBoundary, severity);
1099
- // }
1100
- // }
1101
- };
1102
- env.addPostCheckTask(nd, postChk(env.getCurFileNode(), nd, env.errSeverity));
1103
- env.setType(nd, retTy); // 似乎不可能为空
1104
- return env.getRawType(nd);
1105
- };
1106
- function tpCallInterface(env, nd, tgtTy) {
1107
- const qName = (0, get_q_name_1.getTokenQualifiedName)(nd);
1108
- if (!qName) {
1109
- env.setType(nd, type_manager_1.naslAnyTy);
1110
- return type_manager_1.naslAnyTy;
1111
- }
1112
- const def = env.refMgr.gQNameDefs.get(qName);
1113
- if (!def) {
1114
- env.setType(nd, type_manager_1.naslAnyTy);
1115
- return type_manager_1.naslAnyTy;
1116
- }
1117
- // 说起来你可能不信,但是事实令人震惊,参数与形参的顺序是乱的,仅能通过 keyword 来匹配
1118
- for (const param of def.params) {
1119
- dispatchExpr(env, nd.arguments.find(p => p.keyword === param.name), param.typeAnnotation);
1120
- }
1121
- const retTy = def.returns?.[0]?.typeAnnotation;
1122
- const finalRetTy = nd?.handleError === true
1123
- ? (retTy ? (0, type_manager_1.createUnionTyAnn)([retTy, type_manager_1.naslInterfaceError]) : type_manager_1.naslInterfaceError)
1124
- : (retTy ?? tgtTy);
1125
- env.setType(nd, finalRetTy);
1126
- env.unifier.unify(finalRetTy, tgtTy);
1127
- if (!env.isView) {
1128
- const callInfo = (0, type_manager_1.createFunctionDef)(def.params.map(p => p.typeAnnotation), finalRetTy, def, undefined);
1129
- env.resolvedCallInfo.set(nd, callInfo);
1130
- }
1131
- return finalRetTy;
1132
- }
1133
- exports.tpCallInterface = tpCallInterface;
1134
- exports.tpCallAuthInterface = tpCallInterface;
1135
- exports.tpCallMicroserviceInterface = tpCallInterface;
1136
- exports.tpCallConnector = tpCallLogic;
1137
- function tpAnonymousFunction(env, nd, tgtTy, isListSort = false) {
689
+ const tpAnonymousFunction = (env, nd, tgtTy, isListSort = false) => {
1138
690
  if (!tgtTy || !(0, type_predicate_2.isFuncTy)(tgtTy)) {
1139
691
  env.setType(nd, type_manager_1.naslAnyTy);
1140
692
  env.addError((0, sem_diag_1.mkIncompatibleTyErr)(env, '函数', tgtTy || type_manager_1.naslAnyTy));
@@ -1143,8 +695,9 @@ function tpAnonymousFunction(env, nd, tgtTy, isListSort = false) {
1143
695
  (0, assertion_1.assertTrusy)(tgtTy);
1144
696
  const paramsArr = [];
1145
697
  // TODO: 通过 default value 生成 constraints
698
+ env.refMgr.setLocalSymBindings(nd, nd.params);
1146
699
  nd.params.forEach((param, idx) => {
1147
- (0, helper_1.createOnPush)(env.nameBindings, param.name, param); // param name to mem addr
700
+ env.addLexicalSym(param); // param name to mem addr
1148
701
  paramsArr.push(param);
1149
702
  const ctxParTy = tgtTy.typeArguments[idx];
1150
703
  ctxParTy && env.setType(param, ctxParTy);
@@ -1152,16 +705,18 @@ function tpAnonymousFunction(env, nd, tgtTy, isListSort = false) {
1152
705
  dispatchExpr(env, nd.body, isListSort ? undefined : tgtTy?.returnType?.[0]);
1153
706
  env.setType(nd, (0, type_manager_1.createFnTyFromTyAnns)(// @ts-expect-error
1154
707
  nd.params.map(env.getRawType), env.getRawType(nd.body) ?? type_manager_1.naslAnyTy));
1155
- paramsArr.forEach(p => env.removeVar(p));
708
+ paramsArr.forEach(p => env.removeLexicalSym(p));
1156
709
  const ndTy = env.getRawType(nd);
1157
710
  !isListSort && env.unifier.unify(ndTy, tgtTy);
1158
711
  return ndTy;
1159
- }
1160
- function tpSubLogic(env, nd, tgtTy, isListSort = false) {
712
+ };
713
+ exports.tpAnonymousFunction = tpAnonymousFunction;
714
+ const tpSubLogic = (env, nd, tgtTy, isListSort = false) => {
1161
715
  // 若非前端,则 shallow copy,因为内部会触发 solve,会把进来前的约束清掉;
1162
716
  // 若是前端,则无需 copy
1163
717
  const csCopy = env.isView ? env.unifier.cs : new Map(env.unifier.cs);
1164
718
  const subLogicVars = [...nd.params, ...nd.returns, ...nd.variables];
719
+ env.refMgr.setLocalSymBindings(nd, subLogicVars);
1165
720
  subLogicVars.forEach(v => (0, dispatch_def_1.dispatchDef)(env, v));
1166
721
  // 处理 tgtTy 缺失的情况
1167
722
  if (tgtTy && !(0, type_predicate_2.isFuncTy)(tgtTy) && !isListSort) {
@@ -1178,13 +733,14 @@ function tpSubLogic(env, nd, tgtTy, isListSort = false) {
1178
733
  }
1179
734
  (0, dispatch_stmt_2.tpSolvingStmts)(env, nd.body);
1180
735
  (0, dispatch_stmt_1.tpSolvingPlayground)(env, nd.playground);
1181
- subLogicVars.forEach(env.removeVar);
736
+ subLogicVars.forEach(env.removeLexicalSym);
1182
737
  const ndTy = (0, type_manager_1.createRefTyAnnFromDef)(nd, env);
1183
738
  env.setType(nd, ndTy);
1184
739
  env.unifier.cs = csCopy;
1185
740
  !isListSort && env.unifier.unify(ndTy, tgtTy); // 这里需要额外的 unify,否则 SubLogic 算出来的类型不能与外侧进来时的约束产生关系
1186
741
  return ndTy;
1187
- }
742
+ };
743
+ exports.tpSubLogic = tpSubLogic;
1188
744
  function tpArgument(env, nd, tgtTy) {
1189
745
  // TODO CallConnector 硬塞了一个特殊的 Argument Content_Type,这个 Argument 没有 expression
1190
746
  if (nd.expression) {
@@ -1200,13 +756,14 @@ function tpArgument(env, nd, tgtTy) {
1200
756
  }
1201
757
  // 一个实体逻辑,浪费一整天,LJ。
1202
758
  function tpFunction(env, nd, tgtTy) {
759
+ env.refMgr.setLocalSymBindings(nd, nd.params);
1203
760
  // 历史兼容,似乎只有 实体逻辑的 filter 是这个东西
1204
761
  if (!(0, type_predicate_2.isFuncTy)(tgtTy)) {
1205
762
  throw new Error('In Function__.ts, Function Typing 传入的参数不是函数类型');
1206
763
  }
1207
764
  const paramsArr = [];
1208
765
  nd.params.forEach((param, idx) => {
1209
- (0, helper_1.createOnPush)(env.nameBindings, param.name, param); // param name to mem addr
766
+ env.addLexicalSym(param); // param name to mem addr
1210
767
  paramsArr.push(param);
1211
768
  if (tgtTy) {
1212
769
  const ctxParTy = tgtTy.typeArguments?.[idx];
@@ -1218,7 +775,7 @@ function tpFunction(env, nd, tgtTy) {
1218
775
  env.setType(nd.returns[0], retTy);
1219
776
  // FIXME: 强行一致,现在标的不是函数类型,标的是函数的返回类型
1220
777
  env.setType(nd, retTy);
1221
- paramsArr.forEach(p => env.removeVar(p));
778
+ paramsArr.forEach(p => env.removeLexicalSym(p));
1222
779
  return env.getRawType(nd);
1223
780
  }
1224
781
  function tpCallQueryComponent(env, nd, tgtTy) {
@@ -1271,8 +828,8 @@ function tpCallQueryComponent(env, nd, tgtTy) {
1271
828
  env.ctxTpQFE = undefined;
1272
829
  env.ctxCQC = undefined;
1273
830
  createdVars.forEach(v => {
1274
- const varNode = (0, helper_1.getLastOne)(env.nameBindings, v);
1275
- (0, helper_1.removeLastOne)(env.nameBindings, v);
831
+ const varNode = env.getLexicalSym(v);
832
+ env.removeLexicalVarByName(v);
1276
833
  env.typeBindings.delete(varNode);
1277
834
  });
1278
835
  return env.getRawType(nd);
@@ -1504,14 +1061,14 @@ function tpCallQueryComponent(env, nd, tgtTy) {
1504
1061
  aggrAsNames.forEach((ty, name) => {
1505
1062
  // 反正现在是这样的
1506
1063
  const v = nasl_concepts_1.Variable.createProtoTypeOnly({ name: `inner.${name}` });
1507
- (0, helper_1.createOnPush)(env.nameBindings, v.name, v);
1064
+ env.addLexicalSym(v);
1508
1065
  env.setType(v, ty);
1509
1066
  variables.push(v.name);
1510
1067
  });
1511
1068
  groupByAsNames.forEach((ty, name) => {
1512
1069
  // 反正现在是这样的
1513
1070
  const v = nasl_concepts_1.Variable.createProtoTypeOnly({ name: `inner.${name}` });
1514
- (0, helper_1.createOnPush)(env.nameBindings, v.name, v);
1071
+ env.addLexicalSym(v);
1515
1072
  env.setType(v, ty);
1516
1073
  variables.push(v.name);
1517
1074
  });
@@ -1551,8 +1108,8 @@ function tpNewComposite(env, nd, tgtTy) {
1551
1108
  // 参考:【rg3】+ saas + 批量赋值时,将同一变量(三层变量)同时赋值给两个不同的变量有报错,、New 等自动连线功能失效
1552
1109
  // http://projectmanage.netease-official.lcap.163yun.com/dashboard/BugDetail?id=3148436628556032
1553
1110
  nd.rights.forEach(selMem => {
1554
- dispatchExpr(env, toRaw(selMem.expression), undefined);
1555
- selMem.members.forEach(mem => dispatchExpr(env, toRaw(mem), undefined));
1111
+ dispatchExpr(env, (0, dispatch_stmt_1.toRaw)(selMem.expression), undefined);
1112
+ selMem.members.forEach(mem => dispatchExpr(env, (0, dispatch_stmt_1.toRaw)(mem), undefined));
1556
1113
  });
1557
1114
  const lNameTyPair = (0, exports.extractNameTyPair)(env, nd.typeAnnotation);
1558
1115
  if (!lNameTyPair) {
@@ -1582,11 +1139,12 @@ function tpNewComposite(env, nd, tgtTy) {
1582
1139
  }
1583
1140
  env.unifier.unifyWithBoundary(rTy, lPropTyAnn, right);
1584
1141
  });
1142
+ const properties = toRaws(nd.properties);
1585
1143
  // 没连线的左边的元素们。其实无所谓,但要跟现在保持一致。
1586
- nd.properties.forEach((pIdent, _) => {
1144
+ properties.forEach((pIdent) => {
1587
1145
  if (!env.typeBindings.get(pIdent)) {
1588
1146
  let lPropTyAnn = lNameTyPair.find(([name, _]) => name === pIdent.name)?.[1];
1589
- // setType 应该够了,直接 dispatchExpr 会因为 pIdent 没有加到 env.nameBindings 里,导致找不到而报错
1147
+ // setType 应该够了,直接 dispatchExpr 会因为 pIdent 没有加到 env.lexicalVarStacks 里,导致找不到而报错
1590
1148
  if (!lPropTyAnn) {
1591
1149
  if (nd.typeAnnotation?.typeKind === 'anonymousStructure') {
1592
1150
  lPropTyAnn = type_manager_1.naslStringTy;
@@ -1603,7 +1161,7 @@ function tpNewComposite(env, nd, tgtTy) {
1603
1161
  const propNames = new Array();
1604
1162
  const propTys = new Array();
1605
1163
  // ty.properties 与 nd.properties 顺序不一样,有一个被排序过,神坑!!!
1606
- nd.properties.forEach((pIdent, _) => {
1164
+ properties.forEach((pIdent) => {
1607
1165
  propNames.push(pIdent.name);
1608
1166
  propTys.push(env.getRawType(pIdent) ?? env.unifier.nextFreshTyAnn('free'));
1609
1167
  });
@@ -1737,35 +1295,43 @@ function tpMatch(env, nd, tgtTy) {
1737
1295
  const exprTy = nd.isExpression ?
1738
1296
  dispatchExpr(env, nd.expression, undefined) :
1739
1297
  tpSolvingExpr(env, nd.expression, undefined);
1740
- const tpMatchTypeRefineCase = (nd, tgtTy, exprTy) => (mc) => {
1741
- let exprRefinedTy = exprTy ?? type_manager_1.naslAnyTy;
1742
- if (mc.patterns.length > 0) {
1743
- // type patterns must be type annotations
1744
- exprRefinedTy = (0, type_manager_1.createUnionTyAnnIfNecessary)(env, mc.patterns.map(inferTy));
1745
- // TODO wudengke 求解完成之后,报错
1746
- }
1747
- else { // '其他' 分支或 空模式的分支
1298
+ const tpMatchTypeRefineCase = (nd, exprTy) => (mc) => {
1299
+ let exprRefinedTy = exprTy;
1300
+ // mc.patterns 中可能包含类型模式和值模式,分别对应类型匹配和值匹配。
1301
+ // 产品上要求:当被Match的表达式为Union类型时,只能使用类型匹配;否则只能使用值模式匹配。mc.patterns 中值模式和类型模式不会同时出现。
1302
+ // 因此: mc.pattern 中一旦出现非类型的项,就可以判定为这是值模式匹配。值模式匹配时,无需对匹配项的类型做精化。
1303
+ if (mc.patterns.length > 0 && mc.patterns.every((x) => (0, type_predicate_1.isTypeAnnotation)(x))) {
1304
+ // 模式非空且类型模式匹配
1305
+ exprRefinedTy = (0, type_manager_1.createUnionTyAnnIfNecessary)(env, mc.patterns.map(getPatTy).filter(types_1.isNotNil));
1306
+ env.addPostCheckTask(mc, (env, pSubst) => {
1307
+ const resolvedSub = pSubst(exprRefinedTy);
1308
+ const resolvedSup = pSubst(exprTy);
1309
+ if (!(0, type_predicate_1.isSubTy)(env, resolvedSub, resolvedSup)) {
1310
+ env.addError((0, sem_diag_1.mkIncompatibleTyErr)(env, resolvedSub, resolvedSup), undefined, mc);
1311
+ }
1312
+ });
1313
+ }
1314
+ else {
1315
+ // 类型模式匹配('其他' 分支或 空模式的分支) 或者 值模式匹配的分支
1748
1316
  // 对其他所有 case 的所有类型取关于全集 exprTy 的补集
1749
1317
  const prevCases = nd.cases.filter((c) => c !== mc); // mem addr compare
1750
- const prevPatterns = prevCases.flatMap(pc => pc.patterns);
1318
+ const prevPatterns = prevCases.flatMap((pc) => pc.patterns);
1751
1319
  const pureTys = prevPatterns.filter((x) => (0, type_predicate_1.isTypeAnnotation)(x));
1752
- // 确保我们在处理纯类型的匹配
1320
+ // 确保我们在处理纯类型的匹配。值匹配不用任何精化。
1753
1321
  if (pureTys.length === prevPatterns.length) {
1754
- // 单例模式后改为直接比较内存地址
1755
- const caseRefinedTys = (0, type_predicate_1.isUnionTy)(exprTy) ? exprTy?.typeArguments?.filter(t1 => !pureTys.find(t2 => {
1756
- return (0, type_predicate_1.isEqualTy)(env, t1, t2);
1757
- })) : [];
1322
+ const caseRefinedTys = (0, type_predicate_1.isUnionTy)(exprTy)
1323
+ ? exprTy?.typeArguments?.filter((t1) => !pureTys.find((t2) => (0, type_predicate_1.isEqualTy)(env, t1, t2)))
1324
+ : [];
1758
1325
  if (caseRefinedTys?.length) {
1759
- // TODO 报错
1760
- exprRefinedTy = (0, type_manager_1.createUnionTyAnnIfNecessary)(env, caseRefinedTys);
1326
+ exprRefinedTy = (0, type_manager_1.createUnionTyAnnIfNecessary)(env, caseRefinedTys); // TODO 报错
1761
1327
  }
1762
1328
  }
1763
1329
  }
1764
1330
  const allocatedVars = new Set();
1765
1331
  const itVar = nasl_concepts_1.Variable.createProtoTypeOnly({ name: 'it', typeAnnotation: exprRefinedTy }); // 新加的每个分支里的 'it' 变量
1766
1332
  allocatedVars.add(itVar);
1767
- const isRefined = shouldRefine(nd.expression);
1768
1333
  let matchedVarName = undefined;
1334
+ const isRefined = shouldRefineType(nd.expression, exprTy);
1769
1335
  if (isRefined) {
1770
1336
  matchedVarName = (0, get_q_name_1.getTokenQualifiedNameForMatchedExpr)(env, nd.expression);
1771
1337
  const freshMatchedVar = nasl_concepts_1.Variable.createProtoTypeOnly({
@@ -1788,33 +1354,27 @@ function tpMatch(env, nd, tgtTy) {
1788
1354
  // setType(mc, env.getRawType(getListLast(mc.body))) // Not really useful but to keep the same as the current behaviour
1789
1355
  allocatedVars.forEach(v => {
1790
1356
  // recover un-refined type. Note that `delete` is not proper here.Should use removeLastOne
1791
- (0, helper_1.removeLastOne)(env.nameBindings, v.name);
1357
+ env.removeLexicalVarByName(v.name);
1792
1358
  env.typeBindings.delete(v);
1793
1359
  });
1794
1360
  if (isRefined) {
1795
1361
  env.matchedVars.delete(matchedVarName);
1796
1362
  }
1797
1363
  };
1798
- function handleMatchingAgainstTypes(unionTy) {
1799
- const tpMcTyRefineCase = tpMatchTypeRefineCase(nd, tgtTy, unionTy);
1800
- nd.cases.forEach(tpMcTyRefineCase);
1801
- }
1802
- function inferTy(x) {
1803
- if ((0, type_predicate_1.isTypeAnnotation)(x)) {
1804
- return x;
1805
- }
1806
- return dispatchExpr(env, x, undefined);
1807
- }
1808
- function inferUnionTyFromMatchCases(mcs) {
1809
- // 从已有的 match cases 的类型构造出 union-like type
1810
- const patTys = mcs.flatMap(c => c.patterns).map(inferTy).filter(types_1.isNotNil);
1811
- patTys.push(exprTy);
1812
- return (0, type_manager_1.createUnionTyAnnIfNecessary)(env, patTys);
1813
- }
1814
1364
  if (exprTy) {
1365
+ for (const cs of nd.cases) {
1366
+ for (const p of cs.patterns) {
1367
+ dispatchExpr(env, p, undefined);
1368
+ }
1369
+ }
1815
1370
  if ((0, type_predicate_2.isTyAnnTyParam)(exprTy)) {
1816
- const unionLikeTy = inferUnionTyFromMatchCases(nd.cases);
1817
- handleMatchingAgainstTypes(unionLikeTy);
1371
+ // 从已有的 match cases 的类型构造出 union-like type
1372
+ const patTys = nd.cases.flatMap(c => c.patterns).map(getPatTy).filter(types_1.isNotNil);
1373
+ for (const pTy of patTys) {
1374
+ env.unifier.unify(pTy, exprTy); // 各个分支的类型的 union <: 类型变元
1375
+ }
1376
+ const unionTy = (0, type_manager_1.createUnionTyAnnIfNecessary)(env, patTys);
1377
+ handleMatchingAgainstTypes(unionTy);
1818
1378
  }
1819
1379
  else {
1820
1380
  handleMatchingAgainstTypes(exprTy);
@@ -1833,8 +1393,22 @@ function tpMatch(env, nd, tgtTy) {
1833
1393
  env.setType(nd, type_manager_1.naslVoidTy);
1834
1394
  }
1835
1395
  return env.getRawType(nd);
1836
- function shouldRefine(nd) {
1837
- return nd.concept === 'Identifier' || nd.concept === 'MemberExpression';
1396
+ function handleMatchingAgainstTypes(unionTy) {
1397
+ nd.cases.forEach(tpMatchTypeRefineCase(nd, unionTy));
1398
+ }
1399
+ function getPatTy(x) {
1400
+ if ((0, type_predicate_1.isTypeAnnotation)(x)) {
1401
+ return x;
1402
+ }
1403
+ return env.getRawType(x);
1404
+ // 这不仅引人深思:为什么 1 的类型就不能随着上下文变化呢,而要 argument: Decimal argument.expr : Long
1405
+ // 那好了,match 这里其实是又要特殊处理的
1406
+ }
1407
+ function shouldRefineType(nd, exprRefinedTy) {
1408
+ const validExpr = nd.concept === 'Identifier' || nd.concept === 'MemberExpression';
1409
+ // 仅当输入是 union 类型或可以实例化为 union 类型的类型变元才进行 type refinement
1410
+ const validTy = (0, type_predicate_1.isUnionTy)(exprRefinedTy) || (0, type_predicate_2.isTyAnnTyParam)(exprRefinedTy);
1411
+ return validExpr && validTy;
1838
1412
  }
1839
1413
  }
1840
1414
  exports.tpMatch = tpMatch;
@@ -1844,167 +1418,10 @@ function tpUnparsed(env, nd, tgtTy) {
1844
1418
  env.setType(nd, type_manager_1.naslNullTy);
1845
1419
  return type_manager_1.naslNullTy;
1846
1420
  }
1847
- // 看不懂?一看 NASL 便知
1848
- function tpEntityLogic(env, nd, tgtTy) {
1849
- const def = env.resolveRef(nd);
1850
- if (!def) {
1851
- env.setType(nd, type_manager_1.naslAnyTy);
1852
- return type_manager_1.naslAnyTy;
1853
- }
1854
- // 例如 app.dataSources.${dbName}.entities.${entityName}
1855
- // 从 'a.b.c.logics.e' 中提取 'a.b.c'
1856
- const getEntityQName = (ctxCallLogic) => {
1857
- const qualifiedNames = (0, get_q_name_1.getTokenQualifiedName)(ctxCallLogic);
1858
- const parts = qualifiedNames.split('.');
1859
- return parts.slice(0, parts.length - 2).join('.');
1860
- };
1861
- const calleeName = nd.calleeName;
1862
- const entityDef = env.refMgr.gQNameDefs.get(getEntityQName(nd));
1863
- const entityPrimaryKeys = entityDef?.properties.filter(p => p.primaryKey) ?? [];
1864
- const entityRefTy = entityDef ? (0, type_manager_1.createRefTyAnnFromDef)(entityDef, env) ?? type_manager_1.naslAnyTy : type_manager_1.naslAnyTy;
1865
- const entityOrErrTy = entityRefTy ? (0, type_manager_1.createUnionTyAnn)([entityRefTy, type_manager_1.naslDatabaseDuplicateKeyError]) : undefined;
1866
- const listEntityRefTy = (0, type_manager_1.createListTyAnn)(entityRefTy);
1867
- // pre-determined type of arguments[0]
1868
- const getArg0TgtTy = () => {
1869
- const fstPrimaryKeyTy = entityDef?.properties.find(p => p.primaryKey)?.typeAnnotation;
1870
- switch (calleeName) {
1871
- case 'get': return fstPrimaryKeyTy; // 主键类型
1872
- case 'create': return entityRefTy;
1873
- case 'delete': return fstPrimaryKeyTy; // 主键类型
1874
- case 'update': return entityRefTy;
1875
- case 'createOrUpdate': return entityRefTy;
1876
- case 'updateBy': return (0, type_manager_1.createFnTyFromTyAnns)([entityRefTy ?? type_manager_1.naslAnyTy], type_manager_1.naslBooleanTy);
1877
- case 'deleteBy': return (0, type_manager_1.createFnTyFromTyAnns)([entityRefTy ?? type_manager_1.naslAnyTy], type_manager_1.naslBooleanTy);
1878
- case 'batchCreate': return listEntityRefTy;
1879
- case 'batchUpdate': return listEntityRefTy;
1880
- case 'batchDelete': return (0, type_manager_1.createListTyAnn)(fstPrimaryKeyTy ?? type_manager_1.naslAnyTy); // 主键类型
1881
- case 'import': return type_manager_1.naslBinaryTy;
1882
- }
1883
- };
1884
- const paramTys = new Array();
1885
- const arg0TgtTy = getArg0TgtTy();
1886
- paramTys.push(arg0TgtTy ?? type_manager_1.naslAnyTy);
1887
- env.ctxTpEntityTy = entityRefTy;
1888
- nd.arguments[0] && dispatchExpr(env, nd.arguments[0], arg0TgtTy);
1889
- if (calleeName === 'updateBy' || calleeName === 'deleteBy') {
1890
- const arg1TgtTy = entityRefTy;
1891
- if (nd.arguments[1]) {
1892
- const arg1Ty = dispatchExpr(env, nd.arguments[1], arg1TgtTy);
1893
- paramTys.push(arg1Ty ?? arg1TgtTy ?? type_manager_1.naslAnyTy);
1894
- }
1895
- // 这里不能直接 dispatchExpr(callee.arguments[2]),因为里面藏了个非标准的 NewList,元素因为没有公共父类型而会报错,下同
1896
- const fnDef = nd.arguments[2]?.expression;
1897
- // NASL 实在是太 🐂🍺 拉,到处都是 NewList,人间处处皆学问!
1898
- const fnBody = fnDef?.body;
1899
- if (fnBody?.items) {
1900
- const paramItem = fnDef?.params?.[0];
1901
- checkItemMemExprTy(paramItem, fnBody?.items);
1902
- // FIXME: 只能说是强行保持一致
1903
- env.setType(nd.arguments[2], type_manager_1.naslStringTy);
1904
- paramTys.push(type_manager_1.naslStringTy);
1905
- const itemTys = fnBody?.items?.map(item => env.getRawType(item) ?? type_manager_1.naslAnyTy);
1906
- const bodyListUnionTy = (0, type_manager_1.createListTyAnn)((0, type_manager_1.createUnionTyAnnIfNecessary)(env, itemTys));
1907
- env.setType(fnBody, bodyListUnionTy);
1908
- }
1909
- }
1910
- else if (calleeName === 'update' || calleeName === 'batchUpdate') {
1911
- const fnDef = nd.arguments[1]?.expression;
1912
- const fnBody = fnDef?.body;
1913
- if (fnBody?.items) {
1914
- const paramItem = fnDef?.params?.[0];
1915
- checkItemMemExprTy(paramItem, fnBody?.items);
1916
- // FIXME: 只能说是强行保持一致
1917
- env.setType(nd.arguments[1], type_manager_1.naslStringTy);
1918
- paramTys.push(type_manager_1.naslStringTy);
1919
- const itemTys = fnBody?.items?.map(item => env.getRawType(item) ?? type_manager_1.naslAnyTy);
1920
- const bodyListUnionTy = (0, type_manager_1.createListTyAnn)((0, type_manager_1.createUnionTyAnnIfNecessary)(env, itemTys));
1921
- env.setType(fnBody, bodyListUnionTy);
1922
- }
1923
- }
1924
- else if ((calleeName === 'get' || calleeName === 'delete') && entityPrimaryKeys.length > 1) {
1925
- // 处理多主键
1926
- for (let i = 1; i < entityPrimaryKeys.length; i++) {
1927
- const argTgtTy = entityPrimaryKeys[i].typeAnnotation;
1928
- if (nd.arguments[i]) {
1929
- dispatchExpr(env, nd.arguments[i], argTgtTy);
1930
- paramTys.push(argTgtTy ?? type_manager_1.naslAnyTy);
1931
- }
1932
- }
1933
- }
1934
- env.ctxTpEntityTy = undefined;
1935
- const retTy = getRetTy();
1936
- const finalRetTy = nd.handleError === true
1937
- ? retTy
1938
- // 做了手动处理 Error 需求后,需要 remove Error types from return types
1939
- : (0, exports.removeErrTys)(env, nd, retTy);
1940
- nd.handleError === true && dispatchExpr(env, nd.errorMessage, undefined);
1941
- env.setType(nd, finalRetTy);
1942
- env.unifier.unify(finalRetTy, tgtTy);
1943
- // Create a mock definition for entity logics
1944
- const mockDef = { params: paramTys.map(() => ({ optional: false })) };
1945
- const callInfo = (0, type_manager_1.createFunctionDef)(paramTys, finalRetTy, mockDef, undefined);
1946
- env.resolvedCallInfo.set(nd, callInfo);
1947
- return finalRetTy;
1948
- function getRetTy() {
1949
- switch (calleeName) {
1950
- case 'get': return entityRefTy;
1951
- case 'create': return entityOrErrTy; // 带个 Error 类型
1952
- case 'delete': return type_manager_1.naslLongTy; // 现在如此
1953
- case 'update': return entityRefTy;
1954
- case 'createOrUpdate': return entityOrErrTy; // 带个 Error 类型
1955
- case 'updateBy': return type_manager_1.naslLongTy;
1956
- case 'deleteBy': return type_manager_1.naslLongTy;
1957
- case 'batchCreate': return listEntityRefTy;
1958
- case 'batchUpdate': return listEntityRefTy;
1959
- case 'batchDelete': return type_manager_1.naslLongTy;
1960
- case 'import': return type_manager_1.naslStringTy;
1961
- }
1962
- }
1963
- function checkItemMemExprTy(paramItem, itemMemExprs) {
1964
- // createOnPush(env.nameBindings, 'item', paramItem);
1965
- // FIXME
1966
- (0, dispatch_def_1.dispatchDef)(env, paramItem);
1967
- itemMemExprs.forEach(expr => dispatchExpr(env, expr, undefined));
1968
- env.removeVar(paramItem);
1969
- }
1970
- }
1971
- exports.tpEntityLogic = tpEntityLogic;
1972
1421
  function tpAnchor(env, nd, tgtTy) {
1973
1422
  return dispatchExpr(env, nd.expression, tgtTy);
1974
1423
  }
1975
- // 特性:支持 forward reference (处理一个尚未读到定义的 Callee)
1976
- // 尝试创建一个函数类型placeholderFnTy,并和qName关联起来。
1977
- // 1. 之后遇到callee定义的时候再进行检查
1978
- // 2. 如果在一个批次检查后这个callee仍然没有定义,那么报错
1979
- /**
1980
- * 创建前向引用占位符(简单的函数类型)
1981
- */
1982
- function createAndSetForwardReferencePlaceholder(env, nd) {
1983
- // 为每个参数创建一个新的类型变量
1984
- const paramTypes = nd.arguments.map(() => env.unifier.nextFreshTyAnn('free'));
1985
- // 为返回值创建一个新的类型变量
1986
- const returnType = env.unifier.nextFreshTyAnn('free');
1987
- const placeholderFnTy = (0, type_manager_1.createFnTyFromTyAnns)(paramTypes, returnType);
1988
- return placeholderFnTy;
1989
- }
1990
- // @ts-expect-error
1991
- const toRaw = (nd) => nd?.__v_raw ?? nd;
1992
- const toRaws = (nds) => nds.map(toRaw);
1993
- /**
1994
- * 处理函数返回类型,过滤错误类型并设置节点类型
1995
- */
1996
- const removeErrTys = (env, nd, retTy) => {
1997
- let finalRetTy = retTy;
1998
- if (finalRetTy && finalRetTy.typeKind === 'union') {
1999
- finalRetTy = (0, fp_macros_1.IfBind)(finalRetTy.typeArguments?.filter(ty => !((0, type_predicate_2.isErrorTy)(ty))))(filteredRetTys => (0, type_manager_1.createUnionTyAnnIfNecessary)(env, filteredRetTys))((0, fp_macros_1.feed)(finalRetTy));
2000
- }
2001
- // @ts-ignore
2002
- if ((0, type_predicate_1.isUnionTy)(finalRetTy) && !finalRetTy.typeArguments?.length) {
2003
- return type_manager_1.naslVoidTy; // createUnionTyAnnIfNecessary 得到 Union<> 时表示无返回类型
2004
- }
2005
- return finalRetTy;
2006
- };
2007
- exports.removeErrTys = removeErrTys;
1424
+ const toRaws = (nds) => nds.map(dispatch_stmt_1.toRaw);
2008
1425
  const tpNewStructure = (env, nd, tgtTy) => {
2009
1426
  const ndTy = (0, type_manager_1.createAnonymousTyAnn)(nd.properties.map((p) => p.name), nd.properties.map((p) => {
2010
1427
  // p.name可能有两个取值:format和title。其中:
@@ -2029,10 +1446,10 @@ const tpNewStructure = (env, nd, tgtTy) => {
2029
1446
  // 一个通用的方法,获取各种连线右侧的逻辑项
2030
1447
  const getRightByLine = (nd, itemIdx, memIdx) => {
2031
1448
  if (memIdx !== undefined) {
2032
- return toRaw(nd.rights[itemIdx].members[memIdx]);
1449
+ return (0, dispatch_stmt_1.toRaw)(nd.rights[itemIdx].members[memIdx]);
2033
1450
  }
2034
1451
  else {
2035
- return toRaw(nd.rights[itemIdx].expression);
1452
+ return (0, dispatch_stmt_1.toRaw)(nd.rights[itemIdx].expression);
2036
1453
  }
2037
1454
  };
2038
1455
  exports.getRightByLine = getRightByLine;