You can use SyntaxVisitor
for this: it recursively walks the syntax tree and executes your code for each node, depending on its type.
You will need to specify how exactly should various kinds of statements behave. For example:
- For simple statements (like
ExpressionStatementSyntax
) just return 0. - For nesting statements (including
IfStatementSyntax
and several others), return the depth of its child statement + 1. You get the depth of the child by recursively callingVisit()
on it. - For
BlockSyntax
, return the maximum depth of its children.
In code, that would look something like:
class NestingLevelVisitor : SyntaxVisitor<int>
{
public override int DefaultVisit(SyntaxNode node)
{
throw new NotSupportedException();
}
public override int VisitMethodDeclaration(MethodDeclarationSyntax node)
{
return Visit(node.Body);
}
public override int VisitBlock(BlockSyntax node)
{
return node.Statements.Select(Visit).Max();
}
public override int VisitExpressionStatement(ExpressionStatementSyntax node)
{
return 0;
}
public override int VisitIfStatement(IfStatementSyntax node)
{
int result = Visit(node.Statement);
if (node.Else != null)
{
int elseResult = Visit(node.Else.Statement);
result = Math.Max(result, elseResult);
}
return result + 1;
}
}
This code is incomplete, you will need to add overrides for all the other kinds of statements.
Usage is something like:
MethodDeclarationSyntax method = …;
int methodNestingLevel = new NestingLevelVisitor().Visit(method);