IntelliJ IDEA插件开发入门
Idea提供丰富的扩展功能,若学有余力深入了解IDEA插件API,是一个非常好解决工作中重复造轮子问题的途径,且可适用范围广,非常值得学习
学习一样东西还是应该从 官方文档入手
插件sdk配置
这里提供两种思路
1.SDK选择IDEA安装路径(自带SDK),但是无法观察源码,可以在GITHUB下载社区版源码后添加到Sourcepath
2.获取IDEA源码,后自行编译(不推荐,就着上面简单的来)
工程构建
开发方式有3种
方式1,2如下
方式3:使用官方提供的模板。此方式也不推荐,能自己定制为什么要用模板
注:Gradle相关自行了解
插件开发相关API
先放一个官方DEMO参考
同时建议enable idea自带的plugin devkit和ui desiginer插件,避免新建插件类的时候找不到入口
工程结构介绍如下
常用API总结
1.Tools Windows扩展
public class MyToolWindowFactory implements ToolWindowFactory {
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
//MyToolWindow可以通过ui desiginer插件构建也可以自己用Swing实现
MyToolWindow myToolWindow = new MyToolWindow(toolWindow);
ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
Content content = contentFactory.createContent(myToolWindow.getContent(), "", false);
toolWindow.getContentManager().addContent(content);
}
}
====================================================================
同时plugin.xml声明如下
<extensions defaultExtensionNs="com.intellij">
<toolWindow id="Sample Calendar(展示名称)" secondary="true" icon="AllIcons.General.Modified(展示图标)" anchor="right(生成位置)"
factoryClass="org.intellij.sdk.toolWindow.MyToolWindowFactory(绑定ToolWindowFactory 实现类)"/>
</extensions>
结果演示
2.按钮Action扩展
public class PopupDialogAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent event) {
//构建文本
// Using the event, create and show a dialog
Project currentProject = event.getProject();
StringBuilder dlgMsg = new StringBuilder(event.getPresentation().getText() + " Selected!");
String dlgTitle = event.getPresentation().getDescription();
// If an element is selected in the editor, add info about it.
Navigatable nav = event.getData(CommonDataKeys.NAVIGATABLE);
if (nav != null) {
dlgMsg.append(String.format("\nSelected Element: %s", nav.toString()));
}
//展示弹框
Messages.showMessageDialog(currentProject, dlgMsg.toString(), dlgTitle, Messages.getInformationIcon());
}
}
====================================================================
同时plugin.xml声明如下
<action id="org.intellij.sdk.action.PopupDialogAction" class="org.intellij.sdk.action.PopupDialogAction"
text="Action Basics Plugin: Pop Dialog Action" description="SDK action example"
icon="SdkIcons.Sdk_default_icon">
<add-to-group group-id="ToolsMenu" anchor="first"/>
<override-text place="MainMenu" text="Pop Dialog Action"/>
<keyboard-shortcut first-keystroke="control alt A" second-keystroke="C" keymap="$default"/>
<mouse-shortcut keystroke="control button3 doubleClick" keymap="$default"/>
</action>
结果演示
3.右下角气泡弹出
public class PopNotifyUtil {
/**
* 站立右下通知发送
* @param message 通知消息
*/
public static void standNotify(String message) {
NotificationGroup notificationGroup =
new NotificationGroup("jrelax.id", NotificationDisplayType.BALLOON, true);
Notification notification = notificationGroup.createNotification(message, NotificationType.WARNING);
Notifications.Bus.notify(notification);
}
}
结果演示
4.setting面板集成
public class JRelaxSettingComponent implements SearchableConfigurable {
@Override
public @Nullable
JComponent createComponent() {
//创建面板过程
//JRelaxSettingPanel同上MyToolWindow可以通过ui desiginer插件构建也可以自己用Swing实现
if (null == this.jRelaxSettingPanel) {
this.jRelaxSettingPanel = new JRelaxSettingPanel(timeGapSetting);
}
return this.jRelaxSettingPanel.getMainPanel();
}
@Override
public void apply() {
//setting面板点击apply的逻辑
}
//。。。省略其他需要实现方法
}
====================================================================
同时plugin.xml声明如下
<extensions defaultExtensionNs="com.intellij">
<applicationConfigurable instance="com.daie.jrelax.setting.JRelaxSettingComponent"
id="com.daie.jrelax.setting.JRelaxSettingComponent" displayName="Jrelax Settings"/>
</extensions>
结果演示
5.setting数据持久化
该组件的使用应配合4.setting面板集成,Setting类的全局配置应该实例化,而不是重启IDEA后就失效
@State(name = "TimeGapSetting",
storages = {@Storage(
value = "$APP_CONFIG$/timegap.xml"
)}
)
public class TimeGapSetting implements PersistentStateComponent<TimeGapSetting> {
@Nullable
@Override
public TimeGapSetting getState() {
return null;
}
@Override
public void loadState(@NotNull TimeGapSetting state) {
}
}
====================================================================
同时plugin.xml声明如下
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceImplementation="com.daie.jrelax.setting.TimeGapSetting"/>
</extensions>
该项无结果演示
6.项目启动监听事件
public class JRelaxApplicationComponent implements ApplicationComponent {
@Override
public void initComponent() {
//idea一经启动后的逻辑
}
}
====================================================================
同时plugin.xml声明如下
<application-components>
<component>
<implementation-class>com.daie.jrelax.JRelaxApplicationComponent</implementation-class>
</component>
</application-components>
该项无结果演示
以上API总结均有在个人开发插件中使用,可供参考
1.2048
2.JRelax
打包和发布
打包使用工程自带的插件即可
插件上传
插件更新
思考
1.其实最开始是先搞一个插件解决公司提交MERGE REQUEST的问题,类似队列阻塞,同一个commit节点出来的两次先后提交MR,先提交的MR成功合并后,后提交的MR必定落后主分支一次提交,需要后提交者手动rebase一次,这个通知一般需要需要人工通知(评论无法即使看到),最开始的构想是让idea自动检测到当前的merge request落后主分支,然后以右下角的气泡提示,链接仓库的设置可以通过setting面板配置,还差一步是看看GIT钩子如何触发,想想又是给自己挖了个坑。或者还有什么好的解决办法可以评论提供
2.看明白了这几个API之后其实很多插件的逻辑就好理解了
|-翻译插件。获取到当前选中文本后调用有道API返回结果展示到某个地方
|-generateAllSetter。获取到当前鼠标选中的类,反射获取字段属性,模板生成文本在应用到编辑器内
参考
其中也有一些API的总结
https://blog.xiaohansong.com/idea-plugin-development.html
这也是个大佬
https://juejin.cn/post/6844904127990857742