IntelliJ IDEA 插件开发指南,编写你的第一个IDEA插件
IntelliJ IDEA 插件开发指南
本文面向第一次写 IDEA 插件的开发者,目标是:看完就能创建一个能运行的插件,并知道常见功能怎么做、去哪查文档、怎么打包发布。
记得点赞加收藏哦😁😁😁
1. 基础认知
1.1 IDEA 插件能做什么
IntelliJ 平台的插件本质上是对 IDE 功能的扩展,比如:
- 新增菜单 / 工具栏 / 右键动作(Action)
- 新增工具窗口(Tool Window)
- 自定义代码检查、意图动作(Inspection / Intention)
- 代码生成、代码补全、重构扩展
- 自定义语言支持(语法高亮、Parser、Completion)
- 和外部系统联动(HTTP、数据库、Git、Issue Tracker)
- UI 增强、编辑器增强
1.2 IDEA 插件的运行环境
- 插件是跑在 JetBrains 平台之上的,目标平台叫 IntelliJ Platform。
- 你写的插件可以运行在 IDEA、PyCharm、WebStorm 等基于同一平台的 IDE 中(取决于你依赖的模块)。
- 插件的入口和声明主要在
plugin.xml中。
1.3 必备工具
- JDK 17+(2024 起平台主推 17,具体看你目标版本)
- IntelliJ IDEA(推荐 Ultimate,但 Community 也行)
- Gradle(推荐官方 Gradle 模板)
- IntelliJ Platform SDK 文档:https://plugins.jetbrains.com/docs/intellij
2. 创建项目
2.1 使用 IntelliJ 新建插件项目(最简单)
- 打开 IDEA → New Project
- 左侧选择 IntelliJ Platform Plugin
- 选择构建系统:Gradle (Kotlin DSL) 或 Gradle (Groovy),推荐 Kotlin DSL
- 填写 Group / Artifact / Version
- Finish 后会生成一个基础插件项目
生成的项目结构大致如下:
my-plugin/
├── build.gradle.kts # Gradle 构建脚本
├── gradle.properties
├── settings.gradle.kts
├── src/main/java or kotlin
│ └── ... # 你的代码
└── src/main/resources└── META-INF└── plugin.xml # 插件描述文件
2.2 使用官方 Gradle 插件模板
JetBrains 官方有个模板项目,功能更全:
- GitHub: https://github.com/JetBrains/intellij-platform-plugin-template
- 特点:已经配好 CI、依赖管理、自动打包、签名等
- 做法:直接点 “Use this template” 生成你自己的仓库,clone 下来改名即可
3. 构建系统与配置
3.1 build.gradle.kts 示例
plugins {id("java")id("org.jetbrains.intellij") version "1.17.4"
}group = "com.example"
version = "1.0.0"repositories {mavenCentral()
}intellij {// 目标 IDE 版本,决定你能用哪些 APIversion.set("2024.1")// 需要的插件依赖,比如要写 kotlin 相关的plugins.set(listOf("com.intellij.java"))
}tasks {patchPluginXml {sinceBuild.set("241")untilBuild.set("251.*")}// 启动 IDE 测试插件runIde {// 可选:指定 JVM 参数}
}
要点:
org.jetbrains.intellij是官方的 Gradle 插件,帮你下载 IDE、打包、跑 IDE。intellij.version决定你开发时使用哪个版本的平台。patchPluginXml可以在构建时动态修改plugin.xml的版本范围。
3.2 Gradle 常用任务
./gradlew build:构建./gradlew runIde:下载一个沙箱 IDE 并运行,自动加载你的插件./gradlew verifyPlugin:检查插件./gradlew publishPlugin:发布到 JetBrains Marketplace(需要配置 Token)
4. plugin.xml 详解
plugin.xml 是插件的“身份证”,位置在:src/main/resources/META-INF/plugin.xml。
4.1 最小示例
<idea-plugin><id>com.example.demo</id><name>Demo Plugin</name><version>1.0.0</version><vendor email="you@example.com" url="https://example.com">Your Name</vendor><!-- 插件依赖的模块,比如要用到编辑器、Java 功能 --><depends>com.intellij.modules.platform</depends><!-- 声明扩展点、Action、服务等 -->
</idea-plugin>
4.2 常见标签说明
<id>:唯一 ID,发布后不能随便改<name>:展示用名字<version>:插件版本<vendor>:作者信息<description>:可写 HTML,显示在 Marketplace<depends>:依赖的模块/插件,例如:com.intellij.modules.platform:基础平台com.intellij.modules.java:要使用 Java 的功能- 写错或缺失会导致运行时报错
4.3 注册 Action 示例
<actions><action id="com.example.demo.MyAction"class="com.example.demo.MyAction"text="Say Hello"description="Say hello from plugin"><!-- 将动作放到菜单/工具栏 --><add-to-group group-id="ToolsMenu" anchor="last"/></action>
</actions>
5. 编写第一个 Action
5.1 创建类
package com.example.demo;import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.NotNull;public class MyAction extends AnAction {@Overridepublic void actionPerformed(@NotNull AnActionEvent e) {Messages.showInfoMessage("Hello from plugin!", "My Plugin");}
}
5.2 绑定到 plugin.xml
见上文 <actions> 部分。运行 ./gradlew runIde,打开菜单 Tools → Say Hello,就能看到弹窗。
6. 获取项目、编辑器、文件信息
在插件里,很多功能都从 AnActionEvent 或服务中获取当前上下文。
@Override
public void actionPerformed(@NotNull AnActionEvent e) {var project = e.getProject(); // 当前项目var editor = e.getData(com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR);var psiFile = e.getData(com.intellij.openapi.actionSystem.CommonDataKeys.PSI_FILE);
}
常见数据 Key:
PROJECTEDITORVIRTUAL_FILEPSI_FILENAVIGATABLE
7. PSI & VFS 简介(做代码类功能必读)
7.1 VFS(Virtual File System)
- IDE 抽象的一层文件系统
- 类似
VirtualFile,能读写、监听、刷新 - 用于操作实际文件
7.2 PSI(Program Structure Interface)
- 源代码的语法树表示
- 用于做:代码分析、快速修复、导航、重构
- 不同语言有不同的 PSI 结构
- 获取 PSI 的最简单方式是通过
PsiFile和PsiElement
示例:遍历当前文件的所有子元素
PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
psiFile.accept(new PsiRecursiveElementVisitor() {@Overridepublic void visitElement(@NotNull PsiElement element) {super.visitElement(element);// 在这里处理 element}
});
8. UI 与工具窗口(Tool Window)
8.1 注册工具窗口
在 plugin.xml 中:
<toolWindow id="MyToolWindow"anchor="right"factoryClass="com.example.demo.MyToolWindowFactory"icon="/icons/toolWindow.svg"/>
8.2 编写工厂类
public class MyToolWindowFactory implements com.intellij.openapi.wm.ToolWindowFactory {@Overridepublic void createToolWindowContent(@NotNull Project project,@NotNull ToolWindow toolWindow) {// Swing UIJPanel panel = new JPanel(new BorderLayout());panel.add(new JLabel("Hello Tool Window"), BorderLayout.CENTER);ContentFactory contentFactory = ContentFactory.getInstance();Content content = contentFactory.createContent(panel, "", false);toolWindow.getContentManager().addContent(content);}
}
要点:
- IDEA UI 还是基于 Swing
- 可以用 JB 系列组件(JBPanel、JBLabel)适配主题
- 图标建议用 SVG,放在
resources/icons/下
9. 项目服务与组件
9.1 服务类型
- Application Service:IDE 全局单例
- Project Service:每个项目一个实例
9.2 注册服务(新版推荐服务而不是组件)
plugin.xml:
<applicationService serviceImplementation="com.example.demo.AppService"/>
<projectService serviceImplementation="com.example.demo.ProjectService"/>
Java:
public class AppService {public AppService() {System.out.println("AppService init");}
}
使用:
AppService service = ApplicationManager.getApplication().getService(AppService.class);
10. 动作可用性控制(Update)
有些 Action 只在特定场景下可用,比如只有选中 Java 文件时。
@Override
public void update(@NotNull AnActionEvent e) {PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);boolean visible = psiFile != null && psiFile.getName().endsWith(".java");e.getPresentation().setEnabledAndVisible(visible);
}
11. 运行与调试
11.1 runIde
最常用调试方式:./gradlew runIde
它会:
- 下载一个沙箱 IntelliJ
- 把你的插件装进去
- 启动一个独立的 IDE,不影响你本机的正式 IDE
11.2 调试技巧
- 可以直接打断点
- 可以用
logger打日志(见下一节) - 可以在沙箱里安装其他插件辅助调试
12. 日志与诊断
12.1 使用 IntelliJ Logger
import com.intellij.openapi.diagnostic.Logger;public class MyAction extends AnAction {private static final Logger LOG = Logger.getInstance(MyAction.class);@Overridepublic void actionPerformed(@NotNull AnActionEvent e) {LOG.info("MyAction triggered");LOG.warn("Something is not perfect");}
}
12.2 日志位置
沙箱 IDE 的日志一般在:
- macOS:
~/Library/Logs/JetBrains/IDEA.../idea.log - Windows:
C:\Users\<User>\.cache\JetBrains\IDEA...\log\idea.log - 也可以在 IDE 中:Help → Show Log in…
13. 国际化(i18n)
如果插件要支持多语言,可以在 resources 中放 messages/MyBundle.properties:
hello.message=你好,{0}!
Java 调用:
public class MyBundle {private static final String BUNDLE = "messages.MyBundle";private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE);public static String message(String key, Object... params) {return MessageFormat.format(RESOURCE_BUNDLE.getString(key), params);}
}
在 UI 里用时:
Messages.showInfoMessage(MyBundle.message("hello.message", "张三"), "Title");
14. 动态加载与兼容性
14.1 sinceBuild / untilBuild
在 plugin.xml 中限制插件能在哪些 IDE 版本中安装:
<idea-plugin><id>com.example.demo</id>...<idea-version since-build="241" until-build="251.*"/>
</idea-plugin>
241表示 2024.1- 不写
until-build可以适配未来版本,但要注意 API 兼容性
14.2 可选依赖
如果你的插件要“兼容安装了另外一个插件的情况”,可以用:
<depends optional="true" config-file="optional-config.xml">com.intellij.java</depends>
15. 打包发布
15.1 本地打包
执行:
./gradlew buildPlugin
会在 build/distributions/ 下生成一个 .zip,就是插件包。
15.2 手动安装
- 打开目标 IDE
- Settings → Plugins → ⚙ → Install Plugin from Disk…
- 选择刚才的 zip
- 重启
15.3 发布到 Marketplace
- 注册 JetBrains 账号
- https://plugins.jetbrains.com 里新建插件
- 填写插件 ID 必须和
plugin.xml一致 - 上传 zip
- 等待审核
也可以在 Gradle 里配置 publishPlugin {} 自动上传。
16. 常见功能示例思路
16.1 读取当前编辑器文本
Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
Document document = editor.getDocument();
String text = document.getText();
16.2 修改文件(必须写在 Write Command 中)
WriteCommandAction.runWriteCommandAction(project, () -> {document.insertString(0, "Hello");
});
16.3 弹出输入框
String value = Messages.showInputDialog(project, "请输入内容", "标题", Messages.getQuestionIcon());
16.4 显示通知
NotificationGroupManager.getInstance().getNotificationGroup("My Notification Group").createNotification("任务完成", NotificationType.INFORMATION).notify(project);
需要在 plugin.xml 声明 Notification Group,或者用新的 API。
17. 调试常见问题
-
插件加载失败,ClassNotFound
- 检查
plugin.xml的类名是否填写全限定名 - 检查打包时是否漏了资源
- 检查
-
插件版本不兼容
- 检查
<idea-version>和 Gradle 的intellij.version是否一致 - 检查是否引用了当前 IDE 没有的 API
- 检查
-
图标不显示
- 检查路径是否以
/开头 - 检查是否为 SVG
- 放到
resources/icons/下最安全
- 检查路径是否以
-
修改代码后 runIde 仍然是旧版
- 重新跑
./gradlew runIde - 清理
build/ - 检查是否是沙箱配置问题
- 重新跑
18. 学习资料
- 官方文档(最全):https://plugins.jetbrains.com/docs/intellij
- 官方示例仓库:https://github.com/JetBrains/intellij-sdk-code-samples
- Gradle 插件文档:https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html
- JetBrains 平台 API 源码:在 IDE 里直接 Ctrl+B 进源码看
19. 编写建议
- 优先用官方示例,少自己造轮子
- 插件要注意性能,不要在 UI 线程做耗时操作,要用
BackgroundTask - 尽量支持 Darcula / 新 UI,使用 JB 组件
- 写好日志,方便用户反馈问题
- 发布前跑一次
verifyPlugin
祝你写出第一个能跑的 IDEA 插件 🎉
