一.插件功能
IntelliJ IDEA 是一款流行的JAVA 开发 IDE,对于提高编程效率有非常大的帮助。但是,还是会有一些特殊的需求它并不能满足,此时我们就需要通过开发插件来实现了。
主要的插件功能包含以下四种类型:
- 自定义语言支持:如果有 IDEA 暂时不支持的语言,可以自己写一个插件来支持,例如 Go 语言原来的支持就是通过插件做的,官方有自定义语言插件支持的教程;
- 框架支持:例如Struts 2 的框架支持;
- 工具集成:可以给 IDEA 的自带功能进行增强,例如对 Git 的操作增加 CodeReview 的功能;
- 用户界面:自定义插件来改变用户界面,比如 BackgroundImage;
二.插件开发常用场景
1.常用对象
JAVA相关应用里面的常用对象:
PsiFile: 应用中的文件,如.Java的文件或者是.xml的文件等;
PsiDirectory: 应用中的目录;
PsiJavaFile: Java源文件,如Demo.java;
PsiClass: 某个类,一个文件中可能会有多个类;
PsiMethod: 类中的某个方法;
PsiField: 类中的某个属性;
PsiAnnotation: 注解;
2.常用操作
Action 是 IDEA 插件开发中比较基本的概念,插件利用 Action 来往菜单栏和工具栏添加新的菜单或按钮,它继承了 com.intellij.openapi.actionSystem.AnAction
,当对应的菜单栏或者工具按钮被点击,则Action被调用,最为关键的就是 actionPerformed 方法。它的定义如下:
public void actionPerformed(@NotNull AnActionEvent anActionEvent) {}
定义好之后就可以在方法里面编写我们想要实现的插件功能了,常用的操作如下:
(1). 获取当前项目:
Project project = anActionEvent.getProject();
(2). 获取当前的编辑器对象:
Editor editor = anActionEvent.getData(CommonDataKeys.EDITOR);
(3). 获取当前编辑的文件:
PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
// 如果是Java文件,可以转换成PsiJavaFile
PsiJavaFile javaFile = (PsiJavaFile)psiFile;
(4). 获取JavaFile中的Class:
// 一个文件中可能会定义有多个Class,因此返回的是一个数组
PsiClass[] classes = javaFile.getClasses();
(5). PsiClass的常用方法:
1.获取所有属性:getFields、getAllFields
2.查找属性:findFieldByName(),其中第二个参数是是否查找父类的属性;
3.获取所有方法:getMethods/getAllMethods
4.查找方法:findMethodsByName
(6).在Class中创建Field:
PsiElementFactory elementFactory = PsiElementFactory.SERVICE.getInstance(project);
PsiField cField = elementFactory.createFieldFromText(annotationStringBuilder.toString() + "private String test;", null);
aClass.add(cField);
(7).在Class中创建Method:
PsiMethod method = elementFactory.createMethodFromText("public void test(){}", null);
aClass.add(method);
(8).判断Class或者Field是否包含有某个注解及获取注解属性值:
PsiAnnotation psiAnnotation = field.getAnnotation("javax.persistence.Column");
PsiAnnotationMemberValue memberValue = psiAnnotation.findAttributeValue("columnDefinition");
if (null != memberValue) {
String str = memberValue.getText();
}
(9).Import类:引入类操作是在File中进行的,在Class类上是无法导入的,如果已经获取到了javaFile对象,可以这样导入,否则需要先获取到Class所在的File后再进行导入:
javaFile.importClass(aClass);
(10).根据class获取所在文件:
PsiJavaFile psiJavaFile = (PsiJavaFile) aClass.getContainingFile();
(11).获取类所在包:
// 先获取到文件后再获取文件所在包
String daoPackage = ((PsiJavaFile) aClass.getContainingFile()).getPackageName();
(12).创建文件(包含文件中的类):
javaFile = (PsiJavaFile) PsiFileFactory.getInstance(project).createFileFromText("Test.java", JavaFileType.INSTANCE, "public class Test {}");
(13).获取当前文件所在包:
PsiDirectory containerDirectory = javaFile.getContainingDirectory();
(14).创建子包(子目录):
parentDirectory.createSubdirectory("test");
(15).将文件添加到包中去
psiDirectory.add(javaFile);
(16).获取Resource目录:
ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
List<VirtualFile> sourceRoots = rootManager.getSourceRoots(JavaModuleSourceRootTypes.RESOURCES);
VirtualFile resourceDirectory = sourceRoots.get(0);
(17).创建xml文件并加入到某个目录:
// content对应于XML文件内容
psiFile = PsiFileFactory.getInstance(project).createFileFromText(fileName, XMLLanguage.INSTANCE,content);
psiDirectory.add(psiFile);
(18).IDEA不允许在主线程进行实时的文件写入,需要通过一个异步任务进行:
WriteCommandAction.runWriteCommandAction(project, () -> FileUtil.createFile());
IDEA插件开发的具体实现可参考:
IDEA插件开发之实践篇