One recurring problem I’ve seen people run into with Roslyn is working with fields and symbols. Consider the following:
The above program consists of a
ClassDecarationSyntax with child
In previous blog posts, we discussed how we could use
SemanticModel.GetDeclaredSymbol(SyntaxNode) to retrieve the symbol for pieces of declaration syntax. So it would make sense if we could get the symbols for our field, property and method with the same approach.
Typically one would try the following:
However, there’s a problem here.
fieldSymbol is null! Our approach worked for methods and properties, but didn’t for fields. The reason for this is actually quite simple:
Fields can contain multiple symbols.
This is even clearer when we look at the syntax tree (I’ve omitted tokens and trivia).
What symbol could be returned for the above
FieldDeclarationSyntax? In order to access these symbols we instead look at the individual variables within the field as shown below:
It turns out fields are not the only “special syntax” that cannot be converted into a symbol. If you’re interesting, you can see them all online on the Roslyn Reference Source. They are:
- Global Statements – Global statements don’t declare anything, even though they inherit from MemberDeclarationSyntax.
- IncompleteMembers – Incomplete members don’t declare any symbols.
- Event Field Declaration – Can contain multiple variable declarators. GetDeclaredSymbol should be called on them (the declarators) directly.
- Field Declaration – Can contain multiple variable declarators. GetDeclaredSymbol should be called on them (the declarators) directly.
This bit me in August and I submitted an Issue to the Roslyn team about this. I originally thought an exception should be thrown in these cases, but I’ve since changed my mind. Instead, I think there needs to be clearer documentation on the GetDeclaredSymbol() function. It also might be appropriate for someone to create an analyzer that detects when people do this and warn them.