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

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

我从MethodDeclarationSyntax开始并从中获取符号。 然后我在FindCallersAsync中使用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. ... } 

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

 //Get the syntax node for the first invocation to M() var methodInvocation = doc.GetSyntaxRootAsync().Result.DescendantNodes().OfType().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 (如此处所示 )。

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

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

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

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

从根本上说,不支持在分析器中使用MSBuildWorkspace。 完全。 不要那样做。 这不仅非常慢,而且还有各种正确性问题,特别是如果您在Visual Studio中运行分析器。 如果你的目标是在解决方案的任何地方找到未使用的方法,那么我们并不真正支持将其作为分析器实现,因为这涉及跨项目分析。