原文链接:
http://www.jetbrains.org/intellij/sdk/docs/basics/indexing_and_psi_stubs/file_based_indexes.html
基于文件的索引基于Map/Reduce架构。 每个索引具有某种类型的键和某种类型的值。
键是以后用来从索引检索数据。
例如: 单词索引的键是单词本身。
值是与索引中的键相关联的任意数据。
例如: 单词索引的值是指示该单词(代码,字符串字面量或注释)在哪个上下文中出现的掩码。
在最简单的情况下,当我们只需要知道在数据出现在那些文件中时,值的类型是Void
并且不存储在索引中。
当索引文件时,它接收文件的内容并返回一个从文件中找到的键到关联值的映射。
当访问索引时,你可以指定感兴趣的键便会返回键出现的文件列表和与每个文件关联的值。
实现基于文件的索引
一个相当简单的基于文件索引的实现是UI Designer bound forms index。参考它作为一个例子来更好地理解这个主题。
每个特定的索引实现是一个继承FileBasedIndexExtension的类。 基于文件的索引应该注册<fileBasedIndex>
扩展点。
基于文件的实现包含以下主要部分:
-
getIndexer()
返回索引器类,其负责根据文件内容实际构建一组键/值对; -
getKeyDescriptor()
返回键描述符,其负责比较键并将其存储为序列化的二进制格式。
可能最常用的KeyDescriptor
实现是EnumeratorStringDescriptor
,其设计为高效地存储标识符。
-
getValueExternalizer()
返回值序列化程序,它负责以序列化的二进制格式存储值。 -
getInputFilter()
允许仅将索引限制到某一组文件。 -
getVersion()
返回索引实现的版本。如果当前版本与用于构建索引的索引实现的版本不同,索引将会自动重建。
如果不需要任何值与文件关联(即值类型为Void),你可以使用ScalarIndexExtension作为基类来简化实现。
注意
DataIndexer.map()
返回的数据必须仅依赖于传递给方法的输入数据,不能依赖于任何外部文件。 否则当外部数据更改时,你的索引将无法正确更新并且索引中将有过期数据。
注意 请查阅
com.intellij.util.indexing.DebugAssertions
了解如何在开发期间启用额外调试断言以断言正确的索引实现。
访问基于文件的索引
访问基于文件的索引是通过FileBasedIndex类进行的。
支持的主要操作如下:
-
getAllKeys()
和processAllKeys()
允许获取指定项目部分文件中找到的所有键的列表。
注意 返回的数据保证包含在最新项目内容中找到的所有键,但也可能包含项目中当前未找到的其它键。
-
getValues()
允许获取与指定键关联的所有值但是不包含文件中找到的; -
getContainingFiles()
允许获取遇到指定键的所有文件; -
processValues()
允许遍历遇到指定键的所有文件并同时访问相关的值。
注意 嵌套索引访问是禁止的因为它可能导致死锁。 首先从索引A收集所有必要的数据,然后在访问索引B时处理结果。
标准索引
*IntelliJ平台 *包含许多标准的基于文件的索引。插件开发者最有用的索引是:
- 单词索引
- 文件名索引
通常,单词索引应该被间接访问但可以使用PsiSearchHelper
类中的辅助方法。
第二个索引是FilenameIndex
。它提供了一种快速方法来查找与特定文件名匹配的所有文件。FileTypeIndex
提供了类似的目标:它允许快速找到特定文件类型的所有文件。