PSI:代码结构模型¶
PSI,全称 Program Structure Interface,是 IntelliJ Platform 对源代码结构的抽象模型。它基于文件内容构建语法和语义结构,是补全、跳转、查找用法、检查、重构、格式化等能力的基础。
PSI、Document、VirtualFile 的关系¶
| 概念 | 表示什么 | 常见用途 |
|---|---|---|
VirtualFile |
虚拟文件系统中的文件 | 路径、文件类型、刷新、二进制/文本区分 |
Document |
编辑器里的文本内容 | 文本修改、光标位置、行列信息 |
PsiFile / PsiElement |
代码结构树 | 语法结构、引用、解析、重构 |
常见转换:
val psiFile = event.getData(CommonDataKeys.PSI_FILE)
val virtualFile = psiFile?.virtualFile
val document = psiFile?.let {
PsiDocumentManager.getInstance(project).getDocument(it)
}
读取 PSI¶
后台线程读取 PSI 时要放在 Read Action 中:
val name = com.intellij.openapi.application.ReadAction.compute<String, Throwable> {
psiFile.name
}
Kotlin 且目标平台较新时,优先使用协程风格的 readAction API。
修改 PSI¶
修改 PSI、VFS 或项目模型必须在 Write Action 中执行,并且通常需要从安全的 EDT 上下文调度。
com.intellij.openapi.command.WriteCommandAction.runWriteCommandAction(project) {
element.replace(newElement)
}
如果修改来自用户命令,使用 WriteCommandAction 通常比裸 WriteAction 更合适,因为它会接入撤销栈。
PSI Element 与引用¶
PsiElement 表示语法树节点。引用通常由 PsiReference 提供:
resolve():跳转到声明。getVariants():提供基础补全候选。handleElementRename():支持重命名。
语言插件通常会围绕 PSI Element、Reference、Scope Processor 和 Index 构建核心能力。
调试 PSI¶
开发时建议使用:
- PSI Viewer:查看当前文件的 PSI 树。
- Internal Mode:打开更多 IDE 内部诊断功能。
- Debugger:观察
PsiElement类型、文本范围、父子结构。
常见原则¶
- 不要长期缓存
PsiElement;跨 Read Action 后要重新校验isValid。 - 尽量缓存可恢复的轻量键,例如
SmartPsiElementPointer、文件 URL、FQN。 - 修改 PSI 前先用工厂创建合法节点,例如 Java 使用
PsiElementFactory。 - 不要在 UI renderer、Action
update()或未受控线程里修改 PSI。