@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.
- package/out/checker.d.ts +1 -1
- package/out/checker.d.ts.map +1 -1
- package/out/checker.js +87 -121
- package/out/checker.js.map +1 -1
- package/out/index.d.ts +2 -2
- package/out/index.d.ts.map +1 -1
- package/out/index.js +4 -3
- package/out/index.js.map +1 -1
- package/out/reference-manager/builtin-q-name.d.ts +1 -2
- package/out/reference-manager/builtin-q-name.d.ts.map +1 -1
- package/out/reference-manager/builtin-q-name.js +1 -5
- package/out/reference-manager/builtin-q-name.js.map +1 -1
- package/out/reference-manager/collect-q-name.d.ts.map +1 -1
- package/out/reference-manager/collect-q-name.js +8 -7
- package/out/reference-manager/collect-q-name.js.map +1 -1
- package/out/reference-manager/helper.d.ts +1 -1
- package/out/reference-manager/helper.d.ts.map +1 -1
- package/out/reference-manager/helper.js +11 -1
- package/out/reference-manager/helper.js.map +1 -1
- package/out/reference-manager/reference-manager.d.ts +64 -7
- package/out/reference-manager/reference-manager.d.ts.map +1 -1
- package/out/reference-manager/reference-manager.js +198 -56
- package/out/reference-manager/reference-manager.js.map +1 -1
- package/out/reference-manager/remove-q-name.js +8 -8
- package/out/reference-manager/remove-q-name.js.map +1 -1
- package/out/reference-manager/rename-q-name.d.ts.map +1 -1
- package/out/reference-manager/rename-q-name.js +6 -6
- package/out/reference-manager/rename-q-name.js.map +1 -1
- package/out/reference-manager/update-nasl-fragment.d.ts +0 -1
- package/out/reference-manager/update-nasl-fragment.d.ts.map +1 -1
- package/out/reference-manager/update-nasl-fragment.js +2 -33
- package/out/reference-manager/update-nasl-fragment.js.map +1 -1
- package/out/typer/component-def-manager/utils.js +1 -1
- package/out/typer/component-def-manager/utils.js.map +1 -1
- package/out/typer/dispatch-all.d.ts +10 -3
- package/out/typer/dispatch-all.d.ts.map +1 -1
- package/out/typer/dispatch-all.js +44 -7
- package/out/typer/dispatch-all.js.map +1 -1
- package/out/typer/dispatch-call.d.ts +14 -0
- package/out/typer/dispatch-call.d.ts.map +1 -0
- package/out/typer/dispatch-call.js +637 -0
- package/out/typer/dispatch-call.js.map +1 -0
- package/out/typer/dispatch-def.d.ts +9 -3
- package/out/typer/dispatch-def.d.ts.map +1 -1
- package/out/typer/dispatch-def.js +101 -91
- package/out/typer/dispatch-def.js.map +1 -1
- package/out/typer/dispatch-expr.d.ts +3 -15
- package/out/typer/dispatch-expr.d.ts.map +1 -1
- package/out/typer/dispatch-expr.js +94 -677
- package/out/typer/dispatch-expr.js.map +1 -1
- package/out/typer/dispatch-process.d.ts.map +1 -1
- package/out/typer/dispatch-process.js +28 -11
- package/out/typer/dispatch-process.js.map +1 -1
- package/out/typer/dispatch-stmt.d.ts.map +1 -1
- package/out/typer/dispatch-stmt.js +39 -38
- package/out/typer/dispatch-stmt.js.map +1 -1
- package/out/typer/dispatch-view.d.ts.map +1 -1
- package/out/typer/dispatch-view.js +22 -16
- package/out/typer/dispatch-view.js.map +1 -1
- package/out/typer/get-oql-files.d.ts +13 -0
- package/out/typer/get-oql-files.d.ts.map +1 -0
- package/out/typer/get-oql-files.js +136 -0
- package/out/typer/get-oql-files.js.map +1 -0
- package/out/typer/helper.d.ts +2 -2
- package/out/typer/helper.d.ts.map +1 -1
- package/out/typer/helper.js +5 -5
- package/out/typer/helper.js.map +1 -1
- package/out/typer/incremental-update.d.ts +0 -12
- package/out/typer/incremental-update.d.ts.map +1 -1
- package/out/typer/incremental-update.js +99 -193
- package/out/typer/incremental-update.js.map +1 -1
- package/out/typer/index.d.ts +6 -4
- package/out/typer/index.d.ts.map +1 -1
- package/out/typer/index.js +9 -10
- package/out/typer/index.js.map +1 -1
- package/out/typer/subster.d.ts +0 -1
- package/out/typer/subster.d.ts.map +1 -1
- package/out/typer/subster.js +3 -23
- package/out/typer/subster.js.map +1 -1
- package/out/typer/topo-sort.d.ts +4 -4
- package/out/typer/topo-sort.d.ts.map +1 -1
- package/out/typer/topo-sort.js +5 -1
- package/out/typer/topo-sort.js.map +1 -1
- package/out/typer/type-manager.d.ts +2 -2
- package/out/typer/type-manager.d.ts.map +1 -1
- package/out/typer/type-manager.js +32 -9
- package/out/typer/type-manager.js.map +1 -1
- package/out/typer/type-predicate.d.ts +6 -1
- package/out/typer/type-predicate.d.ts.map +1 -1
- package/out/typer/type-predicate.js +22 -4
- package/out/typer/type-predicate.js.map +1 -1
- package/out/typer/typer.d.ts +27 -6
- package/out/typer/typer.d.ts.map +1 -1
- package/out/typer/typer.js +69 -18
- package/out/typer/typer.js.map +1 -1
- package/out/typer/unifier.d.ts +1 -1
- package/out/typer/unifier.d.ts.map +1 -1
- package/out/typer/unifier.js +48 -69
- package/out/typer/unifier.js.map +1 -1
- package/out/utils/string.d.ts.map +1 -1
- package/out/utils/string.js +1 -0
- package/out/utils/string.js.map +1 -1
- package/package.json +5 -5
- package/out/typer/nasl-predicate.d.ts +0 -8
- package/out/typer/nasl-predicate.d.ts.map +0 -1
- package/out/typer/nasl-predicate.js +0 -25
- 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.
|
|
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
|
|
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':
|
|
53
|
-
case '
|
|
54
|
-
case '
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
1275
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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,
|
|
1741
|
-
let exprRefinedTy = exprTy
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
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
|
-
|
|
1756
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1817
|
-
|
|
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
|
|
1837
|
-
|
|
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
|
-
|
|
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;
|