2015-05-24 3 views
4

Я пишу анализатор кода, который инвертирует оператор if для уменьшения вложенности.Roslyn для вставки узлов после указанного узла

Я могу сгенерировать новый узел if и заменить его на корень документа. Однако я должен переместить весь контент (заявления), исходящий из этого утверждения if, ниже него. Позвольте мне показать, что я достиг до сих пор:

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's no code after specified node. 

return document.WithSyntaxRoot(newRoot); 

До:

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

    return 0; 
} 

После:

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

    var a = 3; 
    return a; 
} 
+0

Это немного сложно (возможно, только для меня), чтобы увидеть, чего вы пытаетесь достичь. Не могли бы вы предоставить до и после того, что вы хотели бы достичь? – JoshVarty

+0

Как @JoshVarty спросил, есть ли пример для до/после. – Gandarez

+0

Как вы выполняете синтаксис @If? – MHGameWork

ответ

2

Carlos, проблема в том, что после того как вы ReplaceNode вы создали новый узел , Когда вы идете InsertNodeAfter и передаете узел из исходного корневого узла, новый узел не может его найти. В анализаторе вам необходимо либо выполнить все изменения сразу, либо аннотировать или отслеживать узлы, чтобы вы могли вернуться к ним позже.

Но так как вы сначала заменяете узел, новый узел будет точно в одном месте. Таким образом, вы можете сократить и FindNode, как это:

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

Я не проверял этот код, но он должен работать.

Смежные вопросы