简体   繁体   English

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

[英]Find all method calls for a specific method using Roslyn

I am working on a code analyser using Roslyn and my current task is to find all internal methods which are unused in the assembly. 我正在使用Roslyn编写代码分析器,我当前的任务是找到程序集中未使用的所有内部方法。

I start with a MethodDeclarationSyntax and get the symbol from that. 我从MethodDeclarationSyntax开始并从中获取符号。 I then use the FindCallersAsync method in SymbolFinder , but it returns an empty collection even when I am making a call to the method in question somewhere in the assembly. 然后我用FindCallersAsync方法SymbolFinder ,但它返回甚至当我有问题在装配拨打电话的方法某处一个空的集合。 See the code below. 请参阅下面的代码。

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.

    ...
}

I have seen similar code here , but in that example the method symbol is obtained using GetSymbolInfo on an InvocationExpressionSyntax : 我在这里看到过类似的代码,但在该示例中,方法符号是使用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;

However, in my case, I need to find the invocations (if any) from a declaration. 但是,就我而言,我需要从声明中找到调用(如果有的话)。 If I do get the invocation first and pass in the symbol from GetSymbolInfo the calls to the method are returned correctly - so the issue seems to be with the symbol parameter and not solution . 如果我首先获得调用并从GetSymbolInfo传入符号,则正确返回对方法的调用 - 因此问题似乎是symbol参数而不是solution

Since I am trying to get the underlying symbol of a declaration, I cannot use GetSymbolInfo , but use GetDeclaredSymbol instead (as suggested here ). 由于我试图获取声明的基础符号,我不能使用GetSymbolInfo ,而是使用GetDeclaredSymbol (如此处所示 )。

My understanding from this article is that the symbols returned from GetDeclaredSymbol and GetSymbolInfo should be the same. 我的理解,从这个文章是符号从返回GetDeclaredSymbolGetSymbolInfo应该是相同的。 However, a simple comparison using Equals returns false . 但是,使用Equals进行简单比较会返回false

Does anyone have any idea of what the difference is between the two symbols returned and how I can get the 'correct' one which works? 有没有人知道返回的两个符号之间有什么区别,以及如何获得有效的“正确”符号? Or perhaps there is a better approach entirely? 或者也许完全有更好的方法? All my research seems to point to FindCallersAsync , but I just can't get it to work. 我的所有研究似乎都指向FindCallersAsync ,但我无法让它工作。

My understanding from this article is that the symbols returned from GetDeclaredSymbol and GetSymbolInfo should be the same. 我对本文的理解是,从GetDeclaredSymbol和GetSymbolInfo返回的符号应该是相同的。 However, a simple comparison using Equals returns false. 但是,使用Equals进行简单比较会返回false。

This is because they're not the same symbol; 这是因为它们不是同一个符号; they are coming from entirely different compilations which might or might not be different. 它们来自完全不同的编辑,可能会也可能不会有所不同。 One is coming from the compiler that is actively compiling, one is coming from MSBuildWorkspace. 一个来自正在积极编译的编译器,一个来自MSBuildWorkspace。

Fundamentally, using MSBuildWorkspace in an analyzer is unsupported. 从根本上说,不支持在分析器中使用MSBuildWorkspace。 Completely. 完全。 Don't do that. 不要那样做。 Not only would that be really slow, but it also has various correctness issues, especially if you're running your analyzer in Visual Studio. 这不仅非常慢,而且还有各种正确性问题,特别是如果您在Visual Studio中运行分析器。 If your goal is to find unused methods anywhere in a solution, that's something we don't really support implementing as an analyzer either, since that involves cross-project analysis. 如果您的目标是在解决方案中的任何位置找到未使用的方法,那么我们并不真正支持将其作为分析器实现,因为这涉及跨项目分析。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM