流程图插件(ActivityDiagram)设计原理
- psi结构
- 程序结构接口(Program Structure Interface),通常称为PSI,是IntelliJ平台中的一个层,负责解析文件并创建支持平台许多功能的语法和语义代码模型。
- psi结构分析工具 psiViewer
- 参考文档:plugins.jetbrains.com/docs/intell…
- 模型设计
- 数据结构
- 栈还是树?
- 栈
- 优点:操作上一元素比较方便,上一栈元素作为下一栈元素的父
- 缺点: 不方便操作其他元素,临时节点无法关联引用
- 树
- 流程图天然可以转换为二叉树
- 同级别元素直接可以表达父子管理
- 栈
- 栈还是树?
- 标记设计
- node:@node type="node",name="",note="",adptive=""
- type: 目前只有两种node和decision 分别标识流程图中的节点和条件
- name: 节点名称
- note: 节点的补充说明
- adptive: 扩展点,可以接入到自扩展的spi实现类中
- node:@node type="node",name="",note="",adptive=""
- java数据结构
int type;//type=1 普通节点,可有多个子节点 type = 2 条件节点 只有两个子节点 type=3 预置节点 String name;//方法中文注释 String methodName;//方法英文名 String argsType; String note;//方法注释 String adptive; Node parent; List<Node> child = new ArrayList<>(); - node类型
0, "根节点", "用作递归的跟节点,初始化uml的start和end", 1, "普通节点", "方法和代码块中标记的node节点,可以有多个孩子", 2, "条件节点", "条件代码,最多有两个孩子", 3, "预置节点", "占位节点", 4, "空白节点", "空白节点,用作decison中只表达right的时候占位使用", 5, "结束节点", "支持节点的结束"; - psiTree转化为二叉树
- psiTree为多子树,关键节点层级关系深度很深
- 采用递归的方法,过滤掉不感知的节点,同一层节点绑定一个父节点,如果当层未创建节点则继承祖父节点
- 难点
- 方法重载的解析
Query<PsiMethod> search = OverridingMethodsSearch.search(psiMethod); - 支持if表达式的注释在if上面和括号后面的解析
//@node type="decision",name="条件X",note="" if(true){ //@node type="node",name="G" } if(true)//@node type="decision",name="条件X",note="" { //@node type="node",name="G" } - 多层if嵌套解析
//@node type="decision",name="条件B",note="" if(true) { //@node type="decision",name="条件C",note="" if(true) { //@node type="node",name="G" return null; }else if(true) //@node type="decision",name="条件D",note="" { //@node type="node",name= H }else { //@node type="node",name= I } //@node type="node",name= M } - return 语法解析
- 采用预置节点的方式,先生产空白节点递归到内部实现的时候预先放置到会调用的节点
- 回栈到当前节点之后才关联空白节点的孩子
- uml不展示预置节点
- 栈深度控制,防止栈溢出
- 对于方法和if代码块,如果没有加特定标识则不再继续往下递归
- 递归方法解析
- 记录节点路径,向上递归查询相同节点来实现递归检测
- throw语法解析
- 识别语法之后创建结束节点
- 方法重载的解析
- 数据结构
- 操作流程
- 方法右键单击使用效果
demo代码
//@node type="node",name="T1",note="" public Boolean test1(){ //@node type="node",name="NA",note="" //@node type="decision",name="DA",note="" if(true){ //@node type="node",name="NB",note="" }else if(true)//@node type="decision",name="DB",note="" { //@node type="node",name="NC",note="" return false; } //@node type="node",name="ND",note="" } ```
- tips 公司时间开发,无法开源源码,后期准备自己按照其他思路再实现一遍然后开源,所以提供不了插件供大家使用,仅仅提供一下实现思路。