Skip to content
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 agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update PossibleIncorrectComparisonWithNull documentation with better example #1244

Merged
merged 3 commits into from
Jun 5, 2019

Conversation

bergmeister
Copy link
Collaborator

PR Summary

Fixes comments received in issue #1227 after it was closed

PR Checklist

RuleDocumentation/PossibleIncorrectComparisonWithNull.md Outdated Show resolved Hide resolved
if ($null -ne @()) { 'true' } else { 'false' } # Returns true
# Both expressions below return 'false' because the comparison does not return an object and therefore the if statement always falls through:
if (@() -eq $null) { 'true' }else { 'false' }
if (@() -ne $null) { 'true' }else { 'false' }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this just a repetition of the line above? I think the existing examples make sense and are illustrative of the difference between a naive comparison with $null and the suggested fix.

It might possibly be worth a more complicated example, but the purpose of the documentation here really isn't to teach people PowerShell concepts.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of changing the example was that the existing example was too confusing for people because it changed 2 things at once, the example in this PR changes only 1 thing (eq to ne) to demonstrate the behaviour that might be unexpected for some people (yes, I know this is how the comparison operator works but most people do not use it with this intention and rather just want a null checks)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two points there:

  1. Unrelated to the example complexity discussion: it looks like this change just uses the same example twice. Is that intended? It seems unhelpful (and arguably confusing) to have the same example twice. Maybe I've missed something.

  2. I don't think taking an example away prevents confusion. I think adding another simpler example as a stepping stone will be much more helpful. In the original issue this PR addresses, I don't think the issue was "the current examples are confusing" so much as "the current examples don't look like what I have"; @PrzemyslawKlys understood the behaviour of the -eq comparison, but not why he was being warned. So I think the answer is more examples and some discussion about the effects, and what to do if you really do intend null comparison like this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first, yes it looks like it is the same example twice (if one already understands the root cause) but the point of the example is to also show on a high level (if the LHS and RHS were a complex, unknown expression) that changing -eq to -ne does not return in inverting the result, which is basic assumption and thereby shows in what kind of tricky situations one can land

Copy link
Contributor

@rjmholt rjmholt Jun 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I honestly missed the operator change. Without trying to blame my own failing on an extrinsic factor, I suspect others might also miss the important difference.

Maybe it's worth breaking up the comment so there's one for each example, like:

# In PowerShell, `$array -operator $value` works the same as `$array | Where-Object -operator $value` because of pipeline enumeration
# For example:
@(1, 2, 3, 4) -ge 3             # Emits `3, 4`
'a','b','c','ab' -like 'a*'     # Emits 'a','ab'
'hi',$null,'bye' -ne $null      # Emits 'hi','bye'
@() -ne $null`                  # Emits nothing (an empty array)

# Equality comparison doesn't work as often intended, because `@() -ne $null` results in a falsey empty value
if (@() -ne $null) { 'true' } else { 'false' }     # Emits 'false'

# Comparison misleadingly appears to work as intended with -eq, but again because a falsey empty value is emitted (not because the `@()` value is non-null)
if (@() -eq $null) { 'true' } else { 'false' }     # Emits 'false'

# Because of this caveat, PSScriptAnalyzer warns about comparisons with $null by default
# If you want to use a filter behaviour, it's recommended to explicitly filter instead:

# Don't use
if ($array -ne $null) { ... }

# DO use
if ($array | Where-Object -ne $null) { ... }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yee, I agree, maybe it is best to have an additional section with more examples so people can go deep and look at different scenarios and root causes, please open a PR for it since this PR got already merged. It makes me wonder if PowerShell would benefit e.g. from a == operator that would be more intuitive than the -eq operator..

Copy link
Member

@JamesWTruher JamesWTruher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the text is fine; the missing space should get fixed.

RuleDocumentation/PossibleIncorrectComparisonWithNull.md Outdated Show resolved Hide resolved
@bergmeister
Copy link
Collaborator Author

I applied Rob's suggestion about the whitespace and added Jim's example as well

@JamesWTruher JamesWTruher merged commit c23bf1c into development Jun 5, 2019
@bergmeister bergmeister deleted the bergmeister-docs-1 branch February 9, 2020 20:40
@SuperflyJon
Copy link

What seems odd is that swapping the $null in the example, i.e.:
$null -eq @() # returns $false
$null -ne @() # returns $true
doesn't make much sense either?

More importantly if a user wanted to check for $null in an array then you have to write this with the $null on the right of the equals test.

I'm not convinced this rule has any value - maybe I'm missing something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants