Learn Roslyn Now: Part 2 Analyzing Syntax Trees with LINQ

Note: I’ve also created a ten-minute video to explore the Syntax Tree API

I won’t spend much time explaining Syntax Trees. There are a number of posts that deal with that including the Roslyn Whitepaper. The main idea is that given a string containing C# code, the compiler creates a tree representation (called a Syntax Tree) of the string. Roslyn’s power is that it allows us to query this Syntax Tree with LINQ.

Here is a sample in which we use Roslyn create a Syntax Tree from a string. We must add references to Microsoft.CodeAnalysis and Microsoft.CodeAnalysis.CSharp. You can do so using Method 1 from Part 1 Installing Roslyn.


using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
var tree = CSharpSyntaxTree.ParseText(@"
public class MyClass
{
public void MyMethod()
{
}
}");
var syntaxRoot = tree.GetRoot();
var MyClass = syntaxRoot.DescendantNodes().OfType<ClassDeclarationSyntax>().First();
var MyMethod = syntaxRoot.DescendantNodes().OfType<MethodDeclarationSyntax>().First();
Console.WriteLine(MyClass.Identifier.ToString());
Console.WriteLine(MyMethod.Identifier.ToString());

view raw

gistfile1.cs

hosted with ❤ by GitHub

We first start by parsing a string containing C# code and getting the root of this syntax tree. From this point it’s extremely easy to retrieve elements we’d like using LINQ. Given the root of the tree, we look at all the descendant objects and filter them by their type. While we’ve only used ClassDeclarationSyntax and MethodDeclarationSyntax there are corresponding pieces of syntax for any C# feature.

Visual Studio’s Intellisense is extremely valuable for exploring the various types of C# syntax we can use.

We can composed more advanced LINQ expressions as one might expect:


var tree = CSharpSyntaxTree.ParseText(@"
public class MyClass
{
public void MyMethod()
{
}
public void MyMethod(int n)
{
}
}");
var syntaxRoot = tree.GetRoot();
var MyMethod = syntaxRoot.DescendantNodes().OfType<MethodDeclarationSyntax>()
.Where(n => n.ParameterList.Parameters.Any()).First();
//Find the type that contains this method
var containingType = MyMethod.Ancestors().OfType<TypeDeclarationSyntax>().First();
Console.WriteLine(containingType.Identifier.ToString());
Console.WriteLine(MyMethod.ToString());

view raw

gistfile1.cs

hosted with ❤ by GitHub

Above, we start by finding all methods, and then filtering by those that accept parameters. We then take this method and work our way upwards through the tree with the Ancestors() method, searching for the first type that contains this method.

Hopefully this acts as a base for you to play around and explore the Syntax Tree API. There are some limitations to the kind of information you can discover at a purely syntactical level and to overcome these we must make use of Roslyn’s Semantic Model, which will be the subject of future posts.

3 thoughts on “Learn Roslyn Now: Part 2 Analyzing Syntax Trees with LINQ

Leave a comment