0

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;
        }
    }
Avi Turner
  • 10,234
  • 7
  • 48
  • 75

1 Answers1

2

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.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Thanks for the quick answer! I'll give it a try. I suspected it was due to creating the compilation from the type's syntax tree. If understand what you are saying, I need to change the compilation creation to: `var compilation = project.GetCompilationAsync().Result;` right? – Avi Turner Jan 09 '17 at 18:06
  • Yes, except that you should call that just once, outside your loop, and `await` it. – SLaks Jan 09 '17 at 18:06
  • Will this also give me cross-project references locations? – Avi Turner Jan 09 '17 at 18:12
  • @AviTurner: Yes; that's why it takes a `Solution`. – SLaks Jan 09 '17 at 18:18