It can be tricky to keep track nodes when applying changes to syntax trees. Every time we “change” a tree, we’re really creating a copy of it with our changes applied to that new tree. The moment we do that, any pieces of syntax we had references to earlier become invalid in the context of the new tree.
What’s this mean in practice? It’s tough to keep track of syntax nodes when we change syntax trees.
A recent Stack Overflow question touched on this. How can we get the symbol for a class that we’ve just added to a document? We can create a new class declaration, but the moment we add it to the document, we lose track of the node. So how can we keep track of the class so we can get the symbol for it once we’ve added it to the document?
The answer: Use a
SyntaxAnnotation is a basically piece of metadata we can attach to a piece of syntax. As we manipulate the tree, the annotation sticks with that piece of syntax making it easy to find.
There are a couple of overloads available when creating a
SyntaxAnnotation. We can specify
Data to be attached to pieces of syntax.
Data is used to attach extra information to a piece of syntax that we’d like to retrieve later.
Kind is a field we can use to search for Syntax Annotations.
So instead of looking for the exact instance of our annotation on each node, we could search for annotations based on their kind:
This is just one of a few different ways for dealing with Roslyn’s immutable trees. It’s probably not the easiest to use if you’re making multiple changes and need to track multiple syntax nodes. (If that’s the case, I’d recommend the DocumentEditor). That said, it’s good to be aware of it so you can use it when it makes sense.