本文主要是介绍着手开发属于自己的第一个Intellij-platform plugin插件程序(三),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
开发第一个插件
- 本节会从0开始构建一个简单的IDE插件,包括插件工程相关的配置。完成后的代码可当做插件开发的基础开发框架使用,这可大大节省新插件开发时工程的构建时间。
- 本节旨在为了在正式学习开发Intellij平台插件之前使开发者对Intellij平台插件的开发流程有个感性的、全局的认识,这样在后续深入学习各主题知识点时会相对轻松很多。
本章配套源码可从 https://download.csdn.net/download/liudonglovehemin/89215713 处下载
构建插件基础工程
配置Intellij Idea工具
在开发插件前需要打开Intellij Idea(简称Idea)的一项配置,方便之后插件程序的开发调试。点击Idea菜单栏中的【帮助-编辑自定义属性】,在打开的文件中添加如下代码以打开内部工具:
idea.is.internal=true
保存后,重启Idea可在【工具】菜单下看到一系列的内部调试工具,如下图所示:
创建Intellij插件工程
新建工程
选择【文件】-【新建】-【项目】,在弹出窗口选择IDE插件。
【注意】:JDK处一定要选择合适版本的jbr SDK(非javaSDK),可在JDK选择下拉选框中选择需要的版本进行下载。如果Intellij idea插件目标版本是2020.3+版本要求最低java11,2022.2+版本要求最低java17,示例Jbr版本为17.0.9。
配置项目
选择【文件】 -【项目结构】,设置SDK和编译版本。
【注意】:此处的语言级别和SDK并不需要一一匹配,但建议选择匹配的级别,这样可以在后续编译代码过程中减少一些没必要的麻烦。
配置 Gradle
选择【首选项】-【构建、执行、部署】-【构建工具】-【Gradle】,修改下图红框内的默认内容为下图所示。Gradle分发选择“包装器”可方便的把插件环境下载到工程中,而不需要依赖系统配置,尤其多人开发时会更灵活,后续章节会详细讲解包装器相关的内容:
初始化Gradle
运行Gradle集成工具的 init 和 wrapper 命令:
命令执行需要几分钟的时间,执行成功后工程目录大概如下图所示,下图中没有的文件可以先手工创建(文件夹除外),后续会详细说明如何配置:
【注意】:关于kotlin和groovy,最新版本的Intellij Idea创建插件工程时默认使用kotlin语言,所以源码路径是src/main/kotlin,如果用java开发的话只需用重构功能把kotlin文件夹重命名为java即可。另外如果创建工程时gradle选groovy语言构建,则build.gradle文件不带.kts后缀,.kts是kotlin语言文件的后缀名,也可直接改文件名称来切换这两种脚本语言。
配置Intellij插件工程
在编写插件代码前还需要对部分工程文件进行必要的配置,主要是gradle工程构建以及plugin配置,共涉及4个文件,在配置工程文件前先详细了解下工程的目录结构:
工程文件 | 详细说明 |
---|---|
.gradle | gradle构建工具文件目录,不需要配置,执行init命令后自动生成 |
.run | 运行插件后自动生成的插件配置,不需要配置,执行runIde命令后自动生成 |
build | 工程编辑目录,相当于java工具的out目录,不需要配置,执行runIde命令后自动生成 |
gradle | gradle构建工具执行文件,不需要配置,创建工程后自动生成 |
src | 插件源码 |
.gitgnore | git版本控制时忽略掉的提交文件 |
build.gradle.kts | gradle构建配置文件,相当于maven的pom.xml文件 |
gradle.properties | (可选但建议)gradle构建配置文件的属性配置文件,可以定义供gradle构建配置文件使用的变量 |
gradlew | gradle构建工具,shell执行脚本,不需要配置,执行wrapper命令后自动生成 |
gradlew.bat | gradle构建工具,bat执行脚本,不需要配置,执行wrapper命令后自动生成 |
settings.gradle.kts | (可选但建议)gradle构建配置文件,用于构建gradle多模块工程。如果插件由多个模块组成,可在此文件中定义公共依赖和依赖版本等信息 |
plugin.xml | 插件主配置文件,此文件位于src/main/resources/META-INF/目录下,创建工程时自动生成 |
gradle-wrapper.properties配置
此配置文件位于gradle目录下,主要是配置Gradle构建工具的版本等信息。常用的就是如下5个属性,其中distributionUrl默认为-bin,建议配置成-all,原因是包含源代码,这样在构建过程出现问题可以更精准的定位问题原因。
#Gradle 解包后存储的父目录,默认在userName/.gradle下面;
distributionBase=GRADLE_USER_HOME#distributionBase指定目录的子目录, distributionBase+distributionPath就是 Gradle 的存放的具体目录
distributionPath=wrapper/dists#Gradle 指定版本的压缩包下载地址,如果你使用IDEA的话,它会推荐下载all版,包含源代码,这样IDEA就可以分析源代码,提供更加精确的gradle脚本支持,可用于全组统一,而不需要在本地安装各自的版本
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip#Gradle 压缩包下载后存储父目录
zipStoreBase=GRADLE_USER_HOME#zipStoreBase指定目录的子目录。zipStoreBase+zipStorePath就是 Gradle 压缩包的存放位置
zipStorePath=wrapper/distsnetworkTimeout=10000
validateDistributionUrl=true
settings.gradle.kts 配置
多模块gradle工程的父模块配置文件,使用gradle构建多模块工程只需在父模块的配置文件中进行配置即可,子模块不需要任何指向配置,这与maven构建有着很大的区别。暂时在此配置文件中添加如下配置,后续随着依赖增加同时修改此文件的相关配置:
rootProject.name = “Custom IntelliJ Platform Plugin"pluginManagement {repositories {mavenLocal()mavenCentral()gradlePluginPortal()maven("https://www.jetbrains.com/intellij-repository/releases")maven("https://cache-redirector.jetbrains.com/intellij-dependencies")maven("https://maven.aliyun.com/nexus/content/groups/public/")maven("https://maven.aliyun.com/nexus/content/repositories/central/")}
}
- rootProject.name:插件工程名称,此名字会显示在idea gradle插件工具栏中,不影响插件行为;
- pluginManagent:插件依仓库地址(与maven库通用),如果国外库下载速度比较慢可以配置成国内镜像,如上述代码中部分为阿里云镜像仓库,gradle在执行工程构建时会按版本库顺序搜索依赖内容;
gradle.properties 配置
可把build.gradle.kts配置文件中的配置参数集中到此文件中以方便工程的管理(相当于maven引入.properties文件的效果)。此文件为可选但建议使用,说明一下,此属性文件为固定名称,build.gradle.kts会自动import此文件。此示例中配置如下,文件内容不过多解释,可结合接下来build.gradle.kts说明一同理解:
###########依赖和环境相关配置#############
#gradle工具配置
gradleVersion = 8.7
org.gradle.unsafe.configuration-cache = true
org.gradle.caching = true
org.gradle.configuration-cache = true
kotlin.stdlib.default.dependency = false
kotlin.incremental.useClasspathSnapshot = false#intellij gradle plugin配置,用于运行本地插件的测试平台:https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType = IC
platformVersion = 2023.2.6
platformDependencyPlugins = java#插件个性化设置,这些设置在发布后值可能会变化
org.jetbrains.intellij.buildFeature.buildSearchableOptions=false
org.jetbrains.intellij.buildFeature.paidPluginSearchableOptionsWarning=false
org.jetbrains.intellij.buildFeature.selfUpdateCheck=false
###########自定义插件属性###########
pluginGroup = com.korgs
pluginName = FirstDemo Intellij Plugin
pluginVersion = 1.0-SNAPSHOT
pluginRepositoryUrl = https://www.korgs.com#自定义插件支持的intellij platform平台目标:https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 232
pluginUntilBuild = 241.*
上述配置文件中“##依赖和环境相关配置##”注释部分下配置的是插件工程所依赖的gradle插件的配置,好比maven开发时也需要在中配置一些三方插件一样,开发IDE插件必须要依赖三个插件:gradle、intellij gradle plugin、java。示例代码中以org.gradle.xxx或org.jetbrains.xxx是依赖的插件的配置,详细的可以查询下插件的文档,示例中的配置都与工程构建时性能相关,详细如下:
- org.gradle.unsafe.configuration-cache = true:开启gradle缓存,加快构建速度
- kotlin.incremental.useClasspathSnapshot=false:Kotlin 编译器抛出内存不足时的解决方法
- kotlin.stdlib.default.dependency = false:如果Kotlin版本大于1.4设置成false,否则设置成true
- org.jetbrains.intellij.buildFeature.selfUpdateCheck=false:设置插件是否自动更新检查
- org.jetbrains.intellij.buildFeature.buildSearchableOptions=false:禁止为插件生成索引信息
- org.jetbrains.intellij.buildFeature.paidPluginSearchableOptionsWarning=false:如果插件为付费的,设置是否可搜索;
- runIde.autoReloadPlugins = true:修改插件源码后可重新运行build插件,这样就可以实现开发时插件动态调试的功能了,而不需要重新runIdea;
- org.gradle.jvmargs=-Xmx2024m -XX:MaxPermSize=512m:如果gradle构建时内存不够用,可以添加此参数;
build.gradle.kts 配置
gradle构建工具build脚本文件,相当于maven的pom.xml文件。一般来讲插件工程需要配置以下四方面的内容:
- 工程基本信息;
- 依赖的插件与插件配置;
- 插件代码依赖的三方.jar文件;
- 任务,即gradle指令,部分任务可以运行时覆盖plugin.xml中的配置;
关于Gradle完整配置说明可参考本系列手册中的《附录手册》,也可参考笔者的在线文档:博客地址。
定义基本函数
主要是为了简化脚本函数,示例中只使用了外部.properties文件,所以重新定义了两个函数。
fun properties(key: String) = providers.gradleProperty(key).get()
fun environment(key: String) = providers.environmentVariable(key).get()
- proerties(key:String):用来读取项目属性文件;
- environment(key:String):用来读取系统环境变量;
定义插件标识信息
下述内容可以在使用Idea向导创建工程时填写,也可以在此处重新修改。
group = properties("pluginGroup")
version = properties("pluginVersion")
引入插件依赖插件
这些工程依赖插件是编写Intellij插件所必需的。每个工程依赖插件完成特定的功能,比如开发依赖java插件、发布依赖changelog插件,按需引入即可:
/*依赖的插件*/
plugins {id("java")id("org.jetbrains.changelog") version "2.2.0"id("org.jetbrains.intellij") version "1.17.3"
}java {sourceCompatibility = JavaVersion.VERSION_17
}intellij {pluginName.set(properties("pluginName"))// Intellij Plugintype.set(properties("platformType")) //ICversion.set(properties("platformVersion")) //2022.2.5plugins.set(listOf(properties("platformPlugins"))) //1.0-SNAPSHOT
}
- plugins{}:引入java和org.jetbrains.intellij插件,org.jetbrains.intellij扩展了gradle基本指令专门用于构建IDE插件并提供了基础功能;
- java{}:插件源码和编译版本设置;
- intllij{}:配置intellij gradle插件,详细配置可查看Intellij plugin插件详细说明。这个标签下的所有配置全部是本地测试时的平台配置和最终发布后的适用版本没太大关系。
- pluginName:发布到插件市场上,插件的名称;
- type.set():插件适用的平台类型,详细可查看Intellij plugin插件详细说明中type属性说明,如IC表示插件适用IntelliJ IDEA Community Edition版本;
- version.set():插件适用的IDE版本,,可查看Intellij plugin插件详细说明中version属性说明,如2022.2.5表示插件适用的最低版本为IC:2022.2.5版本;
- plugins.set():设置自定义插件捆绑的依赖插件,依赖的插件来源于官方库以及插件市场,详细可查看Intellij plugin插件中plugins属性说明,多项依赖用逗号分隔,如配置为com.intellij.java, com.jetbrains.php:203.4449.22表示个人插件同时依赖java和php插件,详细可查看引链接。如果是依赖本地文件也可配置成plugins.set(listOf(file(“/path/to/plugin/lib/”)))
引入工程三方依赖
编写插件代码所需要用到的三方jar包,同maven的标签功能一样。下述代码引入了三个jar包,随着插件功能丰富可以按需引入其它类型jar包。
/*依赖的包*/
dependencies {compileOnly("org.jetbrains:annotations:24.1.0")compileOnly("org.projectlombok:lombok:1.18.30")annotationProcessor(“org.projectlombok:lombok:1.18.30”)implementation(“cn.hutool:hutool-all:5.8.27")
}
自定义执行Task任务
gradle的指令是以Task的方式暴露的,这些Task不单单是简单执行工程构建指令,还可以改变最终插件的行为,基本的配置如下:
tasks {wrapper {gradleVersion = properties("gradleVersion") //8.2.1}withType<JavaCompile> {sourceCompatibility = properties(“sourceVersion")//1.7targetCompatibility = properties("targetVersion")//1.7}jar.configure {duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.INCLUDEfrom(configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) })}runIdeForUiTests {systemProperty("robot-server.port", "8082")systemProperty("ide.mac.message.dialogs.as.sheets", "false")systemProperty("jb.privacy.policy.text", "<!--999.999-->")systemProperty("jb.consents.confirmation.enabled", "false")}tasks {runIde {jvmArgs("-DmyProperty=value")systemProperty("name", "value")autoReloadPlugins.set(false)buildSearchableOptions { enabled = false }}}patchPluginXml {version.set(properties("pluginVersion"))//1.0-SNAPSHOTsinceBuild.set(properties("pluginSinceBuild"))//222untilBuild.set(properties("pluginUntilBuild"))//232.*}
}
- wrapper:指定gradle构建工具的版本,这样就不需要在/gradle/wrapper/gradle-wrapper.properties中进行修改了,修改后会自动修改gradle-wrapper.properties中的配置值;
- withType:设置工程的java源码和编译版本;
- jar.configure:设置工程打包配置,示例中的配置是把依赖的jar包按需抽取到插件jar中;
- runIdeForUiTests:插件UI测试配置,如果有UI界面;
- patchPluginXml:从名字就可以看出此为一个补丁功能,此处的配置会覆盖掉plugin.xml文件中的配置,此配置比较重要,示例如下:
- version.set():设置自定义插件的版本,比如1.0-SNAPSHOT;
- sinceBuild.set():设置自定义插件适用IDE范围的最小构建版本号,详细可查看;
- untilBuild.set():设置自定义插件适用IDE范围的最大小构建版本号,详细可查看;
- tasks.runIde:修改runIde指令默认配置;
Jetbrains公司旗下的所有IDE产品的版本坐标格式为【type:vsersion:buildVesrion】,以Intellij Idea为例,如下图所示:
plugin.xml 配置
自定义插件的配置文件。plugin.xml 文件位于src/main/resources/META-INF/目录下,在此文件中可以定义插件的所有扩展点、动作、侦听器等,在开发过程中可能需要频繁修改。其完整配置可对称《附录手册》中plugin.xml配置一节中的详细描述。
<idea-plugin><id>com.korgs.firstplugin</id><name>FirstDemo</name><vendor email="liudong@me.com" url="https://korg8.com">korgs</vendor><description><![CDATA[This is a test plugin project, so do not use and download for you idea]]></description><depends>com.intellij.modules.platform</depends><depends>com.intellij.java</depends><resource-bundle>messages.default</resource-bundle><change-notes> <![CDATA[ ~~~]]</change-notes><!--扩展点--><extensions defaultExtensionNs=“com.intellij"></extensions><!--动作--><actions></actions>
</idea-plugin>
- id:插件ID,插件市场唯一,相当于插件的唯一标识;
- name:自定义插件的名称,功能同build.gradle.kts中的intllij{}配置,必须全英文;
- vendor:插件作者相关信息,必须全英文;
- description:插件描述,必须全英文;
- depends:插件依赖,功能同build.gradle.kts中的intllij{}配置
- resource-bundle:语言资源文件,示例配置指向src/main/resources/messages/default.properties文件;
- extensions:扩展点,官方提供很多IDE平台的基础功能,并以扩展点的形式公式出来,开发者可根据需要自行扩展增强IDE功能;
- actions:动作,开发者自定义插件的功能菜单,根据开发者需要自行配置;
pluginIcon.svg 配置
插件的图标,位于目录src/main/resources/META-INF/下,IDE插件的图标建议是svg格式,且要求:1、尺寸:40 x 40 或80 x 80像素;2、形状:插件Logo周边至少要留2px的透明边距,可以具体查看官方文档。
此文件在创建工程后自动创建,默认图标内容如下,同时也可以再创建一个名为pluginIcon_dark.svg:可选的替代插件徽标,用于深色 IDE 主题:
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M32.0845 7.94025V4H24.0203V7.9896H16.029V4H7.91553V7.94025H4V36H16.0044V32.0045C16.0058 30.9457 16.4274 29.9308 17.1766 29.1826C17.9258 28.4345 18.9412 28.0143 20 28.0143C21.0588 28.0143 22.0743 28.4345 22.8234 29.1826C23.5726 29.9308 23.9942 30.9457 23.9956 32.0045V36H36V7.94025H32.0845Z" fill="url(#paint0_linear)"/><defs><linearGradient id="paint0_linear" x1="2.94192" y1="4.89955" x2="37.7772" y2="39.7345" gradientUnits="userSpaceOnUse"><stop offset="0.15937" stop-color="#3BEA62"/><stop offset="0.5404" stop-color="#3C99CC"/><stop offset="0.93739" stop-color="#6B57FF"/></linearGradient></defs>
</svg>
基础工程配置测试
上述配置完成后可以使用Intellij gradle plugin提供的Task来验证上述配置是否正确,运行方式为打开gradle插件工具栏,找到Intellij选项然后双击运行:
大概有40多task指令,详细的可查看Intellij plugin插件详细说明,可用于工程验证的命令task如下:
- verifyPluginConfiguration:验证插件项目中配置的SDK、目标平台、API等版本信息;
- verifyPlugin:验证plugin.xml描述符的完整性和内容以及插件的存档结构:
- runPluginVerifier:运行IntelliJ插件验证器工具,以检查与指定IntelliJ IDE构建的二进制兼容性。
另外运行Task时需要注意,gardle很多任务的运行是有前置依赖的,如下图所示,运行verifyPluginConfiguration前会先运行initializenIntellijPlugin和patchPluginXml两个Task。
基础插件编译运行
同样使用ntellij gradle plugin提供的Task,依次运行以下task,也可跳过前两个直接运行runIde:
- initializeIntelliJPlugin:初始化插件;
- buildPlugin:构造插件;
- runIde:运行插件,此时会重新打开一个idea窗口;
如果上述配置没有问题,则此工程可做为插件开发模板使用,之后如果需要开发新的插件不需要按上述向导操作,直接复制已配置好的工程代码再修改即可。
另外一种快速构建插件方程的方法是从Github上下载官方提供的插件开发工程模板,下载地址为 https://github.com/JetBrains/intellij-platform-plugin-template 。
开发第一个插件程序
此示例会在Idea的【工具】菜单栏中添加一个名为【通知】的新菜单,点击后以气泡的方式弹出一句提示语文案,此DEMO非常简单只是为了演示一下如何开发插件,详细开发步骤如下:
创建Action动作类
在idea菜单栏中选择【文件 - 新建 - Plugin DevKit - 操作】后,会显示如下设置页面(熟悉开发后不需要用此向导,直接创建java文件然后在plugin.xml文件中配置即可);
- 操作ID:整个插件范围内全局唯一;
- 类名:插件的java类的名称或全路径;
- 名称:显示在菜单栏上的名称;
- 描述:随便写,主要是为了方便查找,和插件最终显示无关;
- 添加到组–组:插件要添加到工具栏的哪个菜单组中,因为我们是在【工具】栏中添加,所以选择【ToolsMenu】;
- 添加到组–操作:组中已有的菜单项,和定位标记一起来确定新创建的菜单的显示位置,这里选择【SmartSearchActoin】
- 添加到组-定位标记:插件在菜单组中相对于【添加到组—操作】中选择的菜单项的显示位置;
查看Action配置
上述操作完成后,相应配置会写到plugin.xml文件中。此示例中不需要修改任何配置,只是详细解析下,这样对插件运行原理可能更好理解,打开配置plugin.xml配置文件,可看到如下配置代码:
<actions><action id="first_id" class="com.com.korgs.demo.NoticeAction" text="气泡通知" description="我就是一个测试程序,没有实际功能
"><add-to-group group-id="ToolsMenu" anchor="first"/></action>
</actions>
上述配置非常简单,可以参考2.1节参考图片理解,不过多解释,需要注意的是id值为插件内全局唯一。表示添加此菜单到菜单栏【工具】的第一项。
编写Action代码
以上设置好后,在名为【FirstTest.java】类中添加如下代码实现:
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationDisplayType;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.MessageType;public class NoticeAction extends AnAction {@Overridepublic void actionPerformed(AnActionEvent e) {// TODO: insert action logic hereNotificationGroup notificationGroup = new NotificationGroup("testid", NotificationDisplayType.BALLOON, false);/*** content : 通知内容* type :通知的类型,warning,info,error*/Notification notification = notificationGroup.createNotification("测试通知", MessageType.INFO);Notifications.Bus.notify(notification);}
}
运行插件
编译,点击右侧Gradle图标,然后双击【Tasks - build - build】,因为要下载相应的依赖jar包,此处可能会执行十几分钟,第二次运行插件可跳过此步。
运行,点击右侧Gradle图标,然后双击【Tasks - intellij - runIde】,此处会重启一个新的idea窗口专门用于测试插件,支持调试。
测试,新开发的插件会自动安装在新打开的idea中,最好本地新建一个project专门用于插件测试。打开【工具】菜单栏,会看到一个名为【通知】的菜单,点击后会在右下角弹出一句提示,如下图所示:
查看插件运行日志
插件测试时,新打开的idea其实是一个运行沙箱环境中idea实例,沙箱目录会在运行runIde指令后自动生成,相应的插件运行日志也会记录在沙箱的相应文件中,文件位置为:
- Windows: P R O J E C T D I R E C T O R Y PROJECT_DIRECTORY PROJECTDIRECTORY/build/idea-sandbox
- Linux/macOS: P R O J E C T D I R E C T O R Y PROJECT_DIRECTORY PROJECTDIRECTORY/build/idea-sandbox
本地发布插件
本地发布插件
另一种测试方式就是本地打包,然后集成到开发的IDE中, 方法是使用gradle的buildPlugin指令先打包(.zip),然后会在/build/distributions/目录下生成一个.zip文件。
再从本地磁盘安装上述生成的.zip文件:
最后重启IDE,查看插件效果。
开发环境目录
开发IDE插件时需要经常调试和对比本地开发环境,比如查找环境配置、运行日志等,这就需要经常查看不同的文件和目录,以下是开发插件过程中可能会用到的本地开发环境目录(Mac os系统):
- 安装包方式安装的idea软件,则本地系统中主要目录结构如下:
- Configuration (idea.config.path):~/Library/Application Support/JetBrains/IntelliJIdea2022.2
- Plugins (idea.plugins.path):~/Library/Application Support/JetBrains/IntelliJIdea2022.2/plugins
- System (idea.system.path): ~/Library/Caches/JetBrains/IntelliJIdea2022.2
- Logs (idea.log.path): ~/Library/Logs/JetBrains/IntelliJIdea2022.2
- 通过Jetbrains Toolbox App安装的idea,则本地系统中主要目录结构如下:
- Configuration (idea.config.path): ~/Library/Application Support/JetBrains/IntelliJIdea2022.2
- Plugins (idea.plugins.path):~/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U
- System (idea.system.path):~/Library/Caches/JetBrains/IntelliJIdea2022.2
- Logs (idea.log.path):~/Library/Logs/JetBrains/IntelliJIdea2022.2
这篇关于着手开发属于自己的第一个Intellij-platform plugin插件程序(三)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!