IDEA插件开发日记(二)

462 阅读3分钟

IDEA插件开发日记(二)

2024.4.29

PSI

全称 程序结构接口(Program Structure Interface),是IDEA插件开发中比较难的部分。负责解析文件并创建语法和语义代码模型,为平台的众多功能提供支持。个人理解就是将代码的各个元素分解开来,形成一颗树,然后可以定位到我们想要的代码,可以对其进行修改、删除等操作。 ​ PSI主要包含三方面内容:

  • PSI File
  • File View Provider
  • PSI Element

1.PSI File

PSI(程序结构接口)文件是结构的根,将文件内容表示为特定编程语言中元素的层次结构。 ​ PsiFile 类是所有 PSI 文件的公共基类,而特定语言的文件通常由其子类表示。

例如,PsiJavaFile 类表示一个 Java 文件,而 XmlFile 类表示一个 XML 文件。 ​ 与Virtual Files和Documents有应用范围(即使打开多个项目,每个文件都由同一个VirtualFile实例表示)不同,PSI有项目范围:

如果文件属于多个项目,则同一个文件由多个PsiFile实例表示 同时打开。

在 IntelliJ IDEA 插件开发中,可以使用 PSI 文件来完成许多任务,例如:

  1. 导航和查找:通过分析 PSI 文件,可以实现跳转到定义、查找引用等导航功能。插件可以定位代码中的特定元素,并在编辑器中进行高亮显示或进行其他操作。
  2. 代码分析:通过遍历 PSI 树,可以执行静态代码分析。插件可以检测代码中的错误、潜在问题或编码风格违规,并提供相应的警告或建议。
  3. 重构和代码生成:PSI 文件提供了修改代码结构的能力。插件可以使用 PSI 文件来执行重构操作,例如重命名变量、提取方法、内联方法等。此外,还可以基于代码模板生成新的代码。
  4. 代码生成和自动完成:插件可以利用 PSI 文件生成代码片段,并将其插入到编辑器中。这对于自动完成功能非常有用,可以根据上下文为用户提供代码补全建议。

2.File View Provider

    现实情况是编程语言是可以混合多种语言混写的,这时就需要用到了文件视图提供程序 ( FileViewProvider) ,它可以对单个文件中多个 PSI 树的访问。例如,JSPX 页面中的 Java 代码有一个单独的 PSI 树 ( `PsiJavaFile`),XML 代码有一个单独的树 ( `XmlFile`),整个 JSP 有一个单独的树 ( `JspFile`)。
    每种语言被包装成单独的PSI树,然后在源文件的入口处饮食了一个"outer language elements"的点位符。每个 PSI 树都覆盖了文件的全部内容,并在可以找到不同语言内容的地方包含特殊的“外部语言元素”。

总结一下:一个FileViewProviderinstance对应一个VirtualFile,一个single Document,包含一或多个PsiFileinstance

3.PSI Element

上述提到了元素就是这里所说的PSI Element。

How do I get a PSI element? 

ContextAPI
ActionAnActionEvent.getData(CommonDataKeys.PSI_ELEMENT)注意:如果编辑器当前打开并且插入符号下的元素是引用则这将返回解析引用的结果。
PSI FilePsiFile.findElementAt(offset) - 这会返回指定偏移处的叶元素,通常是词法分析器标记。用于PsiTreeUtil.getParentOfType()查找确切类型的元素。PsiRecursiveElementWalkingVisitor
ReferencePsiReference.resolve()