c# - ¿Cómo eliminar una lista de SyntaxNode del documento utilizando las API del proveedor de arreglos de código Roslyn?
visual-studio-2013 vsix (1)
Tengo una declaración de variable generada de forma personalizada utilizando SyntaxFactory.VariableDeclaration
y una lista de SyntaxNode
recopilada según algunas condiciones.
Hice lo siguiente:
Modificar el nodo
var newRoot = root.ReplaceNode(expression, newVariableDeclaration)
Esto modificó correctamente el nodo con la
newVariableDeclaration
.En un bucle, elimine los nodos correspondientes a los que están en la lista
foreach (var listObject in listObjects) { newRoot = newRoot.RemoveNode(listObject, SyntaxRemoveOptions.KeepNoTrivia); }
Esto no cambia el
newRoot
y todo ellistObject
requerido para ser cambiado sigue siendo el mismo.
Si usamos root.RemoveNode(listObject, SyntaxRemoveOptions.KeepNoTrivia)
, obviamente continuará reemplazando los cambios anteriores.
Así que aquí la newVariableDeclaration
es el único nodo que se cambia en todo el documento, esto es porque newRoot
SyntaxNodes
tiene cambios de la del SyntaxNode
que obtuve desde la root
.
Por favor corrígeme si lo estoy haciendo mal.
EDITAR: busqué en CSharpSyntaxRewriter
pero parece que está analizando un solo nodo cada vez que visita un nodo y solo puede modificar un solo nodo a la vez. En mi caso, tendré que visitar un nodo en particular, realizar cambios en él y eliminar otros nodos con respecto a los cambios realizados en el nodo visitado.
El problema con su enfoque es que cada vez que cambie el árbol (utilizando ReplaceNode()
o RemoveNode()
), significa que todos los nodos cambian también. Es por eso que sus llamadas a RemoveNode()
después de ReplaceNode()
no hacen nada.
Una forma de solucionar esto es usar TrackNodes()
, para que pueda encontrar qué nodos en el árbol modificado corresponden a nodos en el árbol original.
De esta forma, un método que reemplaza una secuencia de nodos con un solo nodo podría verse así:
public static T ReplaceNodes<T>(
this T root, IReadOnlyList<SyntaxNode> oldNodes, SyntaxNode newNode)
where T : SyntaxNode
{
if (oldNodes.Count == 0)
throw new ArgumentException();
var newRoot = root.TrackNodes(oldNodes);
var first = newRoot.GetCurrentNode(oldNodes[0]);
newRoot = newRoot.ReplaceNode(first, newNode);
var toRemove = oldNodes.Skip(1).Select(newRoot.GetCurrentNode);
newRoot = newRoot.RemoveNodes(toRemove, SyntaxRemoveOptions.KeepNoTrivia);
return newRoot;
}