@lcap/nasl-language-server-core 4.4.0-beta.3 → 4.4.0-beta.31
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 +4 -1
- package/out/checker.d.ts.map +1 -1
- package/out/checker.js +996 -96
- package/out/checker.js.map +1 -1
- package/out/index.d.ts +1 -1
- package/out/index.d.ts.map +1 -1
- package/out/index.js +5 -3
- package/out/index.js.map +1 -1
- package/out/reference-manager/build-q-name-def.d.ts.map +1 -1
- package/out/reference-manager/build-q-name-def.js +11 -0
- package/out/reference-manager/build-q-name-def.js.map +1 -1
- package/out/reference-manager/builtin-q-name.js +2 -2
- package/out/reference-manager/builtin-q-name.js.map +1 -1
- package/out/reference-manager/collect-q-name.d.ts +1 -1
- package/out/reference-manager/collect-q-name.d.ts.map +1 -1
- package/out/reference-manager/collect-q-name.js +64 -27
- package/out/reference-manager/collect-q-name.js.map +1 -1
- package/out/reference-manager/def-key-helpers.d.ts +38 -0
- package/out/reference-manager/def-key-helpers.d.ts.map +1 -0
- package/out/reference-manager/{get-q-name.js → def-key-helpers.js} +195 -23
- package/out/reference-manager/def-key-helpers.js.map +1 -0
- package/out/reference-manager/helper.js +2 -2
- package/out/reference-manager/helper.js.map +1 -1
- package/out/reference-manager/reference-manager.d.ts +146 -47
- package/out/reference-manager/reference-manager.d.ts.map +1 -1
- package/out/reference-manager/reference-manager.js +632 -204
- package/out/reference-manager/reference-manager.js.map +1 -1
- package/out/reference-manager/remove-q-name.d.ts +1 -1
- package/out/reference-manager/remove-q-name.d.ts.map +1 -1
- package/out/reference-manager/remove-q-name.js +14 -14
- package/out/reference-manager/remove-q-name.js.map +1 -1
- package/out/reference-manager/rename-q-name.d.ts +26 -26
- package/out/reference-manager/rename-q-name.d.ts.map +1 -1
- package/out/reference-manager/rename-q-name.js +48 -167
- package/out/reference-manager/rename-q-name.js.map +1 -1
- package/out/reference-manager/symbol-type.d.ts +8 -3
- package/out/reference-manager/symbol-type.d.ts.map +1 -1
- package/out/reference-manager/symbol-type.js +9 -2
- package/out/reference-manager/symbol-type.js.map +1 -1
- package/out/reference-manager/update-nasl-fragment.d.ts +2 -2
- package/out/reference-manager/update-nasl-fragment.d.ts.map +1 -1
- package/out/reference-manager/update-nasl-fragment.js +33 -28
- package/out/reference-manager/update-nasl-fragment.js.map +1 -1
- package/out/services/bindable-logic-service.js.map +1 -1
- package/out/symbol/traverse/concepts/index.d.ts +1 -1
- package/out/symbol/traverse/concepts/index.d.ts.map +1 -1
- package/out/symbol/traverse/concepts/logic/expression/member-expression.js.map +1 -1
- package/out/typer/collectGlobalDefs.d.ts +8 -0
- package/out/typer/collectGlobalDefs.d.ts.map +1 -1
- package/out/typer/collectGlobalDefs.js +102 -54
- package/out/typer/collectGlobalDefs.js.map +1 -1
- package/out/typer/component-def-manager/component-def-manager.d.ts +16 -0
- package/out/typer/component-def-manager/component-def-manager.d.ts.map +1 -1
- package/out/typer/component-def-manager/component-def-manager.js +63 -2
- package/out/typer/component-def-manager/component-def-manager.js.map +1 -1
- package/out/typer/component-def-manager/utils.d.ts.map +1 -1
- package/out/typer/component-def-manager/utils.js +26 -0
- package/out/typer/component-def-manager/utils.js.map +1 -1
- package/out/typer/dispatch-all.d.ts +3 -1
- package/out/typer/dispatch-all.d.ts.map +1 -1
- package/out/typer/dispatch-all.js +51 -6
- package/out/typer/dispatch-all.js.map +1 -1
- package/out/typer/dispatch-call.d.ts +27 -1
- package/out/typer/dispatch-call.d.ts.map +1 -1
- package/out/typer/dispatch-call.js +151 -107
- package/out/typer/dispatch-call.js.map +1 -1
- package/out/typer/dispatch-def.d.ts.map +1 -1
- package/out/typer/dispatch-def.js +51 -23
- package/out/typer/dispatch-def.js.map +1 -1
- package/out/typer/dispatch-expr.d.ts +2 -1
- package/out/typer/dispatch-expr.d.ts.map +1 -1
- package/out/typer/dispatch-expr.js +240 -199
- package/out/typer/dispatch-expr.js.map +1 -1
- package/out/typer/dispatch-process.d.ts +8 -1
- package/out/typer/dispatch-process.d.ts.map +1 -1
- package/out/typer/dispatch-process.js +37 -4
- 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 -25
- package/out/typer/dispatch-stmt.js.map +1 -1
- package/out/typer/dispatch-view.d.ts +1 -1
- package/out/typer/dispatch-view.d.ts.map +1 -1
- package/out/typer/dispatch-view.js +87 -48
- package/out/typer/dispatch-view.js.map +1 -1
- package/out/typer/fix-use-before-assign.js.map +1 -1
- package/out/typer/get-oql-files.d.ts.map +1 -1
- package/out/typer/get-oql-files.js +3 -9
- package/out/typer/get-oql-files.js.map +1 -1
- package/out/typer/incremental-update.d.ts +14 -7
- package/out/typer/incremental-update.d.ts.map +1 -1
- package/out/typer/incremental-update.js +396 -43
- package/out/typer/incremental-update.js.map +1 -1
- package/out/typer/oql-checker/chain-call-transformer.d.ts.map +1 -1
- package/out/typer/oql-checker/chain-call-transformer.js +17 -4
- package/out/typer/oql-checker/chain-call-transformer.js.map +1 -1
- package/out/typer/oql-checker/ts-parser.d.ts.map +1 -1
- package/out/typer/oql-checker/ts-parser.js +252 -37
- package/out/typer/oql-checker/ts-parser.js.map +1 -1
- package/out/typer/overload-helper.d.ts.map +1 -1
- package/out/typer/overload-helper.js +190 -23
- package/out/typer/overload-helper.js.map +1 -1
- package/out/typer/solver.d.ts +8 -9
- package/out/typer/solver.d.ts.map +1 -1
- package/out/typer/solver.js +54 -31
- package/out/typer/solver.js.map +1 -1
- package/out/typer/subster.d.ts +1 -1
- package/out/typer/subster.d.ts.map +1 -1
- package/out/typer/subster.js +251 -57
- package/out/typer/subster.js.map +1 -1
- package/out/typer/topo-sort.d.ts +38 -0
- package/out/typer/topo-sort.d.ts.map +1 -1
- package/out/typer/topo-sort.js +272 -3
- package/out/typer/topo-sort.js.map +1 -1
- package/out/typer/type-manager.d.ts +1 -0
- package/out/typer/type-manager.d.ts.map +1 -1
- package/out/typer/type-manager.js +14 -11
- package/out/typer/type-manager.js.map +1 -1
- package/out/typer/type-predicate.d.ts +1 -0
- package/out/typer/type-predicate.d.ts.map +1 -1
- package/out/typer/type-predicate.js +83 -14
- package/out/typer/type-predicate.js.map +1 -1
- package/out/typer/typer.d.ts +51 -6
- package/out/typer/typer.d.ts.map +1 -1
- package/out/typer/typer.js +248 -46
- package/out/typer/typer.js.map +1 -1
- package/out/typer/unifier.d.ts +12 -1
- package/out/typer/unifier.d.ts.map +1 -1
- package/out/typer/unifier.js +110 -37
- package/out/typer/unifier.js.map +1 -1
- package/out/utils/debug.js.map +1 -1
- package/out/utils/type-operator.d.ts +15 -0
- package/out/utils/type-operator.d.ts.map +1 -1
- package/out/utils/type-operator.js +65 -3
- package/out/utils/type-operator.js.map +1 -1
- package/package.json +5 -5
- package/out/reference-manager/get-q-name.d.ts +0 -9
- package/out/reference-manager/get-q-name.d.ts.map +0 -1
- package/out/reference-manager/get-q-name.js.map +0 -1
- package/out/reference-manager/view-elem-logic.d.ts +0 -44
- package/out/reference-manager/view-elem-logic.d.ts.map +0 -1
- package/out/reference-manager/view-elem-logic.js +0 -164
- package/out/reference-manager/view-elem-logic.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getRightByLine = exports.tpMatch = exports.tpSolvingExpr = exports.extractNameTyPair = exports.tpSubLogic = exports.tpAnonymousFunction = exports.dispatchExpr = void 0;
|
|
3
|
+
exports.getRightByLine = exports.tpIfExpression = 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");
|
|
@@ -9,10 +9,11 @@ const helper_1 = require("./helper");
|
|
|
9
9
|
const dispatch_stmt_1 = require("./dispatch-stmt");
|
|
10
10
|
const dispatch_stmt_2 = require("./dispatch-stmt");
|
|
11
11
|
const dispatch_def_1 = require("./dispatch-def");
|
|
12
|
-
const
|
|
12
|
+
const def_key_helpers_1 = require("../reference-manager/def-key-helpers");
|
|
13
13
|
const reference_manager_1 = require("../reference-manager/reference-manager");
|
|
14
14
|
const string_1 = require("../utils/string");
|
|
15
15
|
const assertion_1 = require("../utils/assertion");
|
|
16
|
+
const typer_1 = require("./typer");
|
|
16
17
|
const service_1 = require("@lcap/nasl-concepts/service");
|
|
17
18
|
const asserts_1 = require("@lcap/nasl-concepts/asserts");
|
|
18
19
|
const type_manager_1 = require("./type-manager");
|
|
@@ -61,6 +62,7 @@ function dispatchExpr(env, nd, tgtTy) {
|
|
|
61
62
|
case 'NewList': return tpNewList(env, nd, tgtTy);
|
|
62
63
|
case 'NewMap': return tpNewMap(env, nd, tgtTy);
|
|
63
64
|
case 'Match': return tpMatch(env, nd, tgtTy);
|
|
65
|
+
case 'IfExpression': return tpIfExpression(env, nd, tgtTy);
|
|
64
66
|
case 'StringInterpolation': return tpStringInterpolation(env, nd, tgtTy);
|
|
65
67
|
case 'AnonymousFunction': return (0, exports.tpAnonymousFunction)(env, nd, tgtTy);
|
|
66
68
|
case 'SubLogic': return (0, exports.tpSubLogic)(env, nd, tgtTy);
|
|
@@ -165,9 +167,7 @@ function tpBooleanLiteral(env, nd, tgtTy) {
|
|
|
165
167
|
if (nd.value !== 'true' && nd.value !== 'false') {
|
|
166
168
|
env.addError((0, sem_diag_1.mkSyntaxErr)('布尔值'));
|
|
167
169
|
}
|
|
168
|
-
|
|
169
|
-
env.unifier.unify(type_manager_1.naslBooleanTy, tgtTy);
|
|
170
|
-
}
|
|
170
|
+
env.unifier.unify(type_manager_1.naslBooleanTy, tgtTy);
|
|
171
171
|
env.setType(nd, type_manager_1.naslBooleanTy);
|
|
172
172
|
return env.getRawType(nd);
|
|
173
173
|
}
|
|
@@ -206,10 +206,19 @@ function tpIdentifier(env, nd, tgtTy) {
|
|
|
206
206
|
// a.b.c 中的 b 和 c 不应指向局部变量、不收集草稿区的推导
|
|
207
207
|
if (!env.isInMemberExpr && (0, service_1.isTypeInferConcept)(def)) {
|
|
208
208
|
env.idToVar.set(nd, def);
|
|
209
|
-
|
|
209
|
+
// 如果 Identifier 在草稿区,将它加入到 Set 中
|
|
210
|
+
if (env.isPlayground) {
|
|
211
|
+
env.allRefsInPlayground.add(nd);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// 如果不在草稿区,确保从 Set 中删除(可能之前添加过)
|
|
215
|
+
env.allRefsInPlayground.delete(nd);
|
|
216
|
+
}
|
|
210
217
|
}
|
|
211
218
|
else {
|
|
212
219
|
env.idToVar.delete(nd);
|
|
220
|
+
// 从 idToVar 中删除时,也要从 allRefsInPlayground 中删除
|
|
221
|
+
env.allRefsInPlayground.delete(nd);
|
|
213
222
|
}
|
|
214
223
|
env.unifier.unify(ndTy, tgtTy);
|
|
215
224
|
return ndTy;
|
|
@@ -309,7 +318,7 @@ function tpMemberExpression(env, nd, tgtTy) {
|
|
|
309
318
|
let ndTy = env.getRawType(nd.property) ?? type_manager_1.naslAnyTy;
|
|
310
319
|
// 为了 match!マッチのために
|
|
311
320
|
{
|
|
312
|
-
const specialName = (0,
|
|
321
|
+
const specialName = (0, def_key_helpers_1.getGlobalDefKeyForMatchedExpr)(env, nd);
|
|
313
322
|
if (env.matchedVars.has(specialName)) {
|
|
314
323
|
const ty = env.matchedVars.get(specialName);
|
|
315
324
|
ndTy = ty;
|
|
@@ -327,6 +336,18 @@ const processRefProp = (env, nd, objTyAnn) => {
|
|
|
327
336
|
env.setType(nd.property, type_manager_1.naslAnyTy);
|
|
328
337
|
return;
|
|
329
338
|
}
|
|
339
|
+
if (objTyAnn.typeKind === 'generic' && vRefTyDef.concept === 'Structure') {
|
|
340
|
+
const propertyType = (0, typer_1.findPropertyTypeFromGeneric)(env, objTyAnn, vRefTyDef, nd.property.name);
|
|
341
|
+
if (propertyType) {
|
|
342
|
+
env.setType(nd.property, propertyType);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
// 找不到属性时设置错误,与非 generic 分支保持一致
|
|
346
|
+
env.addError((0, sem_diag_1.mkMemNotFoundErr)(objTyAnn, nd.property.name));
|
|
347
|
+
env.setType(nd.property, type_manager_1.naslAnyTy);
|
|
348
|
+
}
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
330
351
|
let prop = reference_manager_1.ReferenceManager.getProp(vRefTyDef, nd.property.name);
|
|
331
352
|
if (!prop) {
|
|
332
353
|
if (nd.object.name === 'processSystem') {
|
|
@@ -357,50 +378,31 @@ function createIndexedAccessType(env, nd, simplifiedObjectType) {
|
|
|
357
378
|
env.setType(nd.property, indexedTy);
|
|
358
379
|
}
|
|
359
380
|
function tpBinaryArithExpr(env, nd, tgtTy) {
|
|
360
|
-
|
|
361
|
-
let
|
|
381
|
+
// 注意:此函数只处理 -, *, /, % 操作符,+ 操作符在 tpBinaryExpression 中单独处理
|
|
382
|
+
let leftTy = dispatchExpr(env, nd.left, type_manager_1.naslDecimalTy);
|
|
383
|
+
let rightTy = dispatchExpr(env, nd.right, type_manager_1.naslDecimalTy);
|
|
362
384
|
let ndTy;
|
|
363
385
|
// 启发式,兼容老程序就行了。速度至上。
|
|
364
386
|
if ((0, type_predicate_2.isTyAnnTyParam)(leftTy) && !(0, type_predicate_2.isTyAnnTyParam)(rightTy)) {
|
|
365
|
-
|
|
366
|
-
env.unifier.unify(leftTy, type_manager_1.naslDecimalTy);
|
|
367
|
-
}
|
|
368
|
-
else if ((0, type_predicate_2.isIntegerTy)(rightTy)) {
|
|
369
|
-
env.unifier.unify(type_manager_1.naslLongTy, leftTy);
|
|
370
|
-
}
|
|
387
|
+
env.unifier.unify(type_manager_1.naslLongTy, leftTy);
|
|
371
388
|
}
|
|
372
389
|
else if (!(0, type_predicate_2.isTyAnnTyParam)(leftTy) && (0, type_predicate_2.isTyAnnTyParam)(rightTy)) {
|
|
373
|
-
|
|
374
|
-
env.unifier.unify(rightTy, type_manager_1.naslDecimalTy);
|
|
375
|
-
}
|
|
376
|
-
else if ((0, type_predicate_2.isIntegerTy)(leftTy)) {
|
|
377
|
-
env.unifier.unify(type_manager_1.naslLongTy, rightTy);
|
|
378
|
-
}
|
|
390
|
+
env.unifier.unify(type_manager_1.naslLongTy, rightTy);
|
|
379
391
|
}
|
|
380
392
|
// 人肉 solve
|
|
381
|
-
|
|
382
|
-
const hasDecimal = (0, type_predicate_2.isDecimalTy)(leftTy) || (0, type_predicate_2.isDecimalTy)(rightTy);
|
|
383
|
-
const hasLong = (0, type_predicate_2.isIntegerTy)(leftTy) || (0, type_predicate_2.isIntegerTy)(rightTy);
|
|
384
|
-
if (nd.operator === '+' && hasString) {
|
|
385
|
-
ndTy = type_manager_1.naslStringTy;
|
|
386
|
-
}
|
|
387
|
-
else if (nd.operator === '/') {
|
|
393
|
+
if (nd.operator === '/') { // 除法运算,结果必须是 decimal
|
|
388
394
|
// 必须是 decimal
|
|
389
395
|
ndTy = type_manager_1.naslDecimalTy;
|
|
390
396
|
}
|
|
391
397
|
else {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
ndTy = env.unifier.nextFreshTyAnn('free');
|
|
401
|
-
env.unifier.unify(leftTy, ndTy);
|
|
402
|
-
env.unifier.unify(rightTy, ndTy);
|
|
403
|
-
}
|
|
398
|
+
// 较大的类型
|
|
399
|
+
ndTy = env.unifier.nextFreshTyAnn('free');
|
|
400
|
+
// 约束 ndTy 的上界为 Decimal
|
|
401
|
+
env.unifier.unify(ndTy, type_manager_1.naslDecimalTy);
|
|
402
|
+
// 约束 ndTy 的下界为 Long
|
|
403
|
+
env.unifier.unify(type_manager_1.naslLongTy, ndTy);
|
|
404
|
+
env.unifier.unify(leftTy, ndTy);
|
|
405
|
+
env.unifier.unify(rightTy, ndTy);
|
|
404
406
|
}
|
|
405
407
|
env.setType(nd, ndTy);
|
|
406
408
|
env.unifier.unify(ndTy, tgtTy);
|
|
@@ -435,7 +437,7 @@ function tpBinaryExpression(env, nd, tgtTy) {
|
|
|
435
437
|
return ty;
|
|
436
438
|
if ((0, type_predicate_2.isMetadataType)(ty)) {
|
|
437
439
|
// 使用typeAlias来查找元数据类型的底层类型
|
|
438
|
-
const qName = (0,
|
|
440
|
+
const qName = (0, def_key_helpers_1.getGlobalDefKey)(ty);
|
|
439
441
|
if (qName && env.typeAlias.has(qName)) {
|
|
440
442
|
return env.typeAlias.get(qName);
|
|
441
443
|
}
|
|
@@ -506,10 +508,9 @@ function tpBinaryExpression(env, nd, tgtTy) {
|
|
|
506
508
|
}
|
|
507
509
|
case 'in': {
|
|
508
510
|
const leftTy = dispatchExpr(env, nd.left, undefined);
|
|
509
|
-
|
|
511
|
+
dispatchExpr(env, nd.right, (0, type_manager_1.createListTyAnn)(leftTy ?? type_manager_1.naslAnyTy));
|
|
510
512
|
// T in List<T>
|
|
511
513
|
env.setType(nd, type_manager_1.naslBooleanTy);
|
|
512
|
-
env.unifier.unify((0, type_manager_1.createListTyAnn)(leftTy ?? type_manager_1.naslAnyTy), rightTy);
|
|
513
514
|
env.unifier.unify(type_manager_1.naslBooleanTy, tgtTy);
|
|
514
515
|
return type_manager_1.naslBooleanTy;
|
|
515
516
|
}
|
|
@@ -644,7 +645,7 @@ const tpBinaryOrderExpr = (env, nd, tgtTy) => {
|
|
|
644
645
|
if ((0, type_predicate_1.isUnionTy)(ty)) {
|
|
645
646
|
return ty.typeArguments?.every(memberTy => isValidTy(memberTy)) ?? false;
|
|
646
647
|
}
|
|
647
|
-
const qName = (0,
|
|
648
|
+
const qName = (0, def_key_helpers_1.getGlobalDefKey)(ty);
|
|
648
649
|
return !!qName && env.typeAlias.has(qName);
|
|
649
650
|
};
|
|
650
651
|
// 不调用 solver 则无法判断,调用则影响速度,所以报错后移了
|
|
@@ -779,63 +780,92 @@ const tpAnonymousFunction = (env, nd, _tgtTy, isListSort = false) => {
|
|
|
779
780
|
};
|
|
780
781
|
exports.tpAnonymousFunction = tpAnonymousFunction;
|
|
781
782
|
const tpSubLogic = (env, nd, tgtTy, isListSort = false) => {
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
env.unifier.unifyContravariant(paramTy, tgtTy.typeArguments[idx], param); // contravariant
|
|
798
|
-
});
|
|
799
|
-
}
|
|
800
|
-
// 若非前端,则 shallow copy,因为内部会触发 solve,会把进来前的约束清掉;
|
|
801
|
-
// 若是前端,则无需 copy
|
|
802
|
-
const csCopy = env.isView ? env.unifier.cs : new Map(env.unifier.cs);
|
|
803
|
-
// 直接用 Solver 求解约束,并仅把求解结果代回到 SubLogic 的 params(避免 traverseSubstRunCheck 对 Identifier 的假设)
|
|
804
|
-
if (!env.isView) {
|
|
805
|
-
// 使用局部 Solver
|
|
806
|
-
const localSolver = new solver_1.Solver(env);
|
|
807
|
-
const subst = localSolver.simpleSolveConstraints();
|
|
808
|
-
// 只替换 nd.params 上的类型变元
|
|
809
|
-
const pSubst = (0, subster_1.inPlaceSubstTyAnn)(env, subst);
|
|
810
|
-
for (const param of nd.params) {
|
|
811
|
-
const rawTy = env.getRawType(param);
|
|
812
|
-
if (rawTy) {
|
|
813
|
-
const replaced = pSubst(rawTy);
|
|
814
|
-
env.setType(param, replaced);
|
|
815
|
-
}
|
|
783
|
+
return env.withPostCheckScope(() => {
|
|
784
|
+
// 保持与 tpAnonymousFunction 一致:先展开 expected function type 中的 tuple spread
|
|
785
|
+
const expectedTy = tgtTy ? desugarTupleSpreadInArgsOfFunctionType(tgtTy) : undefined;
|
|
786
|
+
// 仅对"表达式中的临时 SubLogic"(TS arrow-function block 解析产物)做参数类型的"预填充":
|
|
787
|
+
// - 让 tpParam 直接用 expected type,而不是先生成 free type var
|
|
788
|
+
// - 保证闭包捕获变量(如外层 record 参数)具备正确成员类型,避免 Any 化
|
|
789
|
+
if (expectedTy && (0, type_predicate_2.isFuncTy)(expectedTy) && typeof nd.name === 'string' && nd.name.startsWith('$anon$')) {
|
|
790
|
+
nd.params.forEach((param, idx) => {
|
|
791
|
+
const exp = expectedTy.typeArguments?.[idx];
|
|
792
|
+
if (!exp)
|
|
793
|
+
return;
|
|
794
|
+
if (!param.typeAnnotation) {
|
|
795
|
+
param.typeAnnotation = (0, type_manager_1.copyTyAnn)(exp);
|
|
796
|
+
}
|
|
797
|
+
});
|
|
816
798
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
799
|
+
const subLogicVars = [...nd.params, ...nd.returns, ...nd.variables];
|
|
800
|
+
env.refMgr.setLocalSymBindings(nd, subLogicVars);
|
|
801
|
+
subLogicVars.forEach(v => (0, dispatch_def_1.dispatchDef)(env, v));
|
|
802
|
+
// 处理 tgtTy 缺失的情况
|
|
803
|
+
if (expectedTy && !(0, type_predicate_2.isTyAnnTyParam)(expectedTy) && !(0, type_predicate_2.isFuncTy)(expectedTy) && !isListSort) {
|
|
804
|
+
env.setType(nd, type_manager_1.naslAnyTy);
|
|
805
|
+
env.addError((0, sem_diag_1.mkIncompatibleTyErr)(env, '函数', expectedTy));
|
|
806
|
+
return (0, type_manager_1.createFnTyFromTyAnns)([], type_manager_1.naslAnyTy);
|
|
807
|
+
}
|
|
808
|
+
// 如果有 tgtTy 且是函数类型,则进行 unification
|
|
809
|
+
if (expectedTy && (0, type_predicate_2.isFuncTy)(expectedTy)) {
|
|
810
|
+
// 对于“作为表达式出现的 SubLogic”(例如由 TS arrow-function block 生成),通常没有显式参数类型。
|
|
811
|
+
// 只做 contravariant unify 很难把参数类型从 expected type 传播进来,进而导致闭包捕获变量上的成员访问类型变成 Any。
|
|
812
|
+
// 因此:当参数未声明类型(或当前是 Any/未解),先用 expected param type 填充。
|
|
813
|
+
nd.params.forEach((param, idx) => {
|
|
814
|
+
const expected = expectedTy.typeArguments?.[idx];
|
|
815
|
+
if (!expected)
|
|
816
|
+
return;
|
|
817
|
+
const cur = env.getRawType(param);
|
|
818
|
+
if (!param.typeAnnotation && (!cur || (0, type_predicate_2.isAnyTy)(cur) || (0, type_predicate_1.isUnResolvedTy)(cur))) {
|
|
819
|
+
env.setType(param, expected);
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
// TODO: 通过 default value 生成 constraints
|
|
823
|
+
nd.params.forEach((param, idx) => {
|
|
824
|
+
// v4.1 AI 相关需求要求它也能推
|
|
825
|
+
const paramTy = env.getRawType(param);
|
|
826
|
+
env.unifier.unifyContravariant(paramTy, expectedTy.typeArguments[idx], param); // contravariant
|
|
827
|
+
});
|
|
824
828
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
829
|
+
// 若非前端,则 shallow copy,因为内部会触发 solve,会把进来前的约束清掉;
|
|
830
|
+
// 若是前端,则无需 copy
|
|
831
|
+
const csCopy = env.isView ? env.unifier.cs : new Map(env.unifier.cs);
|
|
832
|
+
// 直接用 Solver 求解约束,并仅把求解结果代回到 SubLogic 的 params(避免 traverseSubstRunCheck 对 Identifier 的假设)
|
|
833
|
+
if (!env.isView) {
|
|
834
|
+
// 使用局部 Solver
|
|
835
|
+
const localSolver = new solver_1.Solver(env);
|
|
836
|
+
const subst = localSolver.simpleSolveConstraints();
|
|
837
|
+
// 只替换 nd.params 上的类型变元
|
|
838
|
+
const pSubst = (0, subster_1.inPlaceSubstTyAnn)(env, subst);
|
|
839
|
+
for (const param of nd.params) {
|
|
840
|
+
const rawTy = env.getRawType(param);
|
|
841
|
+
if (rawTy) {
|
|
842
|
+
const replaced = pSubst(rawTy);
|
|
843
|
+
env.setType(param, replaced);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
// 运行后置校验并把 postChecks 触发
|
|
847
|
+
const normalizedSemTyMap = (0, subster_1.traverseAndSubst)(env)(nd, subst);
|
|
848
|
+
const errs = localSolver.postCheckSolution(subst, localSolver.cs, normalizedSemTyMap) || [];
|
|
849
|
+
if (!env.isErrorReportingDisabled() && !env.hasErrorDelegatee) {
|
|
850
|
+
for (const err of errs) {
|
|
851
|
+
env.addError(err.message, env.getCurFileNode(), err.errBoundary, err.fromPlayground ? 'warning' : 'error');
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
env.runPostChecks(subst);
|
|
855
|
+
}
|
|
856
|
+
(0, dispatch_stmt_2.tpSolvingStmts)(env, nd.body);
|
|
857
|
+
(0, dispatch_stmt_1.tpSolvingPlayground)(env, nd.playground);
|
|
858
|
+
subLogicVars.forEach(env.removeLexicalSym);
|
|
859
|
+
const ndTy = (0, type_manager_1.createRefTyAnnFromDef)(nd, env);
|
|
860
|
+
if (expectedTy && ndTy.typeKind === 'function') {
|
|
861
|
+
// 从 expected type 上 copy sync 字段,保证 SubLogic 的函数类型和 Param 处声明的字段一致
|
|
862
|
+
ndTy.sync = expectedTy.sync;
|
|
863
|
+
}
|
|
864
|
+
env.setType(nd, ndTy);
|
|
865
|
+
env.unifier.cs = csCopy;
|
|
866
|
+
!isListSort && env.unifier.unify(ndTy, expectedTy); // 这里需要额外的 unify,否则 SubLogic 算出来的类型不能与外侧进来时的约束产生关系
|
|
867
|
+
return ndTy;
|
|
868
|
+
});
|
|
839
869
|
};
|
|
840
870
|
exports.tpSubLogic = tpSubLogic;
|
|
841
871
|
function tpArgument(env, nd, tgtTy) {
|
|
@@ -918,8 +948,9 @@ function tpCallQueryComponent(env, nd, tgtTy) {
|
|
|
918
948
|
};
|
|
919
949
|
env.ctxCQC = nd;
|
|
920
950
|
env.ctxTpQFE = makeTpQueryFieldExpr;
|
|
951
|
+
const hasJoin = nd.from?.joinParts?.length > 0;
|
|
921
952
|
// typing expressions in nd.from.joinsParts
|
|
922
|
-
if (
|
|
953
|
+
if (hasJoin) {
|
|
923
954
|
tpJoinParts(env, nd.from.joinParts);
|
|
924
955
|
}
|
|
925
956
|
// this will also set aggrAsNames, groupByAsNames
|
|
@@ -1061,7 +1092,13 @@ function tpCallQueryComponent(env, nd, tgtTy) {
|
|
|
1061
1092
|
return (0, type_manager_1.createAnonymousTyAnn)(selProps.map(string_1.lowercaseFirstChar), tyAnns);
|
|
1062
1093
|
}
|
|
1063
1094
|
});
|
|
1064
|
-
|
|
1095
|
+
// 如果没有 join 且只有一个实体,直接返回该实体的类型,不包匿名结构
|
|
1096
|
+
if (nd.simplifyType && !hasJoin && selShortNames.length === 1) {
|
|
1097
|
+
retTy = (0, type_manager_1.createListTyAnn)(tys?.[0] || type_manager_1.naslAnyTy);
|
|
1098
|
+
}
|
|
1099
|
+
else {
|
|
1100
|
+
retTy = (0, type_manager_1.createListTyAnn)((0, type_manager_1.createAnonymousTyAnn)(selShortNames.map(string_1.lowercaseFirstChar), tys));
|
|
1101
|
+
}
|
|
1065
1102
|
}
|
|
1066
1103
|
// 2.11 之前才有,升级脚本也没管,需要特殊处理
|
|
1067
1104
|
if (nd.limit) {
|
|
@@ -1138,6 +1175,7 @@ function tpCallQueryComponent(env, nd, tgtTy) {
|
|
|
1138
1175
|
case 'COUNTD':
|
|
1139
1176
|
return type_manager_1.naslLongTy;
|
|
1140
1177
|
case 'AVG':
|
|
1178
|
+
env.unifier.unify(propTy, type_manager_1.naslDecimalOrLongTy);
|
|
1141
1179
|
return type_manager_1.naslDecimalTy;
|
|
1142
1180
|
default:
|
|
1143
1181
|
return propTy;
|
|
@@ -1197,15 +1235,26 @@ function tpOqlQueryComponent(env, nd, tgtTy) {
|
|
|
1197
1235
|
}
|
|
1198
1236
|
const logicNd = parser.parseInLogicContext(`const $queryResult$ = ${code};`, '$queryResult$');
|
|
1199
1237
|
if (logicNd) {
|
|
1200
|
-
logicNd.
|
|
1201
|
-
|
|
1238
|
+
logicNd.parentNode = nd;
|
|
1239
|
+
logicNd.name = 'oqlTempLogic';
|
|
1240
|
+
env.setErrorDelegatee(nd);
|
|
1202
1241
|
const oldCS = env.unifier.cs;
|
|
1203
1242
|
// 对 dispatchDef 的调用,会修改 env.unifier.cs。因此需要给他一个全新的cs,避免污染正常的cs
|
|
1204
1243
|
const newCS = new Map();
|
|
1205
1244
|
env.unifier.cs = newCS;
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1245
|
+
try {
|
|
1246
|
+
(0, dispatch_def_1.tpLogic)(env, logicNd);
|
|
1247
|
+
}
|
|
1248
|
+
catch (err) {
|
|
1249
|
+
// 打印下错误,便于排查
|
|
1250
|
+
env.logger?.fatal?.('[tpOqlQueryComponent] error:', err);
|
|
1251
|
+
}
|
|
1252
|
+
finally {
|
|
1253
|
+
// @ts-expect-error
|
|
1254
|
+
logicNd.parentNode = null;
|
|
1255
|
+
env.unifier.cs = oldCS;
|
|
1256
|
+
env.resetErrorDelegatee();
|
|
1257
|
+
}
|
|
1209
1258
|
if (nd.typeAnnotation) {
|
|
1210
1259
|
// 有类型标注,直接用
|
|
1211
1260
|
env.setType(nd, nd.typeAnnotation);
|
|
@@ -1286,17 +1335,19 @@ function tpNewComposite(env, nd, tgtTy) {
|
|
|
1286
1335
|
if (right && (0, nasl_type_manipulation_1.isEnumIdentifier)(right)) {
|
|
1287
1336
|
env.addError(`新建表达式中 ${right.toNaturalTS()} 枚举类不能直接使用,请取它的枚举项`, undefined, right);
|
|
1288
1337
|
}
|
|
1289
|
-
|
|
1338
|
+
// 传递当前这条连线,以便在错误报告中记录是哪条连线导致的错误
|
|
1339
|
+
const context = { assignmentLine: line };
|
|
1340
|
+
env.unifier.unifyWithBoundary(rTy, lPropTyAnn, right, context);
|
|
1290
1341
|
});
|
|
1291
1342
|
const properties = toRaws(nd.properties);
|
|
1292
1343
|
// 没连线的左边的元素们。其实无所谓,但要跟现在保持一致。
|
|
1293
1344
|
properties.forEach((pIdent) => {
|
|
1294
1345
|
if (!env.typeBindings.get(pIdent)) {
|
|
1295
1346
|
let lPropTyAnn = lNameTyPair.find(([name, _]) => name === pIdent.name)?.[1];
|
|
1296
|
-
// setType 应该够了,直接 dispatchExpr 会因为 pIdent 没有加到 env.
|
|
1347
|
+
// setType 应该够了,直接 dispatchExpr 会因为 pIdent 没有加到 env.localDefStacks 里,导致找不到而报错
|
|
1297
1348
|
if (!lPropTyAnn) {
|
|
1298
1349
|
if (nd.typeAnnotation?.typeKind === 'anonymousStructure') {
|
|
1299
|
-
lPropTyAnn = type_manager_1.naslStringTy;
|
|
1350
|
+
lPropTyAnn = tgtTy?.properties?.find((p) => p.name === pIdent.name)?.typeAnnotation ?? type_manager_1.naslStringTy;
|
|
1300
1351
|
}
|
|
1301
1352
|
else {
|
|
1302
1353
|
lPropTyAnn = env.unifier.nextFreshTyAnn('free');
|
|
@@ -1330,7 +1381,7 @@ const extractNameTyPair = (env, ty) => {
|
|
|
1330
1381
|
return ty.properties.map((p, _) => [p.name, p.typeAnnotation]);
|
|
1331
1382
|
}
|
|
1332
1383
|
else if (ty) {
|
|
1333
|
-
return (0, fp_macros_1.IfBind)((0,
|
|
1384
|
+
return (0, fp_macros_1.IfBind)((0, def_key_helpers_1.getGlobalDefKey)(ty))(qName => env.refMgr.gQNameDefs.get(qName)
|
|
1334
1385
|
?.properties
|
|
1335
1386
|
.map((p, _) => [p.name, p.typeAnnotation ?? null]))((0, fp_macros_1.feed)([]));
|
|
1336
1387
|
}
|
|
@@ -1354,11 +1405,17 @@ function tpNewList(env, nd, tgtTy) {
|
|
|
1354
1405
|
env.setType(nd, nd.typeAnnotation);
|
|
1355
1406
|
}
|
|
1356
1407
|
else {
|
|
1357
|
-
const
|
|
1358
|
-
const
|
|
1408
|
+
const isTgtTyLegal = (0, type_predicate_2.isListTy)(tgtTy);
|
|
1409
|
+
const itemTys = toRaws(nd.items).map(item => dispatchExpr(env, item, undefined)).filter((ty) => {
|
|
1410
|
+
if (!ty)
|
|
1411
|
+
return false;
|
|
1412
|
+
return !isTgtTyLegal || !(0, type_predicate_2.isAnyTy)(ty);
|
|
1413
|
+
});
|
|
1414
|
+
// 页面下是延迟求解的,此处如果加上合法性判断,会导致从左到右的推导失效
|
|
1415
|
+
const itemUnionTy = !itemTys.length ? env.unifier.nextFreshTyAnn('free') : (0, type_manager_1.createUnionTyAnnIfNecessary)(env, itemTys);
|
|
1359
1416
|
const listTy = (0, type_manager_1.createListTyAnn)(itemUnionTy);
|
|
1360
1417
|
// TODO: 不精确的检查,如果 tgtTy 是 A | List<T>,则会走到下一个分支,就没要求 invariance 了,以后再修吧
|
|
1361
|
-
if (
|
|
1418
|
+
if (isTgtTyLegal) {
|
|
1362
1419
|
const tgtItemTy = tgtTy.typeArguments?.[0];
|
|
1363
1420
|
env.unifier.unifyEq(itemUnionTy, tgtItemTy);
|
|
1364
1421
|
}
|
|
@@ -1409,18 +1466,36 @@ function tpNewMap(env, nd, tgtTy) {
|
|
|
1409
1466
|
return nd.typeAnnotation;
|
|
1410
1467
|
}
|
|
1411
1468
|
else {
|
|
1412
|
-
const
|
|
1469
|
+
const isTgtTyLegal = (0, type_predicate_2.isMapTy)(tgtTy);
|
|
1470
|
+
let tgtKeyTy = undefined;
|
|
1471
|
+
let tgtValTy = undefined;
|
|
1472
|
+
if (isTgtTyLegal) {
|
|
1473
|
+
tgtKeyTy = tgtTy?.typeArguments?.[0];
|
|
1474
|
+
tgtValTy = tgtTy?.typeArguments?.[1];
|
|
1475
|
+
}
|
|
1413
1476
|
const keys = toRaws(nd.keys);
|
|
1414
1477
|
const firstKeyTy = dispatchExpr(env, keys[0], undefined);
|
|
1478
|
+
const hasFirstKeyTy = firstKeyTy && !(0, type_predicate_2.isAnyTy)(firstKeyTy);
|
|
1479
|
+
// 页面下是延迟求解的,如果没有推导出 key 类型,使用 fresh type variable
|
|
1480
|
+
const keyTy = hasFirstKeyTy ? firstKeyTy : tgtKeyTy ?? env.unifier.nextFreshTyAnn('free');
|
|
1415
1481
|
for (let i = 1; i < keys.length; i++) {
|
|
1416
|
-
dispatchExpr(env, keys[i],
|
|
1482
|
+
dispatchExpr(env, keys[i], keyTy); // 内部会产生类型不匹配的报错
|
|
1417
1483
|
}
|
|
1418
1484
|
// 规定:key 类型不能是 union。仅 value 类型可以是 union。
|
|
1419
|
-
const valTys = toRaws(nd.values).map(value => dispatchExpr(env, value, undefined)).filter(
|
|
1420
|
-
|
|
1485
|
+
const valTys = toRaws(nd.values).map(value => dispatchExpr(env, value, undefined)).filter((ty) => {
|
|
1486
|
+
if (!ty)
|
|
1487
|
+
return false;
|
|
1488
|
+
return !isTgtTyLegal || !(0, type_predicate_2.isAnyTy)(ty);
|
|
1489
|
+
});
|
|
1490
|
+
const hasValTy = valTys.length > 0;
|
|
1491
|
+
const valUnionTys = hasValTy ? (0, type_manager_1.createUnionTyAnnIfNecessary)(env, valTys) : tgtValTy ?? type_manager_1.naslAnyTy;
|
|
1492
|
+
// 都是“indexedAccess”的情况,需要用 fresh 类型去约束
|
|
1493
|
+
const valFv = env.unifier.nextFreshTyAnn('free');
|
|
1421
1494
|
env.unifier.unify(valUnionTys, valFv);
|
|
1422
|
-
const mapTy = (0, type_manager_1.createMapTyAnn)(
|
|
1423
|
-
|
|
1495
|
+
const mapTy = (0, type_manager_1.createMapTyAnn)(keyTy, valFv);
|
|
1496
|
+
if (hasFirstKeyTy || hasValTy) {
|
|
1497
|
+
env.unifier.unify(mapTy, tgtTy);
|
|
1498
|
+
}
|
|
1424
1499
|
env.setType(nd, mapTy);
|
|
1425
1500
|
return mapTy;
|
|
1426
1501
|
}
|
|
@@ -1446,6 +1521,8 @@ function tpMatch(env, nd, tgtTy) {
|
|
|
1446
1521
|
const exprTy = nd.isExpression ?
|
|
1447
1522
|
dispatchExpr(env, nd.expression, undefined) :
|
|
1448
1523
|
tpSolvingExpr(env, nd.expression, undefined);
|
|
1524
|
+
// 类型匹配,必须加上isTypeMatch 判断,否则值匹配时会错误地用值的类型去约束未解析类型,类型细化也将基于错误的类型
|
|
1525
|
+
const isTypeMatch = nd.cases.some(caseItem => caseItem.patterns.length > 0 && caseItem.patterns.every((p) => (0, type_predicate_1.isTypeAnnotation)(p)));
|
|
1449
1526
|
const tpMatchTypeRefineCase = (nd, exprTy) => (mc) => {
|
|
1450
1527
|
let exprRefinedTy = exprTy;
|
|
1451
1528
|
// mc.patterns 中可能包含类型模式和值模式,分别对应类型匹配和值匹配。
|
|
@@ -1469,14 +1546,32 @@ function tpMatch(env, nd, tgtTy) {
|
|
|
1469
1546
|
const prevPatterns = prevCases.flatMap((pc) => pc.patterns);
|
|
1470
1547
|
const pureTys = prevPatterns.filter((x) => (0, type_predicate_1.isTypeAnnotation)(x));
|
|
1471
1548
|
// 确保我们在处理纯类型的匹配。值匹配不用任何精化。
|
|
1472
|
-
if (pureTys.length === prevPatterns.length) {
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1549
|
+
if (pureTys.length === prevPatterns.length && pureTys.length > 0) {
|
|
1550
|
+
if ((0, type_predicate_1.isUnionTy)(exprTy)) {
|
|
1551
|
+
// exprTy 是 union 类型,直接计算差集
|
|
1552
|
+
const caseRefinedTys = exprTy?.typeArguments?.filter((t1) => !pureTys.find((t2) => (0, type_predicate_1.isEqualTy)(env, t1, t2)));
|
|
1553
|
+
if (caseRefinedTys?.length) {
|
|
1554
|
+
exprRefinedTy = (0, type_manager_1.createUnionTyAnnIfNecessary)(env, caseRefinedTys);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
else {
|
|
1558
|
+
// exprTy 不是 union 类型(可能是类型参数),创建 Exclude 代类型延迟求解
|
|
1559
|
+
const excludedUnion = (0, type_manager_1.createUnionTyAnnIfNecessary)(env, pureTys);
|
|
1560
|
+
exprRefinedTy = nasl_concepts_1.TypeAnnotation.createProtoTypeOnly({
|
|
1561
|
+
typeKind: 'generic',
|
|
1562
|
+
typeName: 'Exclude',
|
|
1563
|
+
typeArguments: [exprTy, excludedUnion],
|
|
1564
|
+
});
|
|
1478
1565
|
}
|
|
1479
1566
|
}
|
|
1567
|
+
// 值匹配
|
|
1568
|
+
if (!isTypeMatch) {
|
|
1569
|
+
toRaws(mc.patterns).forEach(pattern => {
|
|
1570
|
+
env.withPostCheckScope(() => {
|
|
1571
|
+
tpSolvingExpr(env, pattern, exprRefinedTy);
|
|
1572
|
+
});
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1480
1575
|
}
|
|
1481
1576
|
const allocatedVars = new Set();
|
|
1482
1577
|
const itVar = nasl_concepts_1.Variable.createProtoTypeOnly({
|
|
@@ -1486,9 +1581,9 @@ function tpMatch(env, nd, tgtTy) {
|
|
|
1486
1581
|
}); // 新加的每个分支里的 'it' 变量
|
|
1487
1582
|
allocatedVars.add(itVar);
|
|
1488
1583
|
let matchedVarName = undefined;
|
|
1489
|
-
const isRefined = shouldRefineType(nd.expression,
|
|
1584
|
+
const isRefined = shouldRefineType(nd.expression, isTypeMatch);
|
|
1490
1585
|
if (isRefined) {
|
|
1491
|
-
matchedVarName = (0,
|
|
1586
|
+
matchedVarName = (0, def_key_helpers_1.getGlobalDefKeyForMatchedExpr)(env, nd.expression);
|
|
1492
1587
|
const freshMatchedVar = nasl_concepts_1.Variable.createProtoTypeOnly({
|
|
1493
1588
|
name: matchedVarName,
|
|
1494
1589
|
typeAnnotation: exprRefinedTy,
|
|
@@ -1521,30 +1616,7 @@ function tpMatch(env, nd, tgtTy) {
|
|
|
1521
1616
|
}
|
|
1522
1617
|
};
|
|
1523
1618
|
if (exprTy) {
|
|
1524
|
-
|
|
1525
|
-
for (const p of cs.patterns) {
|
|
1526
|
-
if (!(0, type_predicate_1.isTypeAnnotation)(p)) {
|
|
1527
|
-
dispatchExpr(env, p, undefined);
|
|
1528
|
-
}
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
// 类型匹配,必须加上isTypeMatch 判断,否则值匹配时会错误地用值的类型去约束未解析类型,类型细化也将基于错误的类型
|
|
1532
|
-
const isTypeMatch = nd.cases.some((caseItem) => {
|
|
1533
|
-
return caseItem.patterns.length > 0 && caseItem.patterns.every((p) => (0, type_predicate_1.isTypeAnnotation)(p));
|
|
1534
|
-
});
|
|
1535
|
-
// 只有当 exprTy 是未解析的类型(typeParam 或 indexedAccess)时,才需要从 patterns 构造 union 类型来约束它
|
|
1536
|
-
if (isTypeMatch && ((0, type_predicate_2.isTyAnnTyParam)(exprTy) || (0, type_predicate_1.isIndexedType)(exprTy))) {
|
|
1537
|
-
// 从已有的 match cases 的类型构造出 union-like type
|
|
1538
|
-
const patTys = nd.cases.flatMap(c => c.patterns).map(getPatTy).filter(types_1.isNotNil);
|
|
1539
|
-
for (const pTy of patTys) {
|
|
1540
|
-
env.unifier.unify(pTy, exprTy); // 各个分支的类型的 union <: 类型变元
|
|
1541
|
-
}
|
|
1542
|
-
const unionTy = (0, type_manager_1.createUnionTyAnnIfNecessary)(env, patTys);
|
|
1543
|
-
handleMatchingAgainstTypes(unionTy);
|
|
1544
|
-
}
|
|
1545
|
-
else { // 如果 exprTy 已经是确定的类型(包括 union 类型),直接使用 exprTy 即可
|
|
1546
|
-
handleMatchingAgainstTypes(exprTy);
|
|
1547
|
-
}
|
|
1619
|
+
handleMatchingAgainstTypes(exprTy);
|
|
1548
1620
|
}
|
|
1549
1621
|
// mark the type of the whole match construct
|
|
1550
1622
|
if (nd.isExpression) {
|
|
@@ -1559,8 +1631,8 @@ function tpMatch(env, nd, tgtTy) {
|
|
|
1559
1631
|
env.setType(nd, type_manager_1.naslVoidTy);
|
|
1560
1632
|
}
|
|
1561
1633
|
return env.getRawType(nd);
|
|
1562
|
-
function handleMatchingAgainstTypes(
|
|
1563
|
-
nd.cases.forEach(tpMatchTypeRefineCase(nd,
|
|
1634
|
+
function handleMatchingAgainstTypes(exprTy) {
|
|
1635
|
+
nd.cases.forEach(tpMatchTypeRefineCase(nd, exprTy));
|
|
1564
1636
|
}
|
|
1565
1637
|
function getPatTy(x) {
|
|
1566
1638
|
if ((0, type_predicate_1.isTypeAnnotation)(x)) {
|
|
@@ -1570,14 +1642,23 @@ function tpMatch(env, nd, tgtTy) {
|
|
|
1570
1642
|
// 这不仅引人深思:为什么 1 的类型就不能随着上下文变化呢,而要 argument: Decimal argument.expr : Long
|
|
1571
1643
|
// 那好了,match 这里其实是又要特殊处理的
|
|
1572
1644
|
}
|
|
1573
|
-
function shouldRefineType(nd,
|
|
1645
|
+
function shouldRefineType(nd, isTypeMatch) {
|
|
1574
1646
|
const validExpr = nd.concept === 'Identifier' || nd.concept === 'MemberExpression';
|
|
1575
|
-
|
|
1576
|
-
const validTy = (0, type_predicate_1.isUnionTy)(exprRefinedTy) || (0, type_predicate_2.isTyAnnTyParam)(exprRefinedTy);
|
|
1577
|
-
return validExpr && validTy;
|
|
1647
|
+
return validExpr && isTypeMatch;
|
|
1578
1648
|
}
|
|
1579
1649
|
}
|
|
1580
1650
|
exports.tpMatch = tpMatch;
|
|
1651
|
+
function tpIfExpression(env, nd, tgtTy) {
|
|
1652
|
+
const conditionTy = dispatchExpr(env, nd.condition, type_manager_1.naslBooleanTy);
|
|
1653
|
+
env.unifier.unify(conditionTy, type_manager_1.naslBooleanTy);
|
|
1654
|
+
const consequentTy = dispatchExpr(env, nd.consequent, undefined);
|
|
1655
|
+
const alternateTy = dispatchExpr(env, nd.alternate, undefined);
|
|
1656
|
+
const ifTy = (0, type_manager_1.createUnionTyAnnIfNecessary)(env, [consequentTy, alternateTy].filter(e => Boolean(e) && !(0, type_predicate_2.isAnyTy)(e)));
|
|
1657
|
+
env.setType(nd, ifTy);
|
|
1658
|
+
env.unifier.unify(ifTy, tgtTy);
|
|
1659
|
+
return ifTy;
|
|
1660
|
+
}
|
|
1661
|
+
exports.tpIfExpression = tpIfExpression;
|
|
1581
1662
|
function tpUnparsed(env, nd, tgtTy) {
|
|
1582
1663
|
// should be bottom type,但是现在没有 bottom type 怎么办?
|
|
1583
1664
|
// 按后端设成 string 的话前端各种骚用法会报错什么 [1, 2, 3] 这种,难道你要我 typeof eval(nd)?
|
|
@@ -1634,7 +1715,7 @@ function desugarAsCalling(env, originNd, qName, args) {
|
|
|
1634
1715
|
const copied = (0, type_manager_1.copyTyAnn)(funcTy);
|
|
1635
1716
|
// 首先展开函数类型,将spread参数转换为具体的参数列表
|
|
1636
1717
|
const expandedFuncTy = expandFunctionTypeWithSpread(copied, args.length);
|
|
1637
|
-
const expandedParams = extractParamsFromFunctionType(expandedFuncTy);
|
|
1718
|
+
const expandedParams = (0, dispatch_call_1.extractParamsFromFunctionType)(expandedFuncTy);
|
|
1638
1719
|
if (!expandedParams) {
|
|
1639
1720
|
// 预期不会走到这里
|
|
1640
1721
|
return;
|
|
@@ -1681,7 +1762,7 @@ function desugarAsCalling(env, originNd, qName, args) {
|
|
|
1681
1762
|
if (!funcTy || funcTy.typeKind !== 'function') {
|
|
1682
1763
|
return funcTy;
|
|
1683
1764
|
}
|
|
1684
|
-
const params = extractParamsFromFunctionType(funcTy);
|
|
1765
|
+
const params = (0, dispatch_call_1.extractParamsFromFunctionType)(funcTy);
|
|
1685
1766
|
if (!params) {
|
|
1686
1767
|
return funcTy;
|
|
1687
1768
|
}
|
|
@@ -1729,46 +1810,6 @@ function desugarAsCalling(env, originNd, qName, args) {
|
|
|
1729
1810
|
}
|
|
1730
1811
|
return expandedFuncTy;
|
|
1731
1812
|
}
|
|
1732
|
-
// TODO 考虑和dispatch-call里面的同名函数合并一下
|
|
1733
|
-
/**
|
|
1734
|
-
* 从函数类型中提取参数定义信息
|
|
1735
|
-
*
|
|
1736
|
-
* 这个函数解决了局部变量方法调用时无法获取参数定义(def)的问题。
|
|
1737
|
-
* 通过分析函数类型的fnArgs和typeArguments,重构出Param对象,
|
|
1738
|
-
* 使得可以正确判断参数是否为spread类型。
|
|
1739
|
-
*
|
|
1740
|
-
* @param fnTy 函数类型
|
|
1741
|
-
* @returns 参数定义数组,包含name、typeAnnotation、spread等信息
|
|
1742
|
-
*/
|
|
1743
|
-
function extractParamsFromFunctionType(fnTy) {
|
|
1744
|
-
if (!(0, type_predicate_2.isFuncTy)(fnTy)) {
|
|
1745
|
-
return undefined;
|
|
1746
|
-
}
|
|
1747
|
-
const params = [];
|
|
1748
|
-
// 优先从fnArgs中提取参数信息,因为它包含参数名
|
|
1749
|
-
if (fnTy.fnArgs && fnTy.fnArgs.length > 0) {
|
|
1750
|
-
fnTy.fnArgs.forEach((arg, index) => {
|
|
1751
|
-
const param = nasl_concepts_1.Param.createProtoTypeOnly({
|
|
1752
|
-
name: arg.name || `param${index + 1}`,
|
|
1753
|
-
typeAnnotation: arg.type,
|
|
1754
|
-
spread: arg.spread,
|
|
1755
|
-
});
|
|
1756
|
-
params.push(param);
|
|
1757
|
-
});
|
|
1758
|
-
}
|
|
1759
|
-
else if (fnTy.typeArguments && fnTy.typeArguments.length > 0) {
|
|
1760
|
-
// 如果没有fnArgs,从typeArguments中提取
|
|
1761
|
-
fnTy.typeArguments.forEach((argType, index) => {
|
|
1762
|
-
const param = nasl_concepts_1.Param.createProtoTypeOnly({
|
|
1763
|
-
name: `param${index + 1}`, // 默认参数名
|
|
1764
|
-
typeAnnotation: argType,
|
|
1765
|
-
spread: argType.spread
|
|
1766
|
-
});
|
|
1767
|
-
params.push(param);
|
|
1768
|
-
});
|
|
1769
|
-
}
|
|
1770
|
-
return params;
|
|
1771
|
-
}
|
|
1772
1813
|
}
|
|
1773
1814
|
function tpNewRegex(env, nd, tgtTy) {
|
|
1774
1815
|
// 我们将对NewRegex的类型检查归约为对nasl.util.NewRegex(nd.pattern, nd.flags)的类型检查
|