为什么 ReSharper Find Usages 命令搜索 resx 文件?

Why does the ReSharper Find Usages command search resx files?

当我右键单击一个符号并运行 Find Usages ReSharper 命令时,ReSharper 似乎通常将大部分时间花在搜索 resx 文件上。在进度对话框可见的大部分时间内,该对话框中显示的文件名是解决方案中的各种 .resx 文件。

ReSharper 是否真的在搜索 .resx 文件?为什么要这样做,为什么要花这么长时间?我可以改变这种行为吗?


设置:ReSharper 8.2.0.2160 C# 版。 Visual Studio 2013 高级版。

我尝试过的:

这个问题的答案全归功于 ReSharper 的底层架构。在处理文件时,ReSharper 会构建一棵抽象语法树,树中的每个节点都可以有一个或多个对语义模型中元素的引用。换句话说,表达式 new Foo(42) 中的 Foo 将引用描述 class 的语义元素 Foo。每个文件都会有很多引用,因为元素(变量、参数、方法、属性、CSS、class、HTML颜色、文件系统路径和more) 对该元素的声明有一个或多个引用。

这些参考资料非常强大。它们通过简单地导航到引用的目标来启用 Ctrl+单击导航。他们可以通过显示满足代码当前位置引用的候选目标来提供代码完成。

当然,它们还通过查找针对特定元素的所有引用来为 Find Usages 提供支持。但这需要逆向工作,从目标到参考。蛮力方法需要检查每个文件中每个引用的目标,试图找到目标。这显然无法扩展,而且数据集太大无法缓存。

为了在合理的时间范围内查找用法 运行,ReSharper 还为所有文件中使用的所有单词维护一个单词索引(这也有助于正常的转到导航)。当您在符号上调用 Find Usages(例如问题屏幕截图中的 EnterDate)时,ReSharper 使用单词索引来缩小它需要搜索的文件的范围 - 它会查找 EnterDate,并且只使用那些包含这个词的文件。一旦减少了要搜索的文件子集,它就需要找到任何以原始元素为目标的引用。为此,它遍历子集中每个文件的语法树。检查每个节点是否有与我们要查找的符号名称匹配的引用,例如EnterDate。如果匹配,则解析引用,并检查目标以查看它是否匹配相同的元素 - EnterDate class 或 属性 或实际上是什么。如果确实指向预期目标,则会将其添加到用法集合中,并显示给用户。

(事情比这稍微复杂一些,因为引用可能有多个名称,例如,如果您尝试查找 [Pure] 上的用法,ReSharper 需要找到 Pure 两者的任何用法或PureAttribute。幸运的是,这些替代名称也存储在单词索引中,用于帮助减少要搜索的文件。在检查参考文献时,所有替代名称都被检查)

因此,如果您有一个包含文本 EnterDate 的 .resx 文件,系统将搜索它以查找对您要查找的 EnterDate 元素的引用 - ReSharper 将遍历语法.resx 文件的树,并检查每个引用以查看它是否匹配 EnterDate.

我们检查所有文件,即使用户认为目标元素不可能在该文件中使用也是显而易见的,因为我们允许跨语言引用。也就是说,VB 文件可以引用 C# 元素,或者 HTML 文件可以引用 CSS 元素,或者 XAML 文件引用 C# 方法元素,等等在。所以没有过滤 "sensible" 用法。例如,如果 EnterDate 是 class,作为用户,您可以判断它不太可能在 .resx 文件中,但 ReSharper 无法知道这一点。毕竟,在 web.config 文件的 type 属性中使用 class 名称或者作为 VB 文件中 typeof 的参数是完全没问题的.或者一个插件可以添加一个引用提供者,允许在 .resx 文件中使用类型名。因此,我们保持简单并搜索所有候选参考,即使它在进度对话框中看起来很奇怪。