2012-11-17 8 views
8

ja chcąc dokonać kilku zmian w składni drzewa Roslyn naraz, wszystko w tym samym obszarze koduDokonywanie kilka modyfikacji do SyntaxTree naraz

tree = tree.ReplaceNodes(oldNode, newNode).RemoveNode(toRemove); 

jednak tylko pierwsza modyfikacja powiedzie. Wygląda na to, że pierwsza zmiana zmienia wszystkie węzły wokół niej, więc metoda RemoveNodes nie znajduje już w powstałym drzewie toRemove. Naprawdę, naprawdę, nie chcę ponownie wykonywać pracy, aby ponownie obliczyć toRemove w nowym drzewie i przy użyciu pojedynczego narzędzia SyntaxRewriter do wykonania wszystkich prac (przesłonięcie metody DefaultVisit) jest śmiesznie powolny.

Jak mogę zrobić, co chcę?

Odpowiedz

5

Zanim zaproponuję kilka alternatyw, twój komentarz, że SyntaxRewriter jest "śmiesznie wolny" jest nieco zaskakujący. Kiedy mówisz "powolny", masz na myśli "to jest dużo kodu do napisania" lub "działa strasznie"? Jest to najszybszy (czas realizacji mądry) sposób wykonywania wielu zamienników, a zarówno ReplaceNodes, jak i RemoveNode używają wewnętrznie rozwieracza. Jeśli masz problemy z wydajnością, upewnij się, że podczas implementacji DefaultVisit odwiedzasz tylko typy podrzędne, jeśli interesujące Cię węzły znajdują się w węźle, do którego są wywoływane. Prosta sztuczka polega na porównaniu przęseł i upewnieniu się, że zasięg węzła przeszedł, przecinając się z przetwarzanymi węzłami.

W każdym razie, SyntaxAnnotations zapewniają użyteczny sposób lokalizowania węzłów w drzewach po modyfikacji. Możesz po prostu utworzyć instancję typu i dołączyć ją do węzła za pomocą metody rozszerzenia WithAdditionalAnnotations. Możesz ponownie zlokalizować węzeł za pomocą metody GetAnnotatedNodesOrTokens.

Jednym ze sposobów rozwiązania problemu jest umieszczenie adnotacji na swoim elemencie remove, a następnie wywołanie ReplaceNodes powoduje wykonanie dwóch zamienników w tym samym wywołaniu - jeden do zastąpienia staregoNode -> newNode, a drugi do wykonania toRemove -> toRemoveWithAnnotation replacement. Następnie znajdź węzeł z adnotacjami w wynikowym drzewie i wywołaj funkcję RemoveNode.

Jeśli wiesz, że oldNode i toRemove nie są żadnymi przodkami (tj. Znajdują się w niepowiązanych częściach drzewa), inną opcją byłoby odwrócenie kolejności. Chwyć węzeł nadrzędny (nazwij go oldNodeParent), aby usunąć i wywołać metodę RemoveNode, co oznacza, że ​​otrzymasz zaktualizowany węzeł nadrzędny (nazwij go oldNodeParentRewritten). Następnie wywołaj ReplaceNodes, wykonując dwie zamienniki: oldNode -> newNode i oldNodeParent -> oldNodeParentRewritten. Brak adnotacji.

Powiązane problemy