Arose92Flatbed2
Arose92Flatbed2

Reputation: 301

C# Roslyn API, Reading a .cs file, updating a class, writing back to .cs file

I have this working code that will load a .cs file into the Roslyn SyntaxTree class, create a new PropertyDeclarationSyntax, insert it into the class, and re-write the .cs file. I'm doing this as a learning experience as well as some potential future ideas. I found that there doesn't really seem to be a full Roslyn API documentation anywhere and I'm unsure if I am doing this efficiently. My main concern is where I call 'root.ToFullString()' - whilst it works, is this the right way to do it?

using System.IO;
using System.Linq;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;

class RoslynWrite
{
    public RoslynWrite()
    {
        const string csFile = "MyClass.cs";

        // Parse .cs file using Roslyn SyntaxTree
        var syntaxTree = SyntaxTree.ParseFile(csFile);
        var root = syntaxTree.GetRoot();
        // Get the first class from the syntax tree
        var myClass = root.DescendantNodes().OfType<ClassDeclarationSyntax>().First();

        // Create a new property : 'public bool MyProperty { get; set; }'
        var myProperty = Syntax.PropertyDeclaration(Syntax.ParseTypeName("bool"), "MyProperty")
                            .WithModifiers(Syntax.Token(SyntaxKind.PublicKeyword))
                            .WithAccessorList(
                            Syntax.AccessorList(Syntax.List(
                                Syntax.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                                    .WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)),
                                Syntax.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                                    .WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)))));

        // Add the new property to the class
        var updatedClass = myClass.AddMembers(myProperty);
        // Update the SyntaxTree and normalize whitespace 
        var updatedRoot = root.ReplaceNode(myClass, updatedClass).NormalizeWhitespace();

        // Is this the way to write the syntax tree? ToFullString?
        File.WriteAllText(csFile, updatedRoot.ToFullString());
    }
}

Upvotes: 16

Views: 6627

Answers (1)

Kevin Pilch
Kevin Pilch

Reputation: 11615

Answered on the Roslyn CTP forum in this post:

That approach is generally fine, though if you are worried about allocating a string for the text of the entire file, you should probably use IText.Write(TextWriter) instead of ToFullString().

Keep in mind that it's possible to generate trees that will not round-trip through the parser. For example, if you generated something that violates precedence rules, the SyntaxTree construction APIs won't catch that.

Upvotes: 3

Related Questions