设为首页 加入收藏

TOP

索引和PSI存根 (Indexing and PSI Stubs?)(一)
2023-07-25 21:26:34 】 浏览:45
Tags:索引和 PSI 存根 Indexing and 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

的文档。

示例:

 

  • 获取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索引。

 文件索引

 

文件索引基于Map/Reduce

的数据结构。每一个索引都有一个指定类型的key,一个指定类型的value.

示例:word索引中,key就是word自己。value是跟key关联的,包含了word的context的对象(code, string literal, 或 comment)

在索引中,如果获取索引中某key的value的 type 等于 Void ,则表示不存在跟key相关的数据。

当一个索引实现类对一个文件创建了索引,那么这个索引实现类会收到该文件的内容,并返回一个Map, Map包含了该文件的索引key,及跟key相关的value

访问索引的时候,传入key,就能获取到跟key相关的所有文件。

提示

某些情况,可以不使用索引,而使用 Gist

# 实现文件索引

是一个相对简单的索引示例,它存储了 GUI Designer

.form中使用的class的全限定命令

注册索引实现类,如下:

 
<!--在plugin.xml里注册索引实现类--> <extensions defaultExtensionNs="com.intellij"> <fileBasedIndex implementation="com.intellij.util.indexing.FileBasedIndexExtension 的子类"></fileBasedIndex> </extensions> 
 

实现 com.intellij.util.indexing.FileBasedIndexExtension

分为以下几部分:

  • getIndexer() :返回 DataIndexer

  • ,它负责根据文件内容构建索引。

  • getKeyDescriptor() :返回以二进制的格式存储key的 KeyDescriptor

,最常用的是 KeyDescriptor的子类 EnumeratorStringDescriptor

  • ,它能提升存储效率。

  • getValueExternalizer() :返回以二进制格式存储value的 DataExternalizer

getInputFilter() :只过滤自己需要的文件。可以使用 DefaultFileTypeSpecificInputFilter

  • getName() :返回唯一的索引ID,推荐使用类的全限定命名,防止冲突,例如可以使用:com.example.myplugin.indexing.MyIndex

  • getVersion() :索引的版本。如果当前使用的索引版本和实现类的版本不一致,将会自动重新构建索引

如果获取到的va

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Redis—问题(1) 下一篇SpringBoot中如何集成Servlet呢?

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目