索引和PSI Stubs
索引
通过索引可以快速查找元素,例如:在代码库中,查找包含某个单词或某个方法的文件。插件开发者可以使用IDE已有的索引来构建和使用自己的索引。
有以下2种索引:
文件索引 :基于文件内容构建的索引。通过该索引可以直接搜索到符合指定条件的文件
Stud索引 :基于序列化Stub trees 构建。 Stub tree 是PSI tree 的子集,只包含PSI tree中外部可见的声明,以二进制格式存储。该索引可以搜索符合指定条件的PSI元素集。
提示
PSI tree: PSI树,例如在java类中,java类会被解构为一个一个的PsiElement(PSI元素),所有的PsiElement构建为一个PSI树,可以参考文档 PSI元素
提示
可以使用 Index Viewer 插件查看索引的内容和属性。
Dumb mode
索引在后台进程中进行构建,在构建索引的过程中,DumbService 限制了 只能使用 文本编辑或版本控制等不需要使用索引的功能 ,如果调用了需要使用索引的功能,会抛出 IndexNotReadyException 异常。
通过DumbService 可以获取当前项目处于 dumb模式(该模式下不能访问索引)还是 smart模式(该模式下,索引构建完成,可以使用索引),也可以等待项目处于smart模式时再执行操作。
//判断项目处于什么模式下
// dumb模式(该模式下不能访问索引)
// smart模式(该模式下,索引构建完成,可以使用索引)
DumbService.getInstance(project).isDumb();
DumbService.isDumb(project);
//等待项目处于 smart模式 时,再执行业务操作
DumbService.getInstance(project).runWhenSmart(()->{//业务逻辑});
Gists
有时候会碰到以下情况:
不需要使用文件索引,只需要计算文件内容的相关数据,并将数据缓存到硬盘上
不需要在索引构建期间执行计算(例如:它会拖慢索引的构建,或者只有一小部分文件曾经需要这些计算数据)
可以根据请求延迟重新计算数据,而不会造成明显的性能损失。
大部分情况下可以使用 文件索引 ,但是通过 gists的API 可以延迟计算,并缓存到硬盘上, 可以参考 VirtualFileGist 和 PsiFileGist 的文档。
示例:
VirtualFileGist :使用 ImageInfoIndex 计算图片的大小尺寸并显示到UI上。
PsiFileGist : 使用 JavaSimplePropertyGist 获取Java类的简单属性
提高索引性能
性能指标
在2020.2及以后的版本中,索引的性能指标以json格式存储在了沙盒中的logs文件夹中,从2021.1版本开始,以HTML格式存储了另外的一些指标,参考下图:
沙盒路径查看文档:插件开发项目配置
避免使用AST
如果可能,尽量使用词法分析器信息而不是解析树。 如果不可能,请使用不会占用大量内存的经量级AST(LighterAST) ,这样可以提升遍历速度。可以通过将传过来的 FileContent参数 转换为 PsiDependentFileContent 然后调用 getLighterAST() 来获取 LighterAST,使用 LighterASTNodeVisitor 和LightTreeUtil 来遍历自己需要用到的节点,
继承 LightStubBuilder 来实现轻量级 Stub 索引
If a custom language contains lazy-parseable elements that never or rarely contain any stubs, consider implementing StubBuilder.skipChildProcessingWhenBuildingStubs() (preferably using Lexer/node text).
考虑使用 NanoXmlUtil 来索引 xml 文件
预创建Stubs
如果你使用的编程语言有大量的对所有用户都一样的组件库,你可以注册 PrebuiltStubsProvider 扩展 来预创建Stubs索引,避免每次安装都需要构建Stubs索引。