idea插件开发(代码片段)

LeBron_Six LeBron_Six     2022-12-10     142

关键词:

文章目录

前言

官方开发文档:http://www.jetbrains.org/intellij/sdk/docs/welcome.html

首先需要开启 Plugin Devkit , IDEA 中默认带了 Plugin Devkit插件,但是没有开启。

插件工程

创建

插件工程结构

BundleFileFinder/
  resources/
    META-INF/
      plugin.xml
        ...
    src/
    com.yuyang.finder
        ...
  • src 实现插件功能的classes
  • resources 存放工程需要用到的资源文件,例如一些引用的jar包、图片资源等。
    • META-INF/plugin.xml 插件的配置文件,指定插件名称、描述、版本号、支持的 IntelliJ IDEA 版本、插件的 components 和 actions 以及软件商等信息。

plugin.xml

<idea-plugin>

  <!-- 插件相关信息, 会展示在IDEA插件的描述中 -->
  
  <!-- 插件唯一id, 遵循使用包名的原则 -->
  <id>com.yuyang.finder</id>
  <!-- 插件名称 -->
  <name>BundleFileFinder</name>
  <!-- 插件版本 -->
  <version>1.0</version>
  <!-- 开发者信息 -->
  <vendor email="smuyyh@gmail.com" url="http://smuyyh.top">$Company|$Name</vendor>
  <!-- 插件的描述 -->
  <description>my plugin description</description>
  <!-- 插件版本变更信息 -->
  <change-notes>Initial release of the plugin.</change-notes>

  <!-- 如果该插件还依赖了其他插件,则配置对对应的插件id -->
  <depends>com.intellij.modules.all</depends>

  <!-- 插件兼容IDEA的最大和最小build号,不配置则不做限制 -->
  <idea-version since-build="94.539" until-build="192"/>

  <!-- Actions: 如添加一个文件右击菜单按钮 -->
  <actions>
    <action id="FinderAction" class="com.yuyang.finder.FinderAction" text="FileFinder" description="FileFinder">
      <add-to-group group-id="ProjectViewPopupMenu" anchor="first"/>
    </action>
  </actions>

  <!-- 插件定义的扩展点,以供其他插件扩展该插件,类似Java的抽象类的功能 -->
  <extensionPoints>
    ...
  </extensionPoints>

  <!-- 声明该插件对IDEA core或其他插件的扩展 -->
  <extensions xmlns="com.intellij">
    ...
  </extensions>
</idea-plugin>

Plugin Action

Action 是什么

Action 用于描述一个动作、行为,可以通过快捷键、点选的方式进行触发。一个 Action 是一个 class,是 AnAction 的子类,actionPerformed 方法在菜单Item或者标题栏按钮被选中的时候会被调用。

Action 允许添加到右键菜单或者Toolbar菜单上面。Action也可以成组添加到具体的一个Group下面。

创建Action

public class FinderAction extends AnAction 

    private Project mProject;

    @Override
    public void actionPerformed(AnActionEvent event) 
        mProject = event.getData(PlatformDataKeys.PROJECT);
        DataContext dataContext = event.getDataContext();
        if ("apk".equals(getFileExtension(dataContext))) 
            //获取选中的文件
            VirtualFile file = DataKeys.VIRTUAL_FILE.getData(event.getDataContext());
            if (file != null) 
                // 创建面板  java swing
                
                // 后面章节会有 java GUI 面板介绍
            
         else 
            Messages.showInfoMessage("请选择.apk文件", "提示");
        
    

    @Override
    public void update(AnActionEvent event) 
        String extension = getFileExtension(event.getDataContext());
        this.getTemplatePresentation().setEnabled(extension != null && "apk".equals(extension));
    

    public String getFileExtension(DataContext dataContext) 
        VirtualFile file = DataKeys.VIRTUAL_FILE.getData(dataContext);
        return file == null ? null : file.getExtension();
    

注册Action

<actions>
  <!-- 添加单个Action -->
  <action 
          id="FinderAction"
          class="com.yuyang.finder.FinderAction"
          text="FileFinder"
          description="当前插件菜单功能说明" 
          icon="icons/garbage.png"
          keymap="未知" 
          popup="" 
          project-type=""
          use-shortcut-of="">

          <!-- 将菜单添加至工程的右击菜单 -->
          <add-to-group group-id="ProjectViewPopupMenu" 
                        anchor="first"
                        relative-to-action="GenerateJavadoc" />
    
          <!-- 设置快捷键 -->
          <keyboard-shortcut keymap="Mac OS X" 
                             first-keystroke="control alt G" 
                             second-keystroke="C" 
                             remove="true"/>
  </action>
  
  <!-- 添加成组的action -->
  <group id="FinderGroup" text="组名" description="描述">
    <add-to-group group-id="MainMenu" anchor="last"  />
        <action id="Action1" 
               class="com.yuyang.finder.FinderAction1" 
               text="名称1" 
               description="描述1" />
        <!-- 添加分割线 -->
        <separator/>
        <action id="Action2" 
               class="com.yuyang.finder.FinderAction2" 
               text="名称2" 
               description="描述2" />
        <!-- 可以添加一个已存在的action到该group -->
        <reference ref="EditorCopy"/>
  </group>
</actions>

如果 anchor 设置为 before 或者 after,则必须设置 relative-to-action。

快速创建Action

Plugin Devkit提供了快捷创建Action的方式。

信息填写基本遵循注册Action时的字段内容。

  • Action ID: action 唯一 id,推荐使用全类名
  • Class Name: 要被创建的 action class 名称
  • Name: menu item 的文本
  • Description: action 描述,toolbar 上按钮的提示文本,可选
  • Add to Group:选择新 action 要被添加到的 action group(Groups, Actions)以及相对其他 actions 的位置(Anchor),比如 EditMenu 就是顶部菜单栏的 Edit 菜单。
  • Keyboard Shortcuts:指定 action 的第一和第二快捷键

运行插件

点击 Run | Edit Configurations,若无配置项,则新建一个,配置一下 Use classpath of module,选择要调试的Module。

若需要查看调试日志,则需要勾选 Logs的选项。运行插件时将会输出log到console,也可以设置输出到具体文件。

打包插件

Build -> Prepare All Plugin Modules For Deployment,一般会将插件输出到工程根目录底下。

如果该插件没有依赖其他的library,则插件会被打包成.jar,否则会被打包成.zip

.jar 类型的文件内容结构
BundleFileFinder.jar/
  com/yuyang/finder/
      ...
  META-INF/
    plugin.xml
 
.zip 类型的文件内容结构
BundleFileFinder.zip/
  lib/
    lib1.jar
    lib2.jar
    BundleFileFinder.jar/
      com/yuyang/finder/
          ...
      META-INF/
        plugin.xml

安装插件

Intellij IDEA -> Preferences -> Plugins -> Install Plugin From Disk,选择打包出来的 .jar 或者 .zip 文件。

Plugin Components

Components 类型

Components 接口类型描述
Application ComponentIDEA启动时会初始化,IDEA生命周期中仅存在一个实例。
Project ComponentIDEA 会为每一个 Project 实例创建一个 Project 级别的component
Module ComponentIDEA 会为每一个 Project 的加载过的Module实例Module级别的component

创建 Component

与 Action 一样,可以通过快捷方式创建。 右击菜单 -> New -> Plugin Devkit -> Application/Project/Module Component。

例如创建 Application Component,默认会生成一个 Application 类 和 plugin.xml 的配置

public class FinderApplication implements ApplicationComponent 
    public FinderApplication() 
    

    @Override
    public void initComponent() 
        // TODO: insert component initialization logic here
    

    @Override
    public void disposeComponent() 
        // TODO: insert component disposal logic here
    

    @Override
    @NotNull
    public String getComponentName() 
        return "FinderApplication";
    

<application-components>
  <component>
    <implementation-class>com.yuyang.finder.FinderApplication</implementation-class>
  </component>
</application-components>

Project Component

public class FinderProject implements ProjectComponent 
    public FinderProject(Project project) 
    

    @Override
    public void initComponent() 
        
    

    @Override
    public void disposeComponent() 
        
    

    @Override
    @NotNull
    public String getComponentName() 
        return "FinderProject";
    

    @Override
    public void projectOpened() 
        // called when project is opened
    

    @Override
    public void projectClosed() 
        // called when project is being closed
    

<project-components>
    <component>
        <implementation-class>com.yuyang.finder.FinderProject</implementation-class>
    </component>
</project-components>

Module Component

public class FinderModule implements ModuleComponent 
    public FinderModule(Module module) 
    

    @Override
    public void initComponent() 
        // TODO: insert component initialization logic here
    

    @Override
    public void disposeComponent() 
        // TODO: insert component disposal logic here
    

    @Override
    @NotNull
    public String getComponentName() 
        return "FinderModule";
    

    @Override
    public void moduleAdded() 
        // Invoked when the module corresponding to this component instance has been completely
        // loaded and added to the project.
    

<module-components>
  <component>
    <implementation-class>com.yuyang.finder.FinderModule</implementation-class>
  </component>
</module-components>

获取 Component 实例

例如 获取定义的一个 Application Component 实例:

//获取application容器中的组件
FinderApplication finderApplication = ApplicationManager.getApplication().getComponent(FinderApplication.class);

Project 与 Module

public class FinderProject implements ProjectComponent 

    private Project project;

    public FinderProject(Project project) 
        this.project = project;
    

    @Override
    public void initComponent() 
        FinderModule finderModule = project.getComponent(FinderModule.class);
    

也可以通过 AnAction 的事件获取。

public class FinderAction extends AnAction 

    private Application mApplication;
    private Project mProject;
    private Module mModule;

    @Override
    public void actionPerformed(AnActionEvent event) 

        DataContext dataContext = event.getDataContext();

        // DataConstants 被标记为 @deprecated
        mProject = (Project)dataContext.getData(DataConstants.PROJECT);
        mModule =(Module)dataContext.getData(DataConstants.MODULE);
        
        // OR
        mProject = event.getData(PlatformDataKeys.PROJECT);
        // mModule = ???
    

持久化

对于IDEA插件的一些配置,一般情况下都不会希望用户每次使用插件时都要配置一遍,所以 IntelliJ Platform 提供了一些 API,来做数据的持久化。

PropertiesComponent

对于简单的 key - value 数据结构,可以使用 PropertiesComponent,用于保存 application 和 project 级别的数据。用法如下:

//获取 application 级别的 PropertiesComponent
PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
//获取 project 级别的 PropertiesComponent,指定相应的 project
PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(Project);

// set & get
propertiesComponent.setValue(name, value)
propertiesComponent.getValue(name)

所有的 PropertiesComponent设置的键值对共用同一个namespance,所以需要避免key冲突。

PersistentStateComponent

对于复杂的数据结构,可以使用 PersistentStateComponent,PersistentStateComponent 可以指定持久化的存储位置。

  • 需要提供一个 PersistentStateComponent 的实现类,T代表需要持久化的数据结构类型,然后重写 getState() 和 loadState() 方法。T可以是任意的类,或者是实现类自身。
  • 若需要指定存储位置,则在实现类上增加 @State 注解
  • 若不希望其中的某个字段被持久化,可以在该字段上增加 @Transient 注解
@State(name = "PersistentStateComponentImpl", 
       storages = 
           @Storage(value = "PersistentStateComponentImpl.xml")
       )
class PersistentStateComponentImpl implements PersistentStateComponent<State> 
    State myState;

    // 当组件被创建或 xml 文件被外部改变(比如git更新)时被调用
    public State getState() 
        return myState;
    
    
    // 当 settings 被保存时,该方法会被调用并保存状态值。
    public void loadState(State state) 
        myState = state;
    


class State 
    public State() 
    
    // 支持基本的数据类型、Map、Collection、enum
    public String value;
    
    @Transient
    public String disableSave;

  • 若是 application 级别的组件
    - 运行调试时 xml 文件的位置: ~/IdeaICxxxx/system/plugins-sandbox/config/options
    - 正式安装时 xml 文件的位置: ~/IdeaICxxxx/config/options
  • 若是 project 级别的组件
    • 默认为项目的 .idea/misc.xml
    • 若指定为 StoragePathMacros.WORKSPACE_FILE,则会被保存在 .idea/worksapce.xml

注册持久化组件

持久化组件可以声明为 Service,也可以声明为 Component,声明为 Component 则与前面介绍注册与获取的方法一致,声明为Service如下:
获取方式为:

<extensions defaultExtensionNs="com.intellij">
    <!-- application 级别-->
    <applicationService serviceImplementation="com.yuyh.finder.PersistentStateComponentImpl1"/>
    <!-- project 级别 -->
    <projectService serviceImplementation="com.yuyh.finder.PersistentStateComponentImpl2"/>
 </extensions>

GUI 面板

IDEA - Preference - Editor - Gui Designer,勾选 Java Source Code,表示我们通过面板编辑后可以生成 java代码。

创建GUI Form

指定位置右击 - New - GUI Form

面板编辑完成之后,点击Toolbar工具条那里的按钮,进行编译。编译完成后,GUI的代码会生成在 对应的 Java文件里面。如图是 Demo.java

文件结构

默认根JPanel是没有配置 “field name”控件属性的,所以我们需要给他配置一下。

生成的java文件如图,$$$setupUI$$$() 方法里面是具体创建布局的代码。

布局预览

在需要插入main方法的地方,按下 Command + n,点击 Form main,则会生成可执行的main方法。

运行 main 方法,可以预览之前创建的布局。

插件上传

插件也支持上传到 idea 仓库,让其他人搜索到。
官方文档:http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/publishing_plugin.html

示例项目

实现反编译APK来查找是否引用了某个类;
仓库地址:BundleFileFinder

参考:https://cloud.tencent.com/developer/article/1348741

idea插件开发(代码片段)

文章目录前言插件工程创建插件工程结构plugin.xmlPluginActionAction是什么创建Action注册Action快速创建Action运行插件打包插件安装插件PluginComponentsComponents类型创建Component获取Component实例持久化PropertiesComponentPersistentStateComponent注册持... 查看详情

idea插件开发-helloworld(代码片段)

idea插件开发-helloworld1.本文环境2.新建插件项目SDK切换build.gradle文件3.新建第一个action4.启动项目并验证插件爬坑1.本文环境idea版本=2021.2.2java版本=11电脑=macbookm1确认是否安装了下面插件:2.新建插件项目使用gradle创建... 查看详情

idea插件开发从0入门idea插件开发,idea插件开发教程,如何开发idea插件(代码片段)

idea插件介绍作为一枚程序员,平时最常用的ide就是IntelliJIDEA。平时会用到各种各样的插件,通过插件的使用,提高自己的开发效率。idea具有全局性,安装好插件后,对idea生效,所有的工程均能找到。idea... 查看详情

idea插件开发---extensionpoints(代码片段)

通过在插件中定义扩展点,您可以允许其他插件扩展您的插件的功能。有两种类型的扩展点:接口扩展点允许其他插件使用代码扩展您的插件。当您定义接口扩展点时,您指定了一个接口,其他插件将提供实现该... 查看详情

idea插件开发(11)---插件配置文件(代码片段)

以下是一个示例插件配置文件。此示例展示并描述了可在plugin.xml文件中使用的所有元素。有关配置的更多信息,请参见第II部分的“操作”部分。和元素中允许使用有限的HTML元素。但是,包含HTML元素的内容必须被<![CDA... 查看详情

idea插件开发(代码片段)

文章目录前言插件工程创建插件工程结构plugin.xmlPluginActionAction是什么创建Action注册Action快速创建Action运行插件打包插件安装插件PluginComponentsComponents类型创建Component获取Component实例持久化PropertiesComponentPersistentStateComponent注册持... 查看详情

史上最全idea插件开发入门实战(傻瓜式教程)(代码片段)

idea插件开发入门实战文章目录idea插件开发入门实战前言一、书写第一个HelloWorld二、IDEA插件开发进阶1.基于java文件的规则校验2.基于XML文件规则的校验3.基于java文件的代码自动生成方法4.基于XML文件的读写方法5.XML跳转Java文件前... 查看详情

idea插件系列(33):restfultool插件——restful服务开发辅助工具集(代码片段)

1.插件介绍RestfulTool插件。一套Restful服务开发辅助工具集:提供了一个Servicestree的显示窗口双击URL直接跳转到对应的方法定义一个简单的http请求工具支持Spring体系(SpringMVC/SpringBoot)支持JAX-RS支持`Navigate->RequestService`搜... 查看详情

idea开发插件,插件依赖|文件路径转virtualfile遇坑随笔(代码片段)

...,但是每次运行起来的时候在菜单就找不到我配置的插件入口了<depends>com.intellij.modules.platform</depends><depends>Dart</depends>原 查看详情

idea开发插件,插件依赖|文件路径转virtualfile遇坑随笔(代码片段)

...,但是每次运行起来的时候在菜单就找不到我配置的插件入口了<depends>com.intellij.modules.platform</depends><depends>Dart</depends>原 查看详情

idea代码生成插件codemaker(代码片段)

...。类似的问题太多,却没找到可以支持自定义代码模板的插件,只能自己动手,丰衣足食,开发了一个IDEA的代码生成插件,通过Velocity支持自定义代码模板来生成代码。项目地址:https://github.com/x-hansong/C 查看详情

idea插件开发(16)---对话框(代码片段)

对话包装器这DialogWrapper是应该用于IntelliJ平台中显示的所有模式对话框(和一些非模式对话框)的基类。它提供以下功能:按钮布局(确定/取消按钮的平台特定顺序,macOS特定的帮助按钮)上下文帮... 查看详情

5个idea必备插件,让效率成为习惯(代码片段)

...已成为Java社区中的友好IDE。本文我想分享一些实用的IDEA插件,可以在让你的编程效率更上一层楼。PS:IDEA安装插件方式,在IDEA中点击File->Settings...->Plugins,然后搜索对应插 查看详情

idea安装lombokplugin插件,实体不用getset简化开发(代码片段)

1.设置下载2.引入pom<!--Lombokplugin实体类getset--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version></d 查看详情

1.antlr4helloworld基础开发与idea插件使用(代码片段)

1.ANTLR4helloworld基础开发与IDEA插件使用下一篇:2.antlr4开发获取源码无需antlr4任何安装,基于IDEA创建一个Java项目,开发antlr的helloworld,使用antlr插件测试规则。输入hello后,才算匹配,然后显示world内容。1.... 查看详情

八window搭建spark+idea开发环境(代码片段)

...境,如下:1)操作系统:windowos2)IDEA开发工具以及scala插件(IDEA和插件版本要对应):  2-1)IDEA2018.2.1:https://www.jetbrains.com/  2-2)scala-intellij-bin-2018.2.11.zip:http://plugins.jetbrains.com/plugin/1347-sca 查看详情

scala安装和idea中开发(代码片段)

...二.windows安装三.linux环境安装四.Ida开发Scala1.在线下载Scala插件2.离线下载Scala插件3.验证五.HelloWorld入门程序1.新建Maven项目/模块2.默认下,maven不支持Scala的开发,需要引入Scala框架3.再main目录下,新建一个scala目录,然后添加为源... 查看详情

干掉postman!idea这款插件太实用了…(代码片段)

接口调试是每个软件开发从业者必不可少的一项技能,一个项目的的完成,可能接口测试调试的时间比真正开发写代码的时间还要多,几乎是每个开发的日常工作项。所谓工欲善其事必先利其器,在没有尝到IDEAREST真香之前,post... 查看详情