Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

661
Visualizações
Replacing multiple nodes in Roslyn syntax tree

I'm trying to replace a couple of nodes in a syntax tree using roslyn. But the immutable nature of it seems to get in my way.

    public static string Rewrite(string content)
    {
        var tree = CSharpSyntaxTree.ParseText(content);
        var root = tree.GetRoot();

        var methods =root
            .DescendantNodes(node=>true)
            .OfType<MethodDeclarationSyntax>()
            .ToList();

        foreach(var method in methods)
        {
            var returnActions = method
                .DescendantNodes(node => true)
                .OfType<BinaryExpressionSyntax>()
                //Ok this is cheating
                .Where(node => node.OperatorToken.ValueText == "==")
                .Where(node => node.Right.ToString() == "\"#exit#\"" || node.Right.ToString() == "\"#break#\"")
                .Select(node => node.Parent as IfStatementSyntax)
                .ToList();

            var lookup = new Dictionary<StatementSyntax,StatementSyntax>();

            if (returnActions.Count > 0)
            {
                foreach(var ifStatement in returnActions)
                {
                    var mainCall = ifStatement.GetPrevious() as ExpressionStatementSyntax;                        
                    var newIfStatement = ifStatement.WithCondition(mainCall.Expression.WithoutTrivia());

                    lookup[mainCall] = null;
                    lookup[ifStatement] = newIfStatement;
                }

                //this only replace some of the nodes
                root = root.ReplaceNodes(lookup.Keys, (s, d) => lookup[s]);
            }
        }

        return root.ToFullString();
    }

The problem is that when I call root.ReplaceNodes only some of the nodes gets replaced.

I guess that the replacement changes the tree so that the other nodes no longer match the original tree and thus cant be replaced.

But what is the best way to deal with this?

Looping over the process over and over untill no more change occurs feels lame :)

The changes can occur nested, and I think that is what causes the problems here. Can I sort the changeset somehow to get around this or is there an idiomatic way to go about things here?

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

I guess that the replacement changes the tree so that the other nodes no longer match the original tree and thus cant be replaced.

You're right. Replacing nodes creates entirely new syntax trees. Nodes from previous syntax trees cannot be compared against these new syntax trees.

There are four ways to apply multiple changes to a syntax tree:

  1. Use the DocumentEditor - See: https://stackoverflow.com/a/30563669/300908
  2. Use Annotations (Lines 236 and 240)
  3. Use .TrackNodes()
  4. Create a CSharpSyntaxRewriter that replaces nodes in a bottom-up approach. I've written about this on my blog.

Of these options, I believe the DocumentEditor has the reputation for being the easiest to use. It may very well be the idiomatic way to apply multiple changes going forward.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda