Search code examples
c#roslynprojects-and-solutionsroslyn-code-analysisfind-all-references

Finding location of all references across solution


I'm trying to find all references for all types across a solution using Roslyn API.

Sure enough, I do get references to the types (using SymbolFinder.FindReferencesAsync), but when I check for their location (using SymbolFinder.FindSourceDefinitionAsync) I get a null result.

What Have I tried so far?

I am loading the solution using:
this._solution = _msWorkspace.OpenSolutionAsync(solutionPath).Result;

and getting the references using:

List<ClassDeclarationSyntax> solutionTypes = this.GetSolutionClassDeclarations();

var res = solutionTypes.ToDictionary(t => t,
                              t =>
                              {
                                  var compilation = CSharpCompilation.Create("MyCompilation", new SyntaxTree[] { t.SyntaxTree }, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) });
                                  var semanticModel = compilation.GetSemanticModel(t.SyntaxTree);
                                  var classSymbols = semanticModel.GetDeclaredSymbol(t);

                                  var references = SymbolFinder.FindReferencesAsync(classSymbols, this._solution).Result;
                                  foreach (var r in references)
                                  {
                                        //=== loc is allways null... ===
                                      var loc = SymbolFinder.FindSourceDefinitionAsync(r.Definition, this._solution).Result;
                                  }

                                  return references.ToList();
                              });

But as I said, all references has no locations.

Null location

When I look for all references in VS (2015) - I do get the references.

enter image description here


Update:

Following up on @Slacks advice I have fixed the code and it is now working properly. I'm posting it here for future reference for the googlers...

    Dictionary<Project, List<ClassDeclarationSyntax>> solutionTypes = this.GetSolutionClassDeclarations();

    var res = new Dictionary<ClassDeclarationSyntax, List<ReferencedSymbol>>();
    foreach (var pair in solutionTypes)
    {
        Project proj = pair.Key;
        List<ClassDeclarationSyntax> types = pair.Value;
        var compilation = proj.GetCompilationAsync().Result;
        foreach (var t in types)
        { 
            var references = new List<ReferencedSymbol>();

            var semanticModel = compilation.GetSemanticModel(t.SyntaxTree);
            var classSymbols = semanticModel.GetDeclaredSymbol(t);

            references = SymbolFinder.FindReferencesAsync(classSymbols, this._solution).Result.ToList();

            res[t] = references;
        }
    }

Solution

  • You're creating a new Compilation with only that source file and no relevant references. Therefore, the symbol in that compilation won't work, and certainly won't be bound to anything in your existing Solution.

    You need to get the Compilation from the Project containing the node.