简体   繁体   中英

Order constructor parameters with Roslyn

I'm trying to create method that orders constructor parameters. It navigates well and even updates the tree but serialised text contains original parameters:

    static void Transform(string sourceCode)
    {
        var tree = CSharpSyntaxTree.ParseText(sourceCode);

        var root = (CompilationUnitSyntax)tree.GetRoot();

        var @namespace = (NamespaceDeclarationSyntax)
            root.ChildNodes().First(n => n.Kind() == SyntaxKind.NamespaceDeclaration);

        var @class = (ClassDeclarationSyntax)
            @namespace.ChildNodes().First(n => n.Kind() == SyntaxKind.ClassDeclaration);

        var constructor = (ConstructorDeclarationSyntax)
           @class.ChildNodes().First(n => n.Kind() == SyntaxKind.ConstructorDeclaration);

        var parameters = constructor.ParameterList
            .ChildNodes()
            .Cast<ParameterSyntax>()
            .OrderBy(node => ((IdentifierNameSyntax) node.Type).Identifier.ToString())
            .Select(node => SyntaxFactory.Parameter(
                SyntaxFactory.List<AttributeListSyntax>(),
                SyntaxFactory.TokenList(),
                SyntaxFactory.ParseTypeName(((IdentifierNameSyntax)node.Type).Identifier.Text),
                SyntaxFactory.Identifier(node.Identifier.Text),
                null));

        var updatedParameterList = SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters));

        ((SyntaxNode)constructor).ReplaceNode(constructor.ParameterList, updatedParameterList);

        Console.WriteLine(root.GetText().ToString());
    }

I call it as follows:

        Transform(@"
namespace Test {
    class Test {
        Test(IParam2 param2, IParam1 param1) { }
    }
}");

and expect to have

namespace Test {
    class Test {
        Test(IParam1 param1, IParam2 param2) { }
    }
}

but the output is still has the parameters in wrong order. Any thoughts?

The issue is that all trees in Roslyn are immutable.

Surprisingly, this line doesn't actually do anything:

((SyntaxNode)constructor).ReplaceNode(constructor.ParameterList, updatedParameterList);

That's because ReplaceNode() returns an entirely new syntax tree, and doesn't manipulate the old one.

This is what you're looking for:

static void TransformParameterOrder(string sourceCode)
{
    var tree = CSharpSyntaxTree.ParseText(sourceCode);

    var root = (CompilationUnitSyntax)tree.GetRoot();

    var @namespace = (NamespaceDeclarationSyntax)
        root.ChildNodes().First(n => n.Kind() == SyntaxKind.NamespaceDeclaration);

    var @class = (ClassDeclarationSyntax)
        @namespace.ChildNodes().First(n => n.Kind() == SyntaxKind.ClassDeclaration);

    var constructor = (ConstructorDeclarationSyntax)
       @class.ChildNodes().First(n => n.Kind() == SyntaxKind.ConstructorDeclaration);

    var child = constructor.ParameterList.ChildNodes().Count();

    var parameters = constructor.ParameterList
        .ChildNodes()
        .Cast<ParameterSyntax>()
        .OrderBy(node => ((IdentifierNameSyntax)node.Type).Identifier.ToString())
        .Select(node => SyntaxFactory.Parameter(
            SyntaxFactory.List<AttributeListSyntax>(),
            SyntaxFactory.TokenList(),
            SyntaxFactory.ParseTypeName(((IdentifierNameSyntax)node.Type).Identifier.Text),
            SyntaxFactory.Identifier(node.Identifier.Text),
            null))
        .Take(2);

    var updatedParameterList = SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters));

    var newNode = ((SyntaxNode)constructor).ReplaceNode(constructor.ParameterList, updatedParameterList);
    //Alternatively you can assign root = root.ReplaceNode...
    var newRoot = root.ReplaceNode(constructor.ParameterList, updatedParameterList);

    Console.WriteLine(root.GetText().ToString());
    Console.WriteLine(newRoot.GetText().ToString());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM