【问题标题】:Find all method calls for a specific method using Roslyn使用 Roslyn 查找特定方法的所有方法调用
【发布时间】:2016-02-17 14:29:35
【问题描述】:

我正在使用 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)。

我对@9​​87654323@文章的理解是GetDeclaredSymbolGetSymbolInfo返回的符号应该是一样的。但是,使用Equals 进行简单比较会返回false

有没有人知道返回的两个符号之间有什么区别,以及我如何才能得到“正确”的符号?或者也许完全有更好的方法?我所有的研究似乎都指向FindCallersAsync,但我就是无法让它发挥作用。

【问题讨论】:

    标签: c# roslyn roslyn-code-analysis


    【解决方案1】:

    我从这篇文章的理解是GetDeclaredSymbol和GetSymbolInfo返回的符号应该是一样的。但是,使用 Equals 的简单比较会返回 false。

    这是因为它们不是同一个符号;它们来自完全不同的编译,可能会或可能不会不同。一个来自正在编译的编译器,一个来自 MSBuildWorkspace。

    基本上,不支持在分析器中使用 MSBuildWorkspace。完全地。不要那样做。这不仅真的很慢,而且还存在各种正确性问题,尤其是当您在 Visual Studio 中运行分析器时。如果您的目标是在解决方案的任何地方找到未使用的方法,那么我们也不真正支持将其作为分析器实施,因为这涉及跨项目分析。

    【讨论】:

    • 对于internal 方法,一种方法是注册以分析定义时的方法符号和调用表达式,并跟踪所有已定义但未调用的符号。 (从技术上讲,调用是不够的,因为它们可能出现在 nameof 中,作为委托创建的一部分等)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    相关资源
    最近更新 更多