It took me a while to get going with Roslyn so thought I'd record some stuff I found useful.
First things first
After downloading Roslyn read the project overview whitepaper. Finished? Read it again. The core concepts are pretty fundamental.
Installed with Roslyn is a handy getting started guide.
Of course I didn't realise this at first *face palm* so I stumbled along blindly for a while. Arguably the most useful inclusion is the Syntax Debugger Visualizer. With this you can explore syntax trees by clicking directly on the code which jumps to the appropriate section of the syntax tree. To view the visualizer click on the magnifying class when debugging a syntax tree or node variable. Here's more information on the Syntax Debugger Visualizer.
Also included in the getting started guide is more documentation and a lot of example code. It's worth taking time to look through both of these. I wanted to write a quick fix, so the make const quick fix sample was particularly useful, as were unit test and tree transformation samples.
Creating code programmatically
The Syntax object can be used to create nodes and tokens. E.g.
Generally I've found it easier to generate statements/syntax trees/whatever from code strings. There are a whole bunch of ParseXyz methods.
Generally I've found it easier to generate statements/syntax trees/whatever from code strings. There are a whole bunch of ParseXyz methods.
Finding stuff in the syntax tree
One way to find nodes/tokens/trivia in a syntax tree is simply to use the Syntax Debugger Visualizer to understand the structure then write your query based on that information. LINQ is your friend. As well as DescendantNodes also look at methods such as Ancestors(), DescendantNodesAndTokens() and DescendantTrivia().
Finding a variable type
The semantic model can be obtained by calling GetSemanticModel from a Compilation or IDocument object. Other ways may be available.
Altering code
There is a lot of ways to alter code. Bare in mind that all Roslyn objects are immutable. The methods I've used the most so far are things like ReplaceNode, RemoveNode, ReplaceToken, RemoveToken etc. In addition there are several With* methods. E.g. WithBlock, WithClassDeclaration. In Roslyn a "block" is exactly what you would expect. I.e. A section of code between two curly braces.
It's worth noting ReplaceNode is an extension method and will only be visible if Roslyn.Compilers and Roslyn.Compilers.CSharp are referenced.
Formatting code
When inserting new code into a syntax tree the formatting will be terrible. You can fix it manually by inserting the relevant trivia. Don't bother. Format() method for the win.
Enabling Roslyn in Visual Studio
One gotcha to look out for. If you write a Roslyn extension then install it, the extension will not work unless Roslyn is enabled. This had me scratching my head for some time. By default Roslyn is only enabled in the debug instance of VS fired up when you run a Roslyn project. To enable it add "/rootsuffix Roslyn" to your VS shortcut. How do you know Roslyn is enabled? Each code tab will include "[Roslyn]". Thanks to Stack Overflow for that tip.
Good day, great article, but one issue with code formatting. I can't find method Format method. What is the type of unformattedNode variable? Is it plain string? If so, where can I fond Format extension method?
ReplyDeleteThank you very much
Solved my problem:
Deletevar unformattedCode = @"using System; namespace HelloWorld{class Program{static void Main(string[]args){Console.WriteLine(""Hello,World!"");}}}";
var tree = SyntaxTree.ParseText(unformattedCode);
var root = tree.GetRoot();
var formattedCode = root.NormalizeWhitespace();
using Roslyn 1.2.20906.2 version
Sorry, I should have included those details in the blog. Format is found in the Roslyn.Services namespace and unformattedNode is type CommonSyntaxNode
Delete