IDEA插件开发指南

一、前言

以下文档将帮助大家撑握基本的插件开发知识,如果需要深入开发,还需要参考官方提供文档 

idea提供了两种方式开发插件, 一种是基于devkit sdk开发(这种已不推荐), 一种是gradle方式开发

使用Gradle方式有以下几点好处:

  • 组织源码结构、modules和项目更方便
  • gradle更加方便构建较复杂的项目
  • gradle的帮助言文档及社区资料非常多

二、使用Gradle开发插件

 gradle-intellij-plugin gradle插件是官方推荐的idea插件开发插件, 插件中有开发插件中的所有依赖

开发语言: java + kotlin

版本要求:Gradle 6.6 or newer, 推荐使用最新版, 但新版的gradle要求使用jdk11

2.1 新建Gradle项目

建gradle项目有两种方式, 一种是直接使用idea创建,另一种是使用官方提供的Github Template, 这里推荐使用github模板仓库, 因为下载下来的模板中已有示例代码、目录已规划后,减少很多不必要的麻烦。

使用Github Template, 需要在登录github之后,可以看到“Use thie template”, 出现一个简单的向导, 创建后就在自己的账号下的仓库中生成了,当然可以将其下载下来上传至公司的仓库中

将项目导入到idea中,目录结构如下

 

推荐开发语言为kotlin, 但是用java也是可以的, kotlin得需要先学习下语法知识 Kotlin 教程 | 菜鸟教程

2.2 新建Actions

右键 -》New →  Plugin Devkit -》 Action

New Action

上面的字段解释:

  • Action ID - Every action must have a unique ID. If the action class is used in only one place in the IDE UI, then the class FQN is a good default for the ID. Using the action class in multiple places requires mangling the ID, such as adding a suffix to the FQN, for each ID.
  • Class Name - The FQN implementation class for the action. If the same action is used in multiple places in the IDE UI, the implementation FQN can be reused with a different Action ID.
  • Name - The text to appear in the menu.
  • Description - Hint text to be displayed.
  • Add to Group - The action group - menu or toolbar - to which the action is added. Clicking in the list of groups and typing invokes a search, such as "ToolsMenu."
  • Anchor - Where the menu action should be placed in the Tools menu relative to the other actions in that menu.

In this case, PopupDialogAction would be available in the Tools menu, it would be placed at the top, and would have no shortcuts.

After finishing the New Action form and applying the changes, the <actions> section of the plugin's plugins.xml file would contain:

<actions>
<action id="org.intellij.sdk.action.PopupDialogAction" class="org.intellij.sdk.action.PopupDialogAction" text="Pop Dialog Action" description="SDK action example">
<add-to-group group-id="ToolsMenu" anchor="first"/>
</action>
</actions>

The <action> element declares the Action ID (id,) Class Name (class,) Name (text,) and Description from the New Action form. The <add-to-group> element declares where the action will appear and mirrors the names of entries from the form.

This declaration is adequate, but adding more attributes is discussed in the next section.

三、调试插件

打开右侧 Gradle 工具视图, search “runIde”, 然后右键debug

Gradle Tool Window

之后就会运行一个idea出来,可以在新打开的idea上找下自己加的特性, 点击新增加的功能时就会进行断点调试

四、发布插件

使用gradle 发布插件

配置Gradle支持后,您可以自动构建插件并将其部署到JetBrains插件存储库.

在发布插件之前,首先需要能将插件源码编译通过,并且打包, 打包之后的文件位于${项目目录}/build/distributions , 编译打包插件可使用 intellij下的buildPlugin 命令

4.1  添加您的帐户凭据

发布插件到JetBrains Plugins仓库时, 首先需要提供 JetBrains Hub Permanent Token.

基于gradle,有以下两种方式可以提供Hub Permanent Token 

1)使用环境变量

配置环境变量

ORG_GRADLE_PROJECT_intellijPublishToken='YOUR_HUB_TOKEN_HERE'

选择Gradle项目,指定publishPlugin任务,然后添加上面的环境变量

publishPlugin {

  token = System.getenv("ORG_GRADLE_PROJECT_intellijPublishToken")

}

请注意,您仍需要在Gradle属性中放置一些默认值(可以为空),否则您将收到编译错误.

2)为Gradle任务提供参数

与使用环境变量类似,您也可以将凭证作为参数传递给Gradle任务.

-Dorg.gradle.project.intellijPublishToken=YOUR_HUB_TOKEN_HERE

4.2 使用gradle 发布

更多知识请参考 Publishing Plugins with Gradle | IntelliJ Platform Plugin SDK

五、plugin 基本知识

5.1 Actions

Actions 继承自AnAction, 需要实现actionPerformed 方法 。  actionPerformed会在菜单项(menu item)或 工具栏上的按扭触发。

Actions 是插件中最常用的方式,可以被放到分组中,以分组的方式呈现

<!-- Actions -->

<actions>

  <!-- The <action> element defines an action to register.

       The mandatory "id" attribute specifies a unique

       identifier for the action.

       The mandatory "class" attribute specifies the

       FQN of the class implementing the action.

       The mandatory "text" attribute specifies the default long-version text to be displayed for the

       action (tooltip for toolbar button or text for menu item).

       The optional "use-shortcut-of" attribute specifies the ID

       of the action whose keyboard shortcut this action will use.

       The optional "description" attribute specifies the text

       which is displayed in the status bar when the action is focused.

       The optional "icon" attribute specifies the icon which is

       displayed on the toolbar button or next to the menu item. -->

  <action id="VssIntegration.GarbageCollection" class="com.foo.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 text for the menu action.

         The mandatory "text" attribute defines the text to be displayed for the action.

         The mandatory "place" attribute declares where the alternate text should be used. In this example,

         any time the action is displayed in the IDE Main Menu (and submenus) the override-text

         version should be used.

         The second <override-text> element uses the alternate attribute "use-text-of-place" to define

         a location (EditorPopup) to use the same text as is used in MainMenu. It is a way to specify

         use of 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 an existing group. An action can be added to several groups.

         The mandatory "group-id" attribute specifies the ID of the group

         to which the action is added.

         The group must be implemented by an instance of the DefaultActionGroup class.

         The mandatory "anchor" attribute specifies the position of the

         action in the relative to other actions. It can have the values

         "first", "last", "before" and "after".

         The "relative-to-action" attribute is mandatory if the anchor

         is set to "before" and "after", and specifies the action before or after which

         the current action is inserted. -->

    <add-to-group group-id="ToolsMenu" relative-to-action="GenerateJavadoc" anchor="after"/>

      <!-- The <keyboard-shortcut> node specifies the keyboard shortcut

           for the action. An action can have several keyboard shortcuts.

           The mandatory "first-keystroke" attribute specifies the first

           keystroke of the action. The keystrokes are specified according

           to the regular Swing rules.

           The optional "second-keystroke" attribute specifies the second

           keystroke of the action.

           The mandatory "keymap" attribute specifies the keymap for which

           the action is active. IDs of the standard keymaps are defined as

           constants in the com.intellij.openapi.keymap.KeymapManager class.

           The optional "remove" attribute in the second <keyboard-shortcut>

           element below means the specified shortcut should be removed from

           the specified action.

           The optional "replace-all" attribute in the third <keyboard-shortcut>

           element below means remove all keyboard and mouse shortcuts from the specified

           action before adding the specified shortcut.  -->

    <!-- Add the first and second keystrokes to all keymaps  -->

    <keyboard-shortcut keymap="$default" first-keystroke="control alt G" second-keystroke="C"/>

    <!-- Except to the "Mac OS X" keymap and its children -->

    <keyboard-shortcut keymap="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 this keyboard shortcut for this action.  -->

    <keyboard-shortcut keymap="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.

           The mandatory "keystroke" attribute specifies the clicks and

           modifiers for the action. It is defined as a sequence of words

           separated by spaces:

           "button1", "button2", "button3" for the mouse buttons;

           "shift", "control", "meta", "alt", "altGraph" for the modifier keys;

           "doubleClick" if the action is activated by a double-click of the button.

           The mandatory "keymap" attribute specifies the keymap for which

           the action is active. IDs of the standard keymaps are defined as

           constants in the com.intellij.openapi.keymap.KeymapManager class.

           The "remove" and "replace-all" attributes can also be used in

           a <mouse-shortcut> element. See <keyboard-shortcut> for documentation.  -->

    <mouse-shortcut keymap="$default" keystroke="control button3 doubleClick"/>

  </action>

  <!--  This action declares neither a text nor description attribute. If it has

        a resource bundle declared the text and descriptions will be retrieved

        based on the action-id incorporated in the key for a translated string -->

  <action id="sdk.action.PopupDialogAction" class="sdk.action.PopupDialogAction"

        icon="SdkIcons.Sdk_default_icon">

  </action>

  <!-- The <group> element defines an action group. <action>, <group> and

       <separator> elements defined within it are automatically included in the group.

       The mandatory "id" attribute specifies a unique identifier for the group.

       The optional "class" attribute specifies the FQN of

       the class implementing the group. If not specified,

       com.intellij.openapi.actionSystem.DefaultActionGroup is used.

       The optional "text" attribute specifies the text of the group (text

       for the menu item showing the submenu).

       The optional "description" attribute specifies the text which is displayed

       in the status bar when the group has focus.

       The optional "icon" attribute specifies the icon which is displayed on

       the toolbar button or next to the menu group.

       The optional "popup" attribute specifies how the group is presented in

       the menu. If a group has popup="true", actions in it are placed in a

       submenu; for popup="false", actions are displayed as a section of the

       same menu delimited by separators.

       The optional "compact" attribute specifies whether an action within that group is visible when disabled.

       Setting compact="true" specifies an action in the group isn't visible unless the action is enabled.        -->

  <group class="com.foo.impl.MyActionGroup" id="TestActionGroup" text="Test Group" description="Group with test actions" icon="icons/testgroup.png" popup="true" compact="true">

    <action id="VssIntegration.TestAction" class="com.foo.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 to add an existing action to the group.

         The mandatory "ref" attribute specifies the ID of the action to add. -->

    <reference ref="EditorCopy"/>

    <add-to-group group-id="MainMenu" relative-to-action="HelpMenu" anchor="before"/>

  </group>

</actions>

详细资料参考

Actions | IntelliJ Platform Plugin SDK

5.2 plugin.xml 配置详解

plugin.xml 文件是核心配置文件,你可以理解成 Java web 开发中的 web.xml 文件,Android 开发中的 AndroidManifest.xml 文件。所有的组件的注册都需要在此文件中进行配置,否则该组件不会生效。

plugin.xml 文件所在位置为 /ProjectRoot/resources/META-INF/plugin.xml

<!-- An optional `url` attribute specifies the link to the plugin homepage. Displayed on the Plugin Page. -->

<idea-plugin url="https://plugins.jetbrains.com">

  <!-- Unique identifier of the plugin. It should be FQN. It cannot be changed between the plugin versions.

       If not specified, <name> will be used (not recommended). -->

  <id>org.jetbrains.plugins.template</id>

  <!-- Public plugin name should be written in Title Case. Guidelines: Plugin Overview page | JetBrains Marketplace -->

  <name>Plugin Template</name>

  <!-- Plugin version. It is recommended to use the SemVer approach: https://semver.org

       Displayed in the "Plugins" settings dialog and the plugin repository Web interface. -->

  <version>1.0.0</version>

  <!-- A displayed Vendor name or Organization ID (if you have one created. The optional `URL` attribute specifies

       the link to the vendor’s homepage.The optional `email` attribute specifies the vendor’s e-mail address.

       Displayed on the Plugins Page. -->

  <vendor url="https://plugins.jetbrains.com" email="marketplace@jetbrains.com">JetBrains</vendor>

  <!-- IMPORTANT: This tag should not be used in case of free plugins.

       If you decide to make your plugin paid, you will need to define the parameters in the <product-descriptor> tag.

       You can also enable free functionality in a paid plugin. Learn more in a guide to selling plugin:

       Plugin Development | JetBrains Marketplace -->

  <product-descriptor code="PLUGINTEMPLATE" release-date="20210901" release-version="20211" optional="true"/>

  <!-- Minimum and maximum build version of IDE compatible with the plugin. -->

  <idea-version since-build="193" until-build="193.*"/>

  <!-- Description of the plugin displayed on the Plugin Page and IDE Plugin Manager.

       Simple HTML elements ( text formatting, paragraphs, and lists) can be added inside of <![CDATA[ ]]> tag.

       Guidelines: Plugin Overview page | JetBrains Marketplace -->

  <description>

  <![CDATA[

    Provides a boilerplate template for easier plugin creation. <br/>

    Speed up the setup phase of plugin development for both new and experienced developers.

  ]]>

  </description>

  <!-- Short summary of new features and bugfixes in the latest plugin version.

       Displayed on the Plugin Page and 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: Plugin Compatibility with IntelliJ Platform Products | IntelliJ Platform Plugin SDK -->

  <depends>com.intellij.modules.platform</depends>

  <depends>com.third.party.plugin</depends>

  <!-- Optional dependency on another plugin. If the plugin with the "com.MySecondPlugin" ID is installed,

       the contents of mysecondplugin.xml (the format of this file conforms to the format of plugin.xml) will be loaded. -->

  <depends optional="true" config-file="mysecondplugin.xml">com.MySecondPlugin</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 registered by a plugin so that other plugins can provide

       this plugin with certain data. Read more: Extension Points | IntelliJ Platform Plugin SDK -->

  <extensionPoints>

    <extensionPoint name="testExtensionPoint" beanClass="com.foo.impl.MyExtensionBean"/>

    <applicationService serviceImplementation="com.foo.impl.MyApplicationService"/>

    <projectService serviceImplementation="com.foo.impl.MyProjectService"/>

  </extensionPoints>

  <!-- Application-level listeners, see: Listeners | IntelliJ Platform Plugin SDK -->

  <applicationListeners>

    <listener class="com.foo.impl.MyListener" topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>

  </applicationListeners>

  <!-- Project-level listeners, see: Listeners | IntelliJ Platform Plugin SDK -->

  <projectListeners>

    <listener class="com.foo.impl.MyToolwindowListener" topic="com.intellij.openapi.wm.ex.ToolWindowManagerListener"/>

  </projectListeners>

  <!-- Actions, see: Actions | IntelliJ Platform Plugin SDK -->

  <actions>

    <action id="VssIntegration.GarbageCollection" class="com.foo.impl.CollectGarbage" text="Collect _Garbage" description="Run garbage collector">

      <keyboard-shortcut first-keystroke="control alt G" second-keystroke="C" keymap="$default"/>

    </action>

  </actions>

  <!-- Custom extensions declaration. Read more: Extensions | IntelliJ Platform Plugin SDK -->

  <extensions defaultExtensionNs="VssIntegration">

    <myExtensionPoint implementation="com.foo.impl.MyExtensionImpl"/>

  </extensions>

  <!-- DEPRECATED: Plugin's application components / do not use in new plugins.

       See Components | IntelliJ Platform Plugin SDK for migration steps. -->

  <application-components>

    <component>

      <!-- Component's interface class -->

      <interface-class>com.foo.Component1Interface</interface-class>

      <!-- Component's implementation class -->

      <implementation-class>com.foo.impl.Component1Impl</implementation-class>

    </component>

  </application-components>

  <!-- DEPRECATED: Plugin's project components - do not use in new plugins.

       See Components | IntelliJ Platform Plugin SDK for migration steps. -->

  <project-components>

    <component>

      <!-- Interface and implementation classes are the same -->

      <implementation-class>com.foo.Component2</implementation-class>

      <!-- If the "workspace" option is set "true", the component

           saves its state to the .iws file instead of the .ipr file.

           Note that the <option> element is used only if the component

           implements the JDOMExternalizable interface. Otherwise, the

           use of the <option> element takes no effect.  -->

      <option name="workspace" value="true" />

      <!-- If the "loadForDefaultProject" tag is present, the project component is instantiated also for the default project. -->

      <loadForDefaultProject/>

    </component>

  </project-components>

  <!-- DEPRECATED: Plugin's module components - do not use in new plugins.

       See Components | IntelliJ Platform Plugin SDK for migration steps. -->

  <module-components>

    <component>

      <implementation-class>com.foo.Component3</implementation-class>

    </component>

  </module-components>

</idea-plugin>

针对一些常用配置整理说明

标签

说明

示例

id插件 ID,唯一表示。用户在插件市场众多插件当中唯一确定你的插件。一旦插件 ID 定义好并启用后,后续不可再更改,否则会成为新的插件
name

插件名称,显示的位置如下图

description插件功能说明,如上图中 插件名称下方的描述
version>插件版本号,如:1.0
change-notes插件更新日志描述,建议保留所有版本的更新说明。书写时,建议写上每个版本的版本号,以及内容。内容支持 html 标签,比喻ul,li
vendor 

标签为作者主站网址和邮箱配置。便于用户有疑问时联系你。

<vendor url="http://www.jetbrains.com" email="support@jetbrains.com" />

actions

 标签之间可以配置多个 action 标签。

action 的快捷键标签。

first-keystroke:首选快捷键

second-keystroke:备选快捷键

keymap:默认快捷键

<action
id="包名 + 插件名称 + 类名"
class="com.duke.demo.HelloAction"
text="HelloActionMenu"
description="当前插件菜单功能说明"
icon="插件图标"
keymap="未知"
popup=""
project-type=""
use-shortcut-of=""/>
最核心的标签。每一个 action 标签代表一个菜单项或工具栏中的一个按钮。在 action 标签中间,还可以配置 keyboard-shortcut 标签,用来设置快捷键。

<keyboard-shortcut first-keystroke="control alt G" second-keystroke="C" keymap="$default"/>

六、参考资料

官方文档 Creating Your First Plugin | IntelliJ Platform Plugin SDK

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值