tests/Hygiene/Analyze-FileStructure.ps1
|
<#
.SYNOPSIS Analyzes the file structure and organization of the project. .DESCRIPTION Provides detailed metrics about project structure including file counts, directory depth, file type distribution, and organizational health. .EXAMPLE .\Analyze-FileStructure.ps1 #> [CmdletBinding()] param( [string]$ProjectRoot = (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) ) function Get-DirectoryDepth { param([string]$Path, [string]$BasePath) $relativePath = $Path.Replace($BasePath, "").TrimStart("\") if ([string]::IsNullOrEmpty($relativePath)) { return 0 } return ($relativePath.Split("\")).Count } function Get-FileTreeRecursive { param( [string]$Path, [int]$CurrentDepth = 0, [int]$MaxDepth = 10 ) if ($CurrentDepth -ge $MaxDepth) { return @() } $items = @() Get-ChildItem -Path $Path -Force | ForEach-Object { $item = @{ Name = $_.Name Path = $_.FullName IsDirectory = $_.PSIsContainer Size = if (-not $_.PSIsContainer) { $_.Length } else { 0 } Depth = $CurrentDepth } $items += $item if ($_.PSIsContainer) { $items += Get-FileTreeRecursive -Path $_.FullName -CurrentDepth ($CurrentDepth + 1) -MaxDepth $MaxDepth } } return $items } Write-Host "`n=== File Structure Analysis ===" -ForegroundColor Cyan Write-Host "Analyzing project: $ProjectRoot`n" # Get all items $allItems = Get-FileTreeRecursive -Path $ProjectRoot # Separate files and directories $files = $allItems | Where-Object { -not $_.IsDirectory } $directories = $allItems | Where-Object { $_.IsDirectory } # Calculate metrics $totalFiles = $files.Count $totalDirectories = $directories.Count $maxDepth = if ($allItems.Count -gt 0) { ($allItems | Measure-Object -Property Depth -Maximum).Maximum } else { 0 } # File type distribution $filesByExtension = $files | Group-Object { [System.IO.Path]::GetExtension($_.Name) } | Select-Object @{N = 'Extension'; E = { if ($_.Name) { "$($_.Name)" }else { "(no extension)" } } }, Count | Sort-Object Count -Descending # Empty directories $emptyDirectories = $directories | Where-Object { $dirPath = $_.Path $childCount = (Get-ChildItem -Path $dirPath -Force).Count $childCount -eq 0 } # Files in root $filesInRoot = $files | Where-Object { $_.Depth -eq 0 } # Build result $result = [PSCustomObject]@{ ProjectRoot = $ProjectRoot TotalFiles = $totalFiles TotalDirectories = $totalDirectories MaxDepth = $maxDepth FilesByExtension = $filesByExtension EmptyDirectories = $emptyDirectories FilesInRoot = $filesInRoot AllItems = $allItems } # Display results Write-Host "=== Structure Metrics ===" -ForegroundColor Yellow Write-Host "Total Files: $totalFiles" Write-Host "Total Directories: $totalDirectories" Write-Host "Maximum Depth: $maxDepth levels" Write-Host "Empty Directories: $($emptyDirectories.Count)" Write-Host "Files in Root: $($filesInRoot.Count)" Write-Host "`n=== File Type Distribution ===" -ForegroundColor Yellow $filesByExtension | Format-Table -AutoSize if ($emptyDirectories.Count -gt 0) { Write-Host "`n=== Empty Directories ===" -ForegroundColor Yellow $emptyDirectories | ForEach-Object { Write-Host " - $($_.Path)" } } if ($filesInRoot.Count -gt 0) { Write-Host "`n=== Files in Root Directory ===" -ForegroundColor Yellow $filesInRoot | ForEach-Object { Write-Host " - $($_.Name)" } } # Export to JSON $outputPath = Join-Path $PSScriptRoot "file_structure_results.json" $result | Select-Object -Property * -ExcludeProperty AllItems | ConvertTo-Json -Depth 5 | Out-File $outputPath Write-Host "`nResults exported to: $outputPath" -ForegroundColor Green return $result |