@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
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeErrTys = exports.tpEntityLogic = exports.tpCallInterface = exports.changeArgTyToParamTy = exports.determineCallLogicFnTy = exports.tpCallLogic = exports.tpCallFunction = void 0;
|
|
4
|
+
const fp_macros_1 = require("../utils/fp-macros");
|
|
5
|
+
const sem_diag_1 = require("./sem-diag");
|
|
6
|
+
const subster_1 = require("./subster");
|
|
7
|
+
const dispatch_stmt_1 = require("./dispatch-stmt");
|
|
8
|
+
const dispatch_def_1 = require("./dispatch-def");
|
|
9
|
+
const get_q_name_1 = require("../reference-manager/get-q-name");
|
|
10
|
+
const symbol_type_1 = require("../reference-manager/symbol-type");
|
|
11
|
+
const service_1 = require("@lcap/nasl-concepts/service");
|
|
12
|
+
const type_manager_1 = require("./type-manager");
|
|
13
|
+
const type_predicate_1 = require("./type-predicate");
|
|
14
|
+
const type_predicate_2 = require("./type-predicate");
|
|
15
|
+
const dispatch_process_1 = require("./dispatch-process");
|
|
16
|
+
const parseTsClassType_1 = require("../utils/parseTsClassType");
|
|
17
|
+
const types_1 = require("../utils/types");
|
|
18
|
+
const type_operator_1 = require("../utils/type-operator");
|
|
19
|
+
const overload_helper_1 = require("./overload-helper");
|
|
20
|
+
const dispatch_expr_1 = require("./dispatch-expr");
|
|
21
|
+
function tpCallFunction(env, nd, tgtTy) {
|
|
22
|
+
let calleeName = nd.calleeName;
|
|
23
|
+
if (!calleeName) {
|
|
24
|
+
env.addError('没有函数名,无法进行调用');
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
// 处理 enum 函数
|
|
28
|
+
if (parseTsClassType_1.enumBuiltinFns.includes(calleeName)) {
|
|
29
|
+
return handleEnumFn(env, nd, tgtTy);
|
|
30
|
+
}
|
|
31
|
+
// 前端全局类型推导 + 重载函数几乎无法做任何类型推导,只能做后置验证。后端可以推导,但简单起见,不区分前后端了。
|
|
32
|
+
// 总结:全局类型推导 + 重载 = 灾难
|
|
33
|
+
if (parseTsClassType_1.overloadedFns.includes(calleeName)) {
|
|
34
|
+
return handleOverloadedFunction(env, nd, tgtTy, calleeName);
|
|
35
|
+
}
|
|
36
|
+
const fnDef = env.quickGetLibDef(nd, calleeName, env.ctxCQC?.dataSourceSqlType);
|
|
37
|
+
let fnTy = fnDef?.__TypeAnnotation;
|
|
38
|
+
if (!fnTy) {
|
|
39
|
+
env.addError('无法找到函数定义(类型)');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (fnTy.typeParams?.length) {
|
|
43
|
+
fnTy = renameAndMakePartialTyApp(env, fnTy, nd);
|
|
44
|
+
}
|
|
45
|
+
for (const [idx, parTy] of fnTy.typeArguments.entries()) {
|
|
46
|
+
if (parTy.spread) { // 抽取 Array<T> 中的 T
|
|
47
|
+
const elemTy = parTy.typeArguments[0];
|
|
48
|
+
// 余下的一并处理
|
|
49
|
+
for (let i = idx; i < nd.arguments.length; ++i) {
|
|
50
|
+
/**
|
|
51
|
+
* ListSort 只能特殊处理了。
|
|
52
|
+
* nasl.util 里定义为 { asc: Boolean, by: Long | Decimal | ... } 的话会有匿名数据类型不匹配报错(invariance)
|
|
53
|
+
* 如果定义为泛型 T2 extends Long | Decimal | ... 且 { asc: Boolean, by: T2 } 的话 T2 不支持实例化成 Union
|
|
54
|
+
* (页面是全局求解,暂时不好区分 T2 的约束是来自多个赋值还是一个赋值,如果是多个则报错,如果是一个则使用 Union 作为解这种复杂的机制
|
|
55
|
+
*/
|
|
56
|
+
if (calleeName === 'ListSort' || calleeName === 'ListSortAsync') {
|
|
57
|
+
const expr = nd.arguments[i].expression;
|
|
58
|
+
// 抠出函数类型的参数和返回类型
|
|
59
|
+
if (!(0, type_predicate_2.isFuncTy)(elemTy)) {
|
|
60
|
+
continue; // 干不了了
|
|
61
|
+
}
|
|
62
|
+
const parTy = elemTy.typeArguments?.[0];
|
|
63
|
+
const retTy = elemTy.returnType?.[0];
|
|
64
|
+
// 留给 checker.ts 去做后置检查吧
|
|
65
|
+
if (expr?.concept === 'AnonymousFunction') {
|
|
66
|
+
(0, dispatch_expr_1.tpAnonymousFunction)(env, expr, (0, type_manager_1.createFnTyFromTyAnns)([parTy], undefined), true);
|
|
67
|
+
// dispatchExpr(env, expr.params[0], parTy);
|
|
68
|
+
// dispatchExpr(env, expr.body, retTy);
|
|
69
|
+
}
|
|
70
|
+
else if (expr?.concept === 'SubLogic') {
|
|
71
|
+
(0, dispatch_expr_1.tpSubLogic)(env, expr, (0, type_manager_1.createFnTyFromTyAnns)([parTy], undefined), true);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// 正常处理
|
|
76
|
+
(0, dispatch_expr_1.dispatchExpr)(env, nd.arguments[i], elemTy);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
(0, dispatch_expr_1.dispatchExpr)(env, nd.arguments[idx], parTy);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const finalRetTy = fnTy.returnType?.[0] ?? tgtTy;
|
|
85
|
+
env.unifier.unify(finalRetTy, tgtTy);
|
|
86
|
+
// TODO:处理可选参数必填选填问题
|
|
87
|
+
env.setType(nd, finalRetTy); // 似乎不可能为空
|
|
88
|
+
const callInfo = (0, type_manager_1.createFunctionDef)(fnTy.typeArguments, finalRetTy, fnDef, // 内置函数
|
|
89
|
+
fnTy.typeParams);
|
|
90
|
+
env.resolvedCallInfo.set(nd, callInfo);
|
|
91
|
+
return finalRetTy ?? type_manager_1.naslVoidTy;
|
|
92
|
+
function handleEnumFn(env, nd, tgtTy) {
|
|
93
|
+
const createAnonymousRetTy = (ty) => (0, type_manager_1.createAnonymousTyAnn)(['text', 'value'], [type_manager_1.naslStringTy, ty]);
|
|
94
|
+
let res = undefined;
|
|
95
|
+
let tyParam = undefined; // <T>. 但是是实例化后的
|
|
96
|
+
let paramTy = undefined; // (T)
|
|
97
|
+
let def = env.resolveRef(nd);
|
|
98
|
+
switch (nd.calleeName) {
|
|
99
|
+
// 暂时不合并代码了,也不是特别长
|
|
100
|
+
case 'EnumToList': {
|
|
101
|
+
if (!nd.typeArguments?.[0]) {
|
|
102
|
+
// 报错 缺参数
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
tyParam = nd.typeArguments[0];
|
|
106
|
+
const enumDef = env.resolveRef(nd.typeArguments[0]);
|
|
107
|
+
if (enumDef?.concept === 'Enum') {
|
|
108
|
+
const ty = enumDef.valueType ?? type_manager_1.naslStringTy; // FIXME:还能是空的,服了
|
|
109
|
+
res = (0, type_manager_1.createListTyAnn)(createAnonymousRetTy(ty));
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
env.addError((0, sem_diag_1.mkIncompatibleTyErr)(env, tyParam || type_manager_1.naslAnyTy, '枚举'), env.getCurFileNode(), nd);
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case 'ToEnumItem': {
|
|
117
|
+
if (!nd.typeArguments?.[0]) {
|
|
118
|
+
// 报错 缺参数
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
tyParam = nd.typeArguments[0];
|
|
122
|
+
const enumDef = env.resolveRef(tyParam);
|
|
123
|
+
if (enumDef?.concept === 'Enum') {
|
|
124
|
+
const exprTy = (0, dispatch_expr_1.dispatchExpr)(env, nd.arguments[0], enumDef.valueType ?? type_manager_1.naslStringTy);
|
|
125
|
+
res = env.getRawType(enumDef);
|
|
126
|
+
paramTy = exprTy;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
env.addError((0, sem_diag_1.mkIncompatibleTyErr)(env, tyParam || type_manager_1.naslAnyTy, '枚举'), env.getCurFileNode(), nd);
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case 'EnumItemToStructure': {
|
|
134
|
+
if (!nd.arguments?.[0]) {
|
|
135
|
+
// 报错 缺参数
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const exprTy = (0, dispatch_expr_1.dispatchExpr)(env, nd.arguments[0], undefined);
|
|
139
|
+
if (!exprTy) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
paramTy = exprTy;
|
|
143
|
+
const enumValueTy = (0, type_operator_1.createValueTypeForAssumedEnumTy)(exprTy);
|
|
144
|
+
const postChk = (fileNode, severity, exprTy) => (env, pSubst) => {
|
|
145
|
+
const ty = (0, subster_1.normalizeWithSubst)(env, pSubst, exprTy);
|
|
146
|
+
// 断言: 它是枚举类型
|
|
147
|
+
if (!(0, type_predicate_1.isEnumTy)(ty)) {
|
|
148
|
+
const errMsg = (0, sem_diag_1.mkIncompatibleTyErr)(env, ty || type_manager_1.naslAnyTy, '枚举');
|
|
149
|
+
env.addError(errMsg, fileNode, nd, severity);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
env.addPostCheckTask(env.errBoundary, postChk(env.getCurFileNode(), env.errSeverity, exprTy));
|
|
153
|
+
res = createAnonymousRetTy(enumValueTy);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case 'EnumItemToText': {
|
|
157
|
+
const exprTy = (0, dispatch_expr_1.dispatchExpr)(env, nd.arguments[0], undefined);
|
|
158
|
+
// 如果不是枚举类型就报错,稍后建立 List、Map、Enums 等通用检测机制
|
|
159
|
+
// FIXME zzr exprTy可能包含类型变元,此时无法立刻判断求解
|
|
160
|
+
paramTy = exprTy;
|
|
161
|
+
res = type_manager_1.naslStringTy;
|
|
162
|
+
const postChk = (fileNode, severity, exprTy) => (env, pSubst) => {
|
|
163
|
+
const ty = (0, subster_1.normalizeWithSubst)(env, pSubst, exprTy);
|
|
164
|
+
if (!(0, type_predicate_1.isEnumTy)(ty)) {
|
|
165
|
+
const errMsg = (0, sem_diag_1.mkIncompatibleTyErr)(env, ty || type_manager_1.naslAnyTy, '枚举');
|
|
166
|
+
env.addError(errMsg, fileNode, nd, severity);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
env.addPostCheckTask(env.errBoundary, postChk(env.getCurFileNode(), env.errSeverity, exprTy));
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
default: {
|
|
173
|
+
throw new Error(`未实现的 enum 枚举内置函数,函数名 ${nd.calleeName}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
env.unifier.unify(res, tgtTy);
|
|
177
|
+
const retTy = res ?? tgtTy;
|
|
178
|
+
env.setType(nd, retTy);
|
|
179
|
+
const callInfo = (0, type_manager_1.createFunctionDef)(paramTy ? [paramTy] : [], type_manager_1.naslBooleanTy, def, tyParam ? [tyParam] : []);
|
|
180
|
+
env.resolvedCallInfo.set(nd, callInfo);
|
|
181
|
+
return retTy;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.tpCallFunction = tpCallFunction;
|
|
185
|
+
function tpCallLogic(env, nd, tgtTy) {
|
|
186
|
+
if (!nd.calleeName) {
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
// 特殊处理咯 ad hoc treatment for entity logics
|
|
190
|
+
if (isEntityLogic(nd.calleeNamespace)) {
|
|
191
|
+
return tpEntityLogic(env, nd, tgtTy);
|
|
192
|
+
}
|
|
193
|
+
// 特殊处理咯,你自己看看你的 Call 的 NASL 和定义能对得上一毫米吗?
|
|
194
|
+
if (isLoggingLogic(nd.calleeNamespace)) {
|
|
195
|
+
// Use a different approach to avoid the parameter issues
|
|
196
|
+
for (const arg of nd.arguments) {
|
|
197
|
+
(0, dispatch_expr_1.dispatchExpr)(env, arg, type_manager_1.naslAnyTy);
|
|
198
|
+
}
|
|
199
|
+
env.setType(nd, type_manager_1.naslVoidTy);
|
|
200
|
+
return type_manager_1.naslVoidTy;
|
|
201
|
+
}
|
|
202
|
+
let def;
|
|
203
|
+
if (nd.calleeNamespace !== 'nasl.util') {
|
|
204
|
+
def = env.resolveRef(nd);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// 'nasl.util' 时 是 json 序列化
|
|
208
|
+
def = env.quickGetLibDef(nd, nd.calleeName, undefined);
|
|
209
|
+
}
|
|
210
|
+
// 处理调用处的验证规则
|
|
211
|
+
if (nd.validation?.rules && nd.validation.rules.length > 0 && def) {
|
|
212
|
+
def.params.forEach(param => (0, dispatch_def_1.dispatchDef)(env, param));
|
|
213
|
+
nd.validation?.rules?.forEach(rule => (0, dispatch_stmt_1.dispatchStmt)(env, rule));
|
|
214
|
+
def.params.forEach(env.removeLexicalSym);
|
|
215
|
+
}
|
|
216
|
+
if ((0, symbol_type_1.isProcessLogicCall)(nd.calleeNamespace) && (0, symbol_type_1.isSpecialProcessLogic)(nd.calleeName)) {
|
|
217
|
+
return (0, dispatch_process_1.tpSpecialProcessLogicCall)(env, nd, tgtTy);
|
|
218
|
+
}
|
|
219
|
+
// 余下的流程逻辑比较正常,就走正常的 CallLogic 处理流程好了
|
|
220
|
+
let fnTy = determineCallLogicFnTy(env, nd, def);
|
|
221
|
+
if (!fnTy) {
|
|
222
|
+
// TODO fnTy 可能为undefined 或 typeKind!=function, 需要考虑
|
|
223
|
+
env.addError(`无法找到逻辑 ${nd.calleeName}`);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (fnTy.typeParams?.length) {
|
|
227
|
+
fnTy = renameAndMakePartialTyApp(env, fnTy, nd);
|
|
228
|
+
}
|
|
229
|
+
// typing arguments
|
|
230
|
+
for (const [idx, parTy] of fnTy.typeArguments.entries()) {
|
|
231
|
+
// 先获取 param,因为 spread 属性在 param 上,而不是在 parTy 上
|
|
232
|
+
let param = def ? def.params?.[idx] : undefined;
|
|
233
|
+
if (param?.spread) {
|
|
234
|
+
// 按照约定,spread为true时,其上TypeAnnotation就已经是List<T>中的T。
|
|
235
|
+
// CallFunction因为大都是从TS parse出来,原样写入List<T>,因此可以看到tpCallFunction中仍然获取了List中的T
|
|
236
|
+
// TODO 修正 spread 相关的 TS parse,让两边一致
|
|
237
|
+
const elemTy = parTy;
|
|
238
|
+
// 余下的一并处理
|
|
239
|
+
for (let i = idx; i < nd.arguments.length; ++i) {
|
|
240
|
+
const arg = nd.arguments[i];
|
|
241
|
+
if (arg?.expression) {
|
|
242
|
+
(0, dispatch_expr_1.dispatchExpr)(env, arg, elemTy);
|
|
243
|
+
changeArgTyToParamTy(env, arg, elemTy);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
env.setType(arg, type_manager_1.naslAnyTy);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
break; // spread 参数处理完毕,跳出循环
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
// TODO: json序列化等没有 def,导致 param 直接 undefined
|
|
253
|
+
const arg = nd.arguments[idx];
|
|
254
|
+
if (!arg) {
|
|
255
|
+
env.setType(nd, type_manager_1.naslAnyTy);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (arg?.expression) {
|
|
259
|
+
(0, dispatch_expr_1.dispatchExpr)(env, arg, parTy);
|
|
260
|
+
changeArgTyToParamTy(env, arg, parTy);
|
|
261
|
+
}
|
|
262
|
+
else if (param) {
|
|
263
|
+
if (param.optional || parTy.optional) { // 组件逻辑等现在没有 def,用 type 判断
|
|
264
|
+
env.setType(arg, parTy);
|
|
265
|
+
}
|
|
266
|
+
else if (param.defaultValue?.expression) {
|
|
267
|
+
env.setType(arg, parTy);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
// 报错:泛型逻辑调用,最后的 callInfo 里有 type variables,会被判定为 unresolved,目前不检查 arg 会缺少报错
|
|
271
|
+
// env.addError(`调用逻辑:参数不能为空`, env.getCurFileNode(), arg);
|
|
272
|
+
env.setType(arg, type_manager_1.naslAnyTy);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
// 报错
|
|
277
|
+
env.setType(arg, type_manager_1.naslAnyTy);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
let finalRetTy = fnTy.returnType?.[0];
|
|
282
|
+
// CallConnector 不支持 handleError 错误处理参数
|
|
283
|
+
if (nd.concept !== 'CallConnector') {
|
|
284
|
+
if (nd.handleError === true) {
|
|
285
|
+
(0, dispatch_expr_1.dispatchExpr)(env, nd.errorMessage, undefined);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
// 做了手动处理 Error 需求后,需要 remove Error types from return types
|
|
289
|
+
finalRetTy = (0, exports.removeErrTys)(env, nd, fnTy?.returnType?.[0]);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
env.unifier.unify(finalRetTy, tgtTy);
|
|
293
|
+
env.setType(nd, finalRetTy);
|
|
294
|
+
// 给 checker 报错用,都给吧,CallLogic 也有要处理 Error | T 返回类型的复杂情形,checker 直接拿结果就行不用重复处理
|
|
295
|
+
// TODO: 前端的部分组件逻辑好像指飞了(env.resoleRef 和 env.resolvedCallInfo 结果不一样)……先用 !env.isView 判断一下
|
|
296
|
+
if (!env.isView || nd.calleeNamespace === 'nasl.util') { // json 序列化 - similarly add param info for nasl.util
|
|
297
|
+
const callInfo = (0, type_manager_1.createFunctionDef)(fnTy.typeArguments, finalRetTy, def, fnTy.typeParams);
|
|
298
|
+
env.resolvedCallInfo.set(nd, callInfo);
|
|
299
|
+
}
|
|
300
|
+
if (fnTy.typeParams?.length) {
|
|
301
|
+
env.addPostCheckTask(nd, (e, pSubst) => {
|
|
302
|
+
// 写入 __TypeArguments 字段,调用泛型依赖库时,代码生成要用。
|
|
303
|
+
const typeArgs = fnTy?.typeParams
|
|
304
|
+
?.map((x) => {
|
|
305
|
+
return e.getType(pSubst(x));
|
|
306
|
+
})
|
|
307
|
+
.filter(types_1.isNotNil) ?? [];
|
|
308
|
+
// 写入来自:_getQuickInfoNodesTypeMapWithGenerator
|
|
309
|
+
nd.__TypeArguments = typeArgs;
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
return finalRetTy ?? type_manager_1.naslVoidTy;
|
|
313
|
+
}
|
|
314
|
+
exports.tpCallLogic = tpCallLogic;
|
|
315
|
+
// sharedApp.appshare.dataSources.defaultDS.entities.EntityShare1.logics
|
|
316
|
+
const sharedEntityLogicReg = /sharedApp\.[^.]+\.dataSources\.[^.]+\.entities\.[^.]+\.logics/;
|
|
317
|
+
function isEntityLogic(nsp) {
|
|
318
|
+
return nsp.startsWith('app.dataSources.') && nsp.endsWith('logics') && /\.entities\./.test(nsp)
|
|
319
|
+
|| sharedEntityLogicReg.test(nsp);
|
|
320
|
+
}
|
|
321
|
+
function isLoggingLogic(nsp) {
|
|
322
|
+
return nsp === 'nasl.logging';
|
|
323
|
+
}
|
|
324
|
+
function determineCallLogicFnTy(env, nd, def) {
|
|
325
|
+
if (def && (0, service_1.isCallableNaslLogic)(def)) {
|
|
326
|
+
// TODO zzr 需要用个 cache 加快速度吗
|
|
327
|
+
return env.getRawType(def);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
const qName = (0, get_q_name_1.getTokenQualifiedName)(nd);
|
|
331
|
+
if (!qName) {
|
|
332
|
+
return undefined;
|
|
333
|
+
}
|
|
334
|
+
const placeholderFnTy = createAndSetForwardReferencePlaceholder(env, nd);
|
|
335
|
+
// @ts-expect-error
|
|
336
|
+
if (def?.concept === 'TypeAnnotation') {
|
|
337
|
+
// 令根据根据本次 Call 计算得出的类型为 placeholderFnTy
|
|
338
|
+
// 所有出现 placeholderFnTy 的地方,都可以被 def 替换,因此 def 为 placeholderFnTy 的子类型
|
|
339
|
+
env.unifier.unify(def, placeholderFnTy);
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
if (env.isDebugMode) {
|
|
343
|
+
// FIXME wudengke 修复use before def的问题,debug模式下先报出来。
|
|
344
|
+
env.addDiagnosticsFor(`[DEBUG] determineCallLogicFnTy: 可能出现了use before def。 ${qName}`, nd);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return placeholderFnTy;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
exports.determineCallLogicFnTy = determineCallLogicFnTy;
|
|
351
|
+
function changeArgTyToParamTy(env, nd, parTy) {
|
|
352
|
+
// 初始时, nd.type === nd.expression.type
|
|
353
|
+
// FIXME: 例如后端需要 argument.type 与 argument.expression.type 不一样做 long -> decimal 的强制转换
|
|
354
|
+
// 这里有个问题,JSON 序列化不是 CallFunction 是 CallLogic,所以会走到这里
|
|
355
|
+
// 但是它 的 paramTy 是 NASL 不存在的类型 Any,炸裂还是得用 argTy
|
|
356
|
+
if (!(0, type_predicate_2.isAnyTy)(parTy)) {
|
|
357
|
+
env.setType(nd, parTy);
|
|
358
|
+
}
|
|
359
|
+
// Magic!
|
|
360
|
+
nd.paramTypeAnnotation = parTy;
|
|
361
|
+
}
|
|
362
|
+
exports.changeArgTyToParamTy = changeArgTyToParamTy;
|
|
363
|
+
function renameAndMakePartialTyApp(env, fnTy, nd) {
|
|
364
|
+
// 先 rename bound type variables
|
|
365
|
+
if ((0, type_predicate_1.isUnResolvedTy)(fnTy)) {
|
|
366
|
+
fnTy = (0, type_manager_1.copyTyAnn)(fnTy);
|
|
367
|
+
env.unifier.inPlaceRenameTy(fnTy);
|
|
368
|
+
}
|
|
369
|
+
// 再做 type arguments partial application
|
|
370
|
+
// 用户选定部分 type params,这一块 Java 依赖库好像还有特殊处理,估计之后要大改
|
|
371
|
+
// 事实证明 Add 这种函数 nd.typeArguments 是 null 不是空数组 []
|
|
372
|
+
if (nd.typeArguments && nd.typeArguments.length > 0) {
|
|
373
|
+
if (fnTy.typeParams) {
|
|
374
|
+
const subst = new Map();
|
|
375
|
+
nd.typeArguments.forEach((ty, idx) => {
|
|
376
|
+
if (ty.typeName && ty.typeKind) {
|
|
377
|
+
fnTy.typeParams[idx] && subst.set(fnTy.typeParams[idx].typeName, ty);
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
fnTy.typeParams = fnTy.typeParams.map((0, subster_1.substTyAnn)(env, subst));
|
|
381
|
+
fnTy = (0, subster_1.substTyAnn)(env, subst)(fnTy);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return fnTy;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* 处理重载函数的调用
|
|
388
|
+
* @param env 语义环境
|
|
389
|
+
* @param nd 函数调用节点
|
|
390
|
+
* @param tgtTy 目标类型
|
|
391
|
+
* @param calleeName 被调用函数名
|
|
392
|
+
* @returns 处理后的类型注解
|
|
393
|
+
*/
|
|
394
|
+
const handleOverloadedFunction = (env, nd, tgtTy, calleeName) => {
|
|
395
|
+
const ovParamIdx = (0, overload_helper_1.getOvParamIdx)(calleeName);
|
|
396
|
+
const argTys = [];
|
|
397
|
+
for (const arg of nd.arguments) {
|
|
398
|
+
argTys.push((0, dispatch_expr_1.dispatchExpr)(env, arg, undefined) ?? type_manager_1.naslAnyTy);
|
|
399
|
+
}
|
|
400
|
+
if (calleeName === 'CAST') {
|
|
401
|
+
argTys[ovParamIdx] = (0, overload_helper_1.createCastLiteralType)(nd.arguments?.[ovParamIdx]?.expression?.value ?? '');
|
|
402
|
+
}
|
|
403
|
+
// Convert, Length, CAST 的返回类型可以从用户选择的类型(通过 type picker)拿到
|
|
404
|
+
// 其他重载函数都在 SQL 里,都在服务端逻辑里,可以立即从参数类型获得,没有页面全局类型推导的问题
|
|
405
|
+
let retTy = (0, overload_helper_1.getOverloadFuncRetTy)(nd, argTys[ovParamIdx]);
|
|
406
|
+
if (!retTy) {
|
|
407
|
+
if (!env.isView) {
|
|
408
|
+
const mangledCalleeName = (0, overload_helper_1.mangleOvFnName)(calleeName, argTys[ovParamIdx]);
|
|
409
|
+
const fnDef = env.quickGetLibDef(nd, mangledCalleeName, env.ctxCQC?.dataSourceSqlType);
|
|
410
|
+
const fnTy = fnDef?.__TypeAnnotation;
|
|
411
|
+
retTy = fnTy?.returnType?.[0];
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
retTy = type_manager_1.naslAnyTy;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
env.unifier.unify(retTy, tgtTy);
|
|
418
|
+
const callInfo = (0, type_manager_1.createFunctionDef)(argTys, retTy, undefined, undefined);
|
|
419
|
+
env.resolvedCallInfo.set(nd, callInfo);
|
|
420
|
+
const capturedDbSqlType = env.ctxCQC?.dataSourceSqlType;
|
|
421
|
+
// 剩下的需要后置处理
|
|
422
|
+
const postChk = (fileNode, errBoundary, severity) => (env) => {
|
|
423
|
+
const argTys = nd.arguments.map((arg) => env.getType(arg.expression));
|
|
424
|
+
if (calleeName === 'CAST') {
|
|
425
|
+
argTys[ovParamIdx] = (0, overload_helper_1.createCastLiteralType)(nd.arguments?.[ovParamIdx]?.expression?.value ?? '');
|
|
426
|
+
}
|
|
427
|
+
const ovArgTy = argTys[ovParamIdx];
|
|
428
|
+
const mangledCalleeName = (0, overload_helper_1.mangleOvFnName)(calleeName, ovArgTy);
|
|
429
|
+
let fnDef = mangledCalleeName ? env.quickGetLibDef(nd, mangledCalleeName, capturedDbSqlType) : undefined;
|
|
430
|
+
let fnTy = fnDef?.__TypeAnnotation;
|
|
431
|
+
// If no matching overload found, validate and report error
|
|
432
|
+
if (!fnDef || !fnTy) {
|
|
433
|
+
// Create fallback definition to prevent further errors
|
|
434
|
+
const fallbackDef = (0, overload_helper_1.createFallbackOverloadDef)(calleeName, nd.calleeNamespace, nd.arguments.length);
|
|
435
|
+
fnDef = fallbackDef;
|
|
436
|
+
fnTy = fallbackDef.__TypeAnnotation;
|
|
437
|
+
// Convert 允许接收任何类型,跳过报错(mangled name convertList convertMap 等查不到定义会产生额外错误)
|
|
438
|
+
if (calleeName !== 'Convert') {
|
|
439
|
+
const possibleTypes = (0, overload_helper_1.getOverloadParameterTypes)(env, nd, capturedDbSqlType);
|
|
440
|
+
if (possibleTypes.length > 0) {
|
|
441
|
+
const errorMsg = (0, sem_diag_1.createOverloadTypeError)(calleeName, ovArgTy, possibleTypes);
|
|
442
|
+
// precise error boundary nd.arguments[i]! is not working here, why?
|
|
443
|
+
env.addError(errorMsg, fileNode, errBoundary, severity);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
// 后置类型校验,暂时都不需要,不可能报错
|
|
448
|
+
// for (let i = 0; i < argTys.length && i < (fnTy?.typeArguments?.length ?? 0); ++i) {
|
|
449
|
+
// const sub = argTys[i];
|
|
450
|
+
// const sup = fnTy!.typeArguments![i];
|
|
451
|
+
// if (!isSubTy(env, sub, sup)) { // precise error boundary nd.arguments[i]! is not working here, why?
|
|
452
|
+
// env.addError(mkIncompatibleTyErr(env, sub, sup), fileNode, errBoundary, severity);
|
|
453
|
+
// }
|
|
454
|
+
// }
|
|
455
|
+
};
|
|
456
|
+
env.addPostCheckTask(nd, postChk(env.getCurFileNode(), nd, env.errSeverity));
|
|
457
|
+
env.setType(nd, retTy); // 似乎不可能为空
|
|
458
|
+
return env.getRawType(nd);
|
|
459
|
+
};
|
|
460
|
+
function tpCallInterface(env, nd, tgtTy) {
|
|
461
|
+
const def = env.resolveRef(nd);
|
|
462
|
+
if (!def) {
|
|
463
|
+
env.setType(nd, type_manager_1.naslAnyTy);
|
|
464
|
+
return type_manager_1.naslAnyTy;
|
|
465
|
+
}
|
|
466
|
+
// 说起来你可能不信,但是事实令人震惊,参数与形参的顺序是乱的,仅能通过 keyword 来匹配
|
|
467
|
+
for (const param of def.params) {
|
|
468
|
+
(0, dispatch_expr_1.dispatchExpr)(env, nd.arguments.find(p => p.keyword === param.name), param.typeAnnotation);
|
|
469
|
+
}
|
|
470
|
+
const retTy = def.returns?.[0]?.typeAnnotation;
|
|
471
|
+
const finalRetTy = nd?.handleError === true
|
|
472
|
+
? (retTy ? (0, type_manager_1.createUnionTyAnn)([retTy, type_manager_1.naslInterfaceError]) : type_manager_1.naslInterfaceError)
|
|
473
|
+
: (retTy ?? tgtTy);
|
|
474
|
+
env.setType(nd, finalRetTy);
|
|
475
|
+
env.unifier.unify(finalRetTy, tgtTy);
|
|
476
|
+
if (!env.isView) {
|
|
477
|
+
const callInfo = (0, type_manager_1.createFunctionDef)(def.params.map(p => p.typeAnnotation), finalRetTy, def, undefined);
|
|
478
|
+
env.resolvedCallInfo.set(nd, callInfo);
|
|
479
|
+
}
|
|
480
|
+
return finalRetTy ?? type_manager_1.naslVoidTy;
|
|
481
|
+
}
|
|
482
|
+
exports.tpCallInterface = tpCallInterface;
|
|
483
|
+
// 一看 NASL 便知
|
|
484
|
+
function tpEntityLogic(env, nd, tgtTy) {
|
|
485
|
+
const def = env.resolveRef(nd);
|
|
486
|
+
if (!def) {
|
|
487
|
+
env.setType(nd, type_manager_1.naslAnyTy);
|
|
488
|
+
return type_manager_1.naslAnyTy;
|
|
489
|
+
}
|
|
490
|
+
// 例如 app.dataSources.${dbName}.entities.${entityName}
|
|
491
|
+
// 从 'a.b.c.logics.e' 中提取 'a.b.c'
|
|
492
|
+
const getEntityQName = (ctxCallLogic) => {
|
|
493
|
+
const qualifiedNames = (0, get_q_name_1.getTokenQualifiedName)(ctxCallLogic);
|
|
494
|
+
const parts = qualifiedNames.split('.');
|
|
495
|
+
return parts.slice(0, parts.length - 2).join('.');
|
|
496
|
+
};
|
|
497
|
+
const calleeName = nd.calleeName;
|
|
498
|
+
const entityDef = env.refMgr.gQNameDefs.get(getEntityQName(nd));
|
|
499
|
+
const entityPrimaryKeys = entityDef?.properties.filter(p => p.primaryKey) ?? [];
|
|
500
|
+
const entityRefTy = entityDef ? (0, type_manager_1.createRefTyAnnFromDef)(entityDef, env) ?? type_manager_1.naslAnyTy : type_manager_1.naslAnyTy;
|
|
501
|
+
const entityOrErrTy = entityRefTy ? (0, type_manager_1.createUnionTyAnn)([entityRefTy, type_manager_1.naslDatabaseDuplicateKeyError]) : undefined;
|
|
502
|
+
const listEntityRefTy = (0, type_manager_1.createListTyAnn)(entityRefTy);
|
|
503
|
+
// pre-determined type of arguments[0]
|
|
504
|
+
const getArg0TgtTy = () => {
|
|
505
|
+
const fstPrimaryKeyTy = entityDef?.properties.find(p => p.primaryKey)?.typeAnnotation;
|
|
506
|
+
switch (calleeName) {
|
|
507
|
+
case 'get': return fstPrimaryKeyTy; // 主键类型
|
|
508
|
+
case 'create': return entityRefTy;
|
|
509
|
+
case 'delete': return fstPrimaryKeyTy; // 主键类型
|
|
510
|
+
case 'update': return entityRefTy;
|
|
511
|
+
case 'createOrUpdate': return entityRefTy;
|
|
512
|
+
case 'updateBy': return (0, type_manager_1.createFnTyFromTyAnns)([entityRefTy ?? type_manager_1.naslAnyTy], type_manager_1.naslBooleanTy);
|
|
513
|
+
case 'deleteBy': return (0, type_manager_1.createFnTyFromTyAnns)([entityRefTy ?? type_manager_1.naslAnyTy], type_manager_1.naslBooleanTy);
|
|
514
|
+
case 'batchCreate': return listEntityRefTy;
|
|
515
|
+
case 'batchUpdate': return listEntityRefTy;
|
|
516
|
+
case 'batchDelete': return (0, type_manager_1.createListTyAnn)(fstPrimaryKeyTy ?? type_manager_1.naslAnyTy); // 主键类型
|
|
517
|
+
case 'import': return type_manager_1.naslBinaryTy;
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
const paramTys = new Array();
|
|
521
|
+
const arg0TgtTy = getArg0TgtTy();
|
|
522
|
+
paramTys.push(arg0TgtTy ?? type_manager_1.naslAnyTy);
|
|
523
|
+
env.ctxTpEntityTy = entityRefTy;
|
|
524
|
+
nd.arguments[0] && (0, dispatch_expr_1.dispatchExpr)(env, nd.arguments[0], arg0TgtTy);
|
|
525
|
+
if (calleeName === 'updateBy' || calleeName === 'deleteBy') {
|
|
526
|
+
const arg1TgtTy = entityRefTy;
|
|
527
|
+
if (nd.arguments[1]) {
|
|
528
|
+
const arg1Ty = (0, dispatch_expr_1.dispatchExpr)(env, nd.arguments[1], arg1TgtTy);
|
|
529
|
+
paramTys.push(arg1Ty ?? arg1TgtTy ?? type_manager_1.naslAnyTy);
|
|
530
|
+
}
|
|
531
|
+
// 这里不能直接 dispatchExpr(callee.arguments[2]),因为里面藏了个非标准的 NewList,元素因为没有公共父类型而会报错,下同
|
|
532
|
+
const fnDef = nd.arguments[2]?.expression;
|
|
533
|
+
// NASL 实在是太 🐂🍺 拉,到处都是 NewList,人间处处皆学问!
|
|
534
|
+
const fnBody = fnDef?.body;
|
|
535
|
+
if (fnBody?.items) {
|
|
536
|
+
const paramItem = fnDef?.params?.[0];
|
|
537
|
+
checkItemMemExprTy(paramItem, fnBody?.items);
|
|
538
|
+
// FIXME: 只能说是强行保持一致
|
|
539
|
+
env.setType(nd.arguments[2], type_manager_1.naslStringTy);
|
|
540
|
+
paramTys.push(type_manager_1.naslStringTy);
|
|
541
|
+
const itemTys = fnBody?.items?.map(item => env.getRawType(item) ?? type_manager_1.naslAnyTy);
|
|
542
|
+
const bodyListUnionTy = (0, type_manager_1.createListTyAnn)((0, type_manager_1.createUnionTyAnnIfNecessary)(env, itemTys));
|
|
543
|
+
env.setType(fnBody, bodyListUnionTy);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
else if (calleeName === 'update' || calleeName === 'batchUpdate') {
|
|
547
|
+
const fnDef = nd.arguments[1]?.expression;
|
|
548
|
+
const fnBody = fnDef?.body;
|
|
549
|
+
if (fnBody?.items) {
|
|
550
|
+
const paramItem = fnDef?.params?.[0];
|
|
551
|
+
checkItemMemExprTy(paramItem, fnBody?.items);
|
|
552
|
+
// FIXME: 只能说是强行保持一致
|
|
553
|
+
env.setType(nd.arguments[1], type_manager_1.naslStringTy);
|
|
554
|
+
paramTys.push(type_manager_1.naslStringTy);
|
|
555
|
+
const itemTys = fnBody?.items?.map(item => env.getRawType(item) ?? type_manager_1.naslAnyTy);
|
|
556
|
+
const bodyListUnionTy = (0, type_manager_1.createListTyAnn)((0, type_manager_1.createUnionTyAnnIfNecessary)(env, itemTys));
|
|
557
|
+
env.setType(fnBody, bodyListUnionTy);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
else if ((calleeName === 'get' || calleeName === 'delete') && entityPrimaryKeys.length > 1) {
|
|
561
|
+
// 处理多主键
|
|
562
|
+
for (let i = 1; i < entityPrimaryKeys.length; i++) {
|
|
563
|
+
const argTgtTy = entityPrimaryKeys[i].typeAnnotation;
|
|
564
|
+
if (nd.arguments[i]) {
|
|
565
|
+
(0, dispatch_expr_1.dispatchExpr)(env, nd.arguments[i], argTgtTy);
|
|
566
|
+
paramTys.push(argTgtTy ?? type_manager_1.naslAnyTy);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
env.ctxTpEntityTy = undefined;
|
|
571
|
+
const retTy = getRetTy();
|
|
572
|
+
const finalRetTy = nd.handleError === true
|
|
573
|
+
? retTy
|
|
574
|
+
// 做了手动处理 Error 需求后,需要 remove Error types from return types
|
|
575
|
+
: (0, exports.removeErrTys)(env, nd, retTy);
|
|
576
|
+
nd.handleError === true && (0, dispatch_expr_1.dispatchExpr)(env, nd.errorMessage, undefined);
|
|
577
|
+
env.setType(nd, finalRetTy);
|
|
578
|
+
env.unifier.unify(finalRetTy, tgtTy);
|
|
579
|
+
// Create a mock definition for entity logics
|
|
580
|
+
const mockDef = { params: paramTys.map(() => ({ optional: false })) };
|
|
581
|
+
const callInfo = (0, type_manager_1.createFunctionDef)(paramTys, finalRetTy, mockDef, undefined);
|
|
582
|
+
env.resolvedCallInfo.set(nd, callInfo);
|
|
583
|
+
return finalRetTy ?? type_manager_1.naslVoidTy;
|
|
584
|
+
function getRetTy() {
|
|
585
|
+
switch (calleeName) {
|
|
586
|
+
case 'get': return entityRefTy;
|
|
587
|
+
case 'create': return entityOrErrTy; // 带个 Error 类型
|
|
588
|
+
case 'delete': return type_manager_1.naslLongTy; // 现在如此
|
|
589
|
+
case 'update': return entityRefTy;
|
|
590
|
+
case 'createOrUpdate': return entityOrErrTy; // 带个 Error 类型
|
|
591
|
+
case 'updateBy': return type_manager_1.naslLongTy;
|
|
592
|
+
case 'deleteBy': return type_manager_1.naslLongTy;
|
|
593
|
+
case 'batchCreate': return listEntityRefTy;
|
|
594
|
+
case 'batchUpdate': return listEntityRefTy;
|
|
595
|
+
case 'batchDelete': return type_manager_1.naslLongTy;
|
|
596
|
+
case 'import': return type_manager_1.naslStringTy;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
function checkItemMemExprTy(paramItem, itemMemExprs) {
|
|
600
|
+
// FIXME
|
|
601
|
+
(0, dispatch_def_1.dispatchDef)(env, paramItem);
|
|
602
|
+
itemMemExprs.forEach(expr => (0, dispatch_expr_1.dispatchExpr)(env, expr, undefined));
|
|
603
|
+
env.removeLexicalSym(paramItem);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
exports.tpEntityLogic = tpEntityLogic;
|
|
607
|
+
// 特性:支持 forward reference (处理一个尚未读到定义的 Callee)
|
|
608
|
+
// 尝试创建一个函数类型placeholderFnTy,并和qName关联起来。
|
|
609
|
+
// 1. 之后遇到callee定义的时候再进行检查
|
|
610
|
+
// 2. 如果在一个批次检查后这个callee仍然没有定义,那么报错
|
|
611
|
+
/**
|
|
612
|
+
* 创建前向引用占位符(简单的函数类型)
|
|
613
|
+
*/
|
|
614
|
+
function createAndSetForwardReferencePlaceholder(env, nd) {
|
|
615
|
+
// 为每个参数创建一个新的类型变量
|
|
616
|
+
const paramTypes = nd.arguments.map(() => env.unifier.nextFreshTyAnn('free'));
|
|
617
|
+
// 为返回值创建一个新的类型变量
|
|
618
|
+
const returnType = env.unifier.nextFreshTyAnn('free');
|
|
619
|
+
const placeholderFnTy = (0, type_manager_1.createFnTyFromTyAnns)(paramTypes, returnType);
|
|
620
|
+
return placeholderFnTy;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* 处理函数返回类型,过滤错误类型并设置节点类型
|
|
624
|
+
*/
|
|
625
|
+
const removeErrTys = (env, nd, retTy) => {
|
|
626
|
+
let finalRetTy = retTy;
|
|
627
|
+
if (finalRetTy && finalRetTy.typeKind === 'union') {
|
|
628
|
+
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));
|
|
629
|
+
}
|
|
630
|
+
// @ts-ignore
|
|
631
|
+
if ((0, type_predicate_1.isUnionTy)(finalRetTy) && !finalRetTy.typeArguments?.length) {
|
|
632
|
+
return type_manager_1.naslVoidTy; // createUnionTyAnnIfNecessary 得到 Union<> 时表示无返回类型
|
|
633
|
+
}
|
|
634
|
+
return finalRetTy;
|
|
635
|
+
};
|
|
636
|
+
exports.removeErrTys = removeErrTys;
|
|
637
|
+
//# sourceMappingURL=dispatch-call.js.map
|