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.