2
0

fixed-layout-scope-chain.ts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. import { inject, optional } from 'inversify';
  2. import { Scope, ScopeChain } from '@flowgram.ai/variable-core';
  3. import { FlowDocument, type FlowVirtualTree } from '@flowgram.ai/document';
  4. import { FlowNodeEntity } from '@flowgram.ai/document';
  5. import { VariableLayoutConfig } from './variable-layout-config';
  6. import { FlowNodeScope, FlowNodeScopeTypeEnum, ScopeChainNode } from './types';
  7. import { FlowNodeVariableData } from './flow-node-variable-data';
  8. /**
  9. * 基于 FlowVirtualTree 的 ScopeOrder 实现
  10. */
  11. export class FixedLayoutScopeChain extends ScopeChain {
  12. // 增加 { id: string } 使得可以灵活添加自定义虚拟节点
  13. tree: FlowVirtualTree<ScopeChainNode> | undefined;
  14. constructor(
  15. @inject(FlowDocument)
  16. protected flowDocument: FlowDocument,
  17. @optional()
  18. @inject(VariableLayoutConfig)
  19. protected configs?: VariableLayoutConfig,
  20. ) {
  21. super();
  22. // 绑定 flowDocument 里面的树
  23. this.bindTree(flowDocument.originTree);
  24. // originTree 发生变化时,触发依赖关系的变化
  25. this.toDispose.push(
  26. // REFRACTOR: onTreeChange 触发时机精细化
  27. flowDocument.originTree.onTreeChange(() => {
  28. this.refreshAllChange();
  29. }),
  30. );
  31. }
  32. // 绑定树
  33. bindTree(tree: FlowVirtualTree<ScopeChainNode>): void {
  34. this.tree = tree;
  35. }
  36. // 获取依赖作用域
  37. getDeps(scope: FlowNodeScope): FlowNodeScope[] {
  38. if (!this.tree) {
  39. return this.transformDeps([], { scope });
  40. }
  41. const node = scope.meta.node;
  42. if (!node) {
  43. return this.transformDeps([], { scope });
  44. }
  45. const deps: FlowNodeScope[] = [];
  46. let curr: ScopeChainNode | undefined = node;
  47. while (curr) {
  48. const { parent, pre } = this.tree.getInfo(curr);
  49. const currData = this.getVariableData(curr);
  50. // 包含子节点,且不是私有作用域
  51. if (curr === node) {
  52. // public 可以依赖 private
  53. if (scope.meta.type === FlowNodeScopeTypeEnum.public && currData?.private) {
  54. deps.unshift(currData.private);
  55. }
  56. } else if (this.hasChildren(curr) && !this.isNodeChildrenPrivate(curr)) {
  57. // 有子元素的节点,则将子元素纳入依赖作用域
  58. deps.unshift(
  59. ...this.getAllSortedChildScope(curr, {
  60. ignoreNodeChildrenPrivate: true,
  61. }),
  62. );
  63. }
  64. // 节点的 public 都可以被访问
  65. if (currData && curr !== node) {
  66. deps.unshift(currData.public);
  67. }
  68. // 上个节点处理
  69. if (pre) {
  70. curr = pre;
  71. continue;
  72. }
  73. // 父节点处理
  74. if (parent) {
  75. let currParent: ScopeChainNode | undefined = parent;
  76. let currParentPre: ScopeChainNode | undefined = this.tree.getPre(currParent);
  77. while (currParent) {
  78. // 父节点的 private 和 public 都能被子节点访问
  79. const currParentData = this.getVariableData(currParent);
  80. if (currParentData) {
  81. deps.unshift(...currParentData.allScopes);
  82. }
  83. // 当前 parent 有 pre 节点,则停止向上查找
  84. if (currParentPre) {
  85. break;
  86. }
  87. currParent = this.tree.getParent(currParent);
  88. currParentPre = currParent ? this.tree.getPre(currParent) : undefined;
  89. }
  90. curr = currParentPre;
  91. continue;
  92. }
  93. // next 和 parent 都没有,直接结束循环
  94. curr = undefined;
  95. }
  96. return this.transformDeps(deps, { scope });
  97. }
  98. // 获取覆盖作用域
  99. getCovers(scope: FlowNodeScope): FlowNodeScope[] {
  100. if (!this.tree) {
  101. return this.transformCovers([], { scope });
  102. }
  103. const node = scope.meta.node;
  104. if (!node) {
  105. return this.transformCovers([], { scope });
  106. }
  107. const covers: FlowNodeScope[] = [];
  108. // 如果是 private 作用域,则只能子节点访问
  109. if (scope.meta.type === FlowNodeScopeTypeEnum.private) {
  110. covers.push(
  111. ...this.getAllSortedChildScope(node, {
  112. addNodePrivateScope: true,
  113. }),
  114. );
  115. return this.transformCovers(covers, { scope });
  116. }
  117. let curr: ScopeChainNode | undefined = node;
  118. while (curr) {
  119. const { next, parent } = this.tree.getInfo(curr);
  120. const currData = this.getVariableData(curr);
  121. // 有子元素的节点,则将子元素纳入覆盖作用域
  122. if (curr !== node) {
  123. if (this.hasChildren(curr)) {
  124. covers.push(
  125. ...this.getAllSortedChildScope(curr, {
  126. addNodePrivateScope: true,
  127. }),
  128. );
  129. } else if (currData) {
  130. covers.push(...currData.allScopes);
  131. }
  132. }
  133. // 下个节点处理
  134. if (next) {
  135. curr = next;
  136. continue;
  137. }
  138. if (parent) {
  139. let currParent: ScopeChainNode | undefined = parent;
  140. let currParentNext: ScopeChainNode | undefined = this.tree.getNext(currParent);
  141. while (currParent) {
  142. // 私有作用域不能被后续节点访问
  143. if (this.isNodeChildrenPrivate(currParent)) {
  144. return this.transformCovers(covers, { scope });
  145. }
  146. // 当前 parent 有 next 节点,则停止向上查找
  147. if (currParentNext) {
  148. break;
  149. }
  150. currParent = this.tree.getParent(currParent);
  151. currParentNext = currParent ? this.tree.getNext(currParent) : undefined;
  152. }
  153. if (!currParentNext && currParent) {
  154. break;
  155. }
  156. curr = currParentNext;
  157. continue;
  158. }
  159. // next 和 parent 都没有,直接结束循环
  160. curr = undefined;
  161. }
  162. return this.transformCovers(covers, { scope });
  163. }
  164. protected transformCovers(covers: Scope[], { scope }: { scope: Scope }): Scope[] {
  165. return this.configs?.transformCovers
  166. ? this.configs.transformCovers(covers, {
  167. scope,
  168. document: this.flowDocument,
  169. variableEngine: this.variableEngine,
  170. })
  171. : covers;
  172. }
  173. protected transformDeps(deps: Scope[], { scope }: { scope: Scope }): Scope[] {
  174. return this.configs?.transformDeps
  175. ? this.configs.transformDeps(deps, {
  176. scope,
  177. document: this.flowDocument,
  178. variableEngine: this.variableEngine,
  179. })
  180. : deps;
  181. }
  182. // 排序所有作用域
  183. sortAll(): Scope[] {
  184. const { startNodeId } = this.configs || {};
  185. const startNode = startNodeId ? this.flowDocument?.getNode(startNodeId) : undefined;
  186. if (!startNode) {
  187. return [];
  188. }
  189. const startVariableData = startNode.getData(FlowNodeVariableData);
  190. return [startVariableData.public, ...this.getCovers(startVariableData.public)];
  191. }
  192. // 获取变量 Data 数据
  193. private getVariableData(node: ScopeChainNode): FlowNodeVariableData | undefined {
  194. if (node.flowNodeType === 'virtualNode') {
  195. return;
  196. }
  197. // TODO 包含 $ 的节点不注册 variableData
  198. if (node.id.startsWith('$')) {
  199. return;
  200. }
  201. return (node as FlowNodeEntity).getData(FlowNodeVariableData);
  202. }
  203. // privateScope:子节点不可以被后续节点访问
  204. private isNodeChildrenPrivate(node?: ScopeChainNode): boolean {
  205. if (this.configs?.isNodeChildrenPrivate) {
  206. return node ? this.configs?.isNodeChildrenPrivate(node) : false;
  207. }
  208. const isSystemNode = node?.id.startsWith('$');
  209. // 兜底:有子节点(节点 id 没有 $ 开头)的全部为私有作用域
  210. return !isSystemNode && this.hasChildren(node);
  211. }
  212. private hasChildren(node?: ScopeChainNode): boolean {
  213. return Boolean(this.tree && node && this.tree.getChildren(node).length > 0);
  214. }
  215. // 子节点按照顺序进行排序(含自身)
  216. private getAllSortedChildScope(
  217. node: ScopeChainNode,
  218. {
  219. ignoreNodeChildrenPrivate,
  220. addNodePrivateScope,
  221. }: { ignoreNodeChildrenPrivate?: boolean; addNodePrivateScope?: boolean } = {},
  222. ): FlowNodeScope[] {
  223. const scopes: FlowNodeScope[] = [];
  224. const variableData = this.getVariableData(node);
  225. if (variableData) {
  226. scopes.push(variableData.public);
  227. }
  228. // 私有作用域,子节点的变量不对外输出
  229. //(父节点如果存在 public 变量则对外输出)
  230. if (ignoreNodeChildrenPrivate && this.isNodeChildrenPrivate(node)) {
  231. return scopes;
  232. }
  233. if (addNodePrivateScope && variableData?.private) {
  234. scopes.push(variableData.private);
  235. }
  236. const children = this.tree?.getChildren(node) || [];
  237. scopes.push(
  238. ...children
  239. .map(child =>
  240. this.getAllSortedChildScope(child, { ignoreNodeChildrenPrivate, addNodePrivateScope }),
  241. )
  242. .flat(),
  243. );
  244. return scopes;
  245. }
  246. }