文章目录
开发流程
下面是一个完整的 IntelliJ IDEA 插件开发流程,从环境搭建到发布,逐步讲解:
一、开发环境准备
-
安装 IntelliJ IDEA
- 推荐使用最新版本的 IntelliJ IDEA Ultimate(社区版也能开发插件,但某些功能受限)。
- 下载地址:https://www.jetbrains.com/idea/
-
安装 JDK
- 需要 JDK 11 或更高版本(推荐 JDK 17)。
- 确保环境变量配置正确。
-
配置 IntelliJ Plugin SDK
- 打开 IDEA,进入
File -> Project Structure -> SDKs。 - 添加 IntelliJ Platform Plugin SDK,选择 IDEA 安装目录(会自动检测所需依赖)。
- 打开 IDEA,进入
二、创建插件项目
-
新建项目
- 选择 File -> New -> Project。
- 项目类型选择 IntelliJ Platform Plugin。
- 模板可选 Gradle(推荐)或 DevKit(旧版)。
- Gradle 更灵活,支持依赖管理,适合复杂插件。
- DevKit 适合简单插件,但已逐渐被弃用。
-
配置项目基本信息
- 填写
GroupId(如com.yourcompany)、ArtifactId(插件名称)、版本号等。 - 确保选择正确的 JDK 和 IntelliJ Platform SDK。
- 填写
-
项目结构
- 生成的项目包含以下关键文件:
src/main/java: Java/Kotlin 代码目录。resources/META-INF/plugin.xml: 插件的核心配置文件。build.gradle.kts(或build.gradle): Gradle 构建脚本。
- 生成的项目包含以下关键文件:
三、插件核心配置(plugin.xml)
在 plugin.xml 中定义插件元数据和功能扩展点:
<idea-plugin>
<id>com.yourcompany.plugin-name</id>
<name>Your Plugin Name</name>
<version>1.0.0</version>
<vendor email="support@yourcompany.com" url="https://yourcompany.com">Your Company</vendor>
<description><![CDATA[
插件功能描述,支持 HTML 格式。
]]></description>
<!-- 依赖的插件(可选) -->
<depends>com.intellij.modules.platform</depends>
<!-- 扩展点定义 -->
<extensions defaultExtensionNs="com.intellij">
<!-- 例如注册工具窗口 -->
<toolWindow id="MyToolWindow" anchor="right" factoryClass="com.yourcompany.MyToolWindowFactory"/>
</extensions>
<!-- 注册动作(Action) -->
<actions>
<action id="YourAction" class="com.yourcompany.YourAction" text="Action Text" description="Action Description">
<add-to-group group-id="ToolsMenu" anchor="first"/>
</action>
</actions>
</idea-plugin>
四、编写插件功能
1. 实现 Action(动作)
Action 是插件的入口点,例如菜单项、工具栏按钮等。
public class MyAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
// 点击动作后的逻辑
Project project = e.getProject();
Messages.showMessageDialog(project, "Hello World!", "Greeting", Messages.getInformationIcon());
}
}
2. 使用扩展点(Extensions)
- 工具窗口(ToolWindow): 创建自定义界面。
- 编辑器监听(EditorListener): 监听编辑器事件。
- 代码分析(Inspection): 自定义代码检查规则。
- 文件类型(FileType): 支持新文件类型。
3. 界面开发
- 使用 Swing 或 IntelliJ 的 UI Designer 创建界面。
- 推荐使用 Kotlin UI DSL(JetBrains 官方推荐)构建现代化界面。
五、调试与运行
-
运行插件
- 点击 Gradle 任务的
runIde,会启动一个沙盒 IDEA 实例,插件已自动加载。 - 在沙盒中测试插件功能。
- 点击 Gradle 任务的
-
调试
- 在代码中设置断点,直接以 Debug 模式运行
runIde。 - 支持热重载(修改代码后无需重启沙盒)。
- 在代码中设置断点,直接以 Debug 模式运行
六、打包与发布
1. 生成 JAR 包
- 执行 Gradle 任务
buildPlugin,生成的 JAR 文件在build/libs目录。 - 插件 JAR 包含所有依赖(如果配置了
shadowJar)。
2. 发布到 JetBrains 插件市场
- 访问 JetBrains Plugins Repository。
- 注册账号并上传 JAR 文件,填写插件描述、截图等信息。
- 审核通过后,用户可通过 IDEA 内置插件市场安装。
3. 本地安装
- 用户可将 JAR 文件拖入 IDEA 窗口,或通过
File -> Settings -> Plugins -> Install Plugin from Disk安装。
七、核心概念与 API
-
PSI(Program Structure Interface)
- 用于操作代码的抽象语法树(AST),例如解析、修改 Java/Kotlin 代码。
-
AnAction
- 定义用户触发的动作(如菜单项、快捷键)。
-
Services
- 插件可以通过
Service实现单例管理或全局状态。
- 插件可以通过
-
PersistentState
- 使用
PersistentStateComponent保存插件配置。
- 使用
八、注意事项
-
兼容性
- 在
build.gradle中指定兼容的 IDEA 版本:intellij { version = '2023.1' // 指定 IDEA 版本 type = 'IC' // 社区版,'IU' 为 Ultimate 版 }
- 在
-
依赖管理
- 通过 Gradle 添加第三方库依赖:
dependencies { implementation 'com.squareup.okhttp3:okhttp:4.9.3' }
- 通过 Gradle 添加第三方库依赖:
-
性能优化
- 避免阻塞 UI 线程,长时间任务需在后台线程执行。
-
文档与社区
九、常见问题
- 插件无法加载: 检查
plugin.xml配置和依赖。 - API 过时: 使用最新版本的 IntelliJ SDK。
- UI 卡顿: 确保耗时操作在后台线程执行。
按照这个流程,你可以从零开始开发一个功能完整的 IntelliJ 插件。如果有具体需求(如代码分析、自定义语言支持等),可以进一步深入相关 API!
核心语法
以下是 IntelliJ IDEA 插件开发的核心语法和关键 API 详解,结合代码示例和关键概念,帮助你快速上手:
1. 动作(Action)
Action 是用户触发操作的核心入口(如菜单项、快捷键、工具栏按钮)。
定义 Action
public class MyAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
// 获取当前项目
Project project = e.getProject();
// 显示对话框
Messages.showMessageDialog(project, "Hello Plugin!", "Greeting", Messages.getInformationIcon());
}
@Override
public void update(@NotNull AnActionEvent e) {
// 动态控制 Action 是否可见/启用
Project project = e.getProject();
e.getPresentation().setEnabledAndVisible(project != null);
}
}
注册 Action(plugin.xml)
<actions>
<action
id="MyPlugin.MyAction"
class="com.example.MyAction"
text="Say Hello"
description="Show a greeting message">
<!-- 添加到菜单 -->
<add-to-group group-id="ToolsMenu" anchor="first"/>
<!-- 绑定快捷键 -->
<keyboard-shortcut keymap="$default" first-keystroke="ctrl shift H"/>
</action>
</actions>
2. 扩展点(Extensions)
通过 plugin.xml 扩展 IDEA 的核心功能(如工具窗口、编辑器监听等)。
工具窗口(ToolWindow)
public class MyToolWindowFactory implements ToolWindowFactory {
@Override
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
// 创建界面组件
JPanel panel = new JPanel();
panel.add(new JLabel("My Tool Window"));
// 将组件添加到工具窗口
ContentFactory contentFactory = ContentFactory.getInstance();
Content content = contentFactory.createContent(panel, "", false);
toolWindow.getContentManager().addContent(content);
}
}
注册工具窗口(plugin.xml):
<extensions defaultExtensionNs="com.intellij">
<toolWindow
id="MyToolWindow"
anchor="right"
factoryClass="com.example.MyToolWindowFactory"/>
</extensions>
3. PSI(Program Structure Interface)
用于操作代码的抽象语法树(AST),支持代码解析和修改。
获取当前文件的 PSI
public void actionPerformed(@NotNull AnActionEvent e) {
Editor editor = e.getData(CommonDataKeys.EDITOR);
PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
if (editor == null || psiFile == null) return;
// 获取当前光标位置元素
int offset = editor.getCaretModel().getOffset();
PsiElement element = psiFile.findElementAt(offset);
}
修改代码
// 在写操作中修改 PSI
WriteCommandAction.runWriteCommandAction(project, () -> {
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
PsiMethod method = factory.createMethodFromText("public void test() {}", null);
// 将方法添加到类中
PsiClass psiClass = ...; // 获取目标类
psiClass.add(method);
});
4. 服务(Services)
用于管理插件全局状态或单例服务。
定义服务
public interface MyService {
void doSomething();
}
// 实现类
@Service
public final class MyServiceImpl implements MyService {
@Override
public void doSomething() {
// 具体逻辑
}
}
使用服务
MyService service = project.getService(MyService.class);
service.doSomething();
5. 持久化状态(PersistentState)
保存插件配置到 IDE 的配置文件。
定义状态类
@State(name = "MyPluginSettings", storages = @Storage("myplugin.xml"))
public class MySettings implements PersistentStateComponent<MySettings.State> {
public static class State {
public String username = "default";
public boolean enabled = true;
}
private State state = new State();
@Override
public State getState() {
return state;
}
@Override
public void loadState(@NotNull State state) {
this.state = state;
}
}
使用配置
MySettings settings = ServiceManager.getService(MySettings.class);
String username = settings.getState().username;
settings.getState().enabled = false;
6. 界面开发
Swing 组件
JPanel panel = new JPanel(new BorderLayout());
JButton button = new JButton("Click Me");
button.addActionListener(e -> {
// 按钮点击事件
});
panel.add(button, BorderLayout.CENTER);
Kotlin UI DSL(推荐)
// 在 Kotlin 中使用
panel {
row {
button("Click Me") {
// 点击事件
}
checkBox("Enable Feature")
}
}
7. 监听编辑器事件
public class MyEditorListener implements EditorFactoryListener {
@Override
public void editorCreated(@NotNull EditorFactoryEvent event) {
Editor editor = event.getEditor();
Document document = editor.getDocument();
// 监听文档变化
document.addDocumentListener(new DocumentListener() {
@Override
public void documentChanged(@NotNull DocumentEvent event) {
// 处理变化
}
});
}
}
注册监听器(plugin.xml):
<applicationListeners>
<listener
class="com.example.MyEditorListener"
topic="com.intellij.openapi.editor.event.EditorFactoryListener"/>
</applicationListeners>
8. 代码检查与快速修复
自定义检查器
public class MyInspection extends AbstractBaseJavaLocalInspectionTool {
@Override
public @NotNull PsiElementVisitor buildVisitor(
@NotNull ProblemsHolder holder,
boolean isOnTheFly
) {
return new JavaElementVisitor() {
@Override
public void visitMethod(PsiMethod method) {
if (method.getName().startsWith("test")) {
holder.registerProblem(
method.getNameIdentifier(),
"方法名不应以 'test' 开头",
ProblemHighlightType.WARNING
);
}
}
};
}
}
快速修复(QuickFix)
public class RenameMethodFix implements LocalQuickFix {
@Override
public @NotNull String getFamilyName() {
return "重命名方法";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiMethod method = (PsiMethod) descriptor.getPsiElement();
method.setName("newName");
}
}
9. 异步任务
避免阻塞 UI 线程,使用 ApplicationManager.getApplication().executeOnPooledThread() 或 AsyncTask。
ApplicationManager.getApplication().executeOnPooledThread(() -> {
// 后台任务
String result = doHeavyWork();
// 更新 UI(需切回 UI 线程)
ApplicationManager.getApplication().invokeLater(() -> {
Messages.showInfoMessage(result, "Result");
});
});
10. 通知与对话框
显示通知
NotificationGroupManager.getInstance()
.getNotificationGroup("MyPlugin")
.createNotification("任务完成", NotificationType.INFORMATION)
.notify(project);
自定义对话框
public class MyDialog extends DialogWrapper {
private JTextField textField;
protected MyDialog(Project project) {
super(project);
init();
setTitle("输入对话框");
}
@Override
protected JComponent createCenterPanel() {
JPanel panel = new JPanel(new BorderLayout());
textField = new JTextField();
panel.add(textField, BorderLayout.CENTER);
return panel;
}
public String getInput() {
return textField.getText();
}
}
总结
- 核心 API:
AnAction,ToolWindow,PSI,Services,PersistentStateComponent - 线程安全:UI 操作必须在主线程,耗时操作需异步执行
- 版本兼容:通过
build.gradle指定兼容的 IDEA 版本 - 官方文档:IntelliJ Platform SDK Docs
通过掌握这些核心语法和 API,你可以实现从简单的工具插件到复杂的代码分析功能。建议结合官方示例代码实践调试!
4526

被折叠的 条评论
为什么被折叠?



