Saturday, March 30, 2013

Code formatting with NRefactory

NRefactory is a library for parsing and analyzing C# source code hosted at GitHub. It is a bit like Roslyn from Microsoft, but fully open source and free to use (MIT X11). It's possible to parse and analyze individual C# files or whole projects. Mainly it was developed for IDEs therefore it has many high level features suited for development environments like type semantic highlighting, refactorings or code completion.
It provides almost everything needed for working with C# code.

NRefactory get's used in SharpDevelop 5, MonoDevelop and Xamarin Studio for providing high level C# features. Even VIM got a C# plugin providing high level C# features: Omnisharp. I've seen many uses of the library in various non IDE releated projects like the Saltarelle C#->JavaScript compiler.

But I've never seen anyone using the C# formatter from nrefactory. The formatter provides rich formatting features and is very easy to use. Let's take an example.
Today I wrote a piece of code using a text editor:

As you see there is a space after the 'null' that shouldn't be there. I could've just removed the space and continue my work - but what would happen if I do it again ? Wouldn't it be nice if it could be auto formatted like in a IDE. Just make the code format itself!

First step - make the program print itself. For that I added some code around the if that repeats the program and prints it:


Now running the program on the console gives:

The first step is done. Now we need to call the formatter. The project needs to reference NRefactory + NRefactory.CSharp and a using to the ICSharpCode.NRefactory.CSharp namespace needs to be added. The WriteLine call should use the CSharpFormatter to print a formatted version of itself:

Now running this will correctly format the if statement:

The self formatting source code - easy and without any external IDE.
The wrong space is finally gone. But the formatter has done something with the brackets. That's because of the options I gave to the formatter.
The C# formatter needs an options object that specifies how the C# code should be formatted. The CSharpFormattingOptions class provides a large set of very fine grained formatting options. The factory gives easy access to the most common indenting styles (see wikipedia). The Allman style is used in Visual Studio .NET which puts all braces on it's own line. That's why the formatter has altered the if brackets.
That's just one way to call the formatter. It was built for in IDE use.
The formatter can generate the minimum change set of replace operations required to do the formatting. Furthermore it's possible to format only a portion of the text inside a document. In monodevelop the on the fly formatter uses this functionality to provide formatting.
The formatting engine in NRefactory is mighty and easy to use - let me know if you find uses for it or have improvements.