2013-04-24 6 views
6

Obecnie pracuję nad łączeniem trójwymiarowym na drzewach składni za pomocą Roslyn. Mam dopasowanie między wszystkimi dziećmi w węźle ClassDeclerationSyntax i chcę wykonać scalenie na elementach podrzędnych, a następnie utworzyć nowe drzewo na podstawie tego scalenia.Zastępowanie kilku węzłów w tym samym drzewie za pomocą metody SyntaxNode.ReplaceNode

O jest wejściem ClassDeclerationSyntax, a dopasowanie ma trzy elementy (A, O, B) typu 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); 
} 

To nie działa. W drugiej iteracji ReplaceNode zwraca się całkowicie niezmodyfikowany węzeł (oldUpdated == updated jest true).

Wygląda na to, że po pierwszej iteracji pętli wszystkie dzieci zostały zrekonstruowane jako nowe obiekty, a oryginalne obiekty potomne przechowywane w moim dopasowaniu nie mogą być już znalezione na liście dzieci (updated.ChildNodes().Where(x => x == m.O) jest pusta).

Jaki byłby dobry sposób na zrobienie tego?

+0

wierzę, powinieneś być w stanie to zrobić przy użyciu adnotacji. – svick

Odpowiedz

6

Moje obecne podejście:

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

To jest właściwe podejście. –