In the previous article we looked at the result of parsing stage of compilation -
syntax graph, how it represent information available to C# compiler from analyzing a
single file of code and, consequentially, reflects that text quite faithfully and how to transform
it to refactor existing code. In this article we will look at symbol graph - result of the
next stage of compilation - binding.
In the syntax graph you can see that core C# concepts are represented by corresponding
node type, like ClassDeclaration or
MethodDeclaration. Inside they often contain IdentifierTokens
representing the textual name of some type, but that is as much information as you initially get.
In order to get information about a particular type, like its namespace or members, you’d
need to get its symbol by performing a costly binding process – check which namespaces
are currently used in the file, look for type declarations through the entire solution and all imported
DLLs that match, compile them if need be, etc. - compile everything.
The symbol graph allows you to answer a lot more meaningful questions than syntax graph.
Want to track down all usages of a specific type? Rename something solution-wide? You can do that.
You can trigger a limited binding for a given piece of syntax graph, or you can hook into the
compilation process of the IDE itself (it is continuously recompiling your solution on every change
to warn you of any errors as you type away). This common way to do this is by creating a class inheriting