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

标签 c# roslyn

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

O 是输入 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)。

似乎在循环的第一次迭代之后,所有的children都被重构为新的对象,而我匹配中存储的原始children-objects在children列表中已经找不到了(updated.ChildNodes( ).Where(x => x == m.O) 为空)。

这样做的好方法是什么?

最佳答案

我目前的做法:

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());

关于c# - 使用 SyntaxNode.ReplaceNode 替换同一棵树中的多个节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16192488/

相关文章:

c# - 为什么在 .NET 中没有保留一些相同的字符串?

c# - 将参数传递给 Action?

c# - 用源代码替换对 Json.NET 的引用时无法编译项目

C#抽象类说明

c# - Roslyn - 查找所有符号

c# - 如何确定 FieldDeclarationSyntax 的类型是否是 Roslyn 中的接口(interface)?

c# - 如何使用 Roslyn 验证特定 Actor 阵容是否有效

c# - .Net Core - CS0012 'Object' 在未引用的程序集中定义

c# - 为什么 Debug 构建中的 C# JIT 汇编代码中的每个方法中都有 cmp + je

c# - 使用不记名身份验证和 webapi2 设置上次登录时间