@lcap/nasl-language-server-core 4.4.0-rc.2 → 4.4.1-rc.2
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.map +1 -1
- package/out/checker.js +241 -111
- 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 +58 -24
- 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} +183 -19
- 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 +60 -43
- package/out/reference-manager/reference-manager.d.ts.map +1 -1
- package/out/reference-manager/reference-manager.js +381 -146
- 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 +7 -10
- 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 +8 -2
- package/out/reference-manager/symbol-type.js.map +1 -1
- package/out/reference-manager/update-nasl-fragment.js +4 -4
- package/out/reference-manager/update-nasl-fragment.js.map +1 -1
- package/out/typer/collectGlobalDefs.js +3 -3
- 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 +48 -5
- 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 +141 -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 +3 -3
- package/out/typer/dispatch-def.js.map +1 -1
- package/out/typer/dispatch-expr.d.ts.map +1 -1
- package/out/typer/dispatch-expr.js +32 -73
- package/out/typer/dispatch-expr.js.map +1 -1
- package/out/typer/dispatch-process.js +3 -3
- 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 +9 -11
- 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 +33 -26
- package/out/typer/dispatch-view.js.map +1 -1
- package/out/typer/get-oql-files.js +1 -1
- package/out/typer/get-oql-files.js.map +1 -1
- package/out/typer/incremental-update.d.ts +2 -2
- package/out/typer/incremental-update.d.ts.map +1 -1
- package/out/typer/incremental-update.js +142 -30
- package/out/typer/incremental-update.js.map +1 -1
- package/out/typer/overload-helper.js +2 -2
- 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 +43 -32
- package/out/typer/solver.js.map +1 -1
- package/out/typer/subster.d.ts.map +1 -1
- package/out/typer/subster.js +101 -20
- package/out/typer/subster.js.map +1 -1
- package/out/typer/topo-sort.d.ts +37 -0
- package/out/typer/topo-sort.d.ts.map +1 -1
- package/out/typer/topo-sort.js +264 -5
- 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.map +1 -1
- package/out/typer/type-predicate.js +38 -16
- package/out/typer/type-predicate.js.map +1 -1
- package/out/typer/typer.d.ts +19 -3
- package/out/typer/typer.d.ts.map +1 -1
- package/out/typer/typer.js +60 -27
- package/out/typer/typer.js.map +1 -1
- package/out/typer/unifier.d.ts +2 -0
- package/out/typer/unifier.d.ts.map +1 -1
- package/out/typer/unifier.js +52 -27
- package/out/typer/unifier.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 -181
- package/out/reference-manager/view-elem-logic.js.map +0 -1
|
@@ -7,7 +7,7 @@ const fp_macros_1 = require("../utils/fp-macros");
|
|
|
7
7
|
const console_1 = require("console");
|
|
8
8
|
const builtin_q_name_1 = require("./builtin-q-name");
|
|
9
9
|
const build_q_name_def_1 = require("./build-q-name-def");
|
|
10
|
-
const
|
|
10
|
+
const def_key_helpers_1 = require("./def-key-helpers");
|
|
11
11
|
const typer_1 = require("../typer");
|
|
12
12
|
const type_predicate_1 = require("../typer/type-predicate");
|
|
13
13
|
const helper_1 = require("../typer/helper");
|
|
@@ -21,7 +21,6 @@ const type_manager_1 = require("../typer/type-manager");
|
|
|
21
21
|
const oql_1 = require("../utils/oql");
|
|
22
22
|
const string_2 = require("../utils/string");
|
|
23
23
|
const traverse_util_1 = require("../utils/traverse-util");
|
|
24
|
-
const view_elem_logic_1 = require("./view-elem-logic");
|
|
25
24
|
const helper_2 = require("./helper");
|
|
26
25
|
const misc_1 = require("../utils/misc");
|
|
27
26
|
const asserts_1 = require("@lcap/nasl-concepts/asserts");
|
|
@@ -46,7 +45,7 @@ class ReferenceManager {
|
|
|
46
45
|
static { this.defConcept = symbol_type_1.defConcept; } /** imported */
|
|
47
46
|
static { this.compositeNodeConcept = symbol_type_1.compositeNodeConcept; } /** imported */
|
|
48
47
|
static { this.connectionNsp = 'app.connections'; }
|
|
49
|
-
// gQNameDefs 和
|
|
48
|
+
// gQNameDefs 和 globalRefs 的构建时机不一样,所以不放在构造器中
|
|
50
49
|
constructor() {
|
|
51
50
|
// qualified names to definition memory address for GLOBAL DEFINITIONS
|
|
52
51
|
this.gQNameDefs = new Map();
|
|
@@ -65,33 +64,26 @@ class ReferenceManager {
|
|
|
65
64
|
*
|
|
66
65
|
* 将实体看成 namespace,所有引用实体逻辑的地方也算引用了实体?
|
|
67
66
|
*/
|
|
68
|
-
this.
|
|
69
|
-
// Accessor methods for
|
|
67
|
+
this.globalRefs = new Map; // 手动管理,小心内存泄漏
|
|
68
|
+
// Accessor methods for globalRefs to normalize input later
|
|
70
69
|
this.getSymbolRefs = (__def) => {
|
|
71
70
|
const def = this.normaliseEntityLogic(__def);
|
|
72
|
-
return this.
|
|
71
|
+
return this.globalRefs.get(def);
|
|
73
72
|
};
|
|
74
73
|
this.setSymbolRefs = (__def, refs) => {
|
|
75
74
|
const def = this.normaliseEntityLogic(__def);
|
|
76
|
-
this.
|
|
75
|
+
this.globalRefs.set(def, refs);
|
|
77
76
|
};
|
|
78
77
|
this.deleteSymbolRefs = (__def) => {
|
|
79
78
|
const def = this.normaliseEntityLogic(__def);
|
|
80
|
-
return this.
|
|
79
|
+
return this.globalRefs.delete(def);
|
|
81
80
|
};
|
|
82
|
-
this.
|
|
83
|
-
this.
|
|
81
|
+
this.clearGlobalRefs = () => {
|
|
82
|
+
this.globalRefs.clear();
|
|
84
83
|
};
|
|
85
|
-
this.
|
|
86
|
-
return this.
|
|
84
|
+
this.getGlobalRefsSize = () => {
|
|
85
|
+
return this.globalRefs.size;
|
|
87
86
|
};
|
|
88
|
-
// 辅助 map
|
|
89
|
-
this.veQNameDefs = new Map();
|
|
90
|
-
/**
|
|
91
|
-
* @warning ViewElement 和 Logic 都是局部符号,可以重名,qName 重复时会出错,不要搞这种例子谢谢
|
|
92
|
-
* key 是 memory addr 而不是 string 的原因:点查找引用时,不好高效获取 qName(如 Logic 没有 namespace 但调用处其实有,对的就是 elements.)
|
|
93
|
-
*/
|
|
94
|
-
this.veRefs = new Map();
|
|
95
87
|
// 当前的 collectRefs 是增加还是删除引用。先这样吧,没时间重构了……
|
|
96
88
|
this.modeForCollect = null;
|
|
97
89
|
/**
|
|
@@ -133,8 +125,8 @@ class ReferenceManager {
|
|
|
133
125
|
// 上一次查找引用局部符号建立的 cache
|
|
134
126
|
this.lastBoundary = undefined;
|
|
135
127
|
this.isLocalCacheValid = true;
|
|
136
|
-
/**
|
|
137
|
-
this.
|
|
128
|
+
/** 局部符号的引用,key 为 getLocalDefKey 返回值(作用域内简单名或完整路径) */
|
|
129
|
+
this.localRefs = new Map();
|
|
138
130
|
// 当前文件节点
|
|
139
131
|
this.curFileNode = undefined;
|
|
140
132
|
/**
|
|
@@ -158,14 +150,26 @@ class ReferenceManager {
|
|
|
158
150
|
/**
|
|
159
151
|
* Remove all recorded local scope variable bindings under a file node.
|
|
160
152
|
* Used by incremental type checking to invalidate stale scope allocations.
|
|
153
|
+
* @param options.skipDescendantFileNodes 为 true 时遇到子级「文件节点」则不再向下遍历,避免误清子 View 等,增量阶段 2 重算前用此选项
|
|
154
|
+
* @param options.isFileNode 与 skipDescendantFileNodes 搭配使用,用于判断某节点是否为文件节点(如 checkNodeIsFileModuleInIdeWithCache)
|
|
161
155
|
*/
|
|
162
|
-
this.clearLocalSymBindingsForFile = (file) => {
|
|
156
|
+
this.clearLocalSymBindingsForFile = (file, options) => {
|
|
163
157
|
if (!file)
|
|
164
158
|
return;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
159
|
+
const { skipDescendantFileNodes, isFileNode } = options ?? {};
|
|
160
|
+
if (skipDescendantFileNodes && isFileNode) {
|
|
161
|
+
file.traverseStrictChildrenWithPruning?.((nd) => {
|
|
162
|
+
const prune = nd !== file && isFileNode(nd);
|
|
163
|
+
if (!prune)
|
|
164
|
+
this.localSymBindings.delete(nd);
|
|
165
|
+
return prune;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
file.traverseStrictChildren((nd) => {
|
|
170
|
+
this.localSymBindings.delete(nd);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
169
173
|
this.localSymBindings.delete(file);
|
|
170
174
|
};
|
|
171
175
|
this.clearAllLocalSymBindings = () => {
|
|
@@ -179,7 +183,7 @@ class ReferenceManager {
|
|
|
179
183
|
* declaration for each variable name is returned (nearest-first ordering).
|
|
180
184
|
*
|
|
181
185
|
* Implementation notes:
|
|
182
|
-
* - We intentionally DO NOT depend on the (ephemeral)
|
|
186
|
+
* - We intentionally DO NOT depend on the (ephemeral) localDefStacks in SemEnv so
|
|
183
187
|
* this works post-typing (e.g. in reference / rename / hover providers) without
|
|
184
188
|
* re-running the typer.
|
|
185
189
|
* - Order:
|
|
@@ -206,20 +210,21 @@ class ReferenceManager {
|
|
|
206
210
|
const localSyms = this.getVisibleLocalSyms(node, options);
|
|
207
211
|
const localVars = localSyms.filter(service_1.isLocalVar);
|
|
208
212
|
const collected = Array.from(localVars);
|
|
209
|
-
|
|
213
|
+
// 用于 shadowing 去重,需用 getLocalDefKey 与引用时的 key 一致
|
|
214
|
+
const seen = new Set(localSyms.map(v => (0, def_key_helpers_1.getLocalDefKey)(v) ?? (0, def_key_helpers_1.getGlobalDefKey)(v)));
|
|
210
215
|
const seenNames = new Set(localVars.map(v => v?.name).filter(Boolean));
|
|
211
216
|
// View-specific: stitch in process variables allocated during typing
|
|
212
217
|
this.stitchProcessVarsForView(node, env, includeShadowed, predicate, collected, seenNames);
|
|
213
218
|
this.stitchValidationVarsForView(node, env, includeShadowed, predicate, collected, seenNames);
|
|
214
219
|
const feVars = getNearestFrontendVars(node);
|
|
215
220
|
for (const v of feVars) {
|
|
216
|
-
const
|
|
217
|
-
if (!
|
|
221
|
+
const vKey = (0, def_key_helpers_1.getLocalDefKey)(v) ?? (0, def_key_helpers_1.getGlobalDefKey)(v);
|
|
222
|
+
if (!vKey)
|
|
218
223
|
continue;
|
|
219
224
|
if (!includeShadowed) {
|
|
220
|
-
if (seen.has(
|
|
225
|
+
if (seen.has(vKey))
|
|
221
226
|
continue;
|
|
222
|
-
seen.add(
|
|
227
|
+
seen.add(vKey);
|
|
223
228
|
}
|
|
224
229
|
if (predicate && !predicate(v))
|
|
225
230
|
continue;
|
|
@@ -278,7 +283,7 @@ class ReferenceManager {
|
|
|
278
283
|
const vars = this.localSymBindings.get(cur);
|
|
279
284
|
if (vars && vars.length > 0) {
|
|
280
285
|
for (const v of vars) {
|
|
281
|
-
const vQName = (0,
|
|
286
|
+
const vQName = (0, def_key_helpers_1.getGlobalDefKey)(v);
|
|
282
287
|
if (!vQName)
|
|
283
288
|
continue;
|
|
284
289
|
if (!includeShadowed) {
|
|
@@ -361,7 +366,7 @@ class ReferenceManager {
|
|
|
361
366
|
const def = this.gQNameDefs.get(qName);
|
|
362
367
|
if (def) {
|
|
363
368
|
// Add reference to existing definition
|
|
364
|
-
(0, helper_1.createSetOnPush)(this.
|
|
369
|
+
(0, helper_1.createSetOnPush)(this.globalRefs, def, ref);
|
|
365
370
|
}
|
|
366
371
|
else {
|
|
367
372
|
// Cache reference for future relinking
|
|
@@ -399,10 +404,6 @@ class ReferenceManager {
|
|
|
399
404
|
this.modeForCollect = null;
|
|
400
405
|
};
|
|
401
406
|
this.addQNameDefs = (0, build_q_name_def_1.mkAddQNameDefs)(this.gQNameDefs, this.compDefMgr);
|
|
402
|
-
/** 注释见具体实现 */
|
|
403
|
-
this.addViewElementLogicQNameDefs = (0, view_elem_logic_1.mkAddViewElementLogicQNameDefs)(this.veQNameDefs, this.gQNameDefs);
|
|
404
|
-
/** 注释见具体实现 */
|
|
405
|
-
this.addViewElementLogicRefs = (0, view_elem_logic_1.mkAddViewElementBindLogicRefs)(this.veQNameDefs, this.veRefs);
|
|
406
407
|
this.queryQNameDef = (qName) => {
|
|
407
408
|
const res = this.gQNameDefs.get(qName);
|
|
408
409
|
if (!res) {
|
|
@@ -462,31 +463,12 @@ class ReferenceManager {
|
|
|
462
463
|
}
|
|
463
464
|
};
|
|
464
465
|
/**
|
|
465
|
-
*
|
|
466
|
-
* @param ref
|
|
467
|
-
* @returns
|
|
466
|
+
* 查找符号的定义(含全局符号、View/BC 内 logics 等,均已在 gQNameDefs 中注册)
|
|
468
467
|
*/
|
|
469
468
|
this.getNodeDef = (ref) => {
|
|
470
|
-
const qName = (0,
|
|
469
|
+
const qName = (0, def_key_helpers_1.getGlobalDefKey)(ref);
|
|
471
470
|
return qName ? this.gQNameDefs.get(qName) : undefined;
|
|
472
471
|
};
|
|
473
|
-
/**
|
|
474
|
-
* 查找符号的定义,同时查找全局定义和 View 级别的定义
|
|
475
|
-
* 用于构建调用图时查找 View 级别的 logics
|
|
476
|
-
* @param ref
|
|
477
|
-
* @returns
|
|
478
|
-
*/
|
|
479
|
-
this.getNodeDefIncludingView = (ref) => {
|
|
480
|
-
const qName = (0, get_q_name_1.getTokenQualifiedName)(ref);
|
|
481
|
-
if (!qName)
|
|
482
|
-
return undefined;
|
|
483
|
-
// 先查找全局定义
|
|
484
|
-
const globalDef = this.gQNameDefs.get(qName);
|
|
485
|
-
if (globalDef)
|
|
486
|
-
return globalDef;
|
|
487
|
-
// 再查找 View 级别的定义
|
|
488
|
-
return this.veQNameDefs.get(qName);
|
|
489
|
-
};
|
|
490
472
|
/**
|
|
491
473
|
* @warning 对外接口,指用户点击 "查找引用",只返回用户手动指定的引用
|
|
492
474
|
* @param __nd 要查找引用的定义
|
|
@@ -495,9 +477,25 @@ class ReferenceManager {
|
|
|
495
477
|
this.getReferences = (env, __nd) => {
|
|
496
478
|
let nd = this.normaliseEntityLogic((0, misc_1.toRaw)(__nd));
|
|
497
479
|
let res = new Set();
|
|
480
|
+
// 逻辑/页面参数:外部引用在 globalRefs(CallLogic 实参),内部引用在 localRefs(Logic 体内同名标识符)
|
|
481
|
+
if (nd.concept === 'Param' || nd.concept === 'ParamWithGroup') {
|
|
482
|
+
const paramQName = (0, def_key_helpers_1.getGlobalDefKey)(nd);
|
|
483
|
+
const isParamOfLogicOrView = (0, symbol_type_1.isLogicViewLike)(nd.parentNode);
|
|
484
|
+
const def = isParamOfLogicOrView && paramQName ? this.gQNameDefs.get(paramQName) : undefined;
|
|
485
|
+
const externalRefs = def ? this.getSymbolRefs(def) ?? new Set() : new Set();
|
|
486
|
+
const boundary = (0, helper_2.getBoundary)(nd);
|
|
487
|
+
if (boundary && (this.lastBoundary !== boundary || !this.isLocalCacheValid)) {
|
|
488
|
+
this.localRefs.clear();
|
|
489
|
+
this.timeAndLog('Get reference: collect local refs for Param', this.buildLocalRefs, env, nd);
|
|
490
|
+
}
|
|
491
|
+
const localKey = (0, def_key_helpers_1.getLocalDefKey)(nd) ?? nd.name;
|
|
492
|
+
const internalRefs = (localKey && this.localRefs.get(localKey)) ?? new Set();
|
|
493
|
+
res = mnemonist_1.set.union(externalRefs, internalRefs);
|
|
494
|
+
return Array.from(res);
|
|
495
|
+
}
|
|
498
496
|
// 比如 OverriddenLogic 和对应的 Logic 名字一样,但引用挂在 Logic 上
|
|
499
497
|
// 比如 实体对应的实体逻辑可能有多份内存地址,归结到现存的一份上
|
|
500
|
-
// nd = this.gQNameDefs.get(
|
|
498
|
+
// nd = this.gQNameDefs.get(getGlobalDefKey(nd)!)!;
|
|
501
499
|
// ==> 好像也不行,很多依赖库逻辑调用又挂了
|
|
502
500
|
const boundary = (0, helper_2.getBoundary)(nd);
|
|
503
501
|
// 全局符号直接查找
|
|
@@ -508,7 +506,7 @@ class ReferenceManager {
|
|
|
508
506
|
if (pConn && boundary) {
|
|
509
507
|
// 那么它也就是个连接器下的局部符号
|
|
510
508
|
const qNameRefs = this.collectRefs(env, boundary); // 注意,从 boundary 开始就行,不是从 connector 开始
|
|
511
|
-
const ndQName = (0,
|
|
509
|
+
const ndQName = (0, def_key_helpers_1.getGlobalDefKey)(nd);
|
|
512
510
|
for (const [ref, qName] of qNameRefs) {
|
|
513
511
|
qName === ndQName && res.add(ref);
|
|
514
512
|
}
|
|
@@ -519,27 +517,28 @@ class ReferenceManager {
|
|
|
519
517
|
// 局部符号需要即时获取
|
|
520
518
|
// 从缓存中获取
|
|
521
519
|
if (this.lastBoundary === boundary && this.isLocalCacheValid) {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
520
|
+
const localKey = (0, def_key_helpers_1.getLocalDefKey)(nd) ?? (0, def_key_helpers_1.getGlobalDefKey)(nd);
|
|
521
|
+
const lRefs = localKey ? (this.localRefs.get(localKey) ?? new Set()) : new Set();
|
|
522
|
+
const gRefs = this.getSymbolRefs(nd) ?? new Set();
|
|
525
523
|
if (nd.concept === 'ViewElement' || nd.concept === 'Logic' || nd.concept === 'BusinessLogic' || nd.concept === 'Event') {
|
|
526
|
-
res = mnemonist_1.set.union(
|
|
524
|
+
res = mnemonist_1.set.union(lRefs, gRefs);
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
res = lRefs;
|
|
527
528
|
}
|
|
528
529
|
}
|
|
529
530
|
else {
|
|
530
531
|
// 局部扫描,建立所有局部引用
|
|
531
|
-
this.
|
|
532
|
-
this.
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
res = mnemonist_1.set.union(res, this.lQNameRefs.get((0, get_q_name_1.getTokenQualifiedName)(nd)) ?? new Set());
|
|
536
|
-
// @ts-expect-error 同上,并且虽然 BindEvent 本身没引用但是要触发对 view 建立引用
|
|
532
|
+
this.localRefs.clear();
|
|
533
|
+
this.timeAndLog('Get reference: collect local refs', this.buildLocalRefs, env, nd);
|
|
534
|
+
const localKey = (0, def_key_helpers_1.getLocalDefKey)(nd) ?? (0, def_key_helpers_1.getGlobalDefKey)(nd);
|
|
535
|
+
res = mnemonist_1.set.union(res, (localKey ? (this.localRefs.get(localKey) ?? new Set()) : new Set()));
|
|
537
536
|
if (nd.concept === 'ViewElement' || nd.concept === 'Logic' || nd.concept === 'BusinessLogic' || nd.concept === 'BindEvent' || nd.concept === 'Event') {
|
|
538
537
|
const ctxViewLike = (0, misc_1.toRaw)((0, nasl_concepts_1.getCtxViewLike)(nd));
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
res = mnemonist_1.set.union(res ?? new Set(), this.
|
|
538
|
+
if (ctxViewLike) {
|
|
539
|
+
this.timeAndLog('Get reference: build view element refs cache', this.buildLocalRefs, env, ctxViewLike);
|
|
540
|
+
}
|
|
541
|
+
res = mnemonist_1.set.union(res ?? new Set(), this.getSymbolRefs(nd) ?? new Set());
|
|
543
542
|
}
|
|
544
543
|
}
|
|
545
544
|
}
|
|
@@ -549,25 +548,24 @@ class ReferenceManager {
|
|
|
549
548
|
* 业务逻辑在页面调用的时候,名字前缀是随着业务组件实例名字而变化的,几乎是全应用查找……
|
|
550
549
|
*/
|
|
551
550
|
if (nd.concept === 'BusinessLogic') {
|
|
552
|
-
//
|
|
551
|
+
// 上面已经找到了业务组件内部对业务组件逻辑的引用(localRefs)
|
|
553
552
|
// 现在再找出所有 业务组件逻辑 所属的业务组件的外部引用
|
|
553
|
+
// buildLocalRefs 会把页面中 elements.bs-xxx.logics.myLogic 的调用写入 globalRefs(BusinessLogic)
|
|
554
554
|
const bs = (0, misc_1.toRaw)((0, nasl_concepts_1.getCtxViewLike)(nd));
|
|
555
555
|
if (bs?.concept === 'BusinessComponent') {
|
|
556
556
|
const bsRefs = this.getSymbolRefs(bs) ?? new Set();
|
|
557
|
-
let bsRefsRefs = new Array(); // 业务组件(在页面的引用)的引用
|
|
558
557
|
/**
|
|
559
|
-
*
|
|
558
|
+
* 对每个 BC 实例所在的页面扫描,buildLocalRefs 会把外部引用写入 globalRefs(nd)
|
|
560
559
|
* @warning 造孽,引用业务组件的每个 view 都要扫描一遍,应该很慢
|
|
561
560
|
*/
|
|
562
561
|
const startTime = Date.now();
|
|
563
562
|
for (const bsInst of bsRefs) {
|
|
564
563
|
const ctxViewLike = (0, misc_1.toRaw)((0, nasl_concepts_1.getCtxViewLike)(bsInst));
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
bsRefsRefs.push(...this.getViewElementRefs(bsInst));
|
|
564
|
+
if (ctxViewLike)
|
|
565
|
+
this.buildLocalRefs(env, ctxViewLike);
|
|
568
566
|
}
|
|
569
|
-
//
|
|
570
|
-
res = mnemonist_1.set.union(res,
|
|
567
|
+
// 外部引用已写入 globalRefs(BusinessLogic),直接取
|
|
568
|
+
res = mnemonist_1.set.union(res, this.getSymbolRefs(nd) ?? new Set());
|
|
571
569
|
const endTime = Date.now();
|
|
572
570
|
if (endTime - startTime > 200) {
|
|
573
571
|
console.log(`Get reference: complex business logic took ${endTime - startTime}ms`);
|
|
@@ -580,7 +578,7 @@ class ReferenceManager {
|
|
|
580
578
|
const allLogics = [...conn.logics, ...conn.namespaces.flatMap(nsp => nsp.logics)];
|
|
581
579
|
for (const l of allLogics) {
|
|
582
580
|
// ConnectorLogic,发布态的连接器里外都有调用,真是里外不是人啊。
|
|
583
|
-
res = mnemonist_1.set.union(res, this.
|
|
581
|
+
res = mnemonist_1.set.union(res, this.globalRefs.get(l) ?? new Set());
|
|
584
582
|
}
|
|
585
583
|
}
|
|
586
584
|
// 加上所有实体逻辑调用的引用(实体逻辑可看做无定义,但要修改调用处的 namespace:实体名是 namespace 的一部分)
|
|
@@ -601,17 +599,15 @@ class ReferenceManager {
|
|
|
601
599
|
};
|
|
602
600
|
/**
|
|
603
601
|
* 给类似 FileNode 级别的定义建立局部引用记录
|
|
604
|
-
* @warning 不包括 ViewElement、BindEvent
|
|
602
|
+
* @warning 不包括 ViewElement、BindEvent 相关的引用,已合并到 getLocalDefKeys 与 collectedRefs 处理
|
|
605
603
|
* @warning 需要包括 SubLogics
|
|
606
604
|
*/
|
|
607
|
-
this.
|
|
605
|
+
this.buildLocalRefs = (env, __nd) => {
|
|
608
606
|
this.modeForCollect = "create" /* Operation.Create */;
|
|
609
607
|
const nd = (0, misc_1.toRaw)(__nd);
|
|
610
608
|
let logicVars = new Array();
|
|
611
609
|
let viewVars = new Array();
|
|
612
610
|
let processVars = new Array();
|
|
613
|
-
/** @warning v4.1 开始,view logics 不在这里处理,在 @link veQNameRefs 那里处理 */
|
|
614
|
-
let isViewLike = false;
|
|
615
611
|
const boundary = (0, helper_2.getBoundary)(nd);
|
|
616
612
|
if (!boundary) {
|
|
617
613
|
return new Set();
|
|
@@ -622,7 +618,33 @@ class ReferenceManager {
|
|
|
622
618
|
if (ctxLogic && 'variables' in ctxLogic) {
|
|
623
619
|
logicVars.push(...ctxLogic.variables?.map(misc_1.toRaw) ?? []);
|
|
624
620
|
}
|
|
625
|
-
|
|
621
|
+
// View/BC 内 logics、events、elements 的引用走 localRefs,需预先初始化 key
|
|
622
|
+
const viewLike = boundary;
|
|
623
|
+
const viewQ = (0, def_key_helpers_1.getGlobalDefKey)(viewLike);
|
|
624
|
+
(viewLike.logics ?? []).forEach((l) => {
|
|
625
|
+
const q = (0, def_key_helpers_1.getLocalDefKey)(l) ?? (0, def_key_helpers_1.getGlobalDefKey)(l);
|
|
626
|
+
q && this.localRefs.set(q, new Set());
|
|
627
|
+
});
|
|
628
|
+
(viewLike.events ?? []).forEach((e) => {
|
|
629
|
+
const q = (0, def_key_helpers_1.getLocalDefKey)(e) ?? (0, def_key_helpers_1.getGlobalDefKey)(e);
|
|
630
|
+
q && this.localRefs.set(q, new Set());
|
|
631
|
+
});
|
|
632
|
+
for (const be of viewLike.bindEvents ?? []) {
|
|
633
|
+
for (const l of be.logics ?? []) {
|
|
634
|
+
this.localRefs.set(`${viewQ}.bindEvents.${be.name}.logics.${l.name}`, new Set());
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
const initElemKeys = (ve, parentNsp, parentKey = 'elements') => {
|
|
638
|
+
const elemKey = `${parentNsp}.${parentKey}.${ve.name}`;
|
|
639
|
+
this.localRefs.set(elemKey, new Set());
|
|
640
|
+
for (const be of ve.bindEvents ?? []) {
|
|
641
|
+
for (const l of be.logics ?? []) {
|
|
642
|
+
this.localRefs.set(`${elemKey}.bindEvents.${be.name}.logics.${l.name}`, new Set());
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
ve.children?.forEach((c) => initElemKeys(c, elemKey, 'children'));
|
|
646
|
+
};
|
|
647
|
+
(viewLike.elements ?? []).forEach((ve) => initElemKeys(ve, viewQ, 'elements'));
|
|
626
648
|
}
|
|
627
649
|
else if (boundary.concept === 'ProcessDefinitionV2') {
|
|
628
650
|
processVars = (0, nasl_concepts_1.getProcessVars)(nd).map(misc_1.toRaw);
|
|
@@ -635,34 +657,47 @@ class ReferenceManager {
|
|
|
635
657
|
logicVars = (0, nasl_concepts_1.getLogicVars)(nd).map(misc_1.toRaw);
|
|
636
658
|
}
|
|
637
659
|
let allVars = logicVars.concat(processVars).concat(viewVars);
|
|
638
|
-
|
|
660
|
+
let collectedRefs = this.collectRefs(env, boundary, true);
|
|
661
|
+
this.lastBoundary = boundary;
|
|
662
|
+
// initialize local cache: 局部变量用 getLocalDefKey;Entity/Structure 属性用 collectRefs 返回的 qName(全局 key)
|
|
639
663
|
allVars.forEach(def => {
|
|
640
|
-
const qName = (0,
|
|
664
|
+
const qName = (0, def_key_helpers_1.getLocalDefKey)(def) ?? (0, def_key_helpers_1.getGlobalDefKey)(def);
|
|
641
665
|
if (qName) {
|
|
642
|
-
this.
|
|
666
|
+
this.localRefs.set(qName, new Set());
|
|
643
667
|
}
|
|
644
668
|
});
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
669
|
+
collectedRefs?.forEach(([rf, qName]) => {
|
|
670
|
+
if (rf.concept === 'Identifier' && qName.includes('.properties.')) {
|
|
671
|
+
this.localRefs.set(qName, this.localRefs.get(qName) ?? new Set());
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
collectedRefs?.forEach(([rf, qName]) => {
|
|
675
|
+
const isEntityOrStructPropRef = rf.concept === 'Identifier' && qName.includes('.properties.');
|
|
676
|
+
const keys = (0, def_key_helpers_1.getLocalDefKeys)(rf);
|
|
677
|
+
const keysToUse = isEntityOrStructPropRef ? [qName] : (keys.length > 0 ? keys : [qName]);
|
|
678
|
+
for (const key of keysToUse) {
|
|
679
|
+
// 简单名 key 不加入属性名 Identifier(NewComposite/BatchAssignment 等)
|
|
680
|
+
if (!key.includes('.') && (0, def_key_helpers_1.isIdentifierAsPropertyName)(rf))
|
|
681
|
+
continue;
|
|
682
|
+
this.localRefs.get(key)?.add(rf);
|
|
683
|
+
}
|
|
684
|
+
// 页面调用 BC 逻辑:外部引用 -> globalRefs
|
|
685
|
+
if (rf.concept === 'CallLogic' && rf.calleeNamespace?.startsWith('elements.') && rf.calleeNamespace?.endsWith('.logics')) {
|
|
686
|
+
const def = this.gQNameDefs.get(qName);
|
|
687
|
+
def && (0, fp_macros_1.createOnAdd)(this.globalRefs, def, rf);
|
|
688
|
+
}
|
|
689
|
+
// Entity/Structure 属性引用 -> globalRefs
|
|
690
|
+
if (isEntityOrStructPropRef) {
|
|
691
|
+
const def = this.gQNameDefs.get(qName);
|
|
692
|
+
def && (0, fp_macros_1.createOnAdd)(this.globalRefs, def, rf);
|
|
693
|
+
}
|
|
650
694
|
});
|
|
651
695
|
// Note: 暂不支持 BindAttr、BindDirective 里的变量的查找引用
|
|
652
696
|
this.isLocalCacheValid = true;
|
|
653
697
|
this.modeForCollect = null;
|
|
654
698
|
};
|
|
655
|
-
/**
|
|
656
|
-
|
|
657
|
-
* 'elements.uLinearLayout1.logics.openLoading'
|
|
658
|
-
*
|
|
659
|
-
* 'elements.uLinearLayout1.property.uLinearLayout1._if._if'
|
|
660
|
-
* "concept": "Identifier",
|
|
661
|
-
* "namespace": "elements.uLinearLayout1.property",
|
|
662
|
-
* "name": "uLinearLayout1",
|
|
663
|
-
*
|
|
664
|
-
*/
|
|
665
|
-
this.getViewElementRefs = (nd) => !nd ? new Set() : this.veRefs.get(nd) ?? new Set();
|
|
699
|
+
/** @deprecated 使用 getSymbolRefs,保留仅为兼容 */
|
|
700
|
+
this.getViewElementRefs = (nd) => !nd ? new Set() : this.getSymbolRefs(nd) ?? new Set();
|
|
666
701
|
/**
|
|
667
702
|
* 非常危险,但是先这样吧
|
|
668
703
|
*/
|
|
@@ -798,8 +833,8 @@ class ReferenceManager {
|
|
|
798
833
|
*/
|
|
799
834
|
this.isRefStillReferencingQName = (ref, qName) => {
|
|
800
835
|
try {
|
|
801
|
-
// 通过
|
|
802
|
-
const currentQName = (0,
|
|
836
|
+
// 通过 getGlobalDefKey 获取引用节点当前引用的 qName
|
|
837
|
+
const currentQName = (0, def_key_helpers_1.getGlobalDefKey)(ref);
|
|
803
838
|
// 检查是否还引用原来的 qName
|
|
804
839
|
return currentQName === qName;
|
|
805
840
|
}
|
|
@@ -891,8 +926,201 @@ class ReferenceManager {
|
|
|
891
926
|
this.pendingRefsForRecreation.clear();
|
|
892
927
|
};
|
|
893
928
|
/**
|
|
894
|
-
|
|
895
|
-
|
|
929
|
+
* 注册 Logic/View/BusinessLogic 的 params 到 gQNameDefs,便于建立「调用逻辑的参数」到「逻辑的参数」的引用
|
|
930
|
+
*/
|
|
931
|
+
this.registerParamsOfLogicOrView = (defNode) => {
|
|
932
|
+
const nd = defNode;
|
|
933
|
+
if (!(0, symbol_type_1.isLogicViewLike)(nd) || !nd.params?.length) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
for (const p of nd.params) {
|
|
937
|
+
const pq = (0, def_key_helpers_1.getGlobalDefKey)(p);
|
|
938
|
+
if (pq) {
|
|
939
|
+
this.gQNameDefs.set(pq, p);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
/**
|
|
944
|
+
* 移除 Logic/View/BusinessLogic 的 params 在 gQNameDefs 的注册及其引用
|
|
945
|
+
*/
|
|
946
|
+
this.unregisterParamsOfLogicOrView = (defNode) => {
|
|
947
|
+
const nd = defNode;
|
|
948
|
+
if (!(0, symbol_type_1.isLogicViewLike)(nd) || !nd.params?.length) {
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
for (const p of nd.params) {
|
|
952
|
+
const pq = (0, def_key_helpers_1.getGlobalDefKey)(p);
|
|
953
|
+
if (pq) {
|
|
954
|
+
this.gQNameDefs.delete(pq);
|
|
955
|
+
this.deleteSymbolRefs(p);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
};
|
|
959
|
+
/**
|
|
960
|
+
* 对「调用该 Logic/View/BusinessComponent 的所有 CallLogic/Destination/ViewElement」重新收集参数引用,把参数引用加进 globalRefs。
|
|
961
|
+
* syncParamsOfLogicOrView 与 registerNewParamAndRecollectRefs 共用,避免重复逻辑。
|
|
962
|
+
* 所有 callers 均在 globalRefs。
|
|
963
|
+
*/
|
|
964
|
+
this.recollectParamRefsForCallers = (env, logicQName) => {
|
|
965
|
+
const logicDef = this.gQNameDefs.get(logicQName);
|
|
966
|
+
const callers = logicDef ? this.getSymbolRefs(logicDef) : undefined;
|
|
967
|
+
if (!callers?.size)
|
|
968
|
+
return;
|
|
969
|
+
const prevMode = this.modeForCollect;
|
|
970
|
+
this.modeForCollect = "create" /* Operation.Create */;
|
|
971
|
+
try {
|
|
972
|
+
for (const ref of callers) {
|
|
973
|
+
if (ref.concept === 'CallLogic' || ref.concept === 'Destination'
|
|
974
|
+
|| (ref.concept === 'ViewElement' && ref.tag?.startsWith('bs-'))) {
|
|
975
|
+
this.handleCallerParamRefs(env, ref);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
finally {
|
|
980
|
+
this.modeForCollect = prevMode;
|
|
981
|
+
}
|
|
982
|
+
};
|
|
983
|
+
/**
|
|
984
|
+
* 对指定 Logic/View/BusinessLogic 重新收集参数引用(CallLogic 实参、Destination 实参 → params)。
|
|
985
|
+
* 增量更新「3: 按新类型添加符号」之后调用,此时 View 的 callers(Destination)已就绪,页面参数才能对应到页面跳转。
|
|
986
|
+
*/
|
|
987
|
+
this.recollectParamRefsForDef = (env, defNode) => {
|
|
988
|
+
if (!(0, symbol_type_1.isLogicViewLike)(defNode))
|
|
989
|
+
return;
|
|
990
|
+
const qName = (0, def_key_helpers_1.getGlobalDefKey)(defNode);
|
|
991
|
+
if (qName)
|
|
992
|
+
this.recollectParamRefsForCallers(env, qName);
|
|
993
|
+
};
|
|
994
|
+
/**
|
|
995
|
+
* Logic/View/BusinessLogic 参数列表变更时同步 gQNameDefs 与 globalRefs。
|
|
996
|
+
* - 仅卸载「已删除」的参数,避免把内部引用清空。
|
|
997
|
+
* - 仍存在的参数:把 refs 从旧 def 迁移到新 def,并更新 gQNameDefs。
|
|
998
|
+
* - 新加参数:只做注册。
|
|
999
|
+
* - 最后对「调用该 Logic/View 的所有 CallLogic」重新收集参数引用,把新参数的引用加进 globalRefs。
|
|
1000
|
+
*/
|
|
1001
|
+
this.syncParamsOfLogicOrView = (env, updatedDefNode, oldDefNode) => {
|
|
1002
|
+
const updated = updatedDefNode;
|
|
1003
|
+
const old = oldDefNode;
|
|
1004
|
+
if (!(0, symbol_type_1.isLogicViewLike)(updated))
|
|
1005
|
+
return;
|
|
1006
|
+
const logicQName = (0, def_key_helpers_1.getGlobalDefKey)(updatedDefNode);
|
|
1007
|
+
if (!logicQName)
|
|
1008
|
+
return;
|
|
1009
|
+
const oldParams = old.params ?? [];
|
|
1010
|
+
const newParams = updated.params ?? [];
|
|
1011
|
+
const newParamNames = new Set(newParams.map((p) => p?.name));
|
|
1012
|
+
const oldParamNames = new Set(oldParams.map((p) => p?.name));
|
|
1013
|
+
// 只卸载已删除的参数,用 getGlobalDefKey(p) 与注册时 key 一致
|
|
1014
|
+
for (const p of oldParams) {
|
|
1015
|
+
const name = p?.name;
|
|
1016
|
+
if (newParamNames.has(name))
|
|
1017
|
+
continue;
|
|
1018
|
+
const pq = (0, def_key_helpers_1.getGlobalDefKey)(p);
|
|
1019
|
+
if (!pq)
|
|
1020
|
+
continue;
|
|
1021
|
+
const def = this.gQNameDefs.get(pq);
|
|
1022
|
+
if (def)
|
|
1023
|
+
this.deleteSymbolRefs(def);
|
|
1024
|
+
this.gQNameDefs.delete(pq);
|
|
1025
|
+
}
|
|
1026
|
+
// 对新参数:存在的迁移 refs,新增的只注册,用 getGlobalDefKey(p) 与注册时 key 一致
|
|
1027
|
+
for (const p of newParams) {
|
|
1028
|
+
const pq = (0, def_key_helpers_1.getGlobalDefKey)(p);
|
|
1029
|
+
if (!pq)
|
|
1030
|
+
continue;
|
|
1031
|
+
const name = p?.name;
|
|
1032
|
+
if (oldParamNames.has(name)) {
|
|
1033
|
+
const oldDef = this.gQNameDefs.get(pq);
|
|
1034
|
+
const refs = oldDef ? this.globalRefs.get(oldDef) : undefined;
|
|
1035
|
+
if (oldDef)
|
|
1036
|
+
this.globalRefs.delete(oldDef);
|
|
1037
|
+
this.gQNameDefs.set(pq, p);
|
|
1038
|
+
if (refs?.size)
|
|
1039
|
+
this.globalRefs.set(p, refs);
|
|
1040
|
+
}
|
|
1041
|
+
else {
|
|
1042
|
+
this.gQNameDefs.set(pq, p);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
this.recollectParamRefsForCallers(env, logicQName);
|
|
1046
|
+
};
|
|
1047
|
+
/**
|
|
1048
|
+
* 新增参数进入 createNodes 时(Param create 事件):注册该参数并对调用该 Logic/View 的 CallLogic 重新收集参数引用。
|
|
1049
|
+
* 与 syncParamsOfLogicOrView 互补:后者处理 Logic update;本方法处理 Param create。
|
|
1050
|
+
*/
|
|
1051
|
+
this.registerNewParamAndRecollectRefs = (env, paramNode) => {
|
|
1052
|
+
const nd = paramNode;
|
|
1053
|
+
if (nd.concept !== 'Param' && nd.concept !== 'ParamWithGroup')
|
|
1054
|
+
return;
|
|
1055
|
+
const parent = nd.parentNode;
|
|
1056
|
+
if (!(0, symbol_type_1.isLogicViewLike)(parent))
|
|
1057
|
+
return;
|
|
1058
|
+
const logicQName = (0, def_key_helpers_1.getGlobalDefKey)(parent);
|
|
1059
|
+
if (!logicQName)
|
|
1060
|
+
return;
|
|
1061
|
+
const pq = (0, def_key_helpers_1.getGlobalDefKey)(nd);
|
|
1062
|
+
if (!pq)
|
|
1063
|
+
return;
|
|
1064
|
+
this.gQNameDefs.set(pq, nd);
|
|
1065
|
+
this.recollectParamRefsForCallers(env, logicQName);
|
|
1066
|
+
};
|
|
1067
|
+
/**
|
|
1068
|
+
* 建立「调用处实参」到「Logic/View/BusinessComponent 形参」的引用。
|
|
1069
|
+
* 支持 CallLogic(调用逻辑)、Destination(页面跳转)、ViewElement(业务组件 bindAttrs)等。
|
|
1070
|
+
* 扩充新类型时只需在此处增加分支。
|
|
1071
|
+
*/
|
|
1072
|
+
this.handleCallerParamRefs = (env, nd) => {
|
|
1073
|
+
if (!this.modeForCollect)
|
|
1074
|
+
return;
|
|
1075
|
+
let callee;
|
|
1076
|
+
let bindings;
|
|
1077
|
+
if (nd.concept === 'CallLogic' || nd.concept === 'Destination') {
|
|
1078
|
+
const calleeQName = (0, def_key_helpers_1.getGlobalDefKey)(nd);
|
|
1079
|
+
if (!calleeQName)
|
|
1080
|
+
return;
|
|
1081
|
+
callee = this.gQNameDefs.get(calleeQName);
|
|
1082
|
+
if (!callee?.params?.length)
|
|
1083
|
+
return;
|
|
1084
|
+
const args = nd.arguments ?? [];
|
|
1085
|
+
bindings = args
|
|
1086
|
+
.map((arg, i) => {
|
|
1087
|
+
const param = callee.params.find((p) => p.name === arg.keyword)
|
|
1088
|
+
?? callee.params[i];
|
|
1089
|
+
return param ? { refNode: arg, param } : null;
|
|
1090
|
+
})
|
|
1091
|
+
.filter((x) => !!x);
|
|
1092
|
+
}
|
|
1093
|
+
else if (nd.concept === 'ViewElement' && nd.tag.startsWith('bs-')) {
|
|
1094
|
+
// 无 bindAttrs 则无需注册实参→形参引用,直接跳过,避免 frontendType/businessComponents 查找
|
|
1095
|
+
if (!nd.bindAttrs?.length)
|
|
1096
|
+
return;
|
|
1097
|
+
const bsName = nd.tag.split('bs-')[1];
|
|
1098
|
+
const fet = nd.frontendType;
|
|
1099
|
+
const bsDef = fet?.businessComponents?.find((bc) => bc.name === bsName);
|
|
1100
|
+
if (!bsDef?.params?.length)
|
|
1101
|
+
return;
|
|
1102
|
+
callee = bsDef;
|
|
1103
|
+
bindings = nd.bindAttrs
|
|
1104
|
+
.map((attr) => {
|
|
1105
|
+
const param = bsDef.params.find((p) => p.name === attr.name);
|
|
1106
|
+
return param ? { refNode: attr, param } : null;
|
|
1107
|
+
})
|
|
1108
|
+
.filter((x) => !!x);
|
|
1109
|
+
}
|
|
1110
|
+
else {
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
for (const { refNode, param } of bindings) {
|
|
1114
|
+
const paramQName = (0, def_key_helpers_1.getGlobalDefKey)(param);
|
|
1115
|
+
if (paramQName) {
|
|
1116
|
+
this.handleRefOp(this.modeForCollect, refNode, paramQName);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
/**
|
|
1121
|
+
* 处理「定义」的增删
|
|
1122
|
+
* @warning Only handle global symbols
|
|
1123
|
+
**/
|
|
896
1124
|
this.handleDefOp = (mode, defNode, qName) => {
|
|
897
1125
|
switch (mode) {
|
|
898
1126
|
// 目前的策略是 re-link:删除 logic1 后,不会删除引用。新建一个 logic1 后,自动关联到老的引用上
|
|
@@ -903,6 +1131,8 @@ class ReferenceManager {
|
|
|
903
1131
|
else {
|
|
904
1132
|
// qName 链接到新的 defNode 的 mem addr
|
|
905
1133
|
this.gQNameDefs.set(qName, defNode);
|
|
1134
|
+
// 逻辑/页面参数一并注册,便于建立「调用逻辑的参数」到「逻辑的参数」的引用
|
|
1135
|
+
this.registerParamsOfLogicOrView(defNode);
|
|
906
1136
|
if ((0, component_def_manager_1.isGeneralViewElementDefinition)(defNode)) {
|
|
907
1137
|
this.compDefMgr.add(defNode, 'handleDefOp');
|
|
908
1138
|
}
|
|
@@ -917,6 +1147,8 @@ class ReferenceManager {
|
|
|
917
1147
|
this.isLocalCacheValid = false;
|
|
918
1148
|
}
|
|
919
1149
|
else {
|
|
1150
|
+
// 先移除逻辑/页面参数的注册及其引用
|
|
1151
|
+
this.unregisterParamsOfLogicOrView(defNode);
|
|
920
1152
|
// 缓存引用以备后续恢复(在删除引用之前调用)
|
|
921
1153
|
this.cacheRefsForRecreation(qName, defNode);
|
|
922
1154
|
// 删除 qName 和引用
|
|
@@ -931,16 +1163,17 @@ class ReferenceManager {
|
|
|
931
1163
|
}
|
|
932
1164
|
};
|
|
933
1165
|
/**
|
|
1166
|
+
* 处理「引用」的增删
|
|
934
1167
|
* @warning Only handle global symbols
|
|
935
|
-
|
|
1168
|
+
**/
|
|
936
1169
|
this.handleRefOp = (mode, refNd, qName) => {
|
|
937
1170
|
const def = this.gQNameDefs.get(qName);
|
|
938
1171
|
if (def) {
|
|
939
1172
|
switch (mode) {
|
|
940
1173
|
case "create" /* Operation.Create */: {
|
|
941
1174
|
// Route reference to the appropriate map based on whether it's explicit or implicit
|
|
942
|
-
// Explicit references go to
|
|
943
|
-
(0, fp_macros_1.createOnAdd)(this.
|
|
1175
|
+
// Explicit references go to globalRefs
|
|
1176
|
+
(0, fp_macros_1.createOnAdd)(this.globalRefs, def, refNd);
|
|
944
1177
|
break;
|
|
945
1178
|
}
|
|
946
1179
|
case "delete" /* Operation.Remove */: {
|
|
@@ -1008,7 +1241,7 @@ class ReferenceManager {
|
|
|
1008
1241
|
if (!(0, type_predicate_1.isEntityTy)(typeAnnotation) && !(0, type_predicate_1.isStructureTy)(typeAnnotation)) {
|
|
1009
1242
|
return;
|
|
1010
1243
|
}
|
|
1011
|
-
const tyQName = (0,
|
|
1244
|
+
const tyQName = (0, def_key_helpers_1.getGlobalDefKey)(typeAnnotation);
|
|
1012
1245
|
if (!tyQName) {
|
|
1013
1246
|
return;
|
|
1014
1247
|
}
|
|
@@ -1043,7 +1276,7 @@ class ReferenceManager {
|
|
|
1043
1276
|
if (!bsDef) {
|
|
1044
1277
|
return;
|
|
1045
1278
|
}
|
|
1046
|
-
this.handleRefOp(this.modeForCollect, nd, (0,
|
|
1279
|
+
this.handleRefOp(this.modeForCollect, nd, (0, def_key_helpers_1.getGlobalDefKey)(bsDef));
|
|
1047
1280
|
};
|
|
1048
1281
|
this.handleBindRoles = (env, nd) => {
|
|
1049
1282
|
for (const roleName of nd.bindRoles ?? nd.roles) {
|
|
@@ -1070,11 +1303,11 @@ class ReferenceManager {
|
|
|
1070
1303
|
parent?.interfaceDependencies?.forEach(dep => {
|
|
1071
1304
|
dep.interfaces.forEach(itfc => {
|
|
1072
1305
|
if (itfc.concept === 'AuthInterface' && itfc.name === nd.calleeName) {
|
|
1073
|
-
// this.handleRefOp(this.modeForCollect!, nd,
|
|
1306
|
+
// this.handleRefOp(this.modeForCollect!, nd, getGlobalDefKey(itfc)!);
|
|
1074
1307
|
const authName = itfc.authLogic;
|
|
1075
1308
|
parent?.authLogicsForCallInterface?.forEach(l => {
|
|
1076
1309
|
if (l.name === authName) {
|
|
1077
|
-
this.handleRefOp(this.modeForCollect, nd, (0,
|
|
1310
|
+
this.handleRefOp(this.modeForCollect, nd, (0, def_key_helpers_1.getGlobalDefKey)(l));
|
|
1078
1311
|
}
|
|
1079
1312
|
});
|
|
1080
1313
|
}
|
|
@@ -1082,12 +1315,12 @@ class ReferenceManager {
|
|
|
1082
1315
|
});
|
|
1083
1316
|
parent.interfaces?.forEach(itfc => {
|
|
1084
1317
|
if (itfc.concept === 'AuthInterface' && itfc.name === nd.calleeName) {
|
|
1085
|
-
// this.handleRefOp(this.modeForCollect!, nd,
|
|
1086
|
-
// this.handleRefOp(this.modeForCollect!, nd,
|
|
1318
|
+
// this.handleRefOp(this.modeForCollect!, nd, getGlobalDefKey(itfc)!);
|
|
1319
|
+
// this.handleRefOp(this.modeForCollect!, nd, getGlobalDefKey(itfc)!);
|
|
1087
1320
|
const authName = itfc.authLogic;
|
|
1088
1321
|
parent?.authLogics?.forEach(l => {
|
|
1089
1322
|
if (l.name === authName) {
|
|
1090
|
-
this.handleRefOp(this.modeForCollect, nd, (0,
|
|
1323
|
+
this.handleRefOp(this.modeForCollect, nd, (0, def_key_helpers_1.getGlobalDefKey)(l));
|
|
1091
1324
|
}
|
|
1092
1325
|
});
|
|
1093
1326
|
}
|
|
@@ -1132,7 +1365,7 @@ class ReferenceManager {
|
|
|
1132
1365
|
!skipSubView && views.push(...(0, misc_1.getSubViews)(nd));
|
|
1133
1366
|
if (nd.concept === 'View' || nd.concept === 'BusinessComponent') {
|
|
1134
1367
|
this.curFileNode = nd;
|
|
1135
|
-
env.viewAssocProcess = env.processV2ViewBindings.get((0,
|
|
1368
|
+
env.viewAssocProcess = env.processV2ViewBindings.get((0, def_key_helpers_1.getGlobalDefKey)(nd)) ?? null;
|
|
1136
1369
|
}
|
|
1137
1370
|
const res = new Array(); // 使用数组而不是 Map
|
|
1138
1371
|
// specialization for speeding up
|
|
@@ -1149,10 +1382,14 @@ class ReferenceManager {
|
|
|
1149
1382
|
n.concept === 'CallAuthInterface' && this.handleAuthLogicRef(env, n);
|
|
1150
1383
|
// 处理流程子流程引用
|
|
1151
1384
|
n.concept === 'ProcessElementV2' && this.handleProcessSubProcessRef(env, n);
|
|
1385
|
+
// 处理 CallLogic、Destination、ViewElement 的调用处实参到形参的引用
|
|
1386
|
+
if (['CallLogic', 'Destination', 'ViewElement'].includes(n.concept)) {
|
|
1387
|
+
this.handleCallerParamRefs(env, n);
|
|
1388
|
+
}
|
|
1152
1389
|
if (!symbol_type_1.refConcept.includes(n.concept)) {
|
|
1153
1390
|
return;
|
|
1154
1391
|
}
|
|
1155
|
-
const qName = (0,
|
|
1392
|
+
const qName = (0, def_key_helpers_1.getGlobalDefKey)(n); // 太慢,后续应该需要优化速度
|
|
1156
1393
|
if (!qName) {
|
|
1157
1394
|
return;
|
|
1158
1395
|
}
|
|
@@ -1179,7 +1416,7 @@ class ReferenceManager {
|
|
|
1179
1416
|
case 'TypeAnnotation':
|
|
1180
1417
|
const refs = this.splitPolyType(n);
|
|
1181
1418
|
for (const ref of refs) {
|
|
1182
|
-
const qName = (0,
|
|
1419
|
+
const qName = (0, def_key_helpers_1.getGlobalDefKey)(ref);
|
|
1183
1420
|
qName && qNameRefs.push([ref, qName]);
|
|
1184
1421
|
}
|
|
1185
1422
|
break;
|
|
@@ -1214,7 +1451,7 @@ class ReferenceManager {
|
|
|
1214
1451
|
for (const v of views) {
|
|
1215
1452
|
v.bindRoles.length && this.handleBindRoles(env, v);
|
|
1216
1453
|
const lastViewAssocProcess = env.viewAssocProcess;
|
|
1217
|
-
env.viewAssocProcess = env.processV2ViewBindings.get((0,
|
|
1454
|
+
env.viewAssocProcess = env.processV2ViewBindings.get((0, def_key_helpers_1.getGlobalDefKey)(v)) ?? null;
|
|
1218
1455
|
const lastCurFileNode = this.curFileNode;
|
|
1219
1456
|
this.curFileNode = v;
|
|
1220
1457
|
// @ts-expect-error contra-variance errors
|
|
@@ -1229,7 +1466,7 @@ class ReferenceManager {
|
|
|
1229
1466
|
(0, traverse_util_1.visitChildrenWith)(nd, normalCb, compositeNodePred, compositeNodeCb);
|
|
1230
1467
|
}
|
|
1231
1468
|
if (nd.concept === 'McpInterface') {
|
|
1232
|
-
const qName = nd.originLogic && (0,
|
|
1469
|
+
const qName = nd.originLogic && (0, def_key_helpers_1.getGlobalDefKey)(nd.originLogic);
|
|
1233
1470
|
qName && res.push([nd, qName]);
|
|
1234
1471
|
}
|
|
1235
1472
|
else if (nd.concept !== 'QueryFieldExpression') {
|
|
@@ -1291,7 +1528,7 @@ class ReferenceManager {
|
|
|
1291
1528
|
const visibleLocalSyms = this.getVisibleLocalSyms(nd);
|
|
1292
1529
|
const localQNameSet = new Set();
|
|
1293
1530
|
for (const s of visibleLocalSyms) {
|
|
1294
|
-
const q = (0,
|
|
1531
|
+
const q = (0, def_key_helpers_1.getGlobalDefKey)(s);
|
|
1295
1532
|
q && localQNameSet.add(q);
|
|
1296
1533
|
}
|
|
1297
1534
|
for (const [ref, qName] of refAndQNames) {
|
|
@@ -1371,7 +1608,7 @@ class ReferenceManager {
|
|
|
1371
1608
|
}
|
|
1372
1609
|
}
|
|
1373
1610
|
else if (symbol_type_1.refConcept.includes(id0.concept)) {
|
|
1374
|
-
const qName = (0,
|
|
1611
|
+
const qName = (0, def_key_helpers_1.getGlobalDefKey)(id0);
|
|
1375
1612
|
let isProcessRef = false;
|
|
1376
1613
|
if (qName) {
|
|
1377
1614
|
// Handle process reference in view
|
|
@@ -1390,7 +1627,7 @@ class ReferenceManager {
|
|
|
1390
1627
|
}
|
|
1391
1628
|
if (isProcessRef) {
|
|
1392
1629
|
const processDef = env.viewAssocProcess;
|
|
1393
|
-
const pId = (0,
|
|
1630
|
+
const pId = (0, def_key_helpers_1.getGlobalDefKey)(processDef);
|
|
1394
1631
|
res.push([ids[0], pId]);
|
|
1395
1632
|
const processBindDataTy = (0, type_manager_1.createTypeofBindData)(pId, env);
|
|
1396
1633
|
env.setType(ids[0], processBindDataTy);
|
|
@@ -1537,8 +1774,8 @@ class ReferenceManager {
|
|
|
1537
1774
|
return res;
|
|
1538
1775
|
}
|
|
1539
1776
|
const entityQName = nd.propertyName === 'data'
|
|
1540
|
-
? (0,
|
|
1541
|
-
: (0,
|
|
1777
|
+
? (0, def_key_helpers_1.getGlobalDefKey)(entityRef.typeAnnotation) // data 是 Entity
|
|
1778
|
+
: (0, def_key_helpers_1.getGlobalDefKey)(entityRef.typeAnnotation.typeArguments[0]); // relation_data 是 List<Entity>
|
|
1542
1779
|
for (const sub of nd.subFieldPermissions) {
|
|
1543
1780
|
res.push([sub, (0, string_2.getPropQName)(entityQName, sub.propertyName, 'Entity')]);
|
|
1544
1781
|
}
|
|
@@ -1550,9 +1787,9 @@ class ReferenceManager {
|
|
|
1550
1787
|
this.getMemoryStats = () => {
|
|
1551
1788
|
const stats = {
|
|
1552
1789
|
gQNameDefs: this.gQNameDefs,
|
|
1553
|
-
|
|
1790
|
+
globalRefs: this.globalRefs, // Exporting private map for serialization
|
|
1554
1791
|
pendingRefsForRecreation: this.pendingRefsForRecreation, // Exporting private map for serialization
|
|
1555
|
-
|
|
1792
|
+
localRefs: this.localRefs,
|
|
1556
1793
|
compDefMgr: this.compDefMgr,
|
|
1557
1794
|
};
|
|
1558
1795
|
const result = {
|
|
@@ -1604,7 +1841,7 @@ class ReferenceManager {
|
|
|
1604
1841
|
if (!(0, helper_2.isEntityLogic)(nd)) {
|
|
1605
1842
|
return nd;
|
|
1606
1843
|
}
|
|
1607
|
-
const qName = (0,
|
|
1844
|
+
const qName = (0, def_key_helpers_1.getGlobalDefKey)(nd);
|
|
1608
1845
|
if (!qName) {
|
|
1609
1846
|
throw new Error('The entity logic does not have namespace');
|
|
1610
1847
|
}
|
|
@@ -1615,8 +1852,8 @@ class ReferenceManager {
|
|
|
1615
1852
|
// 同步跟新引用管理器,跟上实体逻辑内存地址变化的节奏
|
|
1616
1853
|
if (nd !== def) {
|
|
1617
1854
|
this.gQNameDefs.set(qName, nd);
|
|
1618
|
-
const refs = mnemonist_1.set.union(this.
|
|
1619
|
-
refs.size > 0 && this.
|
|
1855
|
+
const refs = mnemonist_1.set.union(this.globalRefs.get(def) ?? new Set(), this.globalRefs.get(nd) ?? new Set());
|
|
1856
|
+
refs.size > 0 && this.globalRefs.set(nd, refs);
|
|
1620
1857
|
}
|
|
1621
1858
|
return nd;
|
|
1622
1859
|
};
|
|
@@ -1635,7 +1872,7 @@ class ReferenceManager {
|
|
|
1635
1872
|
if (!(ctxViewLike && (ctxViewLike.concept === 'View' || ctxViewLike.concept === 'BusinessComponent'))) {
|
|
1636
1873
|
return;
|
|
1637
1874
|
}
|
|
1638
|
-
const ctxQName = (0,
|
|
1875
|
+
const ctxQName = (0, def_key_helpers_1.getGlobalDefKey)(ctxViewLike);
|
|
1639
1876
|
if (!ctxQName)
|
|
1640
1877
|
return;
|
|
1641
1878
|
const assocProc = env.processV2ViewBindings.get(ctxQName);
|
|
@@ -1672,9 +1909,9 @@ class ReferenceManager {
|
|
|
1672
1909
|
if (!ctxViewElement) {
|
|
1673
1910
|
return;
|
|
1674
1911
|
}
|
|
1675
|
-
const
|
|
1676
|
-
const ancestor = !
|
|
1677
|
-
const boundary = (
|
|
1912
|
+
const matched = node.concept === 'BindAttribute';
|
|
1913
|
+
const ancestor = !matched && node.getAncestorRaw('BindAttribute');
|
|
1914
|
+
const boundary = (matched ? node : ancestor);
|
|
1678
1915
|
if (boundary?.name !== 'rules') {
|
|
1679
1916
|
return;
|
|
1680
1917
|
}
|
|
@@ -1714,7 +1951,7 @@ class ReferenceManager {
|
|
|
1714
1951
|
}
|
|
1715
1952
|
}; }
|
|
1716
1953
|
static getEntityLogicQNames(nd) {
|
|
1717
|
-
const qName = (0,
|
|
1954
|
+
const qName = (0, def_key_helpers_1.getGlobalDefKey)(nd);
|
|
1718
1955
|
const res = new Array();
|
|
1719
1956
|
for (const l of nd.logics) {
|
|
1720
1957
|
res.push(`${qName}.logics.${l.name}`);
|
|
@@ -1722,11 +1959,9 @@ class ReferenceManager {
|
|
|
1722
1959
|
return res;
|
|
1723
1960
|
}
|
|
1724
1961
|
clearAll() {
|
|
1725
|
-
this.
|
|
1962
|
+
this.clearGlobalRefs();
|
|
1726
1963
|
this.gQNameDefs.clear();
|
|
1727
|
-
this.
|
|
1728
|
-
this.veQNameDefs.clear();
|
|
1729
|
-
this.veRefs.clear();
|
|
1964
|
+
this.localRefs.clear();
|
|
1730
1965
|
this.compDefMgr.clearAll();
|
|
1731
1966
|
this.clearPendingRefsCache(); // 清除待恢复引用缓存
|
|
1732
1967
|
this.gSymbolImplicitRefs = new WeakMap();
|