基于Intellij 插件开发指南

4,863 阅读2分钟

1. VFS 相关(VirtualFileSystem)

1.1 VFS作用:

  • 提供一个处理文件的通用API,而不关心文件的具体位置(无论文件位于磁盘上、归档文件中还是HTTP服务器上)
  • 追踪文件变化,并且在检测到文件内容发生更改时能提供新旧两个版本的文件
  • 建立文件在VFS和持久化存储之间的关联

1.2. VFS中获取VirtualFile

  • 从本地IO文件中获取
File ioFile = new File("./io.java")
VritualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile)
virtualFile.refresh(false, true)
  • 利用FileChooser获取
FileChooserDescriptor singleFileDescriptor = FileChooserDescriptorFactory.createSingleFileDescriptor();
VirtualFile virtualFile = FileChooser.chooseFile(singleFileDescriptor, project, null);
  • 通过URL获取
VirtualFileManager.getInstance().findFileByUrl("xxx");
VirtualFileManager.getInstance().refreshAndFindFileByUrl("xxx");

1.3对VirtualFile进行读写操作

和Android一样,Intellij Platform不允许直接在主线程进行实时的文件写入,需要通过一个异步任务进行。

WriteCommandAction.runWriteCommandAction(project, new Runnable() {
     @Override
    public void run() {
    //   virtualFile.getInputStream() / virtualFile.getOutputStream()         
    }
 });

1.4 在异步任务结束后,切回UI线程进行UI更新

ApplicationManager.getApplication().invokeLater(new Runnable(){ 
 ...
})

2. PSI相关(Program Structure Interface)

2.1 PSI介绍

PSI(Program Structure Interface)是Intellij Platform中一个非常重要的概念,在IDE所管理的Project中,每个目录,Package,源代码和资源文件都会被抽象成相应的PSI对象。

2.2 常用子类

PsiDirectory、PsiJavaFile和XmlFile

2.3 创建目录和文件

//创建目录
PsiDirectory baseDir = PsiDirectoryFactory.getInstance(project).createDirectory(project.getBaseDir());
//创建Java文件
PsiJavaFile psiFile = (PsiJavaFile) PsiFileFactory.getInstance(project).createFileFromText("", StdFileTypes.JAVA, "");
//创建Xml文件
XmlFile psiFile = (XmlFile) PsiFileFactory.getInstance(project).createFileFromText("", StdFileTypes.XML, "");

2.4 读写文件

和写入VirtualFile一样,读写操作都需要在WriteCommandAction异步线程中进行。

2.5 Xml文件写入属性

XmlDocument document = xmlFile.getDocument();
if (document != null && document.getRootTag() != null) {
XmlTag rootTag = document.getRootTag();
rootTag.getAttribute(attrName).setValue(attrValue);//set value for exists attr.      
rootTag.setAttribute(name,value);//add a new attr and setting value
}

2.6 搜索文件

//  方法一:(全类名)
JavaPsiFacade.getInstance(mFile.getProject()).findClass(qualifiedName,GlobalSearchScope.alScope(mFile.getProject()));
//  方法二: (全类名)
FilenameIndex.getFilesByName()
//  方法三: (短类名)
PsiShortNamesCache.getInstance().getClassesByName()

2.7 创建Class文件类

PsiClass clazz = JavaDirectoryService.getInstance().createClass(subDir, className)

2.8 修改Class内容

 // 创建Class元素生成器
 PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(mFile.getProject());
 // 利用生成器创建对应的元素(每种元素都对应两种生成方式)
 elementFactory.createField() / elementFactory.createFieldFromText()
 elementFactory.createMethod() / elementFactory.createMethodFromText()  
 elementFactory.createClass() / elementFactory.createClassFromText()
      ... 
 //将元素添加到class中
 clazz.add(field)

2.9 修改class的继承关系

respClass.getExtendsList().add(getReferenceClass(elementFactory, BaseModelStr));

3.0 修改元素(class field method)的修饰关键字(public static ... )

// 添加
respClass.getModifierList().add(elementFactory.createKeyword("public"));
// 删除
reqClass.getModifierList().getFirstChild().delete();

3. PSI 与 VFS的联系

// VirtualFile 转 PsiFile
PsiManager.getInstance(project).findFile(virtualFile);

// PsiFile 转 VirtualFile
VirtualFile virtualFile = psiFile.getVirtualFile();

4 其他常用方法

// 格式化代码
CodeStyleManager.getInstance(project).reformat(psiClass);
// 用编辑器打开指定文件
FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, virtualFile), true);

5. 代码实例

github仓库地址