Editing Code whilst preserving its formatting

Earlier in one of my posts, I explained how can you reformat your code using NRefactory library. But, as matter of fact what you really want in your day to day task is not reformatting code, au contraire, you want its formatting to be preserved. You don’t want to commit dozens of files to your repository merely because their formatting’s changed !

Now this question arises that whether is this quest possible in NRefactory or not ? Well of course it is, and it’s really easy. ( Once you know what you have to do, who you have to call and … ) BTW, NRefactory is an essential part of SharpDevelop IDE and we don’t want our idea to reformat our code every time we use intellisens.

NRefactory has a class that’s dedicated to do such and it’s called DocumentScript.

Document scripts works by manipulating IDocument objects, which are specialization of string builder class. This class gives you this opportunity to change your document based on text location that were already stored in syntax tree. It also keeps track of latest modification and map them to current document, so you don’t have to worry about whether multiple changes on the same document will be applied correctly or not.

IDocument document = new StringBuilderDocument("Your code source");
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateAllman();
var options = new TextEditorOptions();

var script = new DocumentScript(document, policy, options);

Now you can use methods like Replace, Remove, scriptInsertAfter and etc. on you AST. It works with both AST nodes as well as offsets.

Beside that, there are some predefined methods on

script.ChangeModifier(declaration, Modifiers.Public);

Binary Operator Expressions

Suppose in a hypothetical scenario you want to reverse all binary operation in your file, and also you want them to be fully parenthesized. What would you do ?
One solution is using recursion which might be a little messy an unclear. Another solution to this problem can be achieved by taking advantage of binary operator expressions in NRefactory.
Fortunately with NRefactory this operation is rather a trivial task. A little tricky, but still simple.
You can use this feature to process any kind of binary operation and interpret it the way you like. ( like generating code )

First, let’s create a test fixture for it ( Hooray ! Now you know what TDD is : )

[Test]
public void BinaryVisitorTest()
{
	string input = " a > b || ( x > y && y > z )";
	var parser = new CSharpParser();
	Expression expression = parser.ParseExpression(input);

	var visitor = new BinaryOpVisitor();
	expression.AcceptVisitor(visitor);
}

Since we’re interested in visiting an expression we don’t bother by parsing a whole C# file, we give the parser our expression as text, and it gives use the expression as AST.
In next step, we create a visitor class and visit binary and identifier expressions :

public class BinaryOpVisitor : DepthFirstAstVisitor
{
	public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
	{
		Console.Write("(");
		binaryOperatorExpression.Right.AcceptVisitor(this);
		Console.Write(binaryOperatorExpression.OperatorToken);
		binaryOperatorExpression.Left.AcceptVisitor(this);
		Console.Write(")");
	}

	public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
	{
		Console.Write(identifierExpression.Identifier);
		base.VisitIdentifierExpression(identifierExpression);
	}
}

Be careful as opposed to what we do regularly in node visiting ( or actually what depth first visiting is all about ), we didn’t call base visitor in binary operator expression visitor.

Now, for this special case, the output will be :

(((z>y)&&(y>x))||(b>a))

Easy peasy !

For readers with data structure background I’d like to mention that what we did in here was actually an in-order visit of the nodes in AST. You can simply turn it into post/pre-order by putting base class call before/after your code in the visitor.

PrettyPrint C# codes via NRefactory

Well, yet another code example via NRefactory. This time we intend to take advantage of reformatting capabilities in NRefactory library.
What does it mean ?  Well, when you become engage in Code generating activities, you usually don’t want to be involved in details of code formatting, indentation and these kind of stuff. All you wanna do, is to concatenate some codes, one behind another and create you desired code. After you’re done with your code, you may have a program in one line, with no indentation. This is where NRefactory steps in.
It can take your code, and by considering tons of available options, automatically reformat your code. easy peasy !

I have created a rudimentary example of this operation that you can download from here. It’s quite simple and straightforward.

PS : I’ve uploaded binary files in here. In case you already download the previous sample, you don’t need to download binary files again. Now all you have to do is to reference to these binary files to be able to build the project.

Oops ! I made an honest mistake and used Formatters. I’ve applied changes and updated the code.
Formatters are appropriate tools when you want to apply modifications in IDE ( like preserving correct indentation after copy-paste or when IDE fills some fields for you ).
In our case, proper tool would be OutputVisitors. We create parse tree of out code, then visit it by CSharpOutputVisitor and … Boom !

NRefactory : Front-end parser for C#

NRefactroy is an open source library for parsing C# source codes, or more precisely a front-end parser for C#.
It can parse your C# codes and provide you with an abstract syntax tree. It can also resolve this parse tree and give you semantic of nodes in the syntax tree.
What makes it more interesting is that the syntax tree produced by this framework is mutable, which means you can change it’s node’s contents; unlike other products, such as not-yet-stable Microsoft® “Roslyn” CTP.
You can use this library to change your source code, analyze it, or reformat it (pretty print);NRefactory project is actually a part of bigger project, SharpDevelop : A free IDE for C#. SharpDevelop takes advantage of this library for IntelliSense implementation and some other stuff.

At the beginning, it may take a while till you become comfortable with representations, APIs and how to interpret and manipulate data structures. To start, take a look this article, wrote by one the authors of NRefactory. In this prologue you can find all preliminary information you need to know in order to dive in.
After that IMHO best practice is to fool around huge unit tests that exist in project itself. It’ll be your best guide through all difficulties and misunderstandings ( there’s about 3000 of theme! ).

I also wrote the simplest possible program with this library that you can download from here. The purpose of this program is only to show you how to glue all the things together and make it work.
Enjoy Parsing.