Make tree construction less verbose

Topics: APIs
Apr 28, 2014 at 9:37 PM
Edited Apr 30, 2014 at 8:08 PM
Currently, using the SyntaxFactory to build up nodes in the tree can create code that is very verbose and hard to read. For example, to create a node to represent C# such as
if (this.field != null)
       ((IDisposable)this.field).Dispose();
I would need to write the following code:
SyntaxFactory.IfStatement(
       SyntaxFactory.BinaryExpression(
              SyntaxKind.NotEqualsExpression,
              fieldAccess,
              nullLiteral),
       SyntaxFactory.ExpressionStatement(
              SyntaxFactory.InvocationExpression(
                     SyntaxFactory.MemberAccessExpression(
                           SyntaxKind.SimpleMemberAccessExpression,
                           SyntaxFactory.ParenthesizedExpression(
                                  SyntaxFactory.CastExpression(
                                         iDisposableType,
                                         fieldAccess)),
                           SyntaxFactory.IdentifierName("Dispose")))));

But if there were (extension) methods on some of the nodes to support easier tree construction, this can become much cleaner with a fluent syntax:
SyntaxFactory.IfStatement(fieldAccess.IsNotEqualTo(nullLiteral),
       fieldAccess.CastTo(iDisposableType).Parenthesize().Member("Dispose").Invoke().ToStatement());

Here are the signatures of some extension methods I've added in my own code to help with tree construction which might be helpful to others if similar methods and more like them were exposed by Roslyn:
BinaryExpressionSyntax AssignFrom(this ExpressionSyntax expression, string identifier);
BinaryExpressionSyntax AssignFrom(this ExpressionSyntax expression, ExpressionSyntax value);
CastExpressionSyntax CastTo(this ExpressionSyntax expression, ITypeSymbol type);
CastExpressionSyntax CastTo(this ExpressionSyntax expression, TypeSyntax type);
InvocationExpressionSyntax Invoke(this ExpressionSyntax expression);
InvocationExpressionSyntax Invoke(this ExpressionSyntax expression, params ExpressionSyntax[] arguments);
InvocationExpressionSyntax Invoke(this ExpressionSyntax expression, params ArgumentSyntax[] arguments);
InvocationExpressionSyntax Invoke(this ExpressionSyntax expression, SeparatedSyntaxList<ArgumentSyntax> arguments);
InvocationExpressionSyntax Invoke(this ExpressionSyntax expression, ArgumentListSyntax arguments);
BinaryExpressionSyntax IsEqualTo(this ExpressionSyntax left, ExpressionSyntax right);
BinaryExpressionSyntax IsGreaterThanOrEqualTo(this ExpressionSyntax left, int right);
BinaryExpressionSyntax IsGreaterThanOrEqualTo(this ExpressionSyntax left, ExpressionSyntax right);
BinaryExpressionSyntax IsNotEqualTo(this ExpressionSyntax left, ExpressionSyntax right);
MemberAccessExpressionSyntax Member(this ExpressionSyntax expression, string name);
MemberAccessExpressionSyntax Member(this ExpressionSyntax expression, SimpleNameSyntax name);
ParenthesizedExpressionSyntax Parenthesize(this ExpressionSyntax expression);
ExpressionSyntax ToExpression(this TypedConstant constant);
SyntaxToken ToRefOrOutKeyword(this RefKind refKind);
ExpressionStatementSyntax ToStatement(this ExpressionSyntax expression);