Reputation:
I am writing a documentation generator that uses Roslyn to extract information from C# source code. As part of that I need to get ISymbol
information for various types of SyntaxNodes
. However, there doesn't seem to be a generalized way of doing this.
Let's say I want to determine the accessibility of a certain type of node (e.g., private
, protected
, public
). That information is readily available if the node contains the DeclaredAccessibility
property. But there doesn't seem to be an interface that indicates a given node does. Consequently you have to either use reflection to see if has that property, which can be computationally expensive, or know exactly what kind of node you're dealing with so you can cast it to the correct type.
Here's an example based on a related situation involving determining the accessibility of a const
:
public const string Dummy = "abc";
When I walk through the syntax tree, and use the corresponding semantic model to extract accessibility information, I end up doing this:
SyntaxNode nodeToTest = null;
switch( syntaxNode )
{
case FieldDeclarationSyntax fieldDecNode:
// all the fields expressed in a field declaration share the same
// modifiers (e.g., public, static, const) and type; they're basically
// all from the same statement/line of code
nodeToTest = fieldDecNode.Declaration.Variables.FirstOrDefault();
break;
default:
nodeToTest = syntaxNode;
break;
}
var nodeInfo = syntaxTree.Model.GetDeclaredSymbol( nodeToTest );
This works, and if it's the least bad approach I'll live with it (and extend it when I run into other quirks). But it feels kludgy, and I'd like to use a better/more flexible approach.
Upvotes: 1
Views: 391
Reputation: 149
Have you considered using CSharpSyntaxWalker
?
Represents a CSharpSyntaxVisitor that descends an entire CSharpSyntaxNode graph visiting each CSharpSyntaxNode and its child SyntaxNodes and SyntaxTokens in depth-first order.
You can create your own walker class which inherits from the CSharpSyntaxWalker
class and override the visit function for each subtype of SyntaxNode
that you are concerned with. This means that the type of the node will be known in the function. For your example, you would override the VisitFieldDeclaration
method. The doc link shows the methods for each type of SyntaxNode
visitor you can override.
internal class TestWalker : CSharpSyntaxWalker
{
private readonly SemanticModel _model;
public TestWalker(SemanticModel model)
{
_model = model;
}
public override void VisitFieldDeclaration(FieldDeclarationSyntax node)
{
// do your const field accessibility analysis here
}
// override any other syntax visitors here
}
You can add any other implementation details you need to the class. When you need to do the analysis, instantiate your walker and call the Visit()
method on the SyntaxNode
you want to start walking from.
Upvotes: 0