开发了一个用于在代码中校验和执行sql的插件,效果如下:
在mapper.java中 ,右键选择 goto->testSQL
以json形式输入参数,即可将执行结果显示出来
但是大多数场景,我只需要看下对于的sql对不对,那么就直接
goto->testValid
会使用自动生成的默认参数去执行sql,不再需要自己输入参数
同理的,复杂的参数也支持,insert update delete 也支持
goto->testValid也可以使用默认参数测试
此次演示用的xml,就是mybatis正常的带标签的xml
支持大多数的xml标签解析
插件 github源码地址:
https://github.com/xiaoxinglai/crudboy
1.插件原理
IDEA 提供了一个IntelliJ Platform SDK开发工具包,里面开放了各种API,可以基于这些API拓展定制出自己需要的功能。
其中最重要的是:
程序结构接口(PSI)。这是一组功能,可用于解析文件,构建代码的丰富句法和语义模型以及从此数据构建索引,从快速导航到文件,类型和符号,到代码完成窗口的内容并查找用法,代码检查和代码重写,快速修复或重构以及许多其他功能。
可以实现诸如以下功能:
自定义语言支持
框架整合
工具整合
用户界面附加组件 等
开发必看:
https://www.jetbrains.org/intellij/sdk/docs/basics/types_of_plugins.html
官网文档介绍
2.开发环境搭建
https://cloud.tencent.com/developer/article/1348741 参考这里
3.项目总结
3.1初始化项目之后,结构大致如下
其中 plugin.xml是核心
在plugin.xml中
这里用到了IOC的原理,插件会在加载的时候初始化定义的类
这里面是初始化的是配置面板的类
3.2 action
action是代表的每一个触发动作
application-components是定义组件的生命周期
3.2 components生命周期
生命周期:负责生命周期管理以及连接组件之间的相互依赖关系。
Application level components,在 IDEA 启动的时候创建和初始化,可以使用 getComponent(Class) 获取它们。
Project level components,在 IDEA 中每个 Project 实例创建的,甚至可以为未打开的项目创建组件,可以使用 getComponent(Class)方法从 Project 实例中获取它们。
Module level components,它们是为 IDEA 中加载的每个项目中每个模块创建,使用 getComponent(Class)方法可以从 Module 实例获取模块级别组件。
顺序:
1.创建,调用构造函数
2.初始化,initComponent 调用该方法(如果组件实现 ApplicationComponent 接口)
3.配置,保存和加载每个组件的状态。(PersistentStateComponent 和 JDOMExternalizable,实例化配置)。
3.注册,对于模块组件,将调用接口的 moduleAdded 方法 ModuleComponent 将模块添加到项目中,对于项目组件,调用接口的 projectOpened 方法 ProjectComponent 加载项目。
4.保存配置,JDOMExternalizable,PersistentStateComponent 的调用。
5.销毁,disposeComponent 调用
线程模型
平台相关数据结构由读/写锁覆盖,适用于 PSI,VFS 和项目模型。允许从任何线程读取数据。从 UI 线程读取数据不需要任何特殊的工作。但是,从任何其他线程执行的读取操作都需要使用 ApplicationManager.getApplication().runReadAction()或 ReadAction.run/compute。
仅允许从 UI 线程写入数据,并且写入操作始终需要用 ApplicationManager.getApplication().runWriteAction()或 WriteAction.run()/compute()。
后台流程管理
后台进度由 ProgressManager 类管理,该类有很多方法可以使用模式(对话框),非模式(在状态栏中可见)或不可见进度来执行给定代码。在所有情况下,代码都是在与 ProgressIndicator 对象关联的后台线程上执行的。
讯息传递
平台中可用的消息传递基础结构,基于 Observer 设计模式扩展实现的,通过该模式能够更好的梳理的一对多关系,实现提供了附加功能,例如在层次结构上进行广播和特殊的嵌套事件处理(此处的嵌套事件是指从另一个事件的回调中(直接或间接)触发新事件的情况)。
这个组件是必须在plugin.xml里面要配置的
然后action
所有的触发操作,都需要继承一个Action类
在actionPerformed的方法中,可以通过AnActionEvent的参数拿到相关的参数,比如说上面的例子,获取当前类的操作路径,并弹窗出来。
然后需要在plugin.xml中配置,它分组在GenerateGroup中
效果如下
3.3 面板
其次,就是有时候,我们会看到在项目里面,需要加配置,并且需要保存下来,比如说maven插件里面的配置maven仓库地址。
我们先创建一个面板
创建之后是有两个类
一个xx.form 一个是xx.java
那么问题来了,面板上新增的数据,如何保存呢?
idea的插件,是将在配置面板上的数据,保存在了xml中,下次打开的时候,再次读取,便可以恢复到之前的配置状态。
为此,我们需要实现一个PersistentStateComponent类的子类,用于保存配置中的数据。
然后也是要在plugin.xml里面配置,这里其实是提供了一个ioc容器的作用
这样任意地方 需要取这个配置的值的时候,使用ServiceManager.getService(CrudBoySettings.class);
即可取出来了。
那么最终,要这个配置面板和保存配置的seting整合起来
需要一个SearchableConfigurable配置类的子类
效果如下
总结:
action的子类->所有的触发事件 比如说菜单 点击
PersistentStateComponent的子类->配置保存
SearchableConfigurable子类->配置面板
4.常用API
4.1 获取plugin.xml里面配置的类
ServiceManager.getService(XXXX.class);
4.2 获取选择的文件夹和项目
IdeView ideView = (IdeView)anActionEvent.getRequiredData(LangDataKeys.IDE_VIEW);
//选择的文件夹
this.psiDirectory = ideView.getOrChooseDirectory();
//选择的项目
this.project = this.psiDirectory.getProject();
4.2 获取选中的类名
// e为 AnActionEvent
PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
//获取选中的类名
String name = psiFile.getVirtualFile().getName();
4.3 获取鼠标选中的元素
//获取鼠标所在的元素
PsiElement psiElement = e.getData(PlatformDataKeys.PSI_ELEMENT);
4.4 获取方法的参数
//获取方法的参数
PsiParameter[] psiParameters = ((PsiMethodImpl) psiElement).getParameterList().getParameters();
4.5 获取指定文件名的文件
PsiFile[] psiFiles = FilenameIndex.getFilesByName(project, name, GlobalSearchScope.projectScope(project));
等等 其他常用的还有根据模版生成代码等,在JavaDirectoryServiceImpl类下面的方法
详细可以参考如下资料 或者参考源码
这个插件也实现了根据数据库表自动生成DO mapper mapper.xml的功能
参考资料:
1.开发环境搭建
https://cloud.tencent.com/developer/article/1348741
腾讯云的这篇文章讲的很清晰。
2.开发手册 参考官网(ps:要有耐心)
https://www.jetbrains.org/intellij/sdk/docs/welcome.html
3.值得参考的项目(很多操作和api 只有在其他项目找)
https://my.oschina.net/u/2526698/blog/1548929 (快速定位到mybatis mapper文件中的sql)
https://blog.csdn.net/soledadzz/article/details/104204791 (结构介绍)
4.概念
https://www.jianshu.com/p/c169ef3c3eed 虚拟文件系统