Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roslyn Find ALL References to a Method in ALL Projects in a Solution

Tags:

c#

roslyn

I have been trying for a while to find ALL references to a method in an entire solution. One would think that the SymbolFinder.FindReferencesAsyncwhich takes as parameters the ISymbol to search for and the Solution Object would do just that but it does not...

All of the articles and SO Questions / Answers seem to point to it as the solution. It works fine for finding all references to the method inside the assembly that contains it, but not for any project referencing it. I have a theory that it's because when you make a reference the Symbol for the Method is different in the referencing assembly and that they want you to get that symbol and then use SymbolFinder.FindSourceDeclarationsAsync to resolve it to the actual symbol you are looking for.

If thats the case I honestly have no good idea on how to go about it? Maybe somehow get a list of ALL the symbols in the assembly, and then make FindSource call on everyone and compare it to see if it refers to your MethodSymbol? I sure hope not!

Here's a simple example

public void Find2()
{
    string solutionPath = @"C:\Projects\RoslynTestTargetProject\RoslynTestTargetProject.sln";
    var msWorkspace = MSBuildWorkspace.Create();
    var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
    var methodProjectComp = solution.Projects.Single(x => x.Name == "RoslynTestTargetProject").GetCompilationAsync().Result;

    // I have loaded these all kinds of different ways but it never impacts the end result
    var classWithMethodToSearchFor = methodProjectComp.GetTypeByMetadataName("RoslynTestTargetProject.Class1");
    var methodToSearchFor = classWithMethodToSearchFor.GetMembers("GetPerson").First() as IMethodSymbol;

    var references = SymbolFinder.FindReferencesAsync(methodToSearchFor, solution).Result;
    var callers = SymbolFinder.FindCallersAsync(methodToSearchFor, solution).Result;

    int c = references.Select(x => x.Locations.Count()).Sum(); 
}

Here is the class with the Method I am searching for and one reference to it.

public class Class1
{
    public Class1() {}        
    public Person GetPerson(Guid id) => new Person();
    public IEnumerable<Person> GetPeople(IEnumerable<Guid> ids) => ids.Select(x => GetPerson(x));
}

The other reference to it is just a simple console project with the following:

public static void GetPersonOutsideReference()
{
    var c = new Class1();
    c.GetPerson(Guid.NewGuid());
} 

I'd expect the count at the end of the Find2 method to return 2, 1 for the reference in the class and 1 for the reference in the other project, but its always 1.

I've tried several approaches including other SO Posts: 1, 2, 3 with no success.

like image 303
jrandomuser Avatar asked Oct 17 '22 21:10

jrandomuser


1 Answers

I figured out a way of doing this that seems to be correct. I have not seen a solution or answer yet that gives you all the references in your solution.

You first want to query the project for the Type in which the method belongs (class). As I alluded in my question though even though multiple projects may reference and consume they same type they do not have the same Symbol for that Type. So what you need to do is ask each compilation is it has a matching Type by passing it a MetadataName.

foreach (var project in solution.Projects)
{
     var compilation = project.GetCompilationAsync().Result;

      // Look for a reference to the Class in the Assembly
      var classRef = compilation.GetTypeByMetadataName("RoslynTestTargetProject.Class1");

If the reference isn't null it means that type is being used in the assembly. Now you can check for your references to the Symbol for the method that is specific to that compilation like so:

//For Methods
var refs = SymbolFinder.FindReferencesAsync(mSymbol, solution).Result;

//For Constructors
var refs = classRef.Constructors.Select(m => SymbolFinder.FindReferencesAsync(m, solution).Result).ToList();
like image 94
jrandomuser Avatar answered Nov 02 '22 22:11

jrandomuser