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

亦疏 亦疏     2023-04-13     253

关键词:

idea插件开发入门实战


文章目录


前言

建议先看一遍官方文档再开始

IDEA插件开发官方文档


一、书写第一个Hello World

新建项目


完事之后先修改plugin.xml配置文件。

<idea-plugin>
  <id>com.yishu.plugin</id>
  <name>插件入门实战</name>
  <version>1.0</version>
  <vendor email="1165883867@qq.com" url="http://www.xxx.com">顺便写啥</vendor>
  <description>描述。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。</description>
  <change-notes>啦啦啦。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。</change-notes>
  <idea-version since-build="173.0"/>

  <extensions defaultExtensionNs="com.intellij">
    <!-- Add your extensions here -->
  </extensions>

  <actions>
    <!-- Add your actions here -->
  </actions>
</idea-plugin>

再新建第一个action


这里新建一个java文件也是可以的,但是这样需要自己配置xml,不推荐。

此时xml文件会多出一行配置

开始编写第一个hello world

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;

public class FirstAction extends AnAction 

    @Override
    public void actionPerformed(AnActionEvent e) 
        Project project = e.getData(PlatformDataKeys.PROJECT);
        Messages.showMessageDialog(project,"Hello,World","First Action", Messages.getInformationIcon());
    

点击运行

点击idea help菜单


恭喜你入门成功。

二、IDEA插件开发进阶

1.基于java文件的规则校验

IDEA默认有对于JAVA的一些校验规则,如果我们想自己定义一些规则,如命名方式什么的,让不符合规则的内容爆红线,应该怎么做呢?
方法如下。

代码:

import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiField;
import org.jetbrains.annotations.NotNull;

public class JavaInspection extends AbstractBaseJavaLocalInspectionTool 
    @Override
    public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly)
        JavaElementVisitor javaElementVisitor = new JavaElementVisitor() 
            @Override
            public void visitField(PsiField field) 
                super.visitField(field);
                if (field.getName().equals("name"))
                    holder.registerProblem(field,"命名非法");
                
            
        ;
        return javaElementVisitor;
    

XML需要新增配置

  <extensions defaultExtensionNs="com.intellij">
    <localInspection
            id="inspection.JavaInspection"
            language="JAVA"
            shortName="JavaInspection"
            displayName="JavaInspection"
            groupName="JavaInspection"
            enabledByDefault="true"
            level="ERROR"
            implementationClass="com.yishu.plugin.inspection.JavaInspection"/>
  </extensions>

language 这里表示作用于JAVA文件
此时我们重新运行,新建查看效果。


如果想实现对方法,类名,包名等的校验,只需要重写相应的方法就行了。这里的方法有很多

2.基于XML文件规则的校验

和Java类似,这里我示范一个对于标签属性的校验。
直接贴代码和配置:

import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.XmlElementVisitor;
import com.intellij.psi.xml.XmlAttribute;
import org.jetbrains.annotations.NotNull;


public class XMLInspection extends AbstractBaseJavaLocalInspectionTool 
    @Override
    public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly)
        XmlElementVisitor xml = new XmlElementVisitor()
            @Override
            public void visitXmlAttribute(XmlAttribute attribute) 
                super.visitXmlAttribute(attribute);
                if (attribute.getName().equals("name") && attribute.getValue().equals("亦疏"))
                  holder.registerProblem(attribute,"描述哔巴拉巴拉");
                
            
        ;
        return xml;
    


配置:

<localInspection
            id="inspection.XMLInspection"
            language="XML"
            shortName="XMLInspection"
            displayName="XMLInspection"
            groupName="XMLInspection"
            enabledByDefault="true"
            level="ERROR"
            implementationClass="com.yishu.plugin.inspection.XMLInspection"/>

效果

3.基于java文件的代码自动生成方法

代码:

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;


public class GeneratedJavaCode extends AnAction 
    @Override
    public void actionPerformed(@NotNull AnActionEvent event) 
        WriteCommandAction.runWriteCommandAction(event.getProject(), () -> 
            PsiJavaFile file = (PsiJavaFile)event.getData(CommonDataKeys.PSI_FILE);
            PsiElementFactory factory = PsiElementFactory.SERVICE.getInstance(event.getProject());
            file.add(factory.createField("age",PsiType.INT));
        );
    

配置:

    <action id="action.GeneratedJavaCode" class="com.yishu.plugin.action.GeneratedJavaCode"
            text="生成java代码">
      <!-- 将action放在哪 -->
      <add-to-group group-id="GenerateGroup" anchor="first"/>
    </action>

效果


这里的age没标记位置,就简单写了个例子,需要自己通过addAfter等方法定位要生成的地方。就不详细说了

4.基于XML文件的读写方法

XML文件比较独特,这里展开讲讲。
建议先看官网介绍
https://plugins.jetbrains.com/docs/intellij/xml-dom-api.html#abstract


官网有提供两种方法读写XML文件,第一种是上面那样的,但是我觉得有点蠢,还不好复用也容易写错。
我们用第二种。
先把示例的XML文件拿到

<root>
    <foo name="Test">
        <bar name="name">123</bar>
        <bar>456</bar>
    </foo>
</root>

定义interface

Root

import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.SubTag;

public interface Root extends DomElement 
    @SubTag("foo")
    Foo getFoo();

Foo

public interface Foo extends DomElement 
    @Attribute("name")
    GenericAttributeValue<String> getName();
    @SubTagList("bar")
    List<Bar> getBars();
    Bar addBar();


Bar

public interface Bar extends DomElement 
    String getValue();
    void setValue(String s);
    @Attribute("name")
    GenericAttributeValue<String> getName();

注解记得加上,因为子标签不是唯一的时候,不加注解会获取不到

注册DomFileDescription:

public class XmlDescription extends DomFileDescription<Root> 
    public XmlDescription() 
        super(Root.class, "root", "");
    

XML配置


读取和生成逻辑的代码

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.xml.DomManager;
import com.yishu.plugin.service.Bar;
import com.yishu.plugin.service.Foo;
import com.yishu.plugin.service.Root;
import org.jetbrains.annotations.NotNull;


public class GeneratedXMLCode extends AnAction 
    @Override
    public void actionPerformed(@NotNull AnActionEvent event) 
        Project project = event.getProject();
        XmlFile xmlFile = (XmlFile)event.getData(LangDataKeys.PSI_FILE);
        DomManager domManager = DomManager.getDomManager(project);
        Root root = domManager.getFileElement(xmlFile, Root.class).getRootElement();
        System.out.println("获取value值"+root.getFoo().getBars().get(0).getValue());
        System.out.println("获取name属性的值"+root.getFoo().getBars().get(0).getName().getValue());
        WriteCommandAction.runWriteCommandAction(project,()->
            //写生成的逻辑
            //比如根据Foo的name 生成name对应java类的字段
            //获取foo
            Foo foo = root.getFoo();
            //获取class
            PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(project);
            PsiClass cla = shortNamesCache.getClassesByName(foo.getName().getValue(), GlobalSearchScope.projectScope(project))[0];
            for (PsiField field:cla.getFields())
                Bar bar = foo.addBar();
                bar.getName().setValue(field.getName());
                bar.setValue("啦啦啦");
            
        );
    

按alt+insert

效果

5.XML跳转Java文件

代码

public class XMLToJavaProvider extends RelatedItemLineMarkerProvider 
    @Override
    protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo> result)
        //获取当前文件
        Project project = element.getProject();
        PsiFile containingFile = element.getContainingFile();
        DomManager domManager = DomManager.getDomManager(project);
        XmlFile xmlFile = (XmlFile) containingFile;
        Root root = domManager.getFileElement(xmlFile, Root.class).getRootElement();
        if (element instanceof XmlTag)
            XmlTag tag = (XmlTag)element;
            System.out.println(tag.getName());
            switch (tag.getName())
                case "foo":
                String className = root.getFoo().getName().getStringValue();
                createMark(className,element,result);
                    break;
                default:
                    break;
            
        
    

    private void createMark(String className,PsiElement element,Collection<? super RelatedItemLineMarkerInfo> result)
        Project project = element.getProject();
        Optional.ofNullable(className).ifPresent(c->
            PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(project);
            PsiClass psiClass <

史上最全android快速入门+进阶教程,求职涨薪必备,无偿分享

目前,Android虽不如几年前火爆,但其应用范围广泛,行业需求量较大,未来的发展前景也很不错。那么Android要怎么学?学多久呢?如果你只是想完成一些简单的Android开发工作,那么掌握Android编程基础,... 查看详情

kotlin入门教程史上最全最易于理解最全面的文章(代码片段)

这里写自定义目录标题前言Kotlin学习笔记1.val和var区别2.简单变量之间的转换3.数组变量的声明4.字符串字符串与基本类型的转换字符串常用方法字符串模板及其拼接5.容器集合Set/MutableSet队列List/MutableList映射Map/MutableMap6.条件分支... 查看详情

python爬虫入门到实战-史上最详细的爬虫教程

马哥高薪实战学员【Python爬虫入门到实战-史上最详细的爬虫教程,限时免费领取】爬虫分类和ROBOTS协议爬虫URLLIB使用和进阶爬虫URL编码和GETPOST请求 查看详情

python爬虫入门到实战-史上最详细的爬虫教程

马哥高薪实战学员【Python爬虫入门到实战-史上最详细的爬虫教程,限时免费领取】爬虫分类和ROBOTS协议爬虫URLLIB使用和进阶爬虫URL编码和GETPOST请求 查看详情

vue2.0史上最全入坑教程(下)——实战案例

前言:经过前两节的学习,我们已经可以创建一个vue工程了。下面我们将一起来学习制作一个简单的实战案例。说明:默认我们已经用vue-cli(vue脚手架或称前端自动化构建工具)创建好项目了一、项目说明ps:这个简单小项目只... 查看详情

fluxmonoreactor实战(史上最全)(代码片段)

文章很长,建议收藏起来慢慢读!疯狂创客圈总目录为您奉上珍贵的学习资源:免费赠送经典图书:《Java高并发核心编程(卷1)》面试必备+大厂必备+涨薪必备加尼恩免费领免费赠送经典图书:《Java高并... 查看详情

阅读源码时:idea中如何使用todo标记活动模板(史上最全)(代码片段)

接下来,尼恩要带大家完成一个超级牛逼的大厂offer收割机项目——100Wqps三级组件实操,实操中,用到caffeine并且,尼恩要带大家穿透式、起底式的学习caffeine的源码和架构,caffeine的源码特别复杂,所以要... 查看详情

最全androidkotlin入门教程(kotlin入门指南高级kotlin强化实战kotlin协程进阶实战)

Kotlin是一种新型的静态类型编程语言,有超过60%的专业Android开发者在使用,它有助于提高工作效率、开发者满意度和代码安全性。不仅可以减少常见代码错误,还可以轻松集成到现有应用中。目前在安卓开发中,... 查看详情

史上elasticsearch最全详细使用教程

‍‍点击上方关注“终端研发部”设为“星标”,和你一起掌握更多数据库知识来源:r6a.cn/cyJw本文介绍了ElasticSearch的必备知识:从入门、索引管理到映射详解。一、快速入门1. 查看集群的健康状况http://localhost:9200/_... 查看详情

初识springboot(傻瓜式教程)

初识springboot(傻瓜式教程)项目所需的版本IDEA2018maven3.xjdk-1.8IDEA创建spring-boot项目(maven方法)1、创建一个maven工程点击CreateNewProject选择新项目的SDK,按图中步骤操作。第一次创建会要求选择jdk位置按图中顺序填写GroupId和ArtifactId... 查看详情

史上最全mybatis框架入门教程,从零开始带你深入♂学习——mybatis入门(代码片段)

Mybatis框架(一)mybatis入门mybatis的使用mybatis中文文档:https://mybatis.org/mybatis-3/zh/index.html如果使用Maven来构建项目,则需将下面的依赖代码置于pom.xml文件中:<dependency><groupId>org.mybatis</groupI 查看详情

github教程史上最全github使用方法:github入门到精通

【初识Github】首先让我们大家一起喊一句“HelloGithub”。YEAH!就是这样。Git是一个分布式的版本控制系统,最初由LinusTorvalds编写,用作Linux内核代码的管理。在推出后,Git在其它项目中也取得了很大成功,尤其是在Ruby社区中。目... 查看详情

史上最全的opencv入门教程!这篇够你学习半个月了!万字长文入门(代码片段)

一、PythonOpenCV入门欢迎阅读系列教程,内容涵盖OpenCV,它是一个图像和视频处理库,包含C++,C,Python和Java的绑定。OpenCV用于各种图像和视频分析,如面部识别和检测,车牌阅读,照片编辑,高级机器人视觉,光学字符识别等等... 查看详情

史上最全springcloudalibaba入门教程,从零开始带你深入♂学习——环境搭建(代码片段)

SpringCloudAlibaba(一)——环境搭建SpringCloudAlibaba简介springcloudspring团队开源微服务工具集,帮助我们快速构建分布式系统(微服务系统),提供spring组织netflixspringcloudalibabaalibaba团队开源微服务工具集,... 查看详情

史上最全vim快捷键键位图(入门到进阶)

经典版下面这个键位图应该是大家最常看见的经典版了。对应的简体中文版其实经典版是一系列的入门教程键位图的组合结果,下面是不同编辑模式下的键位图。入门版基本操作的入门版。进阶版增强版下图是一个更新时间较新... 查看详情

史上最全springcloudalibaba入门教程,从零开始带你深入♂学习——nacos组件:环境配置(代码片段)

SpringCloudAlibaba(二)——Nacos组件:环境配置Nacos组件简介Nacos致力于帮助您发现、配置和管理微服务。Nacos提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理Nacos就是微服... 查看详情

android之一篇史上最适合最全面的jni入门教程(代码片段)

前言:  一定要下载demo,动手动脑,结合本篇博客来跑demo,否则看了也还是不会;写代码还是要勤动手才能掌握,否则里边的坑也只是想当然demoNDK的基础知识,强烈推荐小楠总的NDK系列博客,先... 查看详情

谷歌开源史上最详《kotlin入门进阶实战》,学不动也要学(代码片段)

Kotlin作为Android开发的首选语言,为开发者提供了大量的语法糖和技巧,让开发者可以专注于需求开发,而将语言所带来的影响减少到最少。Java和Kotlin最大的区别,实际上在于Kotlin的函数式编程思想以及语法,... 查看详情