PSI文件

走着路睡觉大约 3 分钟

PSI文件

PSI (Program Structure Interface) 文件用结构化数据来表示文件内容。

PsiFileopen in new window 类是所有 PSI文件的父类,其它的编程语言中的文件都是它的子类,例如,JAVA中表示为 PsiJavaFileopen in new window ,XML中表示为 XmlFileopen in new window

VirtualFileDocument 作用域是 application (即使打开了多个项目,每个文件都使用同一个 VirtualFile 实例)。PSI的作用域是 project:如果同一时间,在多个项目中打开同一个文件,这个文件会有多个PsiFile实例。

如果获取PSI文件

ContextAPI
ActionAnActionEvent.getData(CommonDataKeys.PSI_FILE)open in new window
DocumentPsiDocumentManager.getInstance(project).getPsiFile()open in new window
PSI ElementPsiElement.getContainingFile()open in new window (如果不属于任何文件,则返回null)
Virtual FilePsiManager.getInstance(project).findFile()open in new window
File NameFilenameIndex.getFilesByName(project, name, scope)open in new window

PSI文件能干啥

可以直接修改某个PSI元素,不需要修改整个文件。

可以使用下面代码遍历PSI文件中的PSI元素:

psiFile.accept(new PsiRecursiveElementWalkingVisitor() {
  // 访问PSI元素
});

更多内容请查看文档: PSI导航

PSI文件从哪来

PSI依赖于编程语言,使用Languageopen in new window 实例创建的:

LanguageParserDefinitions.INSTANCE
    .forLanguage(MyLanguage.INSTANCE)
    .createFile(fileViewProvider);

Documents 一样,当访问某个文件的PSI时,就会创建对应的PSI文件

PSI 文件可以保存多长时间?

Documents 一样,PSI文件来自于VirtualFile的弱引用,当不被任何对象引用的时候,会被回收。

如何创建PSI文件

PsiFileFactory.createFileFromText()open in new window 可以根据指定的内容在内存中创建 PSI文件

PsiDirectory.add()open in new window 方法可以把 PSI文件保存在硬盘上。

如何监控PSI文件修改

PsiManager.getInstance(project).addPsiTreeChangeListener() 可以监控项目中PSI树的所有修改。或者在plugin.xml里注册扩展,代码如下:

    <extensions defaultExtensionNs="com.intellij">
        <psi.treeChangeListener implementation="com.intellij.psi.PsiTreeChangeListener 实现类" ></psi.treeChangeListener>
    </extensions>

如何继承PSI

当需要支持新编程语言的时候,需要继承PSI, 具体可查看文档: Custom Language Supportopen in new window

PSI的工作规则

PSI文件的所有修改都会反映到 Document 上,所以和Document 的规则是一样的(读,写,命令,只读等),可以参考它的文档。

上次编辑于:
贡献者: zhaojingbo
Loading...