Functions/GenXdev.Coding.PowerShell.Modules/Get-GenXdevCmdletUsageAnalysis.ps1
<#
.SYNOPSIS Analyzes GenXdev cmdlet usage patterns to identify most frequently called functions. .DESCRIPTION This script uses Get-GenXDevCmdlet to scan all GenXdev PowerShell modules and their functions to analyze which cmdlets are called most frequently by other cmdlets. This helps prioritize which functions to refactor to C# first, starting with the most commonly used ones. .PARAMETER OutputFormat Format for output: Table, List, or CSV. Default is Table. .PARAMETER Top Number of top results to show. Default is 50. .PARAMETER IncludeCallChains Include detailed call chain information showing which functions call which. .PARAMETER IncludeScripts Include script files in addition to module cmdlets. .EXAMPLE Get-GenXdevCmdletUsageAnalysis .EXAMPLE Get-GenXdevCmdletUsageAnalysis -Top 20 -OutputFormat List .EXAMPLE Get-GenXdevCmdletUsageAnalysis -IncludeCallChains -IncludeScripts | Export-Csv -Path "cmdlet-usage.csv" #> function Get-GenXdevCmdletUsageAnalysis { [CmdletBinding()] param( [ValidateSet('Table', 'List', 'CSV')] [string]$OutputFormat = 'Table', [int]$Top = 50, [switch]$IncludeCallChains, [switch]$IncludeScripts ) function GetPowerShellFunctionCalls { param( [string]$FilePath, [hashtable]$AllFunctions ) try { $content = Microsoft.PowerShell.Management\Get-Content -Path $FilePath -Raw -ErrorAction Stop # Remove comments and strings to avoid false positives $cleanedContent = $content -replace '#.*$', '' -replace '(?s)<#.*?#>', '' $cleanedContent = $cleanedContent -replace '"[^"]*"', '""' -replace "'[^']*'", "''" $calls = @() # Find function calls in various patterns $patterns = @( # Direct function calls: FunctionName, Module\FunctionName '(?:^|\s|;|\||\(|\{)([A-Za-z][A-Za-z0-9]*(?:\.[A-Za-z][A-Za-z0-9]*)*\\)?([A-Za-z][A-Za-z0-9]*-[A-Za-z][A-Za-z0-9]*)\s*(?:\s|\(|$)', # Ampersand calls: & FunctionName '&\s+([A-Za-z][A-Za-z0-9]*(?:\.[A-Za-z][A-Za-z0-9]*)*\\)?([A-Za-z][A-Za-z0-9]*-[A-Za-z][A-Za-z0-9]*)', # Dot sourcing: . FunctionName '\.\s+([A-Za-z][A-Za-z0-9]*(?:\.[A-Za-z][A-Za-z0-9]*)*\\)?([A-Za-z][A-Za-z0-9]*-[A-Za-z][A-Za-z0-9]*)' ) foreach ($pattern in $patterns) { $regexMatches = [regex]::Matches($cleanedContent, $pattern, 'IgnoreCase') foreach ($match in $regexMatches) { $fullName = if ($match.Groups[1].Value) { $match.Groups[1].Value + $match.Groups[2].Value } else { $match.Groups[2].Value } $functionName = $match.Groups[2].Value # Only include if it's a known GenXdev function if ($AllFunctions.ContainsKey($functionName) -or $AllFunctions.ContainsKey($fullName)) { $calls += $functionName } } } return $calls | Microsoft.PowerShell.Utility\Sort-Object -Unique } catch { Microsoft.PowerShell.Utility\Write-Warning "Error processing file ${FilePath}: $($_.Exception.Message)" return @() } } function BuildCallGraph { param([hashtable]$AllFunctions) $callGraph = @{} $usageCount = @{} $callChains = @{} # Initialize counts foreach ($funcName in $AllFunctions.Keys) { $usageCount[$funcName] = 0 $callChains[$funcName] = @() } $total = $AllFunctions.Count $current = 0 foreach ($function in $AllFunctions.GetEnumerator()) { $current++ Microsoft.PowerShell.Utility\Write-Progress -Activity "Analyzing GenXdev cmdlet usage patterns" -Status "Processing $($function.Key)" -PercentComplete (($current / $total) * 100) -CurrentOperation "$current of $total functions analyzed" $calledFunctions = GetPowerShellFunctionCalls -FilePath $function.Value.FilePath -AllFunctions $AllFunctions $callGraph[$function.Key] = $calledFunctions # Count usage foreach ($calledFunc in $calledFunctions) { if ($usageCount.ContainsKey($calledFunc)) { $usageCount[$calledFunc]++ $callChains[$calledFunc] += $function.Key } } } Microsoft.PowerShell.Utility\Write-Progress -Activity "Analyzing GenXdev cmdlet usage patterns" -Completed return @{ CallGraph = $callGraph UsageCount = $usageCount CallChains = $callChains } } function GetAllGenXdevFunctions { # Use the existing Get-GenXDevCmdlet to get all cmdlets $cmdlets = if ($IncludeScripts) { GenXdev.Helpers\Get-GenXDevCmdlet -IncludeScripts } else { GenXdev.Helpers\Get-GenXDevCmdlet } $allFunctions = @{} foreach ($cmdlet in $cmdlets) { if ($cmdlet.ScriptFilePath -and (Microsoft.PowerShell.Management\Test-Path $cmdlet.ScriptFilePath)) { $allFunctions[$cmdlet.Name] = @{ FilePath = $cmdlet.ScriptFilePath ModuleName = $cmdlet.ModuleName RelativePath = if ($cmdlet.ScriptFilePath) { try { $relativePath = [System.IO.Path]::GetRelativePath((Microsoft.PowerShell.Management\Get-Location).Path, $cmdlet.ScriptFilePath) if ($relativePath.Length -gt 50) { "..." + $relativePath.Substring($relativePath.Length - 47) } else { $relativePath } } catch { [System.IO.Path]::GetFileName($cmdlet.ScriptFilePath) } } else { "Unknown" } Description = $cmdlet.Description Aliases = $cmdlet.Aliases } } else { Microsoft.PowerShell.Utility\Write-Warning "Skipping $($cmdlet.Name) - file not found: $($cmdlet.ScriptFilePath)" } } return $allFunctions } # Main execution try { # Import GenXdev module to ensure Get-GenXDevCmdlet is available Microsoft.PowerShell.Core\Import-Module GenXdev -Force # Discover all functions using the existing cmdlet Microsoft.PowerShell.Utility\Write-Progress -Activity "Initializing GenXdev cmdlet usage analysis" -Status "Discovering GenXdev functions" -PercentComplete 10 $allFunctions = GetAllGenXdevFunctions if (-not $allFunctions -or $allFunctions.Count -eq 0) { throw "No functions found in GenXdev modules" } # Build call graph and usage analysis Microsoft.PowerShell.Utility\Write-Progress -Activity "Initializing GenXdev cmdlet usage analysis" -Status "Building call graph for $($allFunctions.Count) functions" -PercentComplete 20 $analysis = BuildCallGraph -AllFunctions $allFunctions # Create results Microsoft.PowerShell.Utility\Write-Progress -Activity "Finalizing GenXdev cmdlet usage analysis" -Status "Processing results" -PercentComplete 80 $results = @() foreach ($func in $analysis.UsageCount.GetEnumerator()) { $result = [PSCustomObject]@{ FunctionName = $func.Key UsageCount = $func.Value ModuleName = $allFunctions[$func.Key].ModuleName RelativePath = $allFunctions[$func.Key].RelativePath FilePath = $allFunctions[$func.Key].FilePath Description = $allFunctions[$func.Key].Description Aliases = ($allFunctions[$func.Key].Aliases -join ", ") } if ($IncludeCallChains) { $result | Microsoft.PowerShell.Utility\Add-Member -NotePropertyName "CalledBy" -NotePropertyValue ($analysis.CallChains[$func.Key] -join ", ") $result | Microsoft.PowerShell.Utility\Add-Member -NotePropertyName "Calls" -NotePropertyValue ($analysis.CallGraph[$func.Key] -join ", ") } $results += $result } # Sort by usage count (descending) and take top N Microsoft.PowerShell.Utility\Write-Progress -Activity "Finalizing GenXdev cmdlet usage analysis" -Status "Sorting and formatting results" -PercentComplete 90 $sortedResults = $results | Microsoft.PowerShell.Utility\Sort-Object UsageCount -Descending | Microsoft.PowerShell.Utility\Select-Object -First $Top Microsoft.PowerShell.Utility\Write-Progress -Activity "Finalizing GenXdev cmdlet usage analysis" -Completed switch ($OutputFormat) { 'Table' { if ($IncludeCallChains) { $sortedResults | Microsoft.PowerShell.Utility\Format-Table -Property FunctionName, UsageCount, ModuleName, CalledBy -AutoSize } else { $sortedResults | Microsoft.PowerShell.Utility\Format-Table -Property FunctionName, UsageCount, ModuleName, Aliases -AutoSize } } 'List' { $sortedResults | Microsoft.PowerShell.Utility\Format-List } 'CSV' { $sortedResults | Microsoft.PowerShell.Utility\ConvertTo-Csv -NoTypeInformation } } # Summary statistics $totalFunctions = $results.Count $functionsWithUsage = ($results | Microsoft.PowerShell.Core\Where-Object { $_.UsageCount -gt 0 }).Count $maxUsage = ($results | Microsoft.PowerShell.Utility\Measure-Object UsageCount -Maximum).Maximum $avgUsage = [math]::Round(($results | Microsoft.PowerShell.Utility\Measure-Object UsageCount -Average).Average, 2) # Output summary to console Microsoft.PowerShell.Utility\Write-Output "`nGenXdev Cmdlet Usage Analysis Summary:" Microsoft.PowerShell.Utility\Write-Output "Total Functions: $totalFunctions" Microsoft.PowerShell.Utility\Write-Output "Functions with Usage > 0: $functionsWithUsage" Microsoft.PowerShell.Utility\Write-Output "Maximum Usage Count: $maxUsage" Microsoft.PowerShell.Utility\Write-Output "Average Usage Count: $avgUsage" Microsoft.PowerShell.Utility\Write-Output "`nTop Priority for C# Conversion:" $top5 = $sortedResults | Microsoft.PowerShell.Utility\Select-Object -First 5 foreach ($item in $top5) { Microsoft.PowerShell.Utility\Write-Output " $($item.UsageCount.ToString().PadLeft(3)) uses: $($item.FunctionName)" Microsoft.PowerShell.Utility\Write-Output "$($item.FilePath)" # Output filename to stdout if ($item.Aliases) { Microsoft.PowerShell.Utility\Write-Output " Aliases: $($item.Aliases)" } } # Return the full results for further processing return $sortedResults } catch { Microsoft.PowerShell.Utility\Write-Error "Analysis failed: $($_.Exception.Message)" Microsoft.PowerShell.Utility\Write-Error $_.ScriptStackTrace } } |