使用SyntaxNode.ReplaceNode替换同一树中的多个节点

本文关键字:节点 SyntaxNode ReplaceNode 替换 使用 | 更新日期: 2023-09-27 18:10:45

我目前正在使用Roslyn进行语法树的三向合并。我有一个ClassDeclerationSyntax节点上的所有子节点之间的匹配,并且想对子节点执行合并,然后基于该合并创建一个新树。

0为输入ClassDeclerationSyntax,匹配有三个MemberDeclerationSyntax类型的成员(A, O, B)。

var updated = O;
foreach (var m in matching)
{
    if (m.A != null && m.B != null && m.O != null) {
        var merge = Merge(m.A, m.O, m.B);
        var oldUpdated = updated;
        updated = updated.ReplaceNode(m.O, merge);
    }
    else if (m.A == null && m.O == null && m.B != null)
        updated = updated.AddMembers(m.B);
    else if (m.A != null && m.O == null && m.B == null)
        updated = updated.AddMembers(m.A);
}

这不起作用。在第二次迭代中,ReplaceNode返回一个完全未修改的节点(oldUpdated == updatedtrue)。

似乎在循环的第一次迭代之后,所有的子对象都被重构为新对象,并且在我的匹配中存储的原始子对象再也不能在子列表中找到(updated.ChildNodes().Where(x => x == m.O)为空)。

做这件事的好方法是什么?

使用SyntaxNode.ReplaceNode替换同一树中的多个节点

我目前的做法:

var updateMember = new Dictionary<MemberDeclarationSyntax, MemberDeclarationSyntax>();
var addMembers = new List<MemberDeclarationSyntax>();
foreach (var m in matching) {
    if (m.A != null && m.B != null && m.O != null) {
        var mergeChild = Merge(m.A, m.B, M.O);
        updateMember.Add(m.O, child);
    }
    else if (m.A == null && m.O == null && m.B != null) 
        addMembers.Add(m.B);
    else if (m.A != null && m.O == null && m.B == null)
        addMembers.Add(m.A);
}
var merged = O.ReplaceNodes(updateMember.Keys.AsEnumerable(), (n1, n2) =>
{
    return updateMember[n1];
}).AddMembers(addMembers.ToArray());