2013-04-24 1 views
6

현재 Roslyn을 사용하는 구문 트리에서 3 방향 병합을 수행 중입니다. ClassDeclerationSyntax 노드에있는 모든 자식 사이에 일치하는 항목이 있고 자식을 병합 한 다음 해당 병합을 기반으로 새 트리를 만들려고합니다.SyntaxNode.ReplaceNode를 사용하여 동일한 트리의 여러 노드 교체하기

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)를 반환합니다.

루프의 첫 번째 반복 후에 모든 자식이 새 개체로 재구성되었으며 내 일치에 저장된 원래 자식 개체가 더 이상 자식 목록 (updated.ChildNodes().Where(x => x == m.O)이 비어 있음)에서 찾을 수없는 것으로 보입니다.

어떻게하면 좋을까요?

+0

당신이 사용하는 주석을 할 수있을 전망이다. – svick

답변

6

내 현재의 접근 방식 :

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

이것이 올바른 접근 방법입니다. –