Private/Metrics/Measure-FunctionMaxNestingDepth.ps1

Function Measure-FunctionMaxNestingDepth {
<#
.SYNOPSIS
    Gets the depth of the most deeply nested statement in the function.
.DESCRIPTION
    Gets the depth of the most deeply nested statement in the function.
    Measuring the maximum nesting depth in a function is a way of evaluating its complexity.
 
.PARAMETER FunctionDefinition
    To specify the function definition to analyze.
 
.EXAMPLE
    PS C:\> Measure-FunctionMaxNestingDepth -FunctionDefinition $MyFunctionAst
 
    Gets the depth of the most deeply nested statement in the specified function definition.
 
.OUTPUTS
    System.Int32
 
.LINK
    Additional information on why maximum nesting depth is an interesting measure of code complexity :
    https://www.cqse.eu/en/blog/mccabe-cyclomatic-complexity/
     
#>

    [CmdletBinding()]
    [OutputType([System.Int32])]
    Param (
        [Parameter(Position=0, Mandatory)]
        [System.Management.Automation.Language.FunctionDefinitionAst]$FunctionDefinition
    )

    $FunctionText = $FunctionDefinition.Extent.Text
    $Tokens = $Null
    $Null = [System.Management.Automation.Language.Parser]::ParseInput($FunctionText, [ref]$Tokens, [ref]$Null)

    [System.Collections.ArrayList]$NestingDepthValues = @()
    [System.Int32]$NestingDepth = 0
    [System.Collections.ArrayList]$CurlyBraces = $Tokens.Where({ $_.Kind -in 'AtCurly','LCurly','RCurly' })

    # Removing the first opening curly and the last closing curly because they belong to the function itself
    $CurlyBraces.RemoveAt(0)
    $CurlyBraces.RemoveAt(($CurlyBraces.Count - 1))
    If ( -not $CurlyBraces ) {
        return $NestingDepth
    }

    Foreach ( $CurlyBrace in $CurlyBraces ) {

        If ( $CurlyBrace.Kind -in 'AtCurly','LCurly' ) {
            $NestingDepth++
        }
        ElseIf ( $CurlyBrace.Kind -eq 'RCurly' ) {
            $NestingDepth--
        }
        $Null = $NestingDepthValues.Add($NestingDepth)
    }
        Write-VerboseOutput -Message "Number of nesting depth values : $($NestingDepthValues.Count)"
        $MaxDepthValue = ($NestingDepthValues | Measure-Object -Maximum).Maximum -as [System.Int32]
        return $MaxDepthValue
}