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.
I start with a MethodDeclarationSyntax
and get the symbol from that. 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. 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
:
//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
.
Since I am trying to get the underlying symbol of a declaration, I cannot use GetSymbolInfo
, but use GetDeclaredSymbol
instead (as suggested here).
My understanding from this article is that the symbols returned from GetDeclaredSymbol
and GetSymbolInfo
should be the same. However, a simple comparison using Equals
returns 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.