我目前正在使用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 == updated为true).
似乎在循环的第一次迭代之后,所有子项都被重建为新对象,并且在子列表中不再能够找到存储在我的匹配中的原始子对象(updated.ChildNodes().其中(x = > x == mO)为空).
这样做有什么好办法?
解决方法
我目前的做法:
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());