Modules/businessdev.ALbuild.Apps/Private/ConvertTo-BcCoverageExclusionRule.ps1
|
function ConvertTo-BcCoverageExclusionRule { <# .SYNOPSIS Turns albuild.json 'coverage.exclusions' entries into matchable rules. .DESCRIPTION An entry is { object, procedure?, lines?, reason } (a PSCustomObject from JSON or a hashtable). 'object' is "<Type> <Id>" or "<Type> <Name>" (the name may be quoted). 'lines' is a range text ("10-12, 20") or a number array. An entry without 'object' or without 'reason' is ignored with a warning: an exclusion nobody can explain is exactly what the report must not hide. .OUTPUTS PSCustomObject per valid entry: Type, Key, Procedure, Lines (HashSet[int] or $null), Reason, Label, Matched. #> [CmdletBinding()] [OutputType([PSCustomObject])] param([AllowNull()] [object] $Entry) $read = { param($e, [string] $name) if ($e -is [System.Collections.IDictionary]) { foreach ($k in $e.Keys) { if ("$k" -ieq $name) { return $e[$k] } } return $null } $prop = $e.PSObject.Properties[$name] if ($prop) { return $prop.Value } return $null } foreach ($e in @($Entry)) { if ($null -eq $e) { continue } $object = "$(& $read $e 'object')".Trim() $reason = "$(& $read $e 'reason')".Trim() $procedure = "$(& $read $e 'procedure')".Trim().Trim('"') $label = if ($procedure) { "$object / $procedure" } else { $object } if (-not $object -or $object -notmatch '^(?<type>[A-Za-z]+)\s+(?<key>.+)$') { Write-ALbuildLog -Level Warning "Coverage exclusion ignored: 'object' must be '<Type> <Id>' or '<Type> <Name>', got '$object'." continue } $type = $Matches['type'] $key = $Matches['key'].Trim().Trim('"') if (-not $reason) { Write-ALbuildLog -Level Warning "Coverage exclusion '$label' ignored: it has no 'reason'. Every excluded line needs one." continue } $lineSet = $null $linesValue = & $read $e 'lines' if ($null -ne $linesValue -and "$linesValue".Trim()) { $lineSet = [System.Collections.Generic.HashSet[int]]::new() $parts = if ($linesValue -is [string]) { $linesValue -split ',' } else { @($linesValue) } foreach ($part in $parts) { $t = "$part".Trim() if ($t -match '^(\d+)\s*-\s*(\d+)$') { for ($n = [int]$Matches[1]; $n -le [int]$Matches[2]; $n++) { [void]$lineSet.Add($n) } } elseif ($t -match '^\d+$') { [void]$lineSet.Add([int]$t) } elseif ($t) { Write-ALbuildLog -Level Warning "Coverage exclusion '$label': '$t' is not a line or a range and is ignored." } } $label = "$label (lines $linesValue)" } [PSCustomObject]@{ Type = $type Key = $key Procedure = $procedure Lines = $lineSet Reason = $reason Label = $label Matched = $false } } } function Test-BcCoverageExclusionRuleObject { <# .SYNOPSIS Whether an exclusion rule names the given object, by id or by name (case-insensitive). #> [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory)] [object] $Rule, [Parameter(Mandatory)] [string] $Type, [Parameter(Mandatory)] [int] $Id, [AllowEmptyString()] [string] $Name ) if ($Rule.Type -ine $Type) { return $false } return ($Rule.Key -eq "$Id") -or ($Name -and $Rule.Key -ieq $Name) } |