Roslyn insert node s after the specified node

I am writing a code analyzer that inverts an if statement to reduce nesting.

I can generate a new one if node and replace it with the document root. However, I have to move all the content (statements) coming from this if statement below it. Let me show what I have achieved so far:

var ifNode = @if;
var ifStatement = @if.Statement as BlockSyntax;
var returnNode = (ifNode.Parent as BlockSyntax).Statements.Last() as ReturnStatementSyntax ?? SyntaxFactory.ReturnStatement();
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var invertedIf = ifNode.WithCondition(Negate(ifNode.Condition, semanticModel, cancellationToken))
.WithStatement(returnNode)                
.WithAdditionalAnnotations(Formatter.Annotation);
var root = await document.GetSyntaxRootAsync(cancellationToken);
var newRoot = root.ReplaceNode(ifNode, invertedIf);
newRoot = newRoot.InsertNodesAfter(invertedIf, ifStatement.Statements); //It seems no to be working. There no code after specified node.

return document.WithSyntaxRoot(newRoot);

Before:

public int Foo()
{
    if (true)
    {
        var a = 3;
        return a;
     }

     return 0;
}

After:

public int Foo()
{
    if (false)
        return 0;

    var a = 3;
    return a;
}
+4
source share
1 answer

Carlos, the problem is that after ReplaceNodeyou created a new node. When you go InsertNodeAfterand pass the node from the original root of the node, the new node will not be able to find it. In the analyzer, you need to either make all the changes at once, or annotate or track the nodes so that you can return to them later.

node, node . , FindNode, :

newRoot = newRoot.InsertNodesAfter(newRoot.FindNode(ifNode.Span), ifStatement.Statements);

, .

+2