Roslyn - 查找所有对具有调用详细信息的方法的引用(具体的通用参数)
Roslyn - find all references to method with invocation details (concrete generic arguments)
假设我有一个带有一些通用方法的接口,比如这个:
public interface IService
{
Task DoGenericAsync<T>();
}
然后我有一堆项目的一些解决方案,我有以下参考资料:
class SomeDomainService
{
private readonly IService _service;
public Task Process()
=> _service.DoGenericAsync<A>();
}
现在的目标是找到这个方法的所有调用,更重要的是——具体的泛型参数是什么。在这种特殊情况下,我想发现 IService.DoGenericAsync<T>()
是使用通用参数 <A>
.
调用的
因此,按照几个教程和问题,我能够通过找到我的接口方法声明的 ISymbol
然后调用 SymbolFinder.FindReferencesAsync
来使用 Roslyn 找到对目标方法的所有引用获取所有参考资料。
这很好用,我得到了正确的调用位置(ReferencedSymbol
实例的集合,但是这些结果的 Definition
属性 returns 我只是一般关于符号的信息(好吧,准确定义 :)),那么我如何找出实际参数是什么?
所以 ReferenceLocation
有两个属性,一个 Document
和一个 Location
。该文档允许您获取 SyntaxTree
和 SemanticModel
。当您拥有 SyntaxTree
时,您可以调用 FindNode 并传入 Location.SourceSpan
,这应该会让您获得调用节点。从那里您可以调用 SemanticModel.GetSymbolInfo
,这将为您提供一个包含方法符号的结构,然后您可以从那里查看类型参数。
免责声明: 不幸的是我还没有完成这个宠物项目,但这是我根据接受的答案编写的代码示例:
foreach (var reference in references)
{
foreach (var location in reference.Locations)
{
var syntaxTree = await location.Document.GetSyntaxTreeAsync();
var root = await syntaxTree.GetRootAsync();
var syntaxNode = root.FindNode(location.Location.SourceSpan);
var compilation = compilations.First(x => x.ContainsSyntaxTree(syntaxTree));
var semanticModel = compilation.GetSemanticModel(syntaxTree);
var symbolInfo = semanticModel.GetSymbolInfo(syntaxNode);
var methodSymbol = (symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.First()) as IMethodSymbol;
var typeSymbol = methodSymbol.TypeArguments.First();
// then use 'typeSymbol' to find the actual type etc
}
}
在这种情况下,references
是 ReferencedSymbol
(我在问题中谈论的那个)的集合; compilations
- 是我正在分析的已加载解决方案中所有项目的 Compilation
的集合。
假设我有一个带有一些通用方法的接口,比如这个:
public interface IService
{
Task DoGenericAsync<T>();
}
然后我有一堆项目的一些解决方案,我有以下参考资料:
class SomeDomainService
{
private readonly IService _service;
public Task Process()
=> _service.DoGenericAsync<A>();
}
现在的目标是找到这个方法的所有调用,更重要的是——具体的泛型参数是什么。在这种特殊情况下,我想发现 IService.DoGenericAsync<T>()
是使用通用参数 <A>
.
因此,按照几个教程和问题,我能够通过找到我的接口方法声明的 ISymbol
然后调用 SymbolFinder.FindReferencesAsync
来使用 Roslyn 找到对目标方法的所有引用获取所有参考资料。
这很好用,我得到了正确的调用位置(ReferencedSymbol
实例的集合,但是这些结果的 Definition
属性 returns 我只是一般关于符号的信息(好吧,准确定义 :)),那么我如何找出实际参数是什么?
所以 ReferenceLocation
有两个属性,一个 Document
和一个 Location
。该文档允许您获取 SyntaxTree
和 SemanticModel
。当您拥有 SyntaxTree
时,您可以调用 FindNode 并传入 Location.SourceSpan
,这应该会让您获得调用节点。从那里您可以调用 SemanticModel.GetSymbolInfo
,这将为您提供一个包含方法符号的结构,然后您可以从那里查看类型参数。
免责声明: 不幸的是我还没有完成这个宠物项目,但这是我根据接受的答案编写的代码示例:
foreach (var reference in references)
{
foreach (var location in reference.Locations)
{
var syntaxTree = await location.Document.GetSyntaxTreeAsync();
var root = await syntaxTree.GetRootAsync();
var syntaxNode = root.FindNode(location.Location.SourceSpan);
var compilation = compilations.First(x => x.ContainsSyntaxTree(syntaxTree));
var semanticModel = compilation.GetSemanticModel(syntaxTree);
var symbolInfo = semanticModel.GetSymbolInfo(syntaxNode);
var methodSymbol = (symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.First()) as IMethodSymbol;
var typeSymbol = methodSymbol.TypeArguments.First();
// then use 'typeSymbol' to find the actual type etc
}
}
在这种情况下,references
是 ReferencedSymbol
(我在问题中谈论的那个)的集合; compilations
- 是我正在分析的已加载解决方案中所有项目的 Compilation
的集合。