主要的插件类型

  • UI主题插件
  • 自定义语言支持插件
  • 框架集成插件
  • 工具集成插件

开发插件的三种方式

  • Using Gradle
  • Using GitHub Template
    在github上选择一个模板,会自动根据模板生成一个配置好的插件项目,可以直接clone到本地开发
  • Using DevKit

使用DevKit开发插件

设置开发环境

准备工作

确认启用Plugin DevKit插件,该插件是IDEA自带的插件

为项目配置IntelliJ Platform SDK

  • 创建一个ntelliJ Platform SDK
  • 指定sdk的位置
  • 配置sdk源码路径,如果不需要debug此步可以跳过

  • 设置沙箱目录, 插件项目的setting信息会保存在这个目录, 可以指定任意目录。

创建插件项目

  • 创建项目

  • 创建具体的插件模块, 如果该项目只开发一个插件则不用创建模块。

  • 设置插件的sdk

启动配置

在Run Configuration菜单下配置启动配置, 配置jre。 点击run按钮,会启动一个ieda实例,并且启用当前开发的插件。

部署插件

  • build项目或模块
  • Prepare your plugin for deployment.
    如果插件没有其他依赖,则会创建一个jar包,否则会创建一个zip压缩包。

发布插件

可以发布到自定义仓库或者发布到idea公共仓库

插件架构

插件jar包含的文件

  1. 插件配置文件plugin.xml
  2. 实现插件功能的类
  3. 插件依赖的jar包

插件ClassLoader

每个插件都使用独立的ClassLoader, 所以每个插件可以使用不同版本的依赖,不会相互影响。如果插件的classLoader没有发现某个类,则默认由IDEA的ckassLoader加载。但是可以在plugin.xml中的元素下声明依赖其它插件,那么就会使用其它插件的classLoader加载未找到的类。

Actions

action官方文档
Action是实现插件功能的类, 一个Action类需要继承AnAction并且实现actionPerformed方法。当用户点击菜单或者工具栏按钮, 按快捷键,或者通过Help | Find Action点击时, IntelliJ Platform系统会回调对应Action的actionPerformed方法。
Action会被分组, 一个组可以包含actions也可以包含子组,一个action组就是一个菜单或者工具栏,子组就是子菜单。

注册Action

通过plugin.xml注册action。

<actions><!--- "id" (required) - specifies a unique identifier for the action- "class" (required) - specifies the FQN of the class implementingthe action- "text" (required) - specifies the default long-version text to bedisplayed for the action (tooltip for toolbar button or text formenu item)- "use-shortcut-of" (optional) - specifies the ID of the actionwhose keyboard shortcut this action will use- "description" (optional) - specifies the text which is displayedin the status bar when the action is focused- "icon" (optional) - specifies the icon which is displayed onthe toolbar button or next to the menu item--><actionid="VssIntegration.GarbageCollection"class="com.example.impl.CollectGarbage"text="Garbage Collector: Collect _Garbage"description="Run garbage collector"icon="icons/garbage.png"><!--The <override-text> element defines an alternate version of the textfor the menu action. Attributes:- "text" (required) - defines the text to be displayed for the action- "place" (required) - declares where the alternate text shouldbe used. In this example, any time the action is displayed inthe IDE main menu (and submenus), the override-text version shouldbe used.The second <override-text> element uses the alternate attribute"use-text-of-place" to define a location (EditorPopup) to use the sametext as is used in MainMenu. It is a way to specify the use ofan alternate menu text in multiple discrete menu groups.--><override-text place="MainMenu" text="Collect _Garbage"/><override-text place="EditorPopup" use-text-of-place="MainMenu"/><!-- Provide alternative names for searching action by name --><synonym text="GC"/><!--The <add-to-group> node specifies that the action should be added to anexisting group. An action can be added to several groups. Attributes:- "group-id" (required) - specifies the ID of the group to which theaction is added. The group must be an implementation of theDefaultActionGroup class.- "anchor" (required) - specifies the position of the action inthe relative to other actions. Allowed values: "first", "last","before", and "after".- "relative-to-action" (mandatory if "anchor" is "before" or "after") -specifies the action before or after which the current action isinserted.--><add-to-groupgroup-id="ToolsMenu"relative-to-action="GenerateJavadoc"anchor="after"/><!--The <keyboard-shortcut> node specifies the keyboard shortcut forthe action. An action can have several keyboard shortcuts. Attributes:- "first-keystroke" (required) - specifies the first keystroke ofthe action. The keystrokes are specified according to the regularSwing rules.- "second-keystroke" (optional) - specifies the second keystroke ofthe action.- "keymap" (required) - specifies the keymap for which the actionis active. IDs of the standard keymaps are defined as constantsin the com.intellij.openapi.keymap.KeymapManager class.- "remove" (optional) - shortcut should be removed from the specifiedaction. See the second <keyboard-shortcut> example element below.- "replace-all" (optional) - removes all keyboard and mouse shortcutsfrom the specified action before adding the specified shortcut.See the third <keyboard-shortcut> example element below.--><!-- Add the first and second keystrokes to all keymaps... --><keyboard-shortcutkeymap="$default"first-keystroke="control alt G"second-keystroke="C"/><!-- ...except the "Mac OS X" keymap and its children. --><keyboard-shortcutkeymap="Mac OS X"first-keystroke="control alt G"second-keystroke="C"remove="true"/><!-- The "Mac OS X 10.5+" keymap and its children will have only thiskeyboard shortcut for this action. --><keyboard-shortcutkeymap="Mac OS X 10.5+"first-keystroke="control alt G"second-keystroke="C"replace-all="true"/><!--The <mouse-shortcut> node specifies the mouse shortcut for the action.An action can have several mouse shortcuts. Attributes:- "keystroke" (required) - specifies the clicks and modifiers forthe action. It is defined as a sequence of words separated by spaces:* mouse buttons: "button1", "button2", "button3"* modifier keys: "shift", "control", "meta", "alt", "altGraph"* button double-click: "doubleClick"- "keymap" (required) - specifies the keymap for which the action isactive. IDs of the standard keymaps are defined as constants inthe com.intellij.openapi.keymap.KeymapManager class.The <mouse-shortcut> element can also specify "remove" and "replace-all"attributes. See <keyboard-shortcut> description above for details.--><mouse-shortcutkeymap="$default"keystroke="control button3 doubleClick"/></action><!--This action declares neither a text nor a description attribute. If ithas a resource bundle declared, the text and descriptions will beretrieved based on the action-id incorporated in the key for a translatedstring.--><actionid="sdk.action.PopupDialogAction"class="sdk.action.PopupDialogAction"icon="SdkIcons.Sdk_default_icon"/><!--The <group> element defines an action group. The <action>, <group>and <separator> elements defined within it are automatically includedin the group. Attributes:- "id" (required) - specifies a unique identifier for the group.- "class" (optional) - specifies the FQN of the class implementingthe group. If not specified,com.intellij.openapi.actionSystem.DefaultActionGroup is used.- "text" (optional) - specifies the text of the group (text for the menuitem showing the submenu).- "description" (optional) specifies the text which is displayed in thestatus bar when the group has focus.- "icon" (optional) - specifies the icon which is displayed onthe toolbar button or next to the menu group.- "popup" (optional) - specifies how the group is presented in the menu.* "true" - group actions are placed in a submenu* "false" - actions are displayed as a section of the same menudelimited by separators.- "compact" (optional) - specifies whether an action within that groupis visible when disabled. Setting compact="true" specifies an actionin the group isn't visible unless the action is enabled.--><groupclass="com.example.impl.MyActionGroup"id="TestActionGroup"text="Test Group"description="Group with test actions"icon="icons/testgroup.png"popup="true"compact="true"><actionid="VssIntegration.TestAction"class="com.example.impl.TestAction"text="My Test Action"description="My test action"/><!-- The <separator> element defines a separator between actions.It can also have an <add-to-group> child element. --><separator/><group id="TestActionSubGroup"/><!-- The <reference> element allows adding an existing action tothe group. The mandatory "ref" attribute specifies the ID ofthe action to add. --><reference ref="EditorCopy"/><add-to-groupgroup-id="MainMenu"relative-to-action="HelpMenu"anchor="before"/></group>
</actions>

扩展(Extensions)

扩展是插件最常用的一种扩展IDEA功能的方式, 只是这种方式没有直接把Action加到菜单或者工具栏那么直接。扩展功能是通过IDEA自带的或者其它插件提供的一些扩展点实现的。
声明扩展要在plugin.xml中添加标签。

<!--
defaultExtensionNs属性只有两种值:
1. com.intellij 使用 IntelliJ Platform核心扩展点
2. {ID of a plugin} 使用其它插件的扩展点,必须要配置其它插件的依赖子标签的名称必须和扩展点的名称相同
扩展点有两种类型
3. 扩展点使用interface 属性声明, 则设置扩展点标签的implementation属性, 属性值设置实现了interface对应接口的实现类的全限定名
4. 扩展点使用beanClass属性声明,则可以设置beanClass对应的扩展点类中@Attribute注解标注的属性。可以使用view | quick document 查看扩展点帮助  -->
<extensions defaultExtensionNs="com.intellij"><appStarter implementation="com.example.MyAppStarter"/><projectTemplatesFactory implementation="com.example.MyProjectTemplatesFactory"/>
</extensions><!--Declare extensions to access extension points in a custom plugin "another.plugin".The "myExtensionPoint" extension point has been declared using "beanClass"and exposes custom properties "key" and "implementationClass".
-->
<extensions defaultExtensionNs="another.plugin"><myExtensionPointkey="keyValue"implementationClass="com.example.MyExtensionPointImpl"/>
</extensions>

Service

Service是插件的一个组件, 是为了把公共的逻辑放到一起,Service的实例是单例的。
有三种类型的Service, 应用级别的,项目级别的,模块级别的。

声明Service有两种方式

  1. 类上加@Service注解,service不需要被重写的时候可以使用这种方式

  2. 在plugin.xml中声明,通过applicationService,projectService扩展点声明

<extensions defaultExtensionNs="com.intellij"><!-- Declare the application-level service --><applicationServiceserviceInterface="mypackage.MyApplicationService"serviceImplementation="mypackage.MyApplicationServiceImpl"/><!-- Declare the project-level service --><projectServiceserviceInterface="mypackage.MyProjectService"serviceImplementation="mypackage.MyProjectServiceImpl"/>
</extensions>

获取Service

MyApplicationService applicationService = ApplicationManager.getApplication().getService(MyApplicationService.class);MyProjectService projectService = project.getService(MyProjectService.class);

实现类可以封装静态方法,方便获取

MyApplicationService applicationService = MyApplicationService.getInstance();MyProjectService projectService = MyProjectService.getInstance(project);

和其它Service交互

@Service
public final class ProjectService {private final Project myProject;public ProjectService(Project project) {myProject = project;}public void someServiceMethod(String parameter) {AnotherService anotherService = myProject.getService(AnotherService.class);String result = anotherService.anotherServiceMethod(parameter, false);// do some more stuff}
}

Extension Points

声明扩展点
有两种类型的扩展点

  1. Interface 其它插件提供该接口的实现类
  2. Bean 其它插件提供子类, 这种方式其它插件可以设置一些扩展点类的属性值
<idea-plugin><id>my.plugin</id><extensionPoints><extensionPointname="myExtensionPoint1"beanClass="com.example.MyBeanClass"/><extensionPointname="myExtensionPoint2"interface="com.example.MyInterface"/></extensionPoints></idea-plugin>

扩展点类

public class MyBeanClass extends AbstractExtensionPointBean {@Attribute("key")public String key;@Attribute("implementationClass")public String implementationClass;public String getKey() {return key;}public String getClass() {return implementationClass;}
}

其它插件使用该扩展点

<idea-plugin><id>another.plugin</id><!-- Declare dependency on plugin defining extension point: --><depends>my.plugin</depends><!-- Use "my.plugin" namespace: --><extensions defaultExtensionNs="my.plugin"><myExtensionPoint1key="someKey"implementationClass="another.some.implementation.class"/><myExtensionPoint2implementation="another.MyInterfaceImpl"/></extension></idea-plugin>

声明扩展点的类使用扩展点

public class MyExtensionUsingService {private static final ExtensionPointName<MyBeanClass> EP_NAME =ExtensionPointName.create("my.plugin.myExtensionPoint1");public void useExtensions() {for (MyBeanClass extension : EP_NAME.getExtensionList()) {String key = extension.getKey();String clazz = extension.getClass();// ...}}
}

plugin.xml

这个示例配置文件除了Action的配置,其余配置全部都配置了。

<!--
An optional "url" attribute specifies the link to the plugin homepage.
It is displayed on the plugin page in the Marketplace.
-->
<idea-plugin url="https://example.com/my-plugin-site"><!--Unique identifier of the plugin. It should be a fully qualified nameincluding namespace to not collide with existing plugins. It cannot bechanged between the plugin versions. If not specified, <name> will beused (not recommended).--><id>com.example.myplugin</id><!-- Public plugin name. It should use Title Cases. Guidelines:https://plugins.jetbrains.com/docs/marketplace/plugin-overview-page.html#plugin-name--><name>My Framework Support</name><!--Plugin version. Plugins uploaded to the Marketplace must followthe semantic versioning: https://plugins.jetbrains.com/docs/marketplace/semver.html.It is displayed in the "Plugins" settings dialog and in the Marketplaceplugin page.--><version>1.0.0</version><!--Vendor name or Organization ID (if you have one created).Attributes:- "url" (optional) - specifies the link to the vendor's homepage- "email" (optional) - specifies the vendor's email addressDisplayed on the Plugins Page.--><vendorurl="https://plugins.jetbrains.com/my-company"email="contact@example.com">My Company</vendor><!--IMPORTANT: This tag should not be used in free plugins.If you decide to make your plugin paid, you will need to definethe parameters in the <product-descriptor> tag.You can also enable free functionality in a paid plugin. Learn more ina guide to selling plugin: https://plugins.jetbrains.com/build-and-market--><product-descriptorcode="PMYPLUGIN"release-date="20210901"release-version="20211"optional="true"/><!-- Minimum and maximum IDE build versions compatible with the plugin. --><idea-version since-build="193" until-build="193.*"/><!--Plugin description displayed on the Marketplace plugin page and inthe IDE Plugin Manager.Simple HTML elements (text formatting, paragraphs, lists, etc.) can beadded inside of <![CDATA[ ]]> tag. Guidelines:https://plugins.jetbrains.com/docs/marketplace/plugin-overview-page.html#plugin-description--><description><![CDATA[Provides support for <a href="https://example.com/my-framework">MyFramework</a>.<p>Includes support for:<ul><li>code completion</li><li>references</li><li>refactoring</li></ul></p>]]></description><!--Short summary of new features and bugfixes in the latest plugin version.Displayed on the Marketplace plugin page and in the IDE Plugin Manager.Simple HTML elements can be included between <![CDATA[  ]]> tags.--><change-notes>Initial release of the plugin.</change-notes><!--Product and plugin compatibility requirements. Read more:https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html--><depends>com.intellij.modules.platform</depends><depends>com.example.third-party-plugin</depends><!--Optional dependency on another plugin. If the plugin with the"com.example.my-second-plugin" ID is installed, the contentsof "mysecondplugin.xml" (the format of this file conforms tothe format of plugin.xml) will be loaded.--><dependsoptional="true"config-file="mysecondplugin.xml">com.example.my-second-plugin</depends><!--Resource bundle (/messages/MyPluginBundle.properties) to be used with"key" attributes in extension points and implicit keys like"action.[ActionID].text|description".--><resource-bundle>messages.MyPluginBundle</resource-bundle><!--Extension points defined by the plugin. Extension points are registeredby a plugin so that other plugins can provide this plugin with certaindata. Read more:https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html--><extensionPoints><extensionPointname="testExtensionPoint"beanClass="com.example.impl.MyExtensionBean"/><applicationServiceserviceImplementation="com.example.impl.MyApplicationService"/><projectServiceserviceImplementation="com.example.impl.MyProjectService"/></extensionPoints><!--Application-level listeners. For more information, see:https://plugins.jetbrains.com/docs/intellij/plugin-listeners.html#defining-application-level-listeners--><applicationListeners><listenerclass="com.example.impl.MyListener"topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/></applicationListeners><!--Project-level listeners. For more information, see:https://plugins.jetbrains.com/docs/intellij/plugin-listeners.html#defining-project-level-listeners--><projectListeners><listenerclass="com.example.impl.MyToolwindowListener"topic="com.intellij.openapi.wm.ex.ToolWindowManagerListener"/></projectListeners><!--Actions. For more information, see:https://plugins.jetbrains.com/docs/intellij/basic-action-system.html--><actions><actionid="VssIntegration.GarbageCollection"class="com.example.impl.CollectGarbage"text="Collect _Garbage"description="Run garbage collector"><keyboard-shortcutfirst-keystroke="control alt G"second-keystroke="C"keymap="$default"/></action></actions><!-- Custom extensions declaration. For more information, see:https://plugins.jetbrains.com/docs/intellij/plugin-extensions.html#declaring-extensions--><extensions defaultExtensionNs="VssIntegration"><myExtensionPoint implementation="com.example.impl.MyExtensionImpl"/></extensions><!--DEPRECATED: Do not use in new plugins!Plugin's application components.See https://plugins.jetbrains.com/docs/intellij/plugin-components.htmlfor migration steps.--><application-components><component><!-- Component's interface class --><interface-class>com.example.Component1Interface</interface-class><!-- Component's implementation class --><implementation-class>com.example.impl.Component1Impl</implementation-class></component></application-components><!--DEPRECATED: Do not use in new plugins!Plugin's project components.See https://plugins.jetbrains.com/docs/intellij/plugin-components.htmlfor migration steps.--><project-components><component><!-- Interface and implementation classes are the same --><implementation-class>com.example.Component2</implementation-class><!--If the "workspace" option is set "true", the component saves its stateto the .iws file instead of the .ipr file. Note that the <option>element is used only if the component implements theJDOMExternalizable interface. Otherwise, the use of the <option>element takes no effect.--><option name="workspace" value="true"/><!--If the "loadForDefaultProject" tag is present, the project componentis instantiated also for the default project.--><loadForDefaultProject/></component></project-components><!--DEPRECATED: Do not use in new plugins!Plugin's module components.See https://plugins.jetbrains.com/docs/intellij/plugin-components.htmlfor migration steps.--><module-components><component><implementation-class>com.example.Component3</implementation-class></component></module-components>
</idea-plugin>

idea插件开发教程相关推荐

  1. [原创插件] [服务端插件] [新手开发者必看]优秀插件开发教程列表 欢迎回复讨论

    插件开发者专享套餐 声明:此集锦意在提升插件开发者的姿势水平, 插件版版主邀请编程版的海螺编写的,并非错版,请勿举报. 入门以前 在开始写插件之前,你需要知道插件基于 Java,所以请先学习 Java ...

  2. 我的世界Bukkit服务器插件开发教程(十一)粒子、药水效果与音效

    十一.粒子.药水效果与音效 太简单了吧! 1.粒子效果 1.1.基本操作 播放粒子,首先需要确定粒子需要播放的位置.需要注意,我们一次只能播放一个粒子,如果需要播放多个粒子的话--也不麻烦. 播放粒子 ...

  3. WordPress插件开发教程1:开发第一个WordPress插件

    一.创建一个插件 第一步:在 wp-content \ plugins 目录新建一个目录,随便起个名字,比如:my-first-plugin.         第二步:进入 my-first-plug ...

  4. 我的世界Bukkit服务器插件开发教程(七)计分板

    七.计分板 写在前面 对于计分板,相信大部分人会认为这是一个计分的玩意.但不然,它的用处远远不止计分那样简单,计分板在服务器中起着重要的作用,在大部分插件中都有着它的身影. 另注:本章节有大量干货,请 ...

  5. 我的世界Bukkit服务器插件开发教程(五)方块Blocks

    五.方块Blocks 我怕不更新会被骂,所以更了. 坐标系 小伙纸,求一下∑i=0∞i2\sum_{i=0}^\infty i^2∑i=0∞​i2(bushi 是的,你没猜错,我们要涉及到史上最NB超 ...

  6. 我的世界Bukkit服务器插件开发教程(十五)世界生成器

    十五.世界生成器 如果你仔细观察,会发现有个叫saves的文件夹,这个文件夹是用来存放存档的,即我们平常说的世界. 显然,服务器承担了创建世界.加载世界的任务.Bukkit 中也有专门生成世界的生成器 ...

  7. 我的世界Bukkit服务器插件开发教程(一)第一个插件

    一.第一个插件 这一章节,我们会开发第一个属于自己的插件 在这之前,我们还需了解plugin.yml和config.yml,并大概了解插件的原理 plugin.yml 这个文件必须存在,否则读不出来. ...

  8. 我的世界Bukkit服务器插件开发教程(八)进度条与自定义合成表

    八.进度条与自定义合成表 写在前面 本来我想将进度放入本章节当中,但无奈进度牵扯到json文件,估计我又要叽叽喳喳讲一堆json,出于人最基本的性格,这章节暂且不讲. 进度条 说起进度条,打个最简单的 ...

  9. 学习JQuery插件开发教程

    如果你跟我一样,jQuery属于入门级的,那么我建议你看我下一篇jQuery教程:自己动手开发jquery插件 ,这篇插件比较容易理解和模范,适合新手开发jQuery插件.推荐你去看一看. 在逛cod ...

  10. 我的世界Bukkit服务器插件开发教程(十三)资源包与玩家资料

    十三.资源包与玩家资料 1.资源包(Resource Pack) 早期的 Minecraft 并没有资源包一说,而是被叫做材质包.有些服务器为了让玩家拥有更好的游戏体验,一般会在自己特制的客户端中存放 ...

最新文章

  1. 【机器学习基础】理解关联规则算法
  2. wxWidgets:wxFileDialog类用法
  3. MySQL导出数据遇到secure-file-priv问题的解决方法
  4. Filter案例之敏感词过滤和代理模式
  5. 计算机专业毕业后能做什么工作?
  6. 关于Linux的总结(三)
  7. oracle Client 11g静默安装
  8. C++指针与数组的对比
  9. .NET对存储过程的调用抽象封装
  10. 共享网络获取树莓派ip_树莓派网络设置
  11. 005 IK-analyzer添加搜狗词库
  12. 小米6自动重启android,小米6总是自动重启怎么办?小米6自动重启的解决方法
  13. 体验为王-2021友盟+移动性能优化比赛第一名作品
  14. java科学计算器代码_用JAVA编写的科学计算器源代码是什么?
  15. java poi操作word模版 导出word文档(附工具类)
  16. 解决报错:The Module Root specified is not a module according to Intellij
  17. 深圳云计算培训:云计算是怎么分类的
  18. 何为数据库连接池?其工作原理是什么?
  19. BeanCopier系列之二:使用Converter
  20. java-final关键字修饰变量

热门文章

  1. react 翻书效果_react实现页面切换动画效果
  2. java--人民币小写(金额)转为大写(金额转换)
  3. 论文写作之WPS安装Mathtype插件编写数学公式
  4. SGD ,Adam,momentum等优化算法比较
  5. 6 检验并打印魔方矩阵c语言,检验并打印魔方矩阵
  6. Word批量转PDF,宏批量转PDF
  7. matlab编译平面有限元计算(附有完整代码)
  8. 华为电脑管家最新(11.1.1.95)版安装教程(适合 未安装| 补充说明)
  9. 软件工程——软件详细设计
  10. 【数据采集】-目前比较流行的几种数据采集方式