Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/PSModuleUtils.psd1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@{
RootModule = 'PSModuleUtils.psm1'
ModuleVersion = '4.0.0'
ModuleVersion = '4.1.0'
GUID = '3c63c38f-c32c-4837-a6fa-0b456f4099ce'
Author = ''
CompanyName = ''
Expand Down
22 changes: 17 additions & 5 deletions src/Private/Invoke-PSModuleAnalyzerCasingWorkaround.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ command-casing analysis.
The file or directory to analyze.

.PARAMETER Settings
The PSScriptAnalyzer settings file to use.
A settings file path or a settings hashtable, as Invoke-ScriptAnalyzer itself accepts. A hashtable is
not modified; the split run gets a copy with command casing disabled.

.PARAMETER Recurse
Analyzes files recursively.
Expand Down Expand Up @@ -39,7 +40,7 @@ function Invoke-PSModuleAnalyzerCasingWorkaround {
[String]$Path,

[Parameter(Mandatory)]
[String]$Settings,
[Object]$Settings,

[Switch]$Recurse,

Expand All @@ -57,7 +58,12 @@ function Invoke-PSModuleAnalyzerCasingWorkaround {
$recursiveAnalyzerArguments[$argument.Key] = $argument.Value
}

$settingsData = Import-PowerShellDataFile -Path $Settings -ErrorAction Stop
$settingsData = if ($Settings -is [Collections.IDictionary]) {
$Settings
}
else {
Import-PowerShellDataFile -Path $Settings -ErrorAction Stop
}
$correctCasingRule = $settingsData.Rules.PSUseCorrectCasing
$includeRules = @($settingsData.IncludeRules | Where-Object { $_ })
$excludeRules = @($settingsData.ExcludeRules | Where-Object { $_ })
Expand All @@ -76,8 +82,14 @@ function Invoke-PSModuleAnalyzerCasingWorkaround {
)

if ($splitCommandCasing) {
$settingsData.Rules.PSUseCorrectCasing.Enable = $false
$recursiveAnalyzerArguments.Settings = $settingsData
# Copied rather than edited in place, because a caller that passed a hashtable still owns it.
$recursiveCasingRule = @{} + $correctCasingRule
$recursiveCasingRule.Enable = $false
$recursiveRules = @{} + $settingsData.Rules
$recursiveRules.PSUseCorrectCasing = $recursiveCasingRule
$recursiveSettings = @{} + $settingsData
$recursiveSettings.Rules = $recursiveRules
$recursiveAnalyzerArguments.Settings = $recursiveSettings
$casingSettings = @{
IncludeRules = @('PSUseCorrectCasing')
Rules = @{
Expand Down
12 changes: 9 additions & 3 deletions src/Public/Invoke-PSModuleAnalyzer.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ The directory to analyze. Also accepts a file path or a wildcard such as scripts
with -NoRecurse to analyze a directory's own scripts without descending into folders beneath it.

.PARAMETER Settings
The settings file to use. Defaults to the bundled PSScriptAnalyzerSettings.psd1, resolved for both a
source checkout and a built module layout.
A settings file path or a settings hashtable, as Invoke-ScriptAnalyzer itself accepts. Defaults to the
bundled PSScriptAnalyzerSettings.psd1, resolved for both a source checkout and a built module layout.
Pass a hashtable when the settings are assembled at run time, so nothing has to be written to disk.

.PARAMETER Fix
Whether to fix the issues found.
Expand Down Expand Up @@ -48,6 +49,11 @@ if ($findings) {
.EXAMPLE
Invoke-PSModuleAnalyzer -SourceDirectory $PWD/src -EnableExit

.EXAMPLE
$settings = Import-PowerShellDataFile -Path ./PSScriptAnalyzerSettings.psd1
$settings.ExcludeRules += 'PSUseShouldProcessForStateChangingFunctions'
Invoke-PSModuleAnalyzer -SourceDirectory $PWD/tests -Settings $settings

.NOTES
N/A
#>
Expand All @@ -56,7 +62,7 @@ function Invoke-PSModuleAnalyzer {
[OutputType('Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord')]
param (
[String]$SourceDirectory = "$PWD/src",
[String]$Settings = (Get-PSModuleAnalyzerSettingsPath -CallerScriptRoot $PSScriptRoot),
[Object]$Settings = (Get-PSModuleAnalyzerSettingsPath -CallerScriptRoot $PSScriptRoot),
[Switch]$Fix,
[Switch]$NoRecurse,
[Switch]$EnableExit
Expand Down
15 changes: 15 additions & 0 deletions tests/Invoke-PSModuleAnalyzer.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,21 @@ Describe 'Unit Tests' -Tag 'Unit' {
$topOnlyFindings.ScriptName | Should -Not -Contain 'Alias.ps1'
}

It 'should analyze against a settings hashtable, with nothing written to disk' {
$fixtureDir = Join-Path -Path $TestDrive -ChildPath 'HashtableSettingsRun'
New-Item -ItemType Directory -Path $fixtureDir -Force | Out-Null
'function Get-Aliased { gci }' | Set-Content -Path "$fixtureDir/Aliased.ps1" -Encoding utf8
$settings = Import-PowerShellDataFile -Path (
Resolve-Path -Path $PSScriptRoot/../src/Settings/PSScriptAnalyzerSettings.psd1
).Path
$settings.ExcludeRules = @($settings.ExcludeRules) + 'PSProvideCommentHelp'

$findings = Invoke-PSModuleAnalyzer -SourceDirectory $fixtureDir -Settings $settings

$findings.RuleName | Should -Contain 'PSAvoidUsingCmdletAliases'
$findings.RuleName | Should -Not -Contain 'PSProvideCommentHelp'
}

It 'should hand a finding back to the caller rather than exiting on it' {
$fixtureDir = Join-Path -Path $TestDrive -ChildPath 'DefaultReturnFixture'
New-Item -ItemType Directory -Path $fixtureDir -Force | Out-Null
Expand Down
29 changes: 29 additions & 0 deletions tests/Invoke-PSModuleAnalyzerCasingWorkaround.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,35 @@ Describe 'Invoke-PSModuleAnalyzerCasingWorkaround' -Tag 'Unit' {
$scriptAnalyzerArguments.Settings | Should -BeExactly $script:defaultSettingsPath
}

It 'should accept settings as a hashtable and leave the caller''s copy untouched' {
$fixtureDir = Join-Path -Path $TestDrive -ChildPath 'HashtableSettingsFixture'
$null = New-Item -ItemType Directory -Path $fixtureDir -Force
"function Get-Only { 'only' }" | Set-Content -Path "$fixtureDir/Only.ps1"
$callerSettings = Import-PowerShellDataFile -Path $script:defaultSettingsPath
$scriptAnalyzerArguments = @{
Path = $fixtureDir
Settings = $callerSettings
Recurse = $true
Severity = 'Information'
EnableExit = $false
ReportSummary = $true
ErrorAction = 'Stop'
}
Mock Invoke-ScriptAnalyzer {}

Invoke-PSModuleAnalyzerCasingWorkaround @scriptAnalyzerArguments

Should -Invoke Invoke-ScriptAnalyzer -Exactly -Times 1 -ParameterFilter {
$Settings.IncludeRules -contains 'PSUseCorrectCasing' -and
$Path -like '*Only.ps1'
}
Should -Invoke Invoke-ScriptAnalyzer -Exactly -Times 1 -ParameterFilter {
$Settings.Rules.PSUseCorrectCasing.Enable -eq $false -and
$Recurse -eq $true
}
$callerSettings.Rules.PSUseCorrectCasing.Enable | Should -BeTrue
}

It 'should enumerate only the top level for the casing pass when Recurse is false' {
$fixtureDir = Join-Path -Path $TestDrive -ChildPath 'NonRecursiveCasingFixture'
$nestedDir = Join-Path -Path $fixtureDir -ChildPath 'Nested'
Expand Down