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

Posted 亦疏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了史上最全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>

再新建第一个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 <

以上是关于史上最全idea插件开发入门实战(傻瓜式教程)的主要内容,如果未能解决你的问题,请参考以下文章

史上最全的Android基础教程+入门实战训练+处理技巧(建议收藏)|寻找C站宝藏

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

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

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

Vue安装环境最全教程,傻瓜式安装

史上最全面的Java8教程玩转函数式接口