2015-09-14 60 views
5

我想在沒有預先存在的語法節點的情況下使用Roslyn API生成語法節點。也就是說,我不能簡單地在現有對象上使用WithXYZ()方法來修改它,因爲沒有現有的對象。如何從頭開始在Roslyn中創建語法節點?

例如,我想生成一個InvocationExpressionSyntax對象。假設一個構造函數可用,我可以做類似

var invoke = new InvocationExpressionSyntax(expression, arguments); 

InvocationExpressionSyntax構造似乎沒有公開。

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的方式是通過查看src/Compilers/VisualBasic/Portable目錄下roslyn源代碼(https://github.com/dotnet/roslyn)中的PublicAPI.txt文件。否則,我不知道SyntaxFactory在哪裏記錄。

回答

5

是的,SyntaxFactory類型是從頭創建語法節點的方式。

9

正如其他答案所述,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))); 

如果您不確定如何產生一些特定的代碼節點,基里爾Osenkov在GitHub上創建的Roslyn Quoter project,你可以用於爲您生成SyntaxFactory代碼。

我最近做了一個blog post關於這個話題,如果你想進一步閱讀。