Modules/businessdev.ALbuild.Apps/Private/Invoke-BcCallGraphAnalysis.ps1

function Invoke-BcCallGraphAnalysis {
    <#
    .SYNOPSIS
        Runs the call graph engine over a graph (and optionally a baseline) and returns its result dictionary.
 
    .DESCRIPTION
        Metrics, findings (not reached by tests, obsolete calls, dead code), the architecture (parts from
        callgraph.architecture.json, else from the folders), the AL checks, the report model and - with a
        baseline - the impact: added, modified and removed members, their transitive callers and the tests
        that reach the change. A baseline is the folder of an earlier call graph; its analysis.json supplies
        the per-member source hashes that reveal a changed body.
 
    .OUTPUTS
        System.Collections.Generic.Dictionary[string, object] (the analysis.json content).
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)] [string] $GraphPath,
        [string] $BaselinePath,
        [string] $WorkspaceRoot,
        [string] $ArchitecturePath,
        [int] $MaxListItems = 2000
    )

    $context = Get-BcCallGraphContext -GraphPath $GraphPath -WorkspaceRoot $WorkspaceRoot -ArchitecturePath $ArchitecturePath
    $baseline = $null
    if ($BaselinePath) {
        $baseline = Resolve-BcCallGraphPath -Path $BaselinePath
        if (-not $baseline) { Write-ALbuildLog -Level Warning "Baseline '$BaselinePath' has no call graph; the impact is not computed." }
        elseif (-not $baseline.AnalysisPath) { Write-ALbuildLog -Level Warning "Baseline '$BaselinePath' has no analysis.json; changed bodies are only detected through changed calls." }
    }

    $options = New-Object ALbuild.CallGraph.AnalysisOptions
    $options.WorkspaceRoot = $context.WorkspaceRoot
    $options.MaxListItems = $MaxListItems
    $options.ArchitecturePath = $context.ArchitecturePath
    $sw = [System.Diagnostics.Stopwatch]::StartNew()
    $result = [ALbuild.CallGraph.Analyzer]::Analyze($context.Graph.GraphPath, $context.Apps,
        $(if ($baseline) { $baseline.GraphPath } else { $null }), $(if ($baseline) { $baseline.AnalysisPath } else { $null }), $options)
    $result['baseline'] = if ($baseline) { $baseline.Folder } else { $null }
    $arch = $result['architecture']
    Write-ALbuildLog ("Call graph analysed in {0} s; architecture from {1}: {2} parts, {3} of {4} objects unassigned, {5} described{6}." -f
        [int]$sw.Elapsed.TotalSeconds, $(if ($arch['source'] -eq 'file') { $context.ArchitecturePath } else { 'the folders' }), $arch['parts'].Count,
        $arch['unassigned'], $arch['objects'], $arch['described'], $(if ($arch['warnings'].Count) { ", $($arch['warnings'].Count) warning(s)" } else { '' }))
    foreach ($w in $arch['warnings']) { Write-ALbuildLog -Level Warning "Architecture: $w" }
    return , $result
}