如何从头开始在Roslyn中创建语法节点?

时间:2015-09-14 19:49:55

标签: c# vb.net roslyn

我想使用Roslyn API生成语法节点,而不需要预先存在的语法节点。也就是说,我不能简单地在现有对象上使用WithXYZ()方法来修改它,因为没有现有对象。

例如,我想生成一个InvocationExpressionSyntax对象。假设有一个构造函数,我可以做类似的事情

select_item()

var invoke = new InvocationExpressionSyntax(expression, arguments); 的构造函数似乎不公开。

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

此博客建议我可以使用

等API
InvocationExpressionSyntax

但是我没有看到Syntax.InvocationExpression() 引用的内容,我在Roslyn API中看不到任何与它类似的内容。

我确实找到了允许我这样做的Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory

Syntax

这对我来说效果很好。任何想知道的人都有var invoke = SyntaxFactory.InvocationExpression().WithExpression(expression);

Microsoft.CodeAnalysis.CSharp.SyntaxFactory是创建新语法节点的正确方法吗?

我找到SyntaxFactory.InvocationExpression的方法是查看src / Compilers / VisualBasic / Portable目录下的roslyn源代码(https://github.com/dotnet/roslyn)中的PublicAPI.txt文件。否则,我没有看到记录SyntaxFactory的位置。

2 个答案:

答案 0 :(得分:15)

正如另一个答案所述,SyntaxFactory是正确使用的类。正如您所发现的,有两个语法工厂可用,Microsoft.CodeAnalysis.CSharp.SyntaxFactoryMicrosoft.CodeAnalysis.VisualBasic.SyntaxFactory,具体取决于您使用的语言。

通常,对SyntaxFactory的调用被链接在一起,因此您最终会调用SytnaxFactory方法来生成更简单的代码行。例如,代码Console.WriteLine("A");将由以下对语法工厂的调用表示:

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)));

如果您不确定如何为某些特定代码生成节点,Kirill Osenkov在GitHub上创建了Roslyn Quoter project,您可以使用该代码为您生成SyntaxFactory代码。

如果您想进一步阅读,我最近就此主题做了blog post

答案 1 :(得分:7)

是的,SyntaxFactory类型是从头开始创建语法节点的方法。