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。该文档允许您获取 SyntaxTreeSemanticModel。当您拥有 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
    }
}

在这种情况下,referencesReferencedSymbol(我在问题中谈论的那个)的集合; compilations - 是我正在分析的已加载解决方案中所有项目的 Compilation 的集合。