使用Microsoft Roslyn构建调用层次结构

Bjo*_*pen 5 c# roslyn

我试图静态地构建C#解决方案的调用层次结构,或者换句话说,试图找出解决方案中每个方法调用的方法.

我稍微修改了另一个问题的代码片段,但它没有完全削减它:

无论何时调用基类方法,该链都会被破坏,并且该方法依次调用在子类中实现的抽象或虚方法.

var syntaxTree = SyntaxTree.ParseText(Code);
var compilation = Compilation.Create("name").AddSyntaxTrees(syntaxTree);
var semanticModel = compilation.GetSemanticModel(syntaxTree);
var methods = syntaxTree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>();
foreach (var method in methods)
{
    var invocations = method.DescendantNodes().OfType<InvocationExpressionSyntax>();
    foreach (var syntax in invocations)
        Debug.WriteLine(semanticModel.GetDeclaredSymbol(method) + " calls method " + 
            semanticModel.GetSymbolInfo(syntax).Symbol);
}
Run Code Online (Sandbox Code Playgroud)

以下是一些示例代码来说明问题.基类方法Bar调用在C2中实现的抽象方法Baz.

class Program2
{
    void Main()
    {
        new C2().Bar();
    }
}

abstract class C1
{
    public void Bar()
    {
        Baz();
    }

    public abstract void Baz();
}

class C2 : C1
{
    public override void Baz() { }
}
Run Code Online (Sandbox Code Playgroud)

但是,当在示例代码上运行顶部代码片段时,它认为调用是C1.Baz():

Program2.Main() calls method C1.Bar() 
C1.Bar() calls method C1.Baz()
Run Code Online (Sandbox Code Playgroud)

我们如何使用语义模型来确定它实际上是C2.Baz()?