-
Notifications
You must be signed in to change notification settings - Fork 7.6k
PSScriptAnalyzer fixes by category #4261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you ag 8000 ree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PSScriptAnalyzer fixes by category #4261
Conversation
…ForEach-Object' (alias is '%' or 'foreach')
…Where-Object' (alias is '?' or 'where')
…Select-Object' (alias is 'select')
…thNull. Essentially, $null has to be on the left hand side when using it for comparison. A Test in ParameterBinding.Tests.ps1 needed adapting as this test used to rely on the wrong null comparison It was also suggested in the initial PR PowerShell#4205 to replace a subset of tests of kind '($object -eq $null) | Should Be $true' with '($null -eq $object) | Should BeNullOrEmpty'
@bergmeister, |
@bergmeister Thank you so much for taking extra effort splitting the original PR by the fix categories! |
build.psm1
Outdated
@@ -668,7 +668,7 @@ function Get-PesterTag { | |||
$alltags = @{} | |||
$warnings = @() | |||
|
|||
get-childitem -Recurse $testbase -File |?{$_.name -match "tests.ps1"}| ForEach-Object { | |||
get-childitem -Recurse $testbase -File |Where-Object {$_.name -match "tests.ps1"}| ForEach-Object { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a space before Where-Object and after "tests.ps1"}
demos/Apache/apache-demo.ps1
Outdated
@@ -2,7 +2,7 @@ Import-Module $PSScriptRoot/Apache/Apache.psm1 | |||
|
|||
#list Apache Modules | |||
Write-Host -Foreground Blue "Get installed Apache Modules like *proxy* and Sort by name" | |||
Get-ApacheModule |Where {$_.ModuleName -like "*proxy*"}|Sort-Object ModuleName | Out-Host | |||
Get-ApacheModule | Where-Object {$_.ModuleName -like "*proxy*"}|Sort-Object ModuleName | Out-Host |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add spaces in "*proxy*"}|Sort-Object
.
{{ | ||
$script:PSSession = $PSSession | ||
|
||
if ($createdByModule -and ($script:PSSession -ne $null)) | ||
if ($null -ne $createdByModule -and ($script:PSSession)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please correct.
@@ -417,7 +417,7 @@ Describe "Proxy module is usable when the original runspace is no longer around" | |||
|
|||
It "Verifies Remove-Module removed the runspace that was automatically created" -Pending { | |||
Remove-Module $module -Force | |||
((Get-PSSession -InstanceId $internalSession.InstanceId -ErrorAction SilentlyContinue) -eq $null) | Should Be $true | |||
($null -eq (Get-PSSession -InstanceId $internalSession.InstanceId -ErrorAction SilentlyContinue)) | Should Be $true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change to Should BeNullOrEmpty
.
@@ -452,7 +452,7 @@ Describe "Proxy module is usable when the original runspace is no longer around" | |||
# removing the module should remove the implicitly/magically created runspace | |||
It "Verifies Remove-Module removes automatically created runspace" -Pending { | |||
Remove-Module $module -Force | |||
((Get-PSSession -InstanceId $internalSession.InstanceId -ErrorAction SilentlyContinue) -eq $null) | Should Be $true | |||
($null -eq (Get-PSSession -InstanceId $internalSession.InstanceId -ErrorAction SilentlyContinue)) | Should Be $true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change to Should BeNullOrEmpty
.
@@ -767,7 +767,7 @@ Describe "Import-PSSession functional tests" -tags "Feature" { | |||
} | |||
|
|||
It "Helper functions should not be imported" -Skip:$skipTest { | |||
((Get-Item function:*PSImplicitRemoting* -ErrorAction SilentlyContinue) -eq $null) | Should Be $true | |||
($null -eq (Get-Item function:*PSImplicitRemoting* -ErrorAction SilentlyContinue)) | Should Be $true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change to Should BeNullOrEmpty
.
@@ -808,11 +808,11 @@ Describe "Import-PSSession functional tests" -tags "Feature" { | |||
} | |||
|
|||
It "Temporary module should be automatically removed after runspace is closed" -Skip:$skipTest { | |||
((Get-Module | Where-Object { $_.Path -eq $module.Path }) -eq $null) | Should Be $true | |||
($null -eq (Get-Module | Where-Object { $_.Path -eq $module.Path })) | Should Be $true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change to Should BeNullOrEmpty
.
} | ||
|
||
It "Temporary psm1 file should be automatically removed after runspace is closed" -Skip:$skipTest { | ||
((Get-Item $module.Path -ErrorAction SilentlyContinue) -eq $null) | Should Be $true | ||
($null -eq (Get-Item $module.Path -ErrorAction SilentlyContinue)) | Should Be $true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change to Should BeNullOrEmpty
.
} | ||
|
||
((Get-Item function:Get-MyVariable -ErrorAction SilentlyContinue) -eq $null) | Should Be $true | ||
($null -eq (Get-Item function:Get-MyVariable -ErrorAction SilentlyContinue)) | Should Be $true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change to Should BeNullOrEmpty
.
@@ -117,9 +117,9 @@ Describe "SemanticVersion api tests" -Tags 'CI' { | |||
$operand -eq $operand | Should Be $true | |||
$operand -ne $operand | Should Be $false | |||
$null -eq $operand | Should Be $false | |||
$operand -eq $null | Should Be $false | |||
$null -eq $operand | Should Be $false | |||
$null -ne $operand | Should Be $true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it is special tests - please revert the changes in the file.
…riptAnalyzer fixes by category): -Spacing in build.psm1 and apache-demo.ps1 -Correction of logical mistake in Implicit.Remoting.Tests.ps1 -Changing more tests from '$null -eq $object | Should Be $true' to '$object | Should BeNullOrEmpty' -Revert a change initially made to SemanticVersion.Tests.ps1
LGTM. |
I don't think we should touch CSharp files and Markdown files. PSScriptAnalyzer warnings should be applicable only to powershell script files. |
Should we fix CSharp files and Markdown files in separate PRs? |
I don't think we need to make those changes in non-powershell-script files, since the goal is to avoid PSScriptAnalyzer warnings. |
@daxian-dbw If you say that the only goal is to avoid PSScriptAnalyzer warnings, then I'm not sure if you considered the reason why those rules exist. They are there best practices to avoid unintended/wrong behaviour and therefore apply to any file using PS syntax IMHO. PSPossibleIncorrectComparisonWithNull is the best example where it can result in e.g. an if condition that always evaluates to true. I can understand if you are concerned that in the case of PSPossibleIncorrectComparisonWithNull, changes in the code of the actual product could lead to a regression and should be excluded but in the case of PSAvoidUsingCmdletAliases, I do not see a reason as to why cs/md files should be excluded. WDYT? |
@bergmeister Thanks for the comment, and you have very good points. Yes, my main concern about changing the As for the PSScriptAnalyzer rules, it's very useful to write easy-to-maintain and less error-prone PS script files, but it's not necessarily always applicable to any PSH syntax, for example, the script that serves as a one-liner command for you to run interactively, in which case aliases may be more preferred because they make the command concise and easy to type. The changes in |
Only we don't type samples from code and md files - we copy-paste 😄 |
@iSazonov right :) my point is that for the one-liner scripts like those, it's OK to use aliases to keep them concise. |
docs/KNOWNISSUES.md
Outdated
@@ -51,7 +51,7 @@ Removing the aliases exposes the native command experience to the PowerShell use | |||
|
|||
Currently, PowerShell only does wildcard expansion (globbing) for built-in cmdlets on Windows, and for external commands or binaries as well as cmdlets on Linux. | |||
This means that a command like `ls *.txt` will fail because the asterisk will not be expanded to match file names. | |||
You can work around this by doing `ls (gci *.txt | % name)` or, more simply, `gci *.txt` using the PowerShell built-in equivalent to `ls`. | |||
You can work around this by doing `ls (gci *.txt | ForEach-Object name)` or, more simply, `gci *.txt` using the PowerShell built-in equivalent to `ls`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discussed, this change is not necessary. This is a one-line script to be used interactively. It's OK to use aliases to keep it concise.
@@ -2138,9 +2138,9 @@ private Assembly LoadAssemblyHelper(string assemblyName) | |||
// 10,000 iterations of this method takes ~800 ms for a string array, and ~ 200ms for the dictionary | |||
// | |||
// $dlls = ((dir c:\windows\Microsoft.NET\Framework\ -fi *.dll -rec) + (dir c:\windows\assembly -fi *.dll -rec)) + (dir C:\Windows\Microsoft.NET\assembly) | | |||
// % { [Reflection.Assembly]::LoadFrom($_.FullName) } | |||
// ForEach-Object { [Reflection.Assembly]::LoadFrom($_.FullName) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes probably should be reverted, as dir
is still used here and short form of parameters are also used such as -fi, -rec and -u
. It's OK to use aliases in cases like this to make it concise.
@@ -1646,7 +1646,7 @@ internal static char SetDelimiter(PSCmdlet Cmdlet, string ParameterSetName, char | |||
if (UseCulture == true) | |||
{ | |||
// ListSeparator is apparently always a character even though the property returns a string, checked via: | |||
// [CultureInfo]::GetCultures("AllCultures") | % { ([CultureInfo]($_.Name)).TextInfo.ListSeparator } | ? Length -ne 1 | |||
// [CultureInfo]::GetCultures("AllCultures") | ForEach-Object { ([CultureInfo]($_.Name)).TextInfo.ListSeparator } | Where-Object Length -ne 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
@@ -183,7 +183,7 @@ Function GetParameterInfo | |||
$validateSetAttributes = $parameter.Attributes | Where { | |||
[ValidateSet].IsAssignableFrom($_.GetType()) | |||
} | |||
if (($validateSetAttributes -ne $null) -and ($validateSetAttributes.Count -gt 0)) | |||
if (($null -ne $validateSetAttributes) -and ($validateSetAttributes.Count -gt 0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, $validateSetAttributes
is an array, but this change is good because of the -and ($validateSetAttributes.Count -gt 0)
😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good. Although if I had written the code myself I would have rather declared $validateSetAttributes
as [System.Array]
because then one would not only avoid the problem that the variable can be null but also prevents gotchas where in the case of array size 1 the type would not be an array and therefore addressing it later as $validateSetAttributes[0]
would result in undesired behaviour (in most cases PowerShell would return the first character of the string representation). Just my two cents.
@@ -1634,7 +1634,7 @@ function AddParametersCDXML | |||
[Hashtable] $complexTypeMapping | |||
) | |||
|
|||
$properties | ? { $_ -ne $null } | % { | |||
$properties | Where-Object { $_ -ne $null } | ForEach-Object { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ $_ -ne $null }
Should be { $null -ne $_ }
|
||
## BadVerb-Variable should be a function, not an alias (1) | ||
((Get-Item Function:\BadVerb-Variable -ErrorAction SilentlyContinue) -ne $null) | Should Be $true | ||
Get-Item Function:\BadVerb-Variable -ErrorAction SilentlyContinue | Should BeNullOrEmpty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
|
||
## BadVerb-Variable should be a function, not an alias (2) | ||
((Get-Item Alias:\BadVerb-Variable -ErrorAction SilentlyContinue) -eq $null) | Should Be $true | ||
Get-Item Alias:\BadVerb-Variable -ErrorAction SilentlyContinue | Should BeNullOrEmpty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
|
||
## BadVerb-Variable should be a function, not an alias (2) | ||
((Get-Item Alias:\BadVerb-Variable -ErrorAction SilentlyContinue) -eq $null) | Should Be $true | ||
Get-Item Alias:\BadVerb-Variable -ErrorAction SilentlyContinue | Should BeNullOrEmpty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
|
||
## BadVerb-Variable should be an alias, not a function (2) | ||
((Get-Item Alias:\BadVerb-Variable -ErrorAction SilentlyContinue) -ne $null) | Should Be $true | ||
Get-Item Alias:\BadVerb-Variable -ErrorAction SilentlyContinue | Should BeNullOrEmpty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
if ($rs2 -ne $null) { $rs2.Dispose() } | ||
if ($remoteSession -ne $null) { Remove-PSSession $remoteSession -ErrorAction SilentlyContinue } | ||
if ($null -ne $testDebugger) { $testDebugger.Release() } | ||
if ($null -ne $psl) { $ps.Dispose() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
($null -ne $psl)
Should be $ps
@bergmeister Please push new commits to address the comments and resolve conflicts. Please DO NOT rebase your branch. This way, we can keep the review history which is very important for large size changes like this PR. |
@bergmeister I just resolved the 2 conflicts. I think we need faster review iterations on this PR, because there are many other PRs changing the script files covered in this PR and thus there will be more conflicts very soon. |
…4261 by @daxian-dbw. This includes a revert of a logical error in Microsoft.PowerShell.ODataV4Adapter.ps1 and reverts back some functions to their alias where the reviewer felt that they were still appropriate. Some minor cosmetic changes and test syntax improvements.
@daxian-dbw I have applied your requested changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks @bergmeister!
@bergmeister Thank you for your patience and hard work! |
@iSazonov @daxian
920D
-dbw Thank you both as well. I really had no idea it would turn out to be that complex. I am currently developing a |
This is the updated version of PR #4213, in which it was requested to split the commits on a per kind category.
The intend is to help with fixing #3791. The fixed PSScriptAnalyzer warnings are PSPossibleIncorrectComparisonWithNull and PSAvoidUsingCmdletAliases for ForEach-Object, Where-Object and Select-Object since those warning types were responsible for the majority of warnings.