@lcap/nasl-language-server-core 4.4.0-beta.9 → 4.4.0-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 +2 -1
- package/out/checker.d.ts.map +1 -1
- package/out/checker.js +613 -92
- package/out/checker.js.map +1 -1
- package/out/reference-manager/collect-q-name.d.ts.map +1 -1
- package/out/reference-manager/collect-q-name.js +6 -3
- package/out/reference-manager/collect-q-name.js.map +1 -1
- package/out/reference-manager/get-q-name.d.ts.map +1 -1
- package/out/reference-manager/get-q-name.js +12 -4
- package/out/reference-manager/get-q-name.js.map +1 -1
- package/out/reference-manager/reference-manager.d.ts +94 -12
- package/out/reference-manager/reference-manager.d.ts.map +1 -1
- package/out/reference-manager/reference-manager.js +270 -77
- package/out/reference-manager/reference-manager.js.map +1 -1
- package/out/reference-manager/remove-q-name.d.ts.map +1 -1
- package/out/reference-manager/remove-q-name.js +7 -4
- package/out/reference-manager/remove-q-name.js.map +1 -1
- package/out/reference-manager/symbol-type.d.ts +1 -1
- package/out/reference-manager/symbol-type.d.ts.map +1 -1
- package/out/reference-manager/symbol-type.js +1 -0
- package/out/reference-manager/symbol-type.js.map +1 -1
- package/out/reference-manager/update-nasl-fragment.d.ts +2 -2
- package/out/reference-manager/update-nasl-fragment.d.ts.map +1 -1
- package/out/reference-manager/update-nasl-fragment.js +29 -24
- package/out/reference-manager/update-nasl-fragment.js.map +1 -1
- package/out/reference-manager/view-elem-logic.js.map +1 -1
- package/out/services/bindable-logic-service.js.map +1 -1
- package/out/symbol/traverse/concepts/index.d.ts +1 -1
- package/out/symbol/traverse/concepts/index.d.ts.map +1 -1
- package/out/symbol/traverse/concepts/logic/expression/member-expression.js.map +1 -1
- package/out/typer/collectGlobalDefs.d.ts +8 -0
- package/out/typer/collectGlobalDefs.d.ts.map +1 -1
- package/out/typer/collectGlobalDefs.js +74 -49
- package/out/typer/collectGlobalDefs.js.map +1 -1
- package/out/typer/dispatch-all.d.ts.map +1 -1
- package/out/typer/dispatch-all.js +3 -1
- package/out/typer/dispatch-all.js.map +1 -1
- package/out/typer/dispatch-call.d.ts.map +1 -1
- package/out/typer/dispatch-call.js +4 -0
- 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 +45 -19
- 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 +69 -60
- package/out/typer/dispatch-expr.js.map +1 -1
- package/out/typer/dispatch-process.d.ts +8 -1
- package/out/typer/dispatch-process.d.ts.map +1 -1
- package/out/typer/dispatch-process.js +34 -1
- package/out/typer/dispatch-process.js.map +1 -1
- package/out/typer/dispatch-stmt.js.map +1 -1
- package/out/typer/dispatch-view.d.ts.map +1 -1
- package/out/typer/dispatch-view.js +56 -20
- package/out/typer/dispatch-view.js.map +1 -1
- package/out/typer/fix-use-before-assign.js.map +1 -1
- package/out/typer/get-oql-files.d.ts.map +1 -1
- package/out/typer/get-oql-files.js +2 -8
- package/out/typer/get-oql-files.js.map +1 -1
- package/out/typer/incremental-update.d.ts +2 -5
- package/out/typer/incremental-update.d.ts.map +1 -1
- package/out/typer/incremental-update.js +95 -19
- package/out/typer/incremental-update.js.map +1 -1
- package/out/typer/oql-checker/ts-parser.d.ts.map +1 -1
- package/out/typer/oql-checker/ts-parser.js +99 -20
- package/out/typer/oql-checker/ts-parser.js.map +1 -1
- package/out/typer/overload-helper.d.ts.map +1 -1
- package/out/typer/overload-helper.js +185 -23
- package/out/typer/overload-helper.js.map +1 -1
- package/out/typer/solver.d.ts +1 -1
- package/out/typer/solver.d.ts.map +1 -1
- package/out/typer/solver.js +16 -4
- package/out/typer/solver.js.map +1 -1
- package/out/typer/subster.d.ts.map +1 -1
- package/out/typer/subster.js +32 -5
- package/out/typer/subster.js.map +1 -1
- package/out/typer/topo-sort.d.ts +1 -0
- package/out/typer/topo-sort.d.ts.map +1 -1
- package/out/typer/topo-sort.js +15 -5
- package/out/typer/topo-sort.js.map +1 -1
- package/out/typer/type-predicate.d.ts.map +1 -1
- package/out/typer/type-predicate.js +11 -3
- package/out/typer/type-predicate.js.map +1 -1
- package/out/typer/typer.d.ts +1 -1
- package/out/typer/typer.d.ts.map +1 -1
- package/out/typer/typer.js +14 -3
- package/out/typer/typer.js.map +1 -1
- package/out/typer/unifier.d.ts.map +1 -1
- package/out/typer/unifier.js +9 -7
- package/out/typer/unifier.js.map +1 -1
- package/out/utils/debug.js.map +1 -1
- package/out/utils/type-operator.d.ts +15 -0
- package/out/utils/type-operator.d.ts.map +1 -1
- package/out/utils/type-operator.js +65 -3
- package/out/utils/type-operator.js.map +1 -1
- package/package.json +5 -5
|
@@ -115,8 +115,20 @@ class ReferenceManager {
|
|
|
115
115
|
// 暂无"局部类型",所以简化处理:
|
|
116
116
|
return this.gSymbolImplicitRefs.get(nd) ?? emptySet;
|
|
117
117
|
};
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
/**
|
|
119
|
+
* 待恢复引用缓存:删除节点时保存引用,创建同名节点时恢复引用后立即删除
|
|
120
|
+
* key: qName, value: Set<PendingRefInfo>
|
|
121
|
+
* 只在删除和创建之间临时使用,使用后立即清除,避免内存泄漏
|
|
122
|
+
*
|
|
123
|
+
* 使用场景:
|
|
124
|
+
* 1. 删除节点时:通过 cacheRefsForRecreation 保存引用节点
|
|
125
|
+
* 2. 创建同名节点时:通过 restoreRefsFromCache 恢复引用并清除缓存
|
|
126
|
+
*
|
|
127
|
+
* 设计说明:
|
|
128
|
+
* - 只存储引用节点本身
|
|
129
|
+
* - 恢复时会检查引用节点是否仍在 app 树上且仍引用原来的 qName
|
|
130
|
+
*/
|
|
131
|
+
this.pendingRefsForRecreation = new Map();
|
|
120
132
|
this.compDefMgr = new component_def_manager_1.ComponentDefManager();
|
|
121
133
|
// 上一次查找引用局部符号建立的 cache
|
|
122
134
|
this.lastBoundary = undefined;
|
|
@@ -332,8 +344,10 @@ class ReferenceManager {
|
|
|
332
344
|
for (const triggerLauncher of app.triggerLaunchers) {
|
|
333
345
|
allRefs.push(...this.collectRefs(env, triggerLauncher));
|
|
334
346
|
}
|
|
335
|
-
|
|
336
|
-
|
|
347
|
+
if (String(app?.preferenceMap?.metadataTypeEnable) === 'true') {
|
|
348
|
+
for (const metadataType of app.metadataTypes) {
|
|
349
|
+
allRefs.push(...this.collectRefs(env, metadataType));
|
|
350
|
+
}
|
|
337
351
|
}
|
|
338
352
|
// for (const preference of app.preferenceMap) {
|
|
339
353
|
// allRefs.push(...this.collectRefs(env, preference as any as ValidExtInp));
|
|
@@ -353,7 +367,7 @@ class ReferenceManager {
|
|
|
353
367
|
// Cache reference for future relinking
|
|
354
368
|
// FIXME:这里有问题,脏脏的,比如局部变量、入参等都扔到这里面了,虽然暂时可能没有太大的正确性问题,但有内存泄漏
|
|
355
369
|
if (!(0, helper_2.cheapTestLocalSymbol)(qName)) {
|
|
356
|
-
|
|
370
|
+
this.addRefToPendingCache(qName, ref);
|
|
357
371
|
}
|
|
358
372
|
}
|
|
359
373
|
});
|
|
@@ -456,6 +470,23 @@ class ReferenceManager {
|
|
|
456
470
|
const qName = (0, get_q_name_1.getTokenQualifiedName)(ref);
|
|
457
471
|
return qName ? this.gQNameDefs.get(qName) : undefined;
|
|
458
472
|
};
|
|
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
|
+
};
|
|
459
490
|
/**
|
|
460
491
|
* @warning 对外接口,指用户点击 "查找引用",只返回用户手动指定的引用
|
|
461
492
|
* @param __nd 要查找引用的定义
|
|
@@ -662,52 +693,203 @@ class ReferenceManager {
|
|
|
662
693
|
// 重命名时不需要处理 sourceRef targetRef,好像其他逻辑已经处理掉了
|
|
663
694
|
return result;
|
|
664
695
|
};
|
|
696
|
+
this.updateRefsInNaslFragment = update_nasl_fragment_1.updateRefsInNaslFragment;
|
|
697
|
+
/**
|
|
698
|
+
* 添加引用到缓存(内部方法,统一管理 pendingRefsForRecreation)
|
|
699
|
+
* @param qName 节点的 qName
|
|
700
|
+
* @param ref 要缓存的引用
|
|
701
|
+
*/
|
|
702
|
+
this.addRefToPendingCache = (qName, ref) => {
|
|
703
|
+
if (!this.pendingRefsForRecreation.has(qName)) {
|
|
704
|
+
this.pendingRefsForRecreation.set(qName, new Set());
|
|
705
|
+
}
|
|
706
|
+
// 只记录引用节点本身
|
|
707
|
+
const refInfo = {
|
|
708
|
+
ref,
|
|
709
|
+
};
|
|
710
|
+
this.pendingRefsForRecreation.get(qName).add(refInfo);
|
|
711
|
+
};
|
|
665
712
|
/**
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
* 如果 mode 是 'update',则 newQName 的引用集合是 oldQName 在 symbolRefs 中的既存引用
|
|
670
|
-
* 合并上 新名字在 cachedQNameSymbolRefs 中的既存引用。
|
|
671
|
-
* 新名字在 cachedQNameSymbolRefs 中的引用将被删除。
|
|
713
|
+
* 缓存引用以备后续恢复(在删除节点时调用)
|
|
714
|
+
* @param qName 节点的 qName
|
|
715
|
+
* @param defNode 要删除的节点
|
|
672
716
|
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
717
|
+
* 使用场景:删除节点时,保存引用节点本身到 pendingRefsForRecreation,以便后续创建同名节点时恢复引用
|
|
718
|
+
*
|
|
719
|
+
* 设计说明:
|
|
720
|
+
* - 只存储引用节点本身(因为需要它来建立引用关系)
|
|
721
|
+
* - 恢复时会检查引用节点是否仍在 app 树上且仍引用原来的 qName
|
|
676
722
|
*/
|
|
677
|
-
this.
|
|
678
|
-
if (!
|
|
679
|
-
return;
|
|
680
|
-
const oldDef = this.gQNameDefs.get(oldQName);
|
|
681
|
-
if (!oldDef)
|
|
723
|
+
this.cacheRefsForRecreation = (qName, defNode) => {
|
|
724
|
+
if (!(0, symbol_type_1.isGlobalDef)(defNode)) {
|
|
682
725
|
return;
|
|
683
|
-
// 1. 删除 oldQName,建立 newQName,def 地址不变
|
|
684
|
-
this.gQNameDefs.delete(oldQName);
|
|
685
|
-
this.gQNameDefs.set(newQName, oldDef);
|
|
686
|
-
// 2. 处理引用集合
|
|
687
|
-
if (mode === 'update') {
|
|
688
|
-
// 获取 oldQName 的既存引用
|
|
689
|
-
const oldRefs = this.gSymbolRefs.get(oldDef) ?? new Set();
|
|
690
|
-
// 获取 newQName 在缓存中的引用
|
|
691
|
-
const newCachedRefs = this.gCachedQNameSymbolRefs.get(newQName) ?? new Set();
|
|
692
|
-
// 合并引用集合
|
|
693
|
-
const mergedRefs = mnemonist_1.set.union(oldRefs, newCachedRefs);
|
|
694
|
-
// 设置新名字的引用集合
|
|
695
|
-
mergedRefs.size > 0 && this.setSymbolRefs(oldDef, mergedRefs);
|
|
696
|
-
// 删除 newQName 在缓存中的引用
|
|
697
|
-
this.gCachedQNameSymbolRefs.delete(newQName);
|
|
698
726
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
727
|
+
const refs = this.getSymbolRefs(defNode);
|
|
728
|
+
if (refs && refs.size > 0) {
|
|
729
|
+
// 只记录引用节点本身
|
|
730
|
+
const refInfos = new Set();
|
|
731
|
+
for (const ref of refs) {
|
|
732
|
+
const refInfo = {
|
|
733
|
+
ref,
|
|
734
|
+
};
|
|
735
|
+
refInfos.add(refInfo);
|
|
736
|
+
}
|
|
737
|
+
this.pendingRefsForRecreation.set(qName, refInfos);
|
|
708
738
|
}
|
|
709
739
|
};
|
|
710
|
-
|
|
740
|
+
/**
|
|
741
|
+
* 检查引用是否仍在 app 树上
|
|
742
|
+
*
|
|
743
|
+
* 方法:
|
|
744
|
+
* 向上遍历 parentNode 链,检查每个节点是否在其父节点的子节点集合中
|
|
745
|
+
* (因为删除节点时可能不会把 parentNode 设置为 null,但会从父节点的子节点集合中移除)
|
|
746
|
+
*
|
|
747
|
+
* 如果链上的任何节点不在其父节点的子节点集合中,说明已被删除,不在 app 树上
|
|
748
|
+
* 如果能到达 App 节点,说明引用仍在 app 树上
|
|
749
|
+
*/
|
|
750
|
+
this.isRefStillInAppTree = (ref) => {
|
|
751
|
+
try {
|
|
752
|
+
if (!ref || !ref.concept) {
|
|
753
|
+
return false;
|
|
754
|
+
}
|
|
755
|
+
let currentNode = ref;
|
|
756
|
+
let depth = 0;
|
|
757
|
+
const maxDepth = 100; // 防止无限循环
|
|
758
|
+
// 向上遍历 parentNode 链,查找 App 节点
|
|
759
|
+
while (currentNode && depth < maxDepth) {
|
|
760
|
+
if (currentNode.concept === 'App') {
|
|
761
|
+
// 找到了 App 节点,说明引用仍在 app 树上
|
|
762
|
+
return true;
|
|
763
|
+
}
|
|
764
|
+
// 检查当前节点是否在其父节点的子节点集合中
|
|
765
|
+
// 如果节点被删除了,即使 parentNode 还存在,节点也不会在父节点的子节点集合中
|
|
766
|
+
const parentNode = currentNode.parentNode;
|
|
767
|
+
if (parentNode && currentNode.parentKey) {
|
|
768
|
+
const parentProperty = parentNode[currentNode.parentKey];
|
|
769
|
+
if (Array.isArray(parentProperty)) {
|
|
770
|
+
// 如果是数组,检查节点是否在数组中
|
|
771
|
+
if (parentProperty.indexOf(currentNode) === -1) {
|
|
772
|
+
// 节点不在父节点的子节点集合中,说明已被删除
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
else if (parentProperty !== currentNode) {
|
|
777
|
+
// 如果是单个属性,检查是否指向当前节点
|
|
778
|
+
// 节点不在父节点的子节点集合中,说明已被删除
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
currentNode = parentNode;
|
|
783
|
+
depth++;
|
|
784
|
+
}
|
|
785
|
+
// 无法到达 App 节点,说明引用已不在 app 树上(节点已被删除)
|
|
786
|
+
return false;
|
|
787
|
+
}
|
|
788
|
+
catch {
|
|
789
|
+
// 如果访问节点属性时出错,说明节点已被删除
|
|
790
|
+
return false;
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
/**
|
|
794
|
+
* 检查引用节点是否仍引用指定的 qName
|
|
795
|
+
* @param ref 引用节点
|
|
796
|
+
* @param qName 要检查的 qName
|
|
797
|
+
* @returns 如果引用节点仍引用指定的 qName,返回 true;否则返回 false
|
|
798
|
+
*/
|
|
799
|
+
this.isRefStillReferencingQName = (ref, qName) => {
|
|
800
|
+
try {
|
|
801
|
+
// 通过 getTokenQualifiedName 获取引用节点当前引用的 qName
|
|
802
|
+
const currentQName = (0, get_q_name_1.getTokenQualifiedName)(ref);
|
|
803
|
+
// 检查是否还引用原来的 qName
|
|
804
|
+
return currentQName === qName;
|
|
805
|
+
}
|
|
806
|
+
catch {
|
|
807
|
+
// 如果获取失败,返回 false
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
/**
|
|
812
|
+
* 从缓存恢复引用(在创建节点时调用)
|
|
813
|
+
* @param qName 节点的 qName
|
|
814
|
+
* @param defNode 新创建的节点
|
|
815
|
+
* @returns 是否成功恢复引用
|
|
816
|
+
*
|
|
817
|
+
* 使用场景:创建节点时,如果有缓存的引用信息(来自删除操作),则恢复引用关系
|
|
818
|
+
*
|
|
819
|
+
* 恢复策略:
|
|
820
|
+
* 1. 使用引用节点本身(如果节点仍然有效)
|
|
821
|
+
* 2. 检查引用节点是否仍在 app 树上(过滤掉已删除的引用)
|
|
822
|
+
* 3. **关键**:检查引用节点是否仍引用原来的 qName(如果引用内容已改变,则不恢复)
|
|
823
|
+
* 4. 重新建立引用关系
|
|
824
|
+
*/
|
|
825
|
+
this.restoreRefsFromCache = (qName, defNode) => {
|
|
826
|
+
if (!(0, symbol_type_1.isGlobalDef)(defNode)) {
|
|
827
|
+
return false;
|
|
828
|
+
}
|
|
829
|
+
const cachedRefInfos = this.pendingRefsForRecreation.get(qName);
|
|
830
|
+
if (!cachedRefInfos || cachedRefInfos.size === 0) {
|
|
831
|
+
return false;
|
|
832
|
+
}
|
|
833
|
+
const validRefs = new Set();
|
|
834
|
+
for (const refInfo of cachedRefInfos) {
|
|
835
|
+
// 检查引用节点是否仍在 app 树上
|
|
836
|
+
if (!this.isRefStillInAppTree(refInfo.ref)) {
|
|
837
|
+
continue;
|
|
838
|
+
}
|
|
839
|
+
// 检查引用节点是否仍引用原来的 qName
|
|
840
|
+
if (this.isRefStillReferencingQName(refInfo.ref, qName)) {
|
|
841
|
+
// 引用节点仍然有效且仍引用原来的 qName,添加到恢复集合中
|
|
842
|
+
validRefs.add(refInfo.ref);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
// 如果有有效的引用,恢复它们
|
|
846
|
+
if (validRefs.size > 0) {
|
|
847
|
+
this.setSymbolRefs(defNode, validRefs);
|
|
848
|
+
}
|
|
849
|
+
// 使用后立即删除缓存,避免内存泄漏
|
|
850
|
+
this.pendingRefsForRecreation.delete(qName);
|
|
851
|
+
return validRefs.size > 0;
|
|
852
|
+
};
|
|
853
|
+
/**
|
|
854
|
+
* 获取待恢复引用缓存中的引用(用于查询场景,如 getOqlFiles)
|
|
855
|
+
* @param qName 节点的 qName
|
|
856
|
+
* @param app 可选的 App 实例(保留参数以保持向后兼容,但不再使用)
|
|
857
|
+
* @returns 缓存的引用集合,如果没有则返回 undefined
|
|
858
|
+
*
|
|
859
|
+
* 注意:只使用引用节点本身,检查引用节点是否仍在 app 树上且仍引用原来的 qName
|
|
860
|
+
*/
|
|
861
|
+
this.getPendingRefsForRecreation = (qName, app) => {
|
|
862
|
+
const refInfos = this.pendingRefsForRecreation.get(qName);
|
|
863
|
+
if (!refInfos) {
|
|
864
|
+
return undefined;
|
|
865
|
+
}
|
|
866
|
+
const refs = new Set();
|
|
867
|
+
for (const refInfo of refInfos) {
|
|
868
|
+
// 检查引用节点是否仍在 app 树上
|
|
869
|
+
if (!this.isRefStillInAppTree(refInfo.ref)) {
|
|
870
|
+
continue;
|
|
871
|
+
}
|
|
872
|
+
// 检查引用节点是否仍引用原来的 qName
|
|
873
|
+
if (this.isRefStillReferencingQName(refInfo.ref, qName)) {
|
|
874
|
+
refs.add(refInfo.ref);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
return refs;
|
|
878
|
+
};
|
|
879
|
+
/**
|
|
880
|
+
* 获取待恢复引用缓存的大小(用于测试和调试)
|
|
881
|
+
* @returns 缓存中 qName 的数量
|
|
882
|
+
*/
|
|
883
|
+
this.getPendingRefsForRecreationSize = () => {
|
|
884
|
+
return this.pendingRefsForRecreation.size;
|
|
885
|
+
};
|
|
886
|
+
/**
|
|
887
|
+
* 清除所有待恢复引用缓存
|
|
888
|
+
* 用于清理操作,避免内存泄漏
|
|
889
|
+
*/
|
|
890
|
+
this.clearPendingRefsCache = () => {
|
|
891
|
+
this.pendingRefsForRecreation.clear();
|
|
892
|
+
};
|
|
711
893
|
/**
|
|
712
894
|
* @warning Only handle global symbols
|
|
713
895
|
*/
|
|
@@ -719,16 +901,14 @@ class ReferenceManager {
|
|
|
719
901
|
this.isLocalCacheValid = false;
|
|
720
902
|
}
|
|
721
903
|
else {
|
|
722
|
-
// 可以链接回旧的引用,类似于 rename
|
|
723
|
-
const oldRefs = this.gCachedQNameSymbolRefs.get(qName);
|
|
724
|
-
oldRefs && this.setSymbolRefs(defNode, oldRefs);
|
|
725
904
|
// qName 链接到新的 defNode 的 mem addr
|
|
726
905
|
this.gQNameDefs.set(qName, defNode);
|
|
727
906
|
if ((0, component_def_manager_1.isGeneralViewElementDefinition)(defNode)) {
|
|
728
907
|
this.compDefMgr.add(defNode, 'handleDefOp');
|
|
729
908
|
}
|
|
730
|
-
//
|
|
731
|
-
|
|
909
|
+
// 尝试从缓存恢复引用(来自删除操作)
|
|
910
|
+
// 如果恢复成功,缓存会被自动清除;如果失败,引用会在类型检查时自动重新建立
|
|
911
|
+
this.restoreRefsFromCache(qName, defNode);
|
|
732
912
|
}
|
|
733
913
|
break;
|
|
734
914
|
}
|
|
@@ -737,17 +917,9 @@ class ReferenceManager {
|
|
|
737
917
|
this.isLocalCacheValid = false;
|
|
738
918
|
}
|
|
739
919
|
else {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
// 过滤掉 BindAttribute 的引用,因为 BindAttribute 的引用很容易冗余
|
|
744
|
-
// 使用类型断言因为 BindAttribute 是特殊的引用类型,未包含在 RefConcept 中
|
|
745
|
-
this.gCachedQNameSymbolRefs.set(qName, new Set(Array.from(refs).filter(ref => ref.concept !== 'BindAttribute')));
|
|
746
|
-
}
|
|
747
|
-
else {
|
|
748
|
-
this.gCachedQNameSymbolRefs.set(qName, refs);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
920
|
+
// 缓存引用以备后续恢复(在删除引用之前调用)
|
|
921
|
+
this.cacheRefsForRecreation(qName, defNode);
|
|
922
|
+
// 删除 qName 和引用
|
|
751
923
|
this.gQNameDefs.delete(qName);
|
|
752
924
|
if ((0, component_def_manager_1.isGeneralViewElementDefinition)(defNode)) {
|
|
753
925
|
this.compDefMgr.removeComponentGroup(defNode);
|
|
@@ -778,19 +950,8 @@ class ReferenceManager {
|
|
|
778
950
|
}
|
|
779
951
|
}
|
|
780
952
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
switch (mode) {
|
|
784
|
-
case "create" /* Operation.Create */: {
|
|
785
|
-
(0, fp_macros_1.createOnAdd)(this.gCachedQNameSymbolRefs, qName, refNd);
|
|
786
|
-
break;
|
|
787
|
-
}
|
|
788
|
-
case "delete" /* Operation.Remove */: {
|
|
789
|
-
this.gCachedQNameSymbolRefs.get(qName)?.delete(refNd);
|
|
790
|
-
break;
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
}
|
|
953
|
+
// 注意:如果定义不存在,引用会被忽略
|
|
954
|
+
// 类型检查时会重新建立引用关系
|
|
794
955
|
};
|
|
795
956
|
this.handleSymbolImplicitRefs = (nd) => {
|
|
796
957
|
if (!nd)
|
|
@@ -932,6 +1093,18 @@ class ReferenceManager {
|
|
|
932
1093
|
}
|
|
933
1094
|
});
|
|
934
1095
|
};
|
|
1096
|
+
/**
|
|
1097
|
+
* 处理 ProcessElementV2 的 CallSubProcess 类型对 ProcessV2 的引用
|
|
1098
|
+
* 当 ProcessElementV2 的 type === 'CallSubProcess' 时,subProcessKey 字段引用另一个 ProcessV2 的 uniqueKey
|
|
1099
|
+
*/
|
|
1100
|
+
this.handleProcessSubProcessRef = (env, nd) => {
|
|
1101
|
+
if (nd.type !== 'CallSubProcess' || !nd.subProcessKey) {
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
1104
|
+
// subProcessKey 就是 ProcessV2 的 uniqueKey,直接作为 qName 使用
|
|
1105
|
+
const subProcessQName = nd.subProcessKey;
|
|
1106
|
+
this.handleRefOp(this.modeForCollect, nd, subProcessQName);
|
|
1107
|
+
};
|
|
935
1108
|
/**
|
|
936
1109
|
* 无论根节点是 ref 还是 def,都要递归收集下层所有的引用节点
|
|
937
1110
|
* 会打散 a.b.c、A | B、x.a.b 等结构,并记录必要的信息
|
|
@@ -974,6 +1147,8 @@ class ReferenceManager {
|
|
|
974
1147
|
n.concept === 'EntityProperty' && this.handleForeignKeyRef(env, n);
|
|
975
1148
|
n.concept === 'AssigneeV2' && this.handleBindRoles(env, n);
|
|
976
1149
|
n.concept === 'CallAuthInterface' && this.handleAuthLogicRef(env, n);
|
|
1150
|
+
// 处理流程子流程引用
|
|
1151
|
+
n.concept === 'ProcessElementV2' && this.handleProcessSubProcessRef(env, n);
|
|
977
1152
|
if (!symbol_type_1.refConcept.includes(n.concept)) {
|
|
978
1153
|
return;
|
|
979
1154
|
}
|
|
@@ -1187,7 +1362,15 @@ class ReferenceManager {
|
|
|
1187
1362
|
processVar = (0, typer_1.createProcessVariable)(env, proc);
|
|
1188
1363
|
(0, helper_1.createOnPush)(env.allocatedVirtualNodes, this.curFileNode, processVar);
|
|
1189
1364
|
});
|
|
1190
|
-
|
|
1365
|
+
// 处理 processVariable.variable1 的情况
|
|
1366
|
+
// processVariable 是虚拟变量,不需要添加引用,只需要设置类型以便后续处理
|
|
1367
|
+
if (processVar && id0.name === 'processVariable') {
|
|
1368
|
+
const procVarTy = env.getType(processVar);
|
|
1369
|
+
if (procVarTy) {
|
|
1370
|
+
env.setType(id0, procVarTy);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
else if (symbol_type_1.refConcept.includes(id0.concept)) {
|
|
1191
1374
|
const qName = (0, get_q_name_1.getTokenQualifiedName)(id0);
|
|
1192
1375
|
let isProcessRef = false;
|
|
1193
1376
|
if (qName) {
|
|
@@ -1231,7 +1414,17 @@ class ReferenceManager {
|
|
|
1231
1414
|
}
|
|
1232
1415
|
// 是这样的,为了兼容 processVariable.variable1,前面的是匿名数据结构,只需要 variable1 的引用就行了
|
|
1233
1416
|
let ndDef = this.getNodeDef(ty);
|
|
1234
|
-
|
|
1417
|
+
// 处理 processVariable.variable1 的情况:匿名结构类型,需要添加 processVariable.variable1 的引用
|
|
1418
|
+
if (ty.typeKind === 'anonymousStructure' && ids[0].name === 'processVariable' && processVar) {
|
|
1419
|
+
const procDef = processVar.parentNode;
|
|
1420
|
+
if (procDef && procDef.concept === 'ProcessDefinitionV2') {
|
|
1421
|
+
const procVar = procDef.variables?.find((v) => v.name === ids[i + 1].name);
|
|
1422
|
+
if (procVar) {
|
|
1423
|
+
res.push([ids[i + 1], `processVariable.${ids[i + 1].name}`]);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
else if (ndDef && (ndDef.concept === 'Entity' || ndDef.concept === 'Structure' || ndDef.concept === 'Enum')) {
|
|
1235
1428
|
const propQName = (0, string_2.getPropQName)(`${ty.typeNamespace}.${ty.typeName}`, ids[i + 1].name, 'Entity');
|
|
1236
1429
|
res.push([ids[i + 1], propQName]); // type reference
|
|
1237
1430
|
}
|
|
@@ -1358,7 +1551,7 @@ class ReferenceManager {
|
|
|
1358
1551
|
const stats = {
|
|
1359
1552
|
gQNameDefs: this.gQNameDefs,
|
|
1360
1553
|
symbolRefs: this.gSymbolRefs, // Exporting private map for serialization
|
|
1361
|
-
|
|
1554
|
+
pendingRefsForRecreation: this.pendingRefsForRecreation, // Exporting private map for serialization
|
|
1362
1555
|
localQNameRefs: this.lQNameRefs,
|
|
1363
1556
|
compDefMgr: this.compDefMgr,
|
|
1364
1557
|
};
|
|
@@ -1531,11 +1724,11 @@ class ReferenceManager {
|
|
|
1531
1724
|
clearAll() {
|
|
1532
1725
|
this.clearSymbolRefs();
|
|
1533
1726
|
this.gQNameDefs.clear();
|
|
1534
|
-
this.gCachedQNameSymbolRefs.clear();
|
|
1535
1727
|
this.lQNameRefs.clear();
|
|
1536
1728
|
this.veQNameDefs.clear();
|
|
1537
1729
|
this.veRefs.clear();
|
|
1538
1730
|
this.compDefMgr.clearAll();
|
|
1731
|
+
this.clearPendingRefsCache(); // 清除待恢复引用缓存
|
|
1539
1732
|
this.gSymbolImplicitRefs = new WeakMap();
|
|
1540
1733
|
}
|
|
1541
1734
|
}
|