Puede ser complicado realizar un seguimiento de los nodos al aplicar cambios a los árboles de sintaxis. Cada vez que "cambiamos" un árbol, en realidad estamos creando una copia del mismo con nuestros cambios aplicados a ese nuevo árbol. En el momento en que hacemos eso, cualquier pieza de sintaxis a la que tuviéramos referencias anteriormente se vuelve inválida en el contexto del nuevo árbol.
¿Qué significa esto en la práctica? Es difícil hacer un seguimiento de los nodos de sintaxis cuando cambiamos los árboles de sintaxis.
Una pregunta reciente de Stack Overflow se refirió a esto. ¿Cómo podemos obtener el símbolo de una clase que acabamos de agregar a un documento? Podemos crear una nueva declaración de clase, pero en el momento en que la agregamos al documento, perdemos el rastro del nodo. Entonces, ¿cómo podemos realizar un seguimiento de la clase para que podamos obtener el símbolo una vez que la hayamos agregado al documento?
La respuesta: usar una anotación de sintaxis
Una SyntaxAnnotation es básicamente una pieza de metadatos que podemos adjuntar a una pieza de sintaxis. A medida que manipulamos el árbol, la anotación se adhiere a esa parte de la sintaxis, lo que facilita su búsqueda.
AdhocWorkspace workspace = new AdhocWorkspace();
Project project = workspace.AddProject("SampleProject", LanguageNames.CSharp);
//Attach a syntax annotation to the class declaration
var syntaxAnnotation = new SyntaxAnnotation();
var classDeclaration = SyntaxFactory.ClassDeclaration("MyClass")
.WithAdditionalAnnotations(syntaxAnnotation);
var compilationUnit = SyntaxFactory.CompilationUnit().AddMembers(classDeclaration);
Document document = project.AddDocument("SampleDocument.cs", compilationUnit);
SemanticModel semanticModel = document.GetSemanticModelAsync().Result;
//Use the annotation on our original node to find the new class declaration
var changedClass = document.GetSyntaxRootAsync().Result.DescendantNodes().OfType<ClassDeclarationSyntax>()
.Where(n => n.HasAnnotation(syntaxAnnotation)).Single();
var symbol = semanticModel.GetDeclaredSymbol(changedClass);