流程图插件(ActivityDiagram)设计原理

3,586 阅读2分钟

流程图插件(ActivityDiagram)设计原理

  1. psi结构
    • 程序结构接口(Program Structure Interface),通常称为PSI,是IntelliJ平台中的一个层,负责解析文件并创建支持平台许多功能的语法和语义代码模型。
    • psi结构分析工具 psiViewer
    • 参考文档:plugins.jetbrains.com/docs/intell…
  2. 模型设计
    • 数据结构
      • 栈还是树?
          • 优点:操作上一元素比较方便,上一栈元素作为下一栈元素的父
          • 缺点: 不方便操作其他元素,临时节点无法关联引用
          • 流程图天然可以转换为二叉树
          • 同级别元素直接可以表达父子管理
    • 标记设计
      • node:@node type="node",name="",note="",adptive=""
        • type: 目前只有两种node和decision 分别标识流程图中的节点和条件
        • name: 节点名称
        • note: 节点的补充说明
        • adptive: 扩展点,可以接入到自扩展的spi实现类中
    • 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语法解析
        • 识别语法之后创建结束节点
  • 操作流程

281620788773_.pic.jpg

291620788835_.pic.jpg

  • 方法右键单击使用效果 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=""
    }
     ```
     
    

- PlantUML diagram

  • tips 公司时间开发,无法开源源码,后期准备自己按照其他思路再实现一遍然后开源,所以提供不了插件供大家使用,仅仅提供一下实现思路。