I'm currently working on three-way merging on syntax trees using Roslyn. I have a matching between all children on a a ClassDeclerationSyntax
node, and want to perform a merge on the children, and then create a new tree based on that merge.
O is the input ClassDeclerationSyntax
, and matching has three members (A, O, B) of the type MemberDeclerationSyntax
.
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);
}
This does not work. In the second iteration ReplaceNode
returns a completely unmodified node (oldUpdated == updated
is true
).
It seems that after the first iteration of the loop, all children have been reconstructed as new objects, and the original children-objects stored in my matching can no longer be found in the children list (updated.ChildNodes().Where(x => x == m.O)
is empty).
What would a good way be to do this?
My current approach:
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());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With