自动化编程技术------IDEA插件开发
前言
之前的文章自动化编程---JSR269中,我们实现了使用Processor自动生成代码,但是不能在debug时使用自动生成的代码,要解决这个问题就需要依托IDEA的插件功能了,在这篇文章中,我就来跟大家一起探索一下IDEA插件的开发过程,并实现一个小demo,废话少说,我们现在直接开始。
名词解释
为了更好理解,以下内容将以spring中的概念作类比。
Action:可以理解为spring中的controller,当用户点击插件中的按钮或触发某个事件时,就会调用Action中的方法。所有的Action都需要继承com.intellij.openapi.actionSystem.AnAction抽象类并实现actionPerformed方法。
Service:可以理解为spring中普通的类(不是spring中的service),service分为应用级和工程级
plugin.xml:插件的配置文件,类比spring中的配置文件,这里配置了插件信息、作者信息等,当然他最重要的作用是,所有的Action都需要这这个配置文件中进行配置。
今日目标
- 创建一个IDEA插件工程
- 在IDEA菜单中展示插件
- 点击插件按钮,展示我的信息
创建项目
为了方便我们开发调试,最好还是下载一个IDEA社区版,稍后要将其作为sdk使用,当然你也可以用专业版左右运行的SDK,只是专业版不开源,有bug不好调试。
创建一个新项目,选择IntelliJ platform plugin,SDKs选择我们之前下载好的社区版IDEA的路径,然后提示我们选择JDK,就选择我们本地的jdk即可。
基本配置
项目创建完成之后,在resources.META-INF文件夹下有一个plugin.xml文件,其中我们可以配置我们插件的基本信息,包括作者的信息和组件、事件等的注册信息。
<idea-plugin>
<id>yzstu</id> <!-- 当前插件的唯一id号 -->
<name>A demo</name> <!-- 插件的名称 -->
<version>1.0</version> <!-- 插件的版本号 -->
<vendor email="dikeywang@163.com" url="https://blog.yzstu.cn">yzstu</vendor> <!-- 开发者信息 -->
<description>This is a idea plugin just for test and learning</description> <!-- 插件的描述 -->
<change-notes>This is a idea plugin just for test and learning</change-notes> <!-- 插件的更新信息 -->
<!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="173.0"/> <!-- 表示当前插所支持的idea版本 -->
<!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
on how to target different products -->
<depends>com.intellij.modules.platform</depends>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
</extensions>
<!-- 新增的Action类需要在这里注册 -->
<actions>
<!-- Add your actions here -->
</actions>
</idea-plugin>
实现第一个功能
创建service
先提前说一下,我们这里讲的应用级别的service和项目级别的service是没有实际意义的,只是为了说明有这两种service和他们在创建过程中的差异来进行创建的。
应用级别service
这里我创建了BaseService、HiService两个接口,其实可以不用创建,创建他们是为了变现我们在开发过程中的继承架构。
BaseService
package cn.yzstu.demo.service;
/**
* @author Baldwin
*/
public interface BaseService {
}
HiService
package cn.yzstu.demo.service;
/**
* @author Baldwin
*/
public interface HiService extends BaseService {
String sayHi();
}
HiServiceImpl
package cn.yzstu.demo.service;
/**
* @author Baldwin
*/
public class HiServiceImpl implements HiService {
@Override
public String sayHi() {
return "Hello!!!";
}
}
项目级别service
这个service就没有任何的继承关系,我们在做demo的时候像这样直接创建service就行
package cn.yzstu.demo.service;
/**
* @author Baldwin
*/
public class AuthorInfo {
public String getAuthorInfo() {
return "Baldwin create me -_-!";
}
}
注册service
看完上面创建service后,你可能会感觉到疑惑,他们两个从代码上来看,是没有本质的区别的,那为什么一个是应用级别的而另一个是项目级别的呢?其实决定一个service是什么级别的,是service的注册方式。
<extensions defaultExtensionNs="com.intellij">
<!-- 应用级的service注册 -->
<applicationService serviceImplementation="cn.yzstu.demo.service.HiServiceImpl" id="hiService"/>
<!-- 项目级的service注册 -->
<projectService serviceImplementation="cn.yzstu.demo.service.AuthorInfo" id="authorInfo"/>
</extensions>
应用级别的service是在applicationService节点下注册,而项目级别的是在projectService节点下注册的,其实还有一种service是模块级别的,在moduleService节点下进行注册,我们今天没有关于moduleService的内容。
创建action
package cn.yzstu.demo.action;
import cn.yzstu.demo.service.AuthorInfo;
import cn.yzstu.demo.service.HiServiceImpl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.NotNull;
/**
* @author Baldwin
*/
public class Demo extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
// 获取应用级别的service,所有的idea client共用这一个service
HiServiceImpl hiServiceImpl = ServiceManager.getService(HiServiceImpl.class);
// 获取项目级别的service,当前打开的客户端所拥有的service
AuthorInfo projectService = ServiceManager.getService(anActionEvent.getProject(), AuthorInfo.class);
Messages.showMessageDialog(hiServiceImpl.sayHi() + projectService.getAuthorInfo(), "提示", Messages.getInformationIcon());
}
}
注册Action
现在直接启动插件,我们刚才创建的Action是不会生效的,就像是在spring中的bean,不注册到BeanFactory中也是不生效的,我们在插件开发中需要把所有的Action注册到plugin.xml中才能行。
<actions>
<action class="cn.yzstu.demo.action.Demo" id="demo" text="ShowAuthor" description="test demo" >
<add-to-group group-id="HelpMenu" anchor="first"/>
</action>
</actions>
我们注册一个Action时涉及到了几个设置项:
- class:Action全类名
- id:Action的全局唯一id
- text:在菜单中的名称
- group-id:选择在某一个菜单中展示,我们这里设置的是HelpMenu,也就是会在Help下进行展示。可选的参数有很多,假如你开启代码联想功能,可以直接在提示栏中进行选择
- anchor:在菜单中的位置,我们这里选择的是第一个。代码联想功能下选择
运行插件
就像我们运行springboot项目一样。直接点击debug按钮,假如你是从头开始看这篇文章,并按照流程设置好SDK的话,项目运行之后会在沙盒模式下启动一个IDEA客户端,并且我们的当前开发的插件会自动安装到IDEA客户端上,我们点击菜单栏中的help按钮,就可以看到我们的插件入口了
我们点击ShowAuthor按钮就会出现我们是想的展示作者信息的弹窗
总结
过程中可能会出现问题的环节是SDK的设置,总结一下就是你需要配置jdk和插件运行的SDK,这里的SDK指的就是一个IDEA的安装包路径,我们建议使用社区版作为SDk,最好是把IDEA源码下载下来作为SDK,这暗影对后期的debug有很大帮助。
在编码方面其实没有很多难度,毕竟现在只是初步探索