如何从头开始在 Roslyn 中创建语法节点?
How do I create syntax nodes in Roslyn from scratch?
我想在没有预先存在的语法节点的情况下使用 Roslyn API 生成语法节点。也就是说,我不能简单地对现有对象使用 WithXYZ() 方法来修改它,因为不存在现有对象。
例如,我想生成一个 InvocationExpressionSyntax 对象。假设构造函数可用,我可以做类似
的事情
var invoke = new InvocationExpressionSyntax(expression, arguments);
但是 InvocationExpressionSyntax
的构造函数似乎不是 public。
http://www.philjhale.com/2012/10/getting-started-with-roslyn.html
这篇博客建议我可以使用 API 例如
Syntax.InvocationExpression()
但我没有看到 Syntax
指的是什么,我在 Roslyn API.
中也没有看到任何类似的东西
我确实找到 Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory 让我做
var invoke = SyntaxFactory.InvocationExpression().WithExpression(expression);
这对我来说效果很好。还有 Microsoft.CodeAnalysis.CSharp.SyntaxFactory
给想知道的人。
SyntaxFactory
是创建新语法节点的正确方法吗?
我找到SyntaxFactory.InvocationExpression的方法是查看roslyn源代码(https://github.com/dotnet/roslyn)中src/Compilers/VisualBasic/Portable目录下的PublicAPI.txt文件。否则,我看不到记录 SyntaxFactory
的位置。
是的,SyntaxFactory
类型是从头开始创建语法节点的方式。
正如其他答案所述,SyntaxFactory
是正确的 class。正如您所发现的,有两个可用的语法工厂,Microsoft.CodeAnalysis.CSharp.SyntaxFactory
和 Microsoft.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。
我想在没有预先存在的语法节点的情况下使用 Roslyn API 生成语法节点。也就是说,我不能简单地对现有对象使用 WithXYZ() 方法来修改它,因为不存在现有对象。
例如,我想生成一个 InvocationExpressionSyntax 对象。假设构造函数可用,我可以做类似
的事情var invoke = new InvocationExpressionSyntax(expression, arguments);
但是 InvocationExpressionSyntax
的构造函数似乎不是 public。
http://www.philjhale.com/2012/10/getting-started-with-roslyn.html
这篇博客建议我可以使用 API 例如
Syntax.InvocationExpression()
但我没有看到 Syntax
指的是什么,我在 Roslyn API.
我确实找到 Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory 让我做
var invoke = SyntaxFactory.InvocationExpression().WithExpression(expression);
这对我来说效果很好。还有 Microsoft.CodeAnalysis.CSharp.SyntaxFactory
给想知道的人。
SyntaxFactory
是创建新语法节点的正确方法吗?
我找到SyntaxFactory.InvocationExpression的方法是查看roslyn源代码(https://github.com/dotnet/roslyn)中src/Compilers/VisualBasic/Portable目录下的PublicAPI.txt文件。否则,我看不到记录 SyntaxFactory
的位置。
是的,SyntaxFactory
类型是从头开始创建语法节点的方式。
正如其他答案所述,SyntaxFactory
是正确的 class。正如您所发现的,有两个可用的语法工厂,Microsoft.CodeAnalysis.CSharp.SyntaxFactory
和 Microsoft.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。