Reputation: 966
Suppose I have an interface with some generic method, say this one:
public interface IService
{
Task DoGenericAsync<T>();
}
Then I have some solution with a bunch of projects and I have the following references:
class SomeDomainService
{
private readonly IService _service;
public Task Process()
=> _service.DoGenericAsync<A>();
}
Now the goal is to find all invocations of this method and what is more important - what is the concrete generic argument. In this particular case I want to find that IService.DoGenericAsync<T>()
was called with generic parameter <A>
.
So following several tutorials and questions out there, I'm able to find all references to the target method using Roslyn by finding the ISymbol
of my interface method declaration and then calling SymbolFinder.FindReferencesAsync
to get all references.
This works great and I get correct locations of invocations (a collection of ReferencedSymbol
instances, however the Definition
property of those results returns me only the general info on the symbol (well, exactly definition :) ), so how do I find out what's the actual arguments were?
Upvotes: 1
Views: 1449
Reputation: 966
Disclaimer: Unfortunatelly I haven't finished this pet project yet, but here's the code sample that I composed based on the accepted answer:
foreach (var reference in references)
{
foreach (var location in reference.Locations)
{
var syntaxTree = await location.Document.GetSyntaxTreeAsync();
var root = await syntaxTree.GetRootAsync();
var syntaxNode = root.FindNode(location.Location.SourceSpan);
var compilation = compilations.First(x => x.ContainsSyntaxTree(syntaxTree));
var semanticModel = compilation.GetSemanticModel(syntaxTree);
var symbolInfo = semanticModel.GetSymbolInfo(syntaxNode);
var methodSymbol = (symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.First()) as IMethodSymbol;
var typeSymbol = methodSymbol.TypeArguments.First();
// then use 'typeSymbol' to find the actual type etc
}
}
In this case, references
is a collection of ReferencedSymbol
(the one I'm talking about in the question); and compilations
- is a collection of Compilation
for all projects in loaded solution I'm analyzing.
Upvotes: 1
Reputation: 18976
So the ReferenceLocation
has two properties, a Document
and a Location
. The document lets you fetch the SyntaxTree
and SemanticModel
. When you have the SyntaxTree
, you can call FindNode and pass in Location.SourceSpan
, and that should get you the invocation node. From there you can call SemanticModel.GetSymbolInfo
and that will give you a struct that contains the method symbol, and from there you can take a look at the type arguments.
Upvotes: 1