From f60e5293a0d55417c5926d55c46a5f4d4e60bb93 Mon Sep 17 00:00:00 2001 From: Mark Schofield Date: Sun, 28 Sep 2025 15:17:18 -0700 Subject: [PATCH 1/2] Consolidate 'ancestor search' from 'ResolvePresetProperty' and 'EvaluatePresetCondition' --- .vscode/settings.json | 3 +- PSCMake/Common/CMake.ps1 | 74 +++++++++++++++++---------- Tests/ResolvePresetProperty.Tests.ps1 | 4 +- Tests/SearchAncestors.Tests.ps1 | 70 +++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 31 deletions(-) create mode 100644 Tests/SearchAncestors.Tests.ps1 diff --git a/.vscode/settings.json b/.vscode/settings.json index a83440e..9f7a7f3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "powershell.codeFormatting.pipelineIndentationStyle": "IncreaseIndentationForFirstPipeline", - "powershell.codeFormatting.newLineAfterCloseBrace": false + "powershell.codeFormatting.newLineAfterCloseBrace": false, + "editor.renderWhitespace": "all" } diff --git a/PSCMake/Common/CMake.ps1 b/PSCMake/Common/CMake.ps1 index e61f9d6..5367ddd 100644 --- a/PSCMake/Common/CMake.ps1 +++ b/PSCMake/Common/CMake.ps1 @@ -133,10 +133,12 @@ function GetConfigurePresetNames { $Presets = $CMakePresetsJson.configurePresets # Filter presets that have '"hidden":true' - $Presets = $Presets | Where-Object { -not (Get-MemberValue -InputObject $_ -Name 'hidden' -Or $false) } + $Presets = $Presets | + Where-Object { -not (Get-MemberValue -InputObject $_ -Name 'hidden' -Or $false) } # Filter presets that have (or their ancestors have) conditions that evaluate to $false - $Presets = $Presets | Where-Object { EvaluatePresetCondition $_ $CMakePresetsJson.configurePresets } + $Presets = $Presets | + Where-Object { EvaluatePresetCondition $_ $CMakePresetsJson.configurePresets } $Presets.name } @@ -185,48 +187,64 @@ function ResolvePresets { $PresetJson, $ConfigurePresetJson } -function ResolvePresetProperty { +<# + .Synopsis + Searches the specified preset and its ancestors, invoking the specified action for each preset. + + .Parameter Preset + The preset to start searching from. + + .Parameter Presets + The collection of presets to search for 'inherit' references. + + .Description + The action should return $null to continue searching, or a non-$null value to stop searching and return that value. +#> +function SearchAncestors { param( - $CMakePresetsJson, - $ConfigurePreset, - $PropertyName + $Preset, + $Presets, + [scriptblock] $Action ) - - for ($Preset = $ConfigurePreset; $Preset; ) { - $PropertyValue = Get-MemberValue -InputObject $Preset -Name $PropertyName - if ($PropertyValue) { - return $PropertyValue + for (; $Preset; ) { + $Result = & $Action $Preset + if ($null -ne $Result) { + return $Result } - $BasePreset = Get-MemberValue $Preset 'inherits' if (-not $BasePreset) { break } + $Preset = $Presets | Where-Object { $_.name -eq $BasePreset } | Select-Object -First 1 + } +} - $Preset = $CMakePresetsJson.configurePresets | Where-Object { $_.name -eq $BasePreset } | Select-Object -First 1 +function ResolvePresetProperty { + param( + $Preset, + $Presets, + $PropertyName + ) + SearchAncestors $Preset $Presets { + param($CurrentPreset) + Get-MemberValue -InputObject $CurrentPreset -Name $PropertyName } } function EvaluatePresetCondition { param( - $PresetJson, - $PresetsJson + $Preset, + $Presets ) - - $PresetConditionJson = Get-MemberValue $PresetJson 'condition' - if ($PresetConditionJson) { - if (-not (EvaluateCondition $PresetConditionJson $PresetJson)) { + $Result = SearchAncestors $Preset $Presets { + param($CurrentPreset) + $PresetConditionJson = Get-MemberValue $CurrentPreset 'condition' + if (($PresetConditionJson) -and + (-not (EvaluateCondition $PresetConditionJson $CurrentPreset))) { return $false } } - - $BasePresetName = Get-MemberValue $PresetJson 'inherits' - if (-not $BasePresetName) { - return $true - } - - $BasePreset = $PresetsJson | Where-Object { $_.name -eq $BasePresetName } | Select-Object -First 1 - EvaluatePresetCondition $BasePreset $PresetsJson + $Result -ne $false } function EvaluateCondition { @@ -296,7 +314,7 @@ function GetBinaryDirectory { $CMakePresetsJson, $ConfigurePreset ) - $BinaryDirectory = ResolvePresetProperty -CMakePresetsJson $CMakePresetsJson $ConfigurePreset 'binaryDir' + $BinaryDirectory = ResolvePresetProperty $ConfigurePreset $CMakePresetsJson.configurePresets 'binaryDir' # Perform macro-replacement $Result = MacroReplacement $BinaryDirectory $ConfigurePreset diff --git a/Tests/ResolvePresetProperty.Tests.ps1 b/Tests/ResolvePresetProperty.Tests.ps1 index 92be33b..4d82d3c 100644 --- a/Tests/ResolvePresetProperty.Tests.ps1 +++ b/Tests/ResolvePresetProperty.Tests.ps1 @@ -9,7 +9,7 @@ Describe 'ResolvePresetProperty' { $CMakePresetsJson = Get-Content "$PSScriptRoot/ReferencePresets/CMakePresets.Single.json" | ConvertFrom-Json $ConfigurePreset = $CMakePresetsJson.configurePresets[0] - $BinaryDirectory = ResolvePresetProperty $CMakePresetsJson $ConfigurePreset 'binaryDir' + $BinaryDirectory = ResolvePresetProperty $ConfigurePreset $CMakePresetsJson.configurePresets 'binaryDir' $BinaryDirectory | Should -Be '${sourceDir}/__output/${presetName}' } @@ -17,7 +17,7 @@ Describe 'ResolvePresetProperty' { $CMakePresetsJson = Get-Content "$PSScriptRoot/ReferencePresets/CMakePresets.Inherited.json" | ConvertFrom-Json $ConfigurePreset = $CMakePresetsJson.configurePresets | Where-Object { $_.name -eq 'windows-x64' } | Select-Object -First 1 - $BinaryDirectory = ResolvePresetProperty $CMakePresetsJson $ConfigurePreset 'binaryDir' + $BinaryDirectory = ResolvePresetProperty $ConfigurePreset $CMakePresetsJson.configurePresets 'binaryDir' $BinaryDirectory | Should -Be '${sourceDir}/__output/${presetName}' } } diff --git a/Tests/SearchAncestors.Tests.ps1 b/Tests/SearchAncestors.Tests.ps1 new file mode 100644 index 0000000..90ed470 --- /dev/null +++ b/Tests/SearchAncestors.Tests.ps1 @@ -0,0 +1,70 @@ +#Requires -PSEdition Core + +BeforeAll { + $script:Presets = ConvertFrom-Json -InputObject @" +[ + { + "name": "Preset1" + }, + { + "name": "Preset2", + "inherits": "Preset1" + } +] +"@ + $script:Preset1 = $script:Presets | Where-Object { $_.name -eq 'Preset1' } | Select-Object -First 1 + $script:Preset2 = $script:Presets | Where-Object { $_.name -eq 'Preset2' } | Select-Object -First 1 + + . $PSScriptRoot/../PSCMake/Common/CMake.ps1 +} + +Describe 'SearchAncestors' { + It 'Returns $null when passed a $null preset' { + SearchAncestors $null $Presets { } | + Should -Be $null + } + + It 'Searches a single preset' { + $script:VisitedPresets = @() + SearchAncestors $Preset1 $Presets { + param($CurrentPreset) + $script:VisitedPresets += $CurrentPreset.name + } | + Should -Be $null + + $script:VisitedPresets | + Should -Be @('Preset1') + } + + It 'Searches a preset and its parent' { + $script:VisitedPresets = @() + SearchAncestors $Preset2 $Presets { + param($CurrentPreset) + $script:VisitedPresets += $CurrentPreset.name + } | + Should -Be $null + + $script:VisitedPresets | + Should -Be @('Preset2', 'Preset1') + } + + It 'Returns the result of a found preset' { + $Name = SearchAncestors $Preset2 $Presets { + param($CurrentPreset) + $CurrentPreset.name + } + $Name | Should -Be 'Preset2' + } + + It 'Stops searching when a result is found' { + $script:VisitedPresets = @() + $Name = SearchAncestors $Preset2 $Presets { + param($CurrentPreset) + $script:VisitedPresets += $CurrentPreset.name + $CurrentPreset.name + } + $Name | Should -Be 'Preset2' + $script:VisitedPresets | + Should -Be @('Preset2') + } +} From ea65b8d4a5b093762c5e35f7aed3a7f2755ebf82 Mon Sep 17 00:00:00 2001 From: Mark Schofield Date: Sun, 28 Sep 2025 15:42:38 -0700 Subject: [PATCH 2/2] Accommodate multiple 'inherit' values in a given preset --- PSCMake/Common/CMake.ps1 | 20 ++++++++++++++------ Tests/SearchAncestors.Tests.ps1 | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/PSCMake/Common/CMake.ps1 b/PSCMake/Common/CMake.ps1 index 5367ddd..bfc7188 100644 --- a/PSCMake/Common/CMake.ps1 +++ b/PSCMake/Common/CMake.ps1 @@ -199,6 +199,8 @@ function ResolvePresets { .Description The action should return $null to continue searching, or a non-$null value to stop searching and return that value. + + When searching multiple preset 'inherit' values, the presets will be search in order. #> function SearchAncestors { param( @@ -206,16 +208,22 @@ function SearchAncestors { $Presets, [scriptblock] $Action ) - for (; $Preset; ) { + if ($null -eq $Preset) { + return $null + } + [array] $PendingPresets = @($Preset) + for (; ($null -ne $PendingPresets) -and ($PendingPresets.Count -gt 0); ) { + $Preset, $PendingPresets = $PendingPresets $Result = & $Action $Preset if ($null -ne $Result) { return $Result } - $BasePreset = Get-MemberValue $Preset 'inherits' - if (-not $BasePreset) { - break - } - $Preset = $Presets | Where-Object { $_.name -eq $BasePreset } | Select-Object -First 1 + [array] $BasePresets = Get-MemberValue $Preset 'inherits' -Or @() | + ForEach-Object { + $BaseParentName = $_ + $Presets | Where-Object { $_.name -eq $BaseParentName } | Select-Object -First 1 + } + $PendingPresets = $BasePresets + $PendingPresets } } diff --git a/Tests/SearchAncestors.Tests.ps1 b/Tests/SearchAncestors.Tests.ps1 index 90ed470..cf7e2e3 100644 --- a/Tests/SearchAncestors.Tests.ps1 +++ b/Tests/SearchAncestors.Tests.ps1 @@ -9,11 +9,20 @@ BeforeAll { { "name": "Preset2", "inherits": "Preset1" + }, + { + "name": "Preset3" + }, + { + "name": "Preset4", + "inherits": ["Preset2", "Preset3"] } ] "@ $script:Preset1 = $script:Presets | Where-Object { $_.name -eq 'Preset1' } | Select-Object -First 1 $script:Preset2 = $script:Presets | Where-Object { $_.name -eq 'Preset2' } | Select-Object -First 1 + $script:Preset3 = $script:Presets | Where-Object { $_.name -eq 'Preset3' } | Select-Object -First 1 + $script:Preset4 = $script:Presets | Where-Object { $_.name -eq 'Preset4' } | Select-Object -First 1 . $PSScriptRoot/../PSCMake/Common/CMake.ps1 } @@ -67,4 +76,16 @@ Describe 'SearchAncestors' { $script:VisitedPresets | Should -Be @('Preset2') } + + It 'Searches a preset and its multiple parents' { + $script:VisitedPresets = @() + SearchAncestors $Preset4 $Presets { + param($CurrentPreset) + $script:VisitedPresets += $CurrentPreset.name + } | + Should -Be $null + + $script:VisitedPresets | + Should -Be @('Preset4', 'Preset2', 'Preset1', 'Preset3') + } }