1. 简介
近年来,JetBrains 推出的 IntelliJ IDEA 已迅速成为 Java 开发者的首选 IDE。根据我们最近发布的《Java 技术生态报告》,有 55% 的开发者选择 IntelliJ,相比前一年的 48% 有明显增长。
IntelliJ 深受开发者喜爱的一个关键原因,是它支持通过插件机制扩展功能。本文将带你从零开始编写一个 IntelliJ 插件,展示几种常见的 IDE 扩展方式。
⚠️ 需要说明的是,虽然本文聚焦于 IntelliJ 插件开发,但由于 JetBrains 全家桶(如 PyCharm、RubyMine 等)共享底层代码库,文中大部分技术方案同样适用于其他 JetBrains 产品。
2. 插件功能分类
IntelliJ 插件的功能通常可以划分为以下四类:
- ✅ 自定义语言支持:支持新编程语言的编写、解析与编译
- ✅ 框架集成:对第三方框架(如 Spring)提供深度支持
- ✅ 工具整合:与外部工具(如 Gradle、Maven)无缝对接
- ✅ UI 增强:新增菜单项、工具窗口、按钮等交互元素
⚠️ 实际开发中,一个插件往往横跨多个类别。例如 IntelliJ 内置的 Git 插件,它不仅提供了独立的工具窗口和右键菜单,还深度集成到了项目创建流程、设置面板等多个环节。
3. 创建插件项目
最简单的入门方式是使用 JetBrains 官方提供的 Plugin DevKit。在 IDE 中通过 New > Project 即可创建:
⚠️ 必须使用 JetBrains 提供的 JDK,以确保插件所需的类能正确加载。IntelliJ 通常自带兼容的 JDK,若没有可参考 官方文档 配置。
📌 当前(撰写时)插件开发仅支持 Java 8。原因是 JetBrains 尚未发布对 Java 9+ 的官方 JDK 支持,强行升级可能导致兼容性问题。
4. 实战示例:Stack Overflow 快捷插件
我们来开发一个实用小插件:在 IDE 多个位置快速访问 Stack Overflow。功能包括:
- ✅ 工具菜单中添加“提问”入口
- ✅ 编辑器和控制台右键菜单支持选中文本搜索
4.1 编写 Action
Action 是插件开发的核心组件,用于响应菜单点击、快捷键等 UI 事件。
我们需要创建两个 Action 类,均继承自 AnAction
。
AskQuestionAction:打开提问页面
public class AskQuestionAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
BrowserUtil.browse("https://stackoverflow.com/questions/ask");
}
}
✅ 使用内置 BrowserUtil
可自动处理跨平台浏览器调用,简单粗暴有效。
SearchAction:搜索选中文本
这个 Action 稍复杂,需获取两个参数:
- 语言标签:通过 PSI(Program Structure Interface)获取当前文件语言
- 搜索文本:从编辑器选区获取高亮内容
PSI 是 IntelliJ 的核心 API,能解析项目文件并提供结构化访问。例如:
PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
Language lang = e.getData(CommonDataKeys.PSI_FILE).getLanguage();
String languageTag = "+[" + lang.getDisplayName().toLowerCase() + "]";
💡 PSI 还能做更高级的事,比如提取 Java 类中的所有 public 方法。
获取选中文本则通过 Editor API:
final Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
CaretModel caretModel = editor.getCaretModel();
String selectedText = caretModel.getCurrentCaret().getSelectedText();
最终组合查询并打开:
@Override
public void actionPerformed(AnActionEvent e) {
PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
Language lang = e.getData(CommonDataKeys.PSI_FILE).getLanguage();
String languageTag = "+[" + lang.getDisplayName().toLowerCase() + "]";
Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
CaretModel caretModel = editor.getCaretModel();
String selectedText = caretModel.getCurrentCaret().getSelectedText();
String query = selectedText.replace(' ', '+') + languageTag;
BrowserUtil.browse("https://stackoverflow.com/search?q=" + query);
}
⚠️ 别忘了重写 update
方法,动态控制菜单项可用状态:
@Override
public void update(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 配置(推荐)
项目自动生成的 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>
✅ 优点:启动时自动注册,无需额外编码。
方式二:编程式注册
使用 ActionManager
动态注册:
ActionManager.getInstance().registerAction("StackOverflow.SearchAction", new SearchAction());
✅ 优势:支持运行时动态注册,适合对接远程 API 版本差异等场景。
❌ 缺点:需配合 ApplicationComponent
实现,配置更复杂,且不支持启动时加载。
5. 插件测试
任何代码都需要测试,插件也不例外。
手动测试(推荐小项目)
使用 Plugin 运行配置 启动沙盒实例:
新打开的 IntelliJ 实例会加载你的插件,可直接点击菜单验证功能。
单元测试
如需自动化测试,IntelliJ 提供了无头测试环境,支持 JUnit 等主流框架,且能使用真实 IDE 组件(无需 Mock)。
6. 打包与发布
Plugin DevKit 提供了一键打包功能:
右键项目 → “Prepare plugin module for Deployment” → 生成 JAR 包。
该 JAR 包包含所有代码和配置,可用于:
- ✅ 本地安装测试
- ✅ 发布到 JetBrains 插件仓库 供他人使用
效果预览:
7. 总结
本文通过一个简单的 Stack Overflow 快捷插件,演示了 IntelliJ 插件开发的基本流程。
虽然我们主要使用了 Action 机制,但 SDK 还提供了 PSI、Custom Language、ToolWindow 等更多扩展点。想深入学习可查阅 官方入门指南。
📌 示例代码已托管至 GitHub:https://github.com/eugenp/tutorials/tree/master/intelliJ-modules