Finding all references to a method with Roslyn

James Ko picture James Ko · Aug 6, 2015 · Viewed 15.7k times · Source

I'm looking to scan a group of .cs files to see which ones call the Value property of a Nullable<T> (finding all references). For example, this would match:

class Program
{
    static void Main()
    {
        int? nullable = 123;
        int value = nullable.Value;
    }
}

I found out about Roslyn and looked at some of the samples, but many of them are outdated and the API is huge. How would I go about doing this?

I'm stuck after parsing the syntax tree. This is what I have so far:

public static void Analyze(string sourceCode)
{
    var tree = CSharpSyntaxTree.ParseText(sourceCode);

    tree./* ??? What goes here? */
}

Answer

JoshVarty picture JoshVarty · Aug 6, 2015

You're probably looking for the SymbolFinder class and specifically the FindAllReferences method.

It sounds like you're having some trouble getting familiar with Roslyn. I've got a series of blog posts to help people get introduced to Roslyn called Learn Roslyn Now.

As @SLaks mentions you're going to need access to the semantic model which I cover in Part 7: Introduction to the Semantic Model

Here's a sample that shows you how the API can be used. If you're able to, I'd use MSBuildWorkspace and load the project from disk instead of creating it in an AdHocWorkspace like this.

var mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var ws = new AdhocWorkspace();
//Create new solution
var solId = SolutionId.CreateNewId();
var solutionInfo = SolutionInfo.Create(solId, VersionStamp.Create());
//Create new project
var project = ws.AddProject("Sample", "C#");
project = project.AddMetadataReference(mscorlib);
//Add project to workspace
ws.TryApplyChanges(project.Solution);
string text = @"
class C
{
    void M()
    {
        M();
        M();
    }
}";
var sourceText = SourceText.From(text);
//Create new document
var doc = ws.AddDocument(project.Id, "NewDoc", sourceText);
//Get the semantic model
var model = doc.GetSemanticModelAsync().Result;
//Get the syntax node for the first invocation to M()
var methodInvocation = doc.GetSyntaxRootAsync().Result.DescendantNodes().OfType<InvocationExpressionSyntax>().First();
var methodSymbol = model.GetSymbolInfo(methodInvocation).Symbol;
//Finds all references to M()
var referencesToM = SymbolFinder.FindReferencesAsync(methodSymbol,  doc.Project.Solution).Result;