0%

IntelliJ IDEA插件开发

​ 公司中提交MYSQL脚本有相应的规范,需要编写为groovy文件,同时里面包含了一些其他信息项,有对应版本、编写人、模块编码、日期等等,每次写脚本时都通过拷贝旧文件,再修修改改之后提交,所以错误率比较高,想着通过配置信息项以及通过代码来直接生成对应脚本。完成之后发现,虽然达到了生成脚本的预期,但是交互是在console控制台上交互,使用上有点繁琐,偶然看到关于IDEA插件开发的博客,想着是否可以通过IDEA插件来写一个UI,生成逻辑直接使用原有代码移植过来。同时记录在开发IntelliJ IDEA插件过程中遇到的一些问题和踩到的一些坑。

环境准备

IntelliJ IDEA插件开发有两种方式,一种是直接引入Plugin DevKit,然后配置IntelliJ Platform Plugin SDK进行开发,另一种是使用gradle构建项目并引入IDEA插件开发包。使用gradle的好处是同时也可以引入一些其他的库进行使用。

​ 在IDEA 2021.3以及之后的版本,开发需要使用JDK 11进行开发,在我开发的时候我本地也没有JDK 11(一台电脑可以支持多个版本的JDK,问题在于环境变量配置的是哪个版本而已。因为目前只有这里插件开发我才会用到JDK 11,所以没有将它添加到环境变量中,仅通过IDEA工具添加了JDK路径)。

​ 我使用的是gradle的方式进行插件的开发。gradle导入之后,在Libraries下会有一个com.jetbrains:ideaIC:2021.3,这就是IDEA插件的开发包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
plugins {
// IDEA的插件开发包
id 'org.jetbrains.intellij' version '1.8.1'
id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
// 设置阿里云maven仓库
maven { url 'https://maven.aliyun.com/repository/public/' }
mavenCentral()
}

dependencies {
implementation 'cn.hutool:hutool-all:5.6.7'
implementation 'com.alibaba:fastjson:1.2.28'

implementation 'org.apache.logging.log4j:log4j-core:2.14.1'
implementation 'org.apache.logging.log4j:log4j-jul:2.14.1'
implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.14.1'
implementation 'mysql:mysql-connector-java:8.0.25'


testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0'
implementation 'org.projectlombok:lombok:1.18.8'
annotationProcessor 'org.projectlombok:lombok:1.18.8'
}

// idea的使用版本
intellij {
version = '2021.3'
}
patchPluginXml {
changeNotes = """
Add change notes here.<br>
<em>most HTML tags may be used</em>"""
}
test {
useJUnitPlatform()
}

gradle中一些常用项:

intellij -> runIde:这时会新启动一个IDEA工具,可以进行调试插件。

intellij -> buildPlugin:构建插件,用来完成之后将代码打包成.zip。(路径为build/distributions)。

辅助工具

点击Help -> Edit Custom Properties...,添加以下配置后重启IDEA

1
idea.is.internal=true

Tool下会出现Interal ActionsView PSI Structure...按钮。

ideaInternal.png

参考面板:Internal Actions -> UI -> Show Standard Panels:会弹出一个UI面板,结合UI Debug就可以参考到对应的源码。

standPanel.png

通过Internal Actions ->UI Debugger可以监控在IDEA中鼠标操作对应的Action。比如创建一个类,在UI Debugger面板上可以看到一个CreateClassAction的类,就可以看到这个创建一个类的源码,如果功能类似甚至可以直接复用。

PSI相关API目前占时没有使用,具体如果需要插件能实现在代码里根据某种规则生成内容,则就需要通过PSI相关内容进行处理。

工程结构

结构

1
2
3
4
5
6
7
8
9
idea-plugin
├── src
└── main
└── resources
│ └── META-INF
│ └── plugin.xml
└── java
└── cn.com.xiaocainiao
└── MyWindowFactory.java

plugin.xml配置

我使用的是ToolWindowFactory创建右侧窗体。若是创建Action,可以直接通过New -> Plugin DevKit -> Action进行创建,通过这种方式创建,会自动在plugin.xml文件中添加<action>的配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<idea-plugin>
<id>org.example.SecondIdeaPlugin</id>
<name>SecondIdeaPlugin</name>
<vendor email="xiaocainiaoya@foxmail.com" url="http://xxx.com">bosssoft</vendor>

<description><![CDATA[
For simple and quick generation of SQL script files<br>
<em>Tools that are easy to use</em>
]]></description>

<!-- please see https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html
on how to target different products -->
<depends>com.intellij.modules.platform</depends>

<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->

<toolWindow id="generatorSQL"
secondary="true"
anchor="right" factoryClass="cn.com.xiaocainiaoya.MyWindowFactory">

</toolWindow>
</extensions>

<actions>
<!-- Add your actions here -->
</actions>
</idea-plugin>

UI

​ 由于IDEA插件的UI采用的是SwingAwt来进行窗体开发,当知道使用的是Swing一度想要放弃掉,确实是使用Swing是一件比较痛苦的事情。后借助于IDEASwing UI Designer功能通过拖拽简单组件的方式,硬着头皮画出了UI界面。

ideaSwing.png

兼容性问题

1.路径

​ 可能由于项目有别于常用的java项目、spring项目,所以在获取资源文件(/resources/**)时,总是感觉摸不着头脑。参考了一些其他博主写的IDEA插件项目,获取资源文件的方式,与java项目、Spring项目并无差别,但是我在获取资源文件时,一直提交获取不到资源文件,也有可能是velocity组件的问题。

​ 原本使用velocity模板引擎来加载对应模板文件,但是一直报错获取不到对应资源文件之后,将这种动作修改为代码层获取到资源文件内容,在将模板内容提交给velocity模板引擎。

注:velocity组件和groovy库相关包在com.jetbrains:ideaIC:20201.3中已经存在,所以不能由自身再引入。

在调试开发过程中,velocity正常使用,但是打包成插件之后,通过插件的方式运行,一直报一个日志相关的异常。

添加velocity.proerties配置文件相关配置

1
2
3
runtime.log.logsystem.class=org.apache.velocity.runtime.log.SimpleLog4JLogSystem
runtime.log.logsystem.log4j.category=velocity
runtime.log.logsystem.log4j.logger=velocity

因为在调试过程的运行和实际插件方式运行是对应的相对路径是不一致的,所以在使用系统级有关的相对路径是需通过使用com.intellij.openapi.application.PathManager类来获取对应的路径:

比如使用PathManager.getBinPath()

在调试运行获取到的路劲为:/usr/local/Cellar/gradle/7.3.1/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/ideaIC/2021.3/75777e10a0e2880bc02945066dda2480a696c3d9/ideaIC-2021.3/bin

在实际插件方式允许获取的路径为:/Applications/IntelliJ IDEA.app/Contents/bin

参考连接

IntelliJ IDEA 插件开发指南

插件入门官网

-------------本文结束感谢您的阅读-------------