Building a SyntaxTree from the ground up

前端 未结 2 1313
臣服心动
臣服心动 2020-12-13 04:29

I previously asked this question, which was answered, but someone gave a suggestion that might help me prevent making similar mistakes as I move forward.

Adding Au

相关标签:
2条回答
  • 2020-12-13 05:08

    Believe it or not, I have written a tool called Roslyn Code Quoter especially to answer this question.

    http://roslynquoter.azurewebsites.net

    The tool can take any C# program and automatically generate a snippet of code like Matt has written above. Since it also generates everything perfectly including all the whitespace, the code can get rather unwieldy. But you can exclude parts that generate trivia, and then just call NormalizeWhitespace() on the resulting node, it will automatically insert the trivia so that the code is correctly formatted.

    For the sake of completeness I'm posting the code in all its gory detail, so that you can see how to construct whitespace and all those little details.

    CompilationUnit().WithMembers(
    SingletonList<MemberDeclarationSyntax>(
        NamespaceDeclaration(
            IdentifierName("ACO"))
        .WithMembers(
            SingletonList<MemberDeclarationSyntax>(
                ClassDeclaration("MainForm")
                .WithModifiers(
                    TokenList(
                        Token(SyntaxKind.PublicKeyword)))
                .WithBaseList(
                    BaseList(
                        SingletonSeparatedList<BaseTypeSyntax>(
                            SimpleBaseType(
                                QualifiedName(
                                    QualifiedName(
                                        QualifiedName(
                                            IdentifierName("System"),
                                            IdentifierName("Windows")),
                                        IdentifierName("Forms")),
                                    IdentifierName("Form"))))))
                .WithMembers(
                    List<MemberDeclarationSyntax>(
                        new MemberDeclarationSyntax[]{
                            PropertyDeclaration(
                                QualifiedName(
                                    QualifiedName(
                                        QualifiedName(
                                            IdentifierName("System"),
                                            IdentifierName("Windows")),
                                        IdentifierName("Forms")),
                                    IdentifierName("Timer")),
                                Identifier("Ticker"))
                            .WithModifiers(
                                TokenList(
                                    Token(SyntaxKind.PublicKeyword)))
                            .WithAccessorList(
                                AccessorList(
                                    List<AccessorDeclarationSyntax>(
                                        new AccessorDeclarationSyntax[]{
                                            AccessorDeclaration(
                                                SyntaxKind.GetAccessorDeclaration)
                                            .WithSemicolonToken(
                                                Token(SyntaxKind.SemicolonToken)),
                                            AccessorDeclaration(
                                                SyntaxKind.SetAccessorDeclaration)
                                            .WithSemicolonToken(
                                                Token(SyntaxKind.SemicolonToken))}))),
                            MethodDeclaration(
                                PredefinedType(
                                    Token(SyntaxKind.VoidKeyword)),
                                Identifier("Main"))
                            .WithAttributeLists(
                                SingletonList<AttributeListSyntax>(
                                    AttributeList(
                                        SingletonSeparatedList<AttributeSyntax>(
                                            Attribute(
                                                IdentifierName("STAThread"))))))
                            .WithModifiers(
                                TokenList(
                                    Token(SyntaxKind.PublicKeyword)))
                            .WithBody(
                                Block())}))))))
    .NormalizeWhitespace()
    
    0 讨论(0)
  • 2020-12-13 05:22

    This will build up your entire compilation unit tree in one expression.

    var cu = SyntaxFactory.CompilationUnit()
                .AddMembers(
                    SyntaxFactory.NamespaceDeclaration(Syntax.IdentifierName("ACO"))
                            .AddMembers(
                            SyntaxFactory.ClassDeclaration("MainForm")
                                .AddBaseListTypes(SyntaxFactory.ParseTypeName("System.Windows.Forms.Form"))
                                .WithModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                                .AddMembers(
                                    Syntax.PropertyDeclaration(SyntaxFactory.ParseTypeName("System.Windows.Forms.Timer"), "Ticker")
                                            .AddAccessorListAccessors(
                                            SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
                                            SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))),
                                    SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "Main")
                                            .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                                            .AddAttributes(SyntaxFactory.AttributeDeclaration().AddAttributes(SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("STAThread"))))
                                            .WithBody(SyntaxFactory.Block())
                                    )
                            )
                    );
    

    Of course, you don't have to do it as a single expression. I could have used separate local variables to collect the pieces I wanted and then added them in the construction of the containing syntax piece.

    0 讨论(0)
提交回复
热议问题