1. 简介
近年来,JetBrains 推出的 IntelliJ IDEA 已迅速成为 Java 开发者的首选 IDE。根据最新的 Java 技术生态报告,有 61% 的开发者选择 IntelliJ,相比前一年的 55% 有显著增长。
让 IntelliJ 如此受欢迎的关键特性之一,就是 支持通过插件扩展功能或添加新能力。
本文将介绍如何使用当前官方推荐的 Gradle 方式开发一个 IntelliJ 插件,展示几种扩展 IDE 的常见手段。这篇文章是对之前一篇使用 Plugin Devkit 创建插件文章的升级重制版。
2. 插件的主要类型
常见的插件类型主要包括以下几类:
- ✅ 自定义语言支持:支持编写、解析和编译特定语言代码(如 Kotlin、Scala)
- ✅ 框架集成:对第三方框架提供深度支持(如 Spring、MyBatis)
- ✅ 工具集成:与外部工具联动(如 Maven、Gradle、Docker)
- ✅ UI 扩展:新增菜单项、工具窗口、状态栏组件等
⚠️ 实际开发中,一个插件往往同时属于多个类别。例如 IntelliJ 内置的 Git 插件,它不仅提供了独立的工具窗口和右键菜单,还深度集成到项目创建流程、设置界面等多个环节。
3. 创建插件项目
目前官方支持两种插件开发方式。本文采用新项目推荐的 Gradle 构建方式,而非传统的 Plugin Devkit。
使用 Gradle 创建插件项目非常简单,通过 IDE 的 New > Project
菜单即可完成:
⚠️ 创建时注意:
- 必须勾选 Java 和 IntelliJ Platform Plugin 模块
- 当前插件开发 仅支持 JDK 8,高版本 JDK 可能导致兼容性问题
4. 实战:Stack Overflow 快捷访问插件
我们来开发一个实用小插件:在 IDE 中快速访问 Stack Overflow。功能包括:
- ✅ 工具菜单中添加“提问”入口
- ✅ 在编辑器和控制台中通过右键菜单搜索选中文本
4.1 创建 Action
Action 是插件与用户交互的核心机制,可通过菜单、快捷键、工具栏等方式触发。
基础结构
所有自定义 Action 都需继承 AnAction
类。我们先创建打开提问页面的简单 Action:
public class AskQuestionAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
BrowserUtil.browse("https://stackoverflow.com/questions/ask");
}
}
这里使用了 SDK 提供的 BrowserUtil
,它能跨平台兼容地打开浏览器,省去了手动处理不同 OS 的麻烦。
高级功能:智能搜索
搜索功能需要两个参数:
- 当前文件的编程语言(作为搜索标签)
- 用户选中的文本内容
获取语言标签(Language Tag)
通过 PSI(Program Structure Interface)API 获取当前文件的语言信息:
Optional<PsiFile> psiFile = Optional.ofNullable(e.getData(LangDataKeys.PSI_FILE));
String languageTag = psiFile.map(PsiFile::getLanguage)
.map(Language::getDisplayName)
.map(String::toLowerCase)
.map(lang -> "[" + lang + "]")
.orElse("");
PSI 是 IntelliJ 的核心解析引擎,能将代码文件转换为可编程操作的语法树。
获取选中文本
使用 Editor API 获取高亮内容:
Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
CaretModel caretModel = editor.getCaretModel();
String selectedText = caretModel.getCurrentCaret().getSelectedText();
这个方法在编辑器和控制台中都适用,API 设计很统一。
完整搜索 Action
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Optional<PsiFile> psiFile = Optional.ofNullable(e.getData(LangDataKeys.PSI_FILE));
String languageTag = psiFile.map(PsiFile::getLanguage)
.map(Language::getDisplayName)
.map(String::toLowerCase)
.map(lang -> "[" + lang + "]")
.orElse("");
Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
CaretModel caretModel = editor.getCaretModel();
String selectedText = caretModel.getCurrentCaret().getSelectedText();
BrowserUtil.browse("https://stackoverflow.com/search?q=" + languageTag + selectedText);
}
状态控制:动态启用/禁用
重写 update
方法实现智能状态管理:
@Override
public void update(@NotNull AnActionEvent e) {
Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
CaretModel caretModel = editor.getCaretModel();
e.getPresentation().setEnabledAndVisible(caretModel.getCurrentCaret().hasSelection());
}
这样当没有选中文本时,右键菜单项会自动变灰,用户体验更自然。
4.2 注册 Action
创建完 Action 后,需要将其注册到 IDE 中。
方式一:通过 plugin.xml(推荐)
在 src/main/resources/META-INF/plugin.xml
中配置:
<actions>
<action
id="StackOverflow.AskQuestion.ToolsMenu"
class="com.baeldung.intellij.stackoverflowplugin.AskQuestionAction"
text="Ask Question on Stack Overflow"
description="Ask a Question on Stack Overflow">
<add-to-group group-id="ToolsMenu" anchor="last"/>
</action>
<action
id="StackOverflow.Search.Editor"
class="com.baeldung.intellij.stackoverflowplugin.SearchAction"
text="Search on Stack Overflow"
description="Search on Stack Overflow">
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
</action>
<action
id="StackOverflow.Search.Console"
class="com.baeldung.intellij.stackoverflowplugin.SearchAction"
text="Search on Stack Overflow"
description="Search on Stack Overflow">
<add-to-group group-id="ConsoleEditorPopupMenu" anchor="last"/>
</action>
</actions>
✅ 优点:启动时自动注册,配置集中
✅ 支持多位置复用同一 Action(如编辑器和控制台)
方式二:编程式注册
ActionManager.getInstance().registerAction("StackOverflow.SearchAction", new SearchAction());
⚠️ 适用场景:
- 需要动态注册(如根据远程 API 版本加载不同功能)
- 插件功能按需加载
❌ 缺点:需额外实现 ApplicationComponent
管理生命周期,复杂度较高
5. 插件测试
插件开发同样需要测试保障质量。
手动测试(推荐)
执行 Gradle 的 runIde
任务:
会启动一个沙盒环境的 IntelliJ 实例,可直接验证功能。
单元测试
IntelliJ SDK 提供了无头测试环境,支持使用 JUnit 等框架编写集成测试,且能调用真实的 IDE 组件,无需 mock。
6. 插件发布
Gradle 插件提供了便捷的打包命令:
./gradlew buildPlugin
执行后会在 build/distributions
目录生成 ZIP 包,包含:
- 编译后的 class 文件
- 资源文件
- plugin.xml 配置
发布方式:
- ✅ 本地安装:通过 IDE 的
Install Plugin from Disk
- ✅ 公开发布:上传至 JetBrains 插件仓库
最终效果展示:
7. 总结
本文通过一个实用的 Stack Overflow 插件,演示了 IntelliJ 插件开发的核心流程。
虽然我们主要聚焦在 Action 的使用上,但 IntelliJ Plugin SDK 还提供了丰富的扩展点,如:
- 自定义文件类型
- 代码检查(Inspection)
- 模板引擎(Live Templates)
- VCS 集成
想深入学习?建议直接阅读官方 入门指南。
完整代码已托管至 GitHub:https://github.com/eugenp/tutorials/tree/master/intelliJ-modules