文章目录
idea插件开发入门实战前言一、书写第一个Hello World二、IDEA插件开发进阶
1.基于java文件的规则校验2.基于XML文件规则的校验3.基于java文件的代码自动生成方法4.基于XML文件的读写方法
前言
建议先看一遍官方文档再开始
IDEA插件开发官方文档
一、书写第一个Hello World
新建项目
完事之后先修改plugin.xml配置文件。
com.yishu.plugin 插件入门实战 1.0 顺便写啥 描述。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 啦啦啦。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
再新建第一个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默认有对于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需要新增配置
language 这里表示作用于JAVA文件
此时我们重新运行,新建查看效果。
如果想实现对方法,类名,包名等的校验,只需要重写相应的方法就行了。这里的方法有很多
和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;
}
}
配置:
效果
代码:
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));
});
}
}
配置:
效果
这里的age没标记位置,就简单写了个例子,需要自己通过addAfter等方法定位要生成的地方。就不详细说了
XML文件比较独特,这里展开讲讲。
建议先看官网介绍
https://plugins.jetbrains.com/docs/intellij/xml-dom-api.html#abstract
官网有提供两种方法读写XML文件,第一种是上面那样的,但是我觉得有点蠢,还不好复用也容易写错。
我们用第二种。
先把示例的XML文件拿到
123 456
定义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 getName();
@SubTagList("bar")
List getBars();
Bar addBar();
}
Bar
public interface Bar extends DomElement {
String getValue();
void setValue(String s);
@Attribute("name")
GenericAttributevalue getName();
}
注解记得加上,因为子标签不是唯一的时候,不加注解会获取不到
注册DomFileDescription:
public class XmlDescription extends DomFileDescription{ 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
效果



