下面是一个完整的 IntelliJ IDEA 插件开发流程,从环境搭建到发布,逐步讲解:
安装 IntelliJ IDEA
安装 JDK
配置 IntelliJ Plugin SDK
File -> Project Structure -> SDKs
。新建项目
配置项目基本信息
GroupId
(如 com.yourcompany
)、ArtifactId
(插件名称)、版本号等。项目结构
src/main/java
: Java/Kotlin 代码目录。resources/META-INF/plugin.xml
: 插件的核心配置文件。build.gradle.kts
(或 build.gradle
): Gradle 构建脚本。在 plugin.xml
中定义插件元数据和功能扩展点:
<idea-plugin>
<id>com.yourcompany.plugin-nameid>
<name>Your Plugin Namename>
<version>1.0.0version>
<vendor email="[email protected]" url="https://yourcompany.com">Your Companyvendor>
<description>description>
<depends>com.intellij.modules.platformdepends>
<extensions defaultExtensionNs="com.intellij">
<toolWindow id="MyToolWindow" anchor="right" factoryClass="com.yourcompany.MyToolWindowFactory"/>
extensions>
<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>
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());
}
}
运行插件
runIde
,会启动一个沙盒 IDEA 实例,插件已自动加载。调试
runIde
。buildPlugin
,生成的 JAR 文件在 build/libs
目录。shadowJar
)。File -> Settings -> Plugins -> Install Plugin from Disk
安装。PSI(Program Structure Interface)
AnAction
Services
Service
实现单例管理或全局状态。PersistentState
PersistentStateComponent
保存插件配置。兼容性
build.gradle
中指定兼容的 IDEA 版本:intellij {
version = '2023.1' // 指定 IDEA 版本
type = 'IC' // 社区版,'IU' 为 Ultimate 版
}
依赖管理
dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
}
性能优化
文档与社区
plugin.xml
配置和依赖。按照这个流程,你可以从零开始开发一个功能完整的 IntelliJ 插件。如果有具体需求(如代码分析、自定义语言支持等),可以进一步深入相关 API!
以下是 IntelliJ IDEA 插件开发的核心语法和关键 API 详解,结合代码示例和关键概念,帮助你快速上手:
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);
}
}
<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>
通过 plugin.xml
扩展 IDEA 的核心功能(如工具窗口、编辑器监听等)。
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>
用于操作代码的抽象语法树(AST),支持代码解析和修改。
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);
});
用于管理插件全局状态或单例服务。
public interface MyService {
void doSomething();
}
// 实现类
@Service
public final class MyServiceImpl implements MyService {
@Override
public void doSomething() {
// 具体逻辑
}
}
MyService service = project.getService(MyService.class);
service.doSomething();
保存插件配置到 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;
JPanel panel = new JPanel(new BorderLayout());
JButton button = new JButton("Click Me");
button.addActionListener(e -> {
// 按钮点击事件
});
panel.add(button, BorderLayout.CENTER);
// 在 Kotlin 中使用
panel {
row {
button("Click Me") {
// 点击事件
}
checkBox("Enable Feature")
}
}
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>
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
);
}
}
};
}
}
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");
}
}
避免阻塞 UI 线程,使用 ApplicationManager.getApplication().executeOnPooledThread()
或 AsyncTask
。
ApplicationManager.getApplication().executeOnPooledThread(() -> {
// 后台任务
String result = doHeavyWork();
// 更新 UI(需切回 UI 线程)
ApplicationManager.getApplication().invokeLater(() -> {
Messages.showInfoMessage(result, "Result");
});
});
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();
}
}
AnAction
, ToolWindow
, PSI
, Services
, PersistentStateComponent
build.gradle
指定兼容的 IDEA 版本通过掌握这些核心语法和 API,你可以实现从简单的工具插件到复杂的代码分析功能。建议结合官方示例代码实践调试!