@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.
Files changed (114) hide show
  1. package/out/checker.d.ts.map +1 -1
  2. package/out/checker.js +241 -111
  3. package/out/checker.js.map +1 -1
  4. package/out/index.d.ts +1 -1
  5. package/out/index.d.ts.map +1 -1
  6. package/out/index.js +5 -3
  7. package/out/index.js.map +1 -1
  8. package/out/reference-manager/build-q-name-def.d.ts.map +1 -1
  9. package/out/reference-manager/build-q-name-def.js +11 -0
  10. package/out/reference-manager/build-q-name-def.js.map +1 -1
  11. package/out/reference-manager/builtin-q-name.js +2 -2
  12. package/out/reference-manager/builtin-q-name.js.map +1 -1
  13. package/out/reference-manager/collect-q-name.d.ts +1 -1
  14. package/out/reference-manager/collect-q-name.d.ts.map +1 -1
  15. package/out/reference-manager/collect-q-name.js +58 -24
  16. package/out/reference-manager/collect-q-name.js.map +1 -1
  17. package/out/reference-manager/def-key-helpers.d.ts +38 -0
  18. package/out/reference-manager/def-key-helpers.d.ts.map +1 -0
  19. package/out/reference-manager/{get-q-name.js → def-key-helpers.js} +183 -19
  20. package/out/reference-manager/def-key-helpers.js.map +1 -0
  21. package/out/reference-manager/helper.js +2 -2
  22. package/out/reference-manager/helper.js.map +1 -1
  23. package/out/reference-manager/reference-manager.d.ts +60 -43
  24. package/out/reference-manager/reference-manager.d.ts.map +1 -1
  25. package/out/reference-manager/reference-manager.js +381 -146
  26. package/out/reference-manager/reference-manager.js.map +1 -1
  27. package/out/reference-manager/remove-q-name.d.ts +1 -1
  28. package/out/reference-manager/remove-q-name.d.ts.map +1 -1
  29. package/out/reference-manager/remove-q-name.js +7 -10
  30. package/out/reference-manager/remove-q-name.js.map +1 -1
  31. package/out/reference-manager/rename-q-name.d.ts +26 -26
  32. package/out/reference-manager/rename-q-name.d.ts.map +1 -1
  33. package/out/reference-manager/rename-q-name.js +48 -167
  34. package/out/reference-manager/rename-q-name.js.map +1 -1
  35. package/out/reference-manager/symbol-type.d.ts +8 -3
  36. package/out/reference-manager/symbol-type.d.ts.map +1 -1
  37. package/out/reference-manager/symbol-type.js +8 -2
  38. package/out/reference-manager/symbol-type.js.map +1 -1
  39. package/out/reference-manager/update-nasl-fragment.js +4 -4
  40. package/out/reference-manager/update-nasl-fragment.js.map +1 -1
  41. package/out/typer/collectGlobalDefs.js +3 -3
  42. package/out/typer/collectGlobalDefs.js.map +1 -1
  43. package/out/typer/component-def-manager/component-def-manager.d.ts +16 -0
  44. package/out/typer/component-def-manager/component-def-manager.d.ts.map +1 -1
  45. package/out/typer/component-def-manager/component-def-manager.js +63 -2
  46. package/out/typer/component-def-manager/component-def-manager.js.map +1 -1
  47. package/out/typer/component-def-manager/utils.d.ts.map +1 -1
  48. package/out/typer/component-def-manager/utils.js +26 -0
  49. package/out/typer/component-def-manager/utils.js.map +1 -1
  50. package/out/typer/dispatch-all.d.ts +3 -1
  51. package/out/typer/dispatch-all.d.ts.map +1 -1
  52. package/out/typer/dispatch-all.js +48 -5
  53. package/out/typer/dispatch-all.js.map +1 -1
  54. package/out/typer/dispatch-call.d.ts +27 -1
  55. package/out/typer/dispatch-call.d.ts.map +1 -1
  56. package/out/typer/dispatch-call.js +141 -107
  57. package/out/typer/dispatch-call.js.map +1 -1
  58. package/out/typer/dispatch-def.d.ts.map +1 -1
  59. package/out/typer/dispatch-def.js +3 -3
  60. package/out/typer/dispatch-def.js.map +1 -1
  61. package/out/typer/dispatch-expr.d.ts.map +1 -1
  62. package/out/typer/dispatch-expr.js +32 -73
  63. package/out/typer/dispatch-expr.js.map +1 -1
  64. package/out/typer/dispatch-process.js +3 -3
  65. package/out/typer/dispatch-process.js.map +1 -1
  66. package/out/typer/dispatch-stmt.d.ts.map +1 -1
  67. package/out/typer/dispatch-stmt.js +9 -11
  68. package/out/typer/dispatch-stmt.js.map +1 -1
  69. package/out/typer/dispatch-view.d.ts +1 -1
  70. package/out/typer/dispatch-view.d.ts.map +1 -1
  71. package/out/typer/dispatch-view.js +33 -26
  72. package/out/typer/dispatch-view.js.map +1 -1
  73. package/out/typer/get-oql-files.js +1 -1
  74. package/out/typer/get-oql-files.js.map +1 -1
  75. package/out/typer/incremental-update.d.ts +2 -2
  76. package/out/typer/incremental-update.d.ts.map +1 -1
  77. package/out/typer/incremental-update.js +142 -30
  78. package/out/typer/incremental-update.js.map +1 -1
  79. package/out/typer/overload-helper.js +2 -2
  80. package/out/typer/overload-helper.js.map +1 -1
  81. package/out/typer/solver.d.ts +8 -9
  82. package/out/typer/solver.d.ts.map +1 -1
  83. package/out/typer/solver.js +43 -32
  84. package/out/typer/solver.js.map +1 -1
  85. package/out/typer/subster.d.ts.map +1 -1
  86. package/out/typer/subster.js +101 -20
  87. package/out/typer/subster.js.map +1 -1
  88. package/out/typer/topo-sort.d.ts +37 -0
  89. package/out/typer/topo-sort.d.ts.map +1 -1
  90. package/out/typer/topo-sort.js +264 -5
  91. package/out/typer/topo-sort.js.map +1 -1
  92. package/out/typer/type-manager.d.ts +1 -0
  93. package/out/typer/type-manager.d.ts.map +1 -1
  94. package/out/typer/type-manager.js +14 -11
  95. package/out/typer/type-manager.js.map +1 -1
  96. package/out/typer/type-predicate.d.ts.map +1 -1
  97. package/out/typer/type-predicate.js +38 -16
  98. package/out/typer/type-predicate.js.map +1 -1
  99. package/out/typer/typer.d.ts +19 -3
  100. package/out/typer/typer.d.ts.map +1 -1
  101. package/out/typer/typer.js +60 -27
  102. package/out/typer/typer.js.map +1 -1
  103. package/out/typer/unifier.d.ts +2 -0
  104. package/out/typer/unifier.d.ts.map +1 -1
  105. package/out/typer/unifier.js +52 -27
  106. package/out/typer/unifier.js.map +1 -1
  107. package/package.json +5 -5
  108. package/out/reference-manager/get-q-name.d.ts +0 -9
  109. package/out/reference-manager/get-q-name.d.ts.map +0 -1
  110. package/out/reference-manager/get-q-name.js.map +0 -1
  111. package/out/reference-manager/view-elem-logic.d.ts +0 -44
  112. package/out/reference-manager/view-elem-logic.d.ts.map +0 -1
  113. package/out/reference-manager/view-elem-logic.js +0 -181
  114. 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 get_q_name_1 = require("./get-q-name");
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 和 symbolRefs 的构建时机不一样,所以不放在构造器中
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.gSymbolRefs = new Map; // 手动管理,小心内存泄漏
69
- // Accessor methods for symbolRefs to normalize input later
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.gSymbolRefs.get(def);
71
+ return this.globalRefs.get(def);
73
72
  };
74
73
  this.setSymbolRefs = (__def, refs) => {
75
74
  const def = this.normaliseEntityLogic(__def);
76
- this.gSymbolRefs.set(def, refs);
75
+ this.globalRefs.set(def, refs);
77
76
  };
78
77
  this.deleteSymbolRefs = (__def) => {
79
78
  const def = this.normaliseEntityLogic(__def);
80
- return this.gSymbolRefs.delete(def);
79
+ return this.globalRefs.delete(def);
81
80
  };
82
- this.clearSymbolRefs = () => {
83
- this.gSymbolRefs.clear();
81
+ this.clearGlobalRefs = () => {
82
+ this.globalRefs.clear();
84
83
  };
85
- this.getSymbolRefsSize = () => {
86
- return this.gSymbolRefs.size;
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
- /** local qName refs 局部符号的引用 */
137
- this.lQNameRefs = new Map();
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
- file.traverseStrictChildren((nd) => {
166
- this.localSymBindings.delete(nd);
167
- });
168
- // also clear the file node itself
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) lexicalVarStacks in SemEnv so
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
- const seen = new Set(localSyms.map(v => (0, get_q_name_1.getTokenQualifiedName)(v)));
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 vQName = (0, get_q_name_1.getTokenQualifiedName)(v);
217
- if (!vQName)
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(vQName))
225
+ if (seen.has(vKey))
221
226
  continue;
222
- seen.add(vQName);
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, get_q_name_1.getTokenQualifiedName)(v);
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.gSymbolRefs, def, ref);
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, get_q_name_1.getTokenQualifiedName)(ref);
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(getTokenQualifiedName(nd)!)!;
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, get_q_name_1.getTokenQualifiedName)(nd);
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
- res = this.lQNameRefs.get((0, get_q_name_1.getTokenQualifiedName)(nd)) ?? new Set();
523
- // 此处的 Logic 必然不是全局逻辑
524
- // @ts-expect-error 目前的 AST 设计,ViewElement 既是引用又是定义
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(res, this.getViewElementRefs(nd));
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.lQNameRefs.clear();
532
- this.veQNameDefs.clear();
533
- this.veRefs.clear();
534
- this.timeAndLog('Get reference: collect local refs', this.buildMinimalLocalQNameRefs, env, nd);
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
- this.timeAndLog('Get reference: build view element logic qName defs cache', this.addViewElementLogicQNameDefs, ctxViewLike);
540
- this.timeAndLog('Get reference: build view element refs cache', this.addViewElementLogicRefs, ctxViewLike);
541
- // @ts-expect-error get 出来一个 undefined 无所谓
542
- res = mnemonist_1.set.union(res ?? new Set(), this.getViewElementRefs(nd));
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
- this.addViewElementLogicQNameDefs(ctxViewLike);
566
- this.addViewElementLogicRefs(ctxViewLike);
567
- bsRefsRefs.push(...this.getViewElementRefs(bsInst));
564
+ if (ctxViewLike)
565
+ this.buildLocalRefs(env, ctxViewLike);
568
566
  }
569
- // 再从引用中过滤出找到当前业务逻辑的调用
570
- res = mnemonist_1.set.union(res, new Set(bsRefsRefs.filter(r => r.concept === 'CallLogic' && r.calleeName === nd.name))); // amazing!
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.gSymbolRefs.get(l) ?? new Set());
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 相关的引用,那个在 @link addViewElementLogicRefs
602
+ * @warning 不包括 ViewElement、BindEvent 相关的引用,已合并到 getLocalDefKeys 与 collectedRefs 处理
605
603
  * @warning 需要包括 SubLogics
606
604
  */
607
- this.buildMinimalLocalQNameRefs = (env, __nd) => {
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
- isViewLike = true;
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
- // initialize local cache
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, get_q_name_1.getTokenQualifiedName)(def);
664
+ const qName = (0, def_key_helpers_1.getLocalDefKey)(def) ?? (0, def_key_helpers_1.getGlobalDefKey)(def);
641
665
  if (qName) {
642
- this.lQNameRefs.set(qName, new Set());
666
+ this.localRefs.set(qName, new Set());
643
667
  }
644
668
  });
645
- let subRefs = this.collectRefs(env, boundary, true);
646
- this.lastBoundary = boundary;
647
- subRefs?.forEach(([rf, qName]) => {
648
- // 不存在则表示不是局部符号
649
- this.lQNameRefs.get(qName)?.add(rf);
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
- * References to view elements are calls of component logic and access of properties
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
- // 通过 getTokenQualifiedName 获取引用节点当前引用的 qName
802
- const currentQName = (0, get_q_name_1.getTokenQualifiedName)(ref);
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
- * @warning Only handle global symbols
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 symbolRefs
943
- (0, fp_macros_1.createOnAdd)(this.gSymbolRefs, def, refNd);
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, get_q_name_1.getTokenQualifiedName)(typeAnnotation);
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, get_q_name_1.getTokenQualifiedName)(bsDef));
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, getTokenQualifiedName(itfc)!);
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, get_q_name_1.getTokenQualifiedName)(l));
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, getTokenQualifiedName(itfc)!);
1086
- // this.handleRefOp(this.modeForCollect!, nd, getTokenQualifiedName(itfc)!);
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, get_q_name_1.getTokenQualifiedName)(l));
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, get_q_name_1.getTokenQualifiedName)(nd)) ?? null;
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, get_q_name_1.getTokenQualifiedName)(n); // 太慢,后续应该需要优化速度
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, get_q_name_1.getTokenQualifiedName)(ref);
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, get_q_name_1.getTokenQualifiedName)(v)) ?? null;
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, get_q_name_1.getTokenQualifiedName)(nd.originLogic);
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, get_q_name_1.getTokenQualifiedName)(s);
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, get_q_name_1.getTokenQualifiedName)(id0);
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, get_q_name_1.getTokenQualifiedName)(processDef);
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, get_q_name_1.getTokenQualifiedName)(entityRef.typeAnnotation) // data 是 Entity
1541
- : (0, get_q_name_1.getTokenQualifiedName)(entityRef.typeAnnotation.typeArguments[0]); // relation_data 是 List<Entity>
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
- symbolRefs: this.gSymbolRefs, // Exporting private map for serialization
1790
+ globalRefs: this.globalRefs, // Exporting private map for serialization
1554
1791
  pendingRefsForRecreation: this.pendingRefsForRecreation, // Exporting private map for serialization
1555
- localQNameRefs: this.lQNameRefs,
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, get_q_name_1.getTokenQualifiedName)(nd);
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.gSymbolRefs.get(def) ?? new Set(), this.gSymbolRefs.get(nd) ?? new Set());
1619
- refs.size > 0 && this.gSymbolRefs.set(nd, refs);
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, get_q_name_1.getTokenQualifiedName)(ctxViewLike);
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 macthed = node.concept === 'BindAttribute';
1676
- const ancestor = !macthed && node.getAncestorRaw('BindAttribute');
1677
- const boundary = (macthed ? node : ancestor);
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, get_q_name_1.getTokenQualifiedName)(nd);
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.clearSymbolRefs();
1962
+ this.clearGlobalRefs();
1726
1963
  this.gQNameDefs.clear();
1727
- this.lQNameRefs.clear();
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();