'How can I have all references of a method in Roslyn (method is called by other classes)?
Thanks to Roslyn, having access to .Net compiler, in our project Gcop we need to have list of references where are calling a method.
VS IDE shows the reference places very suitable like this:
Actually I want to understand which class/name space and even assembly is calling my method by Roslyn C# syntax.
Currently I have access to MethodSymbol here :
var methodSymbol = semanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol;
what should I write to get access to references of this method?
//added recently for double check
var solutionPath = Utilities.DteExtensions.SolutionFullPath;
var msWorkspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
var result = new List<ReferenceLocation>();
var refrences = SymbolFinder.FindReferencesAsync(methodSymbol, solution).Result;
foreach (var refernc in refrences)
{
foreach (var location in refernc.Locations)
{
result.Add(location);
}
}
///???????? why the result is empty ?
Solution 1:[1]
You're looking for the FindReferencesAsync() methods on the SymbolFinder class.
Solution 2:[2]
I tested this approach but is not quick , and can not find some syntax
protected override void Analyze(SyntaxNodeAnalysisContext context)
{
NodeToAnalyze = context.Node;
Method = context.Node as MethodDeclarationSyntax;
// only public method should be checked
if (!IsModifiersValid) return;
var methodSymbol = context.SemanticModel.GetDeclaredSymbol(Method) as IMethodSymbol;
var solutionPath = Utilities.DteExtensions.SolutionFullPath;
var msWorkspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
// looking in all projects inside of one solution
var allDocumentsInEntireSolution = solution.Projects.SelectMany(it => it.Documents);
//skip rule when in entire solution we have web form project
if (allDocumentsInEntireSolution.Any(x => x.Name == "Default.aspx.cs")) return;
//Looking for all references
var refrencesFound = FindAllMethodReferences(Method.GetName(), solution);
if (refrencesFound.Count() ==0)
ReportDiagnostic(context, Method);
else
{
var xyx = refrencesFound.Count();
}
}
IEnumerable<ReferenceLocation> FindAllMethodReferences(string methodName, Solution solution)
{
IMethodSymbol methodSymbol = null;
bool found = false;
foreach (var project in solution.Projects)
{
foreach (var document in project.Documents)
{
var model = document.GetSemanticModelAsync().Result;
var methodInvocation = document.GetSyntaxRootAsync().Result;
try
{
var nodes = methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>().Where(x => x.Expression.ToString().Contains(methodName));
foreach (var node in nodes)
{
if (node == null) continue;
var member = node?.Expression as MemberAccessExpressionSyntax;
if (member == null)
continue;
var name = member?.Name?.ToString();
if (name.IsEmpty()) continue;
if (name != methodName) continue;
methodSymbol = model.GetSymbolInfo(node).Symbol as IMethodSymbol;
found = true;
break;
}
}
catch (Exception exp)
{
// Swallow the exception of type cast.
// Could be avoided by a better filtering on above linq.
continue;
}
}
if (found) break;
}
if (found == false) return Enumerable.Empty<ReferenceLocation>();
if (methodSymbol == null) return Enumerable.Empty<ReferenceLocation>();
var result = new List<ReferenceLocation>();
var refrences = SymbolFinder.FindReferencesAsync(methodSymbol, solution).Result;
foreach (var refernc in refrences)
{
foreach (var location in refernc.Locations)
{
result.Add(location);
}
}
return result;
}
Solution 3:[3]
I prefer to change following to make it work:
var nodes = methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>()
.Where(x => x.Expression.ToString().Contains(methodName));
To:
var nodes = new List<InvocationExpressionSyntax>();
foreach (var methodInvocationExpression in methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>())
{
if(methodInvocationExpression.DescendantNodes().OfType<MemberAccessExpressionSyntax>().Any(x => x.Name.Identifier.ValueText == methodName))
{
nodes.Add(methodInvocationExpression);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | SLaks |
| Solution 2 | |
| Solution 3 | ouflak |

