首页 文章

使用Roslyn查找特定方法的所有方法调用

提问于
浏览
3

我正在使用Roslyn编写代码分析器,我当前的任务是找到程序集中未使用的所有内部方法 .

我从 MethodDeclarationSyntax 开始并从中获取符号 . 然后我在 SymbolFinder 中使用 FindCallersAsync 方法,但是即使我在程序集中某处调用了相关方法,它也会返回一个空集合 . 请参阅下面的代码 .

protected override void Analyze(SyntaxNodeAnalysisContext context)
{
    NodeToAnalyze = context.Node;
    var methodDeclaration = NodeToAnalyze as MethodDeclarationSyntax;

    if (methodDeclaration == null)
        return;

    var methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration) as ISymbol;

    if (methodSymbol.DeclaredAccessibility != Accessibility.Internal)
        return;

    var solutionPath = GetSolutionPath();

    var msWorkspace = MSBuildWorkspace.Create();
    var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;

    var callers = SymbolFinder.FindCallersAsync(symbol, solution).Result;  // Returns empty collection.

    ...
}

我见过类似的代码here,但在该示例中,方法符号是在 InvocationExpressionSyntax 上使用 GetSymbolInfo 获得的:

//Get the syntax node for the first invocation to M()
var methodInvocation = doc.GetSyntaxRootAsync().Result.DescendantNodes().OfType<InvocationExpressionSyntax>().First();
var methodSymbol = model.GetSymbolInfo(methodInvocation).Symbol;
//Finds all references to M()
var referencesToM = SymbolFinder.FindReferencesAsync(methodSymbol,  doc.Project.Solution).Result;

但是,就我而言,我需要从声明中找到调用(如果有的话) . 如果我首先获得调用并从 GetSymbolInfo 传递符号,则正确返回对方法的调用 - 因此问题似乎是 symbol 参数而不是 solution .

由于我试图获取声明的基础符号,我不能使用 GetSymbolInfo ,而是使用 GetDeclaredSymbol (如建议here) .

我在this文章中的理解是,从 GetDeclaredSymbolGetSymbolInfo 返回的符号应该是相同的 . 但是,使用 Equals 进行简单比较会返回 false .

有没有人知道返回的两个符号之间有什么区别,以及我如何获得有效的'correct'?或者也许完全有更好的方法?我所有的研究似乎都指向 FindCallersAsync ,但我无法让它发挥作用 .

1 回答

  • 3

    我对本文的理解是,GetDeclaredSymbol和GetSymbolInfo返回的符号应该相同 . 但是,使用Equals进行简单比较会返回false .

    这是因为它们不是同一个符号;它们来自完全不同的编辑,可能会也可能不会有所不同 . 一个来自正在积极编译的编译器,一个来自MSBuildWorkspace .

    从根本上说,不支持在分析器中使用MSBuildWorkspace . 完全 . 不要那样做 . 这不仅会非常缓慢,而且还会产生各种正确性问题,特别是如果你们不支持实现分析器,那么这涉及到跨项目分析 .

相关问题