Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create syntax nodes in Roslyn from scratch?

Tags:

c#

vb.net

roslyn

I would like to generate syntax nodes with the Roslyn API without having a pre-existing syntax node. That is, I cannot simply use the WithXYZ() methods on an existing object to modify it because there is no existing object.

For example, I would like to generate an InvocationExpressionSyntax object. Assuming a constructor was available, I could do something like

var invoke = new InvocationExpressionSyntax(expression, arguments);

But the constructor for InvocationExpressionSyntax seems to not be public.

http://www.philjhale.com/2012/10/getting-started-with-roslyn.html

this blog suggests that I can use an API such as

Syntax.InvocationExpression()

but I don't see what Syntax refers to, and I don't see anything that resembles it in the Roslyn API.

I did find Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory that lets me do

var invoke = SyntaxFactory.InvocationExpression().WithExpression(expression);

And this works well enough for me. There is also Microsoft.CodeAnalysis.CSharp.SyntaxFactory for anyone wondering.

Is SyntaxFactory the proper way to create new syntax nodes?

The way I found SyntaxFactory.InvocationExpression was by looking at the PublicAPI.txt file in the roslyn source code (https://github.com/dotnet/roslyn) under the src/Compilers/VisualBasic/Portable directory. Otherwise, I don't see where SyntaxFactory is documented.

like image 669
jonr Avatar asked Sep 14 '15 19:09

jonr


1 Answers

As the other answer stated, the SyntaxFactory is the correct class to use. As you have found there are two syntax factories available, Microsoft.CodeAnalysis.CSharp.SyntaxFactory and Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory, depending on which language you are using.

Usually the calls into the SyntaxFactory are chained together, so you end up with many calls to the SytnaxFactory methods to generate even simple lines of code. For example, the code Console.WriteLine("A"); would be represented by the following calls to the Syntax Factory:

var console = SyntaxFactory.IdentifierName("Console");
var writeline = SyntaxFactory.IdentifierName("WriteLine");
var memberaccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, console, writeline);

var argument = SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal("A")));
var argumentList = SyntaxFactory.SeparatedList(new[] { argument });

var writeLineCall =
    SyntaxFactory.ExpressionStatement(
    SyntaxFactory.InvocationExpression(memberaccess,
    SyntaxFactory.ArgumentList(argumentList)));

If you are unsure of how to generate nodes for some specific code, Kirill Osenkov created the Roslyn Quoter project on GitHub, which you can use to generate the SyntaxFactory code for you.

I recently did a blog post on this topic if you would like to read further.

like image 63
John Koerner Avatar answered Sep 27 '22 15:09

John Koerner