C# 如何通过添加和删除从旧根中检索的节点来创建新根?
我正在创建一个代码修复程序来更改以下内容:C# 如何通过添加和删除从旧根中检索的节点来创建新根?,c#,roslyn,C#,Roslyn,我正在创建一个代码修复程序来更改以下内容: if(obj is MyClass) { var castedObj = obj as MyClass; } 为此: var castedObj = obj as MyClass; if(castedObj != null) { } 这意味着我必须做3件事: 更改if语句中的条件 将铸件向右移动到if语句上方 删除正文中的语句 到目前为止,我所有的尝试都让我无法让这些东西中的最多两个发挥作用 我认为出现这个问题是因为在同一级别上基本上有
if(obj is MyClass)
{
var castedObj = obj as MyClass;
}
为此:
var castedObj = obj as MyClass;
if(castedObj != null)
{
}
这意味着我必须做3件事:
- 更改
语句中的条件if
- 将铸件向右移动到
语句上方if
- 删除正文中的语句
if
语句之外,要么设法更改条件并删除变量赋值。永远都不会
我该如何解决这个问题
为了更好地衡量,以下是我更改条件并删除赋值的代码:
var newIfStatement = ifStatement.RemoveNode(
variableDeclaration,
SyntaxRemoveOptions.KeepExteriorTrivia);
newIfStatement = newIfStatement.ReplaceNode(newIfStatement.Condition, newCondition);
var ifParent = ifStatement.Parent;
var newParent = ifParent.ReplaceNode(ifStatement, newIfStatement);
newParent = newParent.InsertNodesBefore(
newIfStatement,
new[] { variableDeclaration })
.WithAdditionalAnnotations(Formatter.Annotation);
var newRoot = root.ReplaceNode(ifParent, newParent);
你看过这门课了吗?它在处理修改语法时非常有用,尤其是当应用于树的更改可能导致无效问题时。这些操作与您已经定义的操作基本相同,只需使用DocumentEditor
方法,看看是否有帮助。我无法验证这是否解决了您的ATM问题,但我认为它在过去曾经为我解决过类似的问题。如果可以的话,我以后再测试
像这样的东西可以做到:
var editor = await DocumentEditor.CreateAsync(document);
editor.RemoveNode(variableDeclaration);
editor.ReplaceNode(ifStatement.Condition, newCondition);
editor.InsertBefore(ifStatement,
new[] { variableDeclaration.WithAdditionalAnnotations(Formatter.Annotation) });
var newDocument = editor.GetChangedDocument();
我已经设法以以下方式做了一些非常类似的事情。 我提取while条件并将其移动到while之前,并用新节点替换该条件。 在while的主体中,我添加了一个新语句。 在本例中,您将从主体中删除所需的语句,而不是添加语句 开始于
Refactor(BlockSyntax oldBody)
步骤1:我首先访问并标记我要更改的节点,同时生成新节点,但不添加新节点
步骤2:跟踪标记的节点并替换为新节点
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<SyntaxNode> markedNodes = new List<SyntaxNode>();
private readonly List<Tuple<ExpressionSyntax, IdentifierNameSyntax, StatementSyntax, WhileStatementSyntax>> replacementNodes =
new List<Tuple<ExpressionSyntax, IdentifierNameSyntax, StatementSyntax, WhileStatementSyntax>>();
//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<ExpressionSyntax, IdentifierNameSyntax, StatementSyntax, WhileStatementSyntax>(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<SyntaxNode>() { 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;
}
}
类WhileConditionRefactoringVisitor:CSharpSyntaxRewriter
{
专用静态int条件_计数器=0;
私有静态字符串条件\u VAR=“whileCondition”;
私有静态字符串条件标识符
{
获取{return CONDITION_VAR+CONDITION_COUNTER++;}
}
private readonly List markedNodes=new List();
私有只读列表替换节点=
新列表();
//第一步
public override SyntaxNode VisitWhileStatement(whilestatementsynax节点)
{
var nodeVisited=(WhileStatementSyntax)base.VisitWhileStatement(节点);
var条件=nodeVisited.condition;
if(condition.Kind()==SyntaxKind.IdentifierName)
返回nodevisite;
字符串ConditionVariIdentifier=ConditionIdentifier;
var newConditionVar=SyntaxFactoryExtensions.GenerateLocalVariableDeclaration(ConditionVarieIdentifier,
条件,SyntaxKind.BoolKeyword).normalizeeWhitespace().WithTriviaFrom(nodeVisited);
var newCondition=SyntaxFactory.IdentifierName(ConditionVariIdentifier).WithTriviaFrom(condition);
添加(条件);
添加(节点);
Add(新元组(condition,newCondition,newConditionVar,node));
返回nodevisite;
}
//步骤2
私有块语法替换节点(块语法旧体)
{
oldBody=oldBody.TrackNodes(this.markedNodes);
foreach(此.replacementNodes中的变量元组)
{
var currentA=oldBody.GetCurrentNode(tuple.Item1);
如果(currentA!=null)
{
var whileStatement=current a.Parent;
oldBody=oldBody.InsertNodesBefore(whileStatement,new List(){tuple.Item3});
var currentB=oldBody.GetCurrentNode(tuple.Item1);
oldBody=oldBody.ReplaceNode(currentB,tuple.Item2);
var currentwile=oldBody.GetCurrentNode(tuple.Item4);
//修饰体
var whileBody=currentWhile.Statement作为块语法;
//创建新语句
var localCondition=tuple.Item3作为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(赋值);
whileBody=whileBody.带声明(新闻声明);
//更新时
var newWhile=当前带状态的while(whileBody);
oldBody=oldBody.ReplaceNode(currentWhile,newWhile);
}
}
返回旧体;
}
公共块语法重构(块语法oldBody)
{
markedNodes.Clear();
replacementNodes.Clear();
//第一步
oldBody=(BlockSyntax)this.Visit(oldBody);
//步骤2
oldBody=此.ReplaceNodes(oldBody);
返回旧体;
}
}
我希望我以前就知道这个类:不可变节点不在一起工作就不会有麻烦了。只需要几行代码就可以替换上面的所有内容,而且读起来非常流畅。我将编辑您的答案,以包含我以前完成的代码。