当前位置:   article > 正文

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

idea插件开发

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

再新建第一个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());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

点击运行
在这里插入图片描述
点击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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

配置:
在这里插入图片描述

<localInspection
            id="inspection.XMLInspection"
            language="XML"
            shortName="XMLInspection"
            displayName="XMLInspection"
            groupName="XMLInspection"
            enabledByDefault="true"
            level="ERROR"
            implementationClass="com.yishu.plugin.inspection.XMLInspection"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

效果
在这里插入图片描述

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));
        });
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

配置:

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

效果
在这里插入图片描述
在这里插入图片描述
这里的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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

定义interface
在这里插入图片描述

Root

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

public interface Root extends DomElement {
    @SubTag("foo")
    Foo getFoo();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Foo

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Bar

public interface Bar extends DomElement {
    String getValue();
    void setValue(String s);
    @Attribute("name")
    GenericAttributeValue<String> getName();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

注册DomFileDescription:

public class XmlDescription extends DomFileDescription<Root> {
    public XmlDescription() {
        super(Root.class, "root", "");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5

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("啦啦啦");
            }
        });
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

按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 = shortNamesCache.getClassesByName(className, GlobalSearchScope.projectScope(project))[0];
            Optional.ofNullable(psiClass).ifPresent(p->{
                NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder
                        .create(AllIcons.Actions.Back)
                        .setTarget(psiClass)
                        .setTooltipTitle("跳转java文件");
                result.add(builder.createLineMarkerInfo(element));
            });
        });

    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

配置:放在extensions标签下

<codeInsight.lineMarkerProvider implementationClass="com.yishu.plugin.provider.XMLToJavaProvider" language="XML"/>
  • 1

启动看看效果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/112144
推荐阅读
相关标签
  

闽ICP备14008679号