当我右键单击一个符号并运行 Find Usages ReSharper命令时,ReSharper通常会花费大部分时间来搜索resx文件。在进度对话框可见的大部分时间内,该对话框中显示的文件名是解决方案中的各种.resx文件。
ReSharper实际上是在搜索.resx文件吗?为什么会这样做,为什么需要这么长时间?我可以改变这种行为吗?
设置:ReSharper 8.2.0.2160 C#Edition。 Visual Studio 2013 Premium。
我尝试过的事情:
答案 0 :(得分:8)
答案完全归功于ReSharper的底层架构。处理文件时,ReSharper将构建一个抽象语法树,树中的每个节点都可以对语义模型中的元素进行一次或多次引用。换句话说,表达式Foo
中的new Foo(42)
将引用描述名为Foo
的类的语义元素。每个文件都有很多引用,因为元素的任何使用(变量,参数,方法,属性,CSS类,HTML颜色,文件系统路径等)都有一个或多个对该元素声明的引用。
这些引用非常强大。它们启用 Ctrl +单击导航,只需导航到引用的目标即可。他们可以通过显示满足代码中当前位置的引用的候选目标来提供代码完成。
当然,他们还通过查找针对特定元素的所有引用来为Find Usages提供支持。但这需要向后工作,从目标到参考。蛮力方法需要检查每个文件中每个引用的目标,试图找到目标。这显然不会扩展,而且数据集太大而无法缓存。
为了使Find Usages以理智的时间刻度运行,ReSharper还维护所有文件中使用的所有单词的单词索引(这也有助于正常的Go To导航)。当你在一个符号上调用查找用法时(例如问题屏幕截图中的EnterDate
),ReSharper使用单词index缩小搜索所需的文件 - 它会查找EnterDate
,并且仅使用包含该单词的那些文件。一旦它有一个缩小的文件子集进行搜索,它需要找到任何以原始元素为目标的引用。为此,它遍历子集中每个文件的语法树。检查每个节点是否有与我们正在寻找的符号名称匹配的引用,例如, EnterDate
。如果匹配,则解析引用,并检查目标以查看它是否匹配相同的元素 - EnterDate
类,或属性或实际上的任何内容。如果确实指向预期目标,则会将其添加到用法集合中,并显示给用户。
(事情稍微复杂一点,因为引用可能有多个名称,例如,如果您尝试在[Pure]
上找到用法,ReSharper需要查找Pure
或{{}}的任何用法{1}}。幸运的是,这些替代名称也存储在单词索引中,用于帮助减少要搜索的文件。检查引用时,会检查所有替代名称)
因此,如果您的.resx文件包含文本PureAttribute
,则会搜索其中您要查找的EnterDate
元素的引用 - ReSharper将使用语法.resx文件的树,并检查每个引用以查看它是否与EnterDate
匹配。
我们检查所有文件,即使用户似乎很明显目标元素也不能在该文件中使用,因为我们允许引用是跨语言的。也就是说,VB文件可以引用C#元素,或者HTML文件可以引用CSS元素,或者XAML文件引用C#方法元素,等等。所以没有过滤"明智的"用法。例如,如果EnterDate
是一个类,那么作为用户,您可以告诉它不可能在.resx文件中,但ReSharper无法知道这一点。毕竟,在web.config文件的EnterDate
属性中使用类名,或在VB文件中使用type
的参数是完全正确的。或者插件可以添加一个引用提供程序,允许在.resx文件中使用类型名称。因此,我们保持简单并搜索所有候选引用,即使它在进度对话框中看起来很奇怪。