How do I create a new root by adding and removing nodes retrieved from the old root?

前端 未结 2 1489
南笙
南笙 2020-12-09 05:21

I am creating a Code Fix that changes this:

if(obj is MyClass)
{
    var castedObj = obj as MyClass;
}

into this:

var caste         


        
2条回答
  •  情书的邮戳
    2020-12-09 05:44

    I have managed to do something very similar in the following manner. I extract the while condition and move it before the while and replace the condition with a new node. In the body of while, I add a new statement. In your case, instead of adding a statement, you will remove the desired statement from the body.

    Start at

    Refactor(BlockSyntax oldBody)
    

    STEP 1: I first visit and mark the nodes that I want to change and at the same time generate new nodes, but don't add the new ones yet.

    STEP 2: Track the marked nodes and replace with new ones.

    class WhileConditionRefactoringVisitor : CSharpSyntaxRewriter
    {
        private static int CONDITION_COUNTER = 0;
        private static string CONDITION_VAR = "whileCondition_";
    
        private static string ConditionIdentifier
        {
            get { return CONDITION_VAR + CONDITION_COUNTER++; }
        }
    
        private readonly List markedNodes = new List();
    
        private readonly List> replacementNodes =
            new List>();
    
    
            //STEP 1
            public override SyntaxNode VisitWhileStatement(WhileStatementSyntax node)
        {
            var nodeVisited = (WhileStatementSyntax) base.VisitWhileStatement(node);
    
            var condition = nodeVisited.Condition;
            if (condition.Kind() == SyntaxKind.IdentifierName)
                return nodeVisited;
    
    
            string conditionVarIdentifier = ConditionIdentifier;
            var newConditionVar = SyntaxFactoryExtensions.GenerateLocalVariableDeclaration(conditionVarIdentifier,
                condition, SyntaxKind.BoolKeyword).NormalizeWhitespace().WithTriviaFrom(nodeVisited);
            var newCondition = SyntaxFactory.IdentifierName(conditionVarIdentifier).WithTriviaFrom(condition);
    
            markedNodes.Add(condition);
            markedNodes.Add(node);
            replacementNodes.Add(new Tuple(condition, newCondition, newConditionVar, node));
    
            return nodeVisited;
        }
    
            //STEP 2
             private BlockSyntax ReplaceNodes(BlockSyntax oldBody)
        {
            oldBody = oldBody.TrackNodes(this.markedNodes);
            foreach (var tuple in this.replacementNodes)
            {
                var currentA = oldBody.GetCurrentNode(tuple.Item1);
                if (currentA != null)
                {
                    var whileStatement = currentA.Parent;
                    oldBody = oldBody.InsertNodesBefore(whileStatement, new List() { tuple.Item3 });
                    var currentB = oldBody.GetCurrentNode(tuple.Item1);
                    oldBody = oldBody.ReplaceNode(currentB, tuple.Item2);
                    var currentWhile = oldBody.GetCurrentNode(tuple.Item4);
                    //modify body
                    var whileBody = currentWhile.Statement as BlockSyntax;
                    //create new statement
                    var localCondition = tuple.Item3 as LocalDeclarationStatementSyntax;
                    var initializer = localCondition.Declaration.Variables.First();
                    var assignment = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                        SyntaxFactory.IdentifierName(initializer.Identifier), initializer.Initializer.Value));
                    var newStatements = whileBody.Statements.Add(assignment);
                    whileBody = whileBody.WithStatements(newStatements);
                    //updateWhile
                    var newWhile = currentWhile.WithStatement(whileBody);
                    oldBody = oldBody.ReplaceNode(currentWhile, newWhile);
                }
            }
            return oldBody;
        }
    
            public BlockSyntax Refactor(BlockSyntax oldBody)
            {
                markedNodes.Clear();
                replacementNodes.Clear();
                //STEP 1
                oldBody = (BlockSyntax)this.Visit(oldBody);
                //STEP 2
                oldBody = this.ReplaceNodes(oldBody);
    
                return oldBody;
            }
    
        }
    

提交回复
热议问题