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

Enable Style/InvertibleUnlessCondition cop #15265

Merged
merged 4 commits into from
Apr 26, 2023

Conversation

dduugg
Copy link
Sponsor Member

@dduugg dduugg commented Apr 18, 2023

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew style with your changes locally?
  • Have you successfully run brew typecheck with your changes locally?
  • Have you successfully run brew tests with your changes locally?

This is a new cop introduced in rubocop v1.44.0. It's disabled by default but i think it's enough of a readability improvement to enable. (I also added a rule to favor if a != b over unless a == b.)

It is invalid in at least one case – when comparing class hierarchies that do not share inheritance (see the disable below).

cc @issyl0

else
remaining_root_files << pn unless pn.basename.to_s == ".DS_Store"
elsif pn.basename.to_s != ".DS_Store"
remaining_root_files << pn
Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

This is an especially nice fix, imo

Copy link
Member

Choose a reason for hiding this comment

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

Yes, else ... unless was weird!

@dduugg
Copy link
Sponsor Member Author

dduugg commented Apr 18, 2023

Currently failing CI due to upstream violations, will hold off on fixing until initial feedback is in

Copy link
Member

@issyl0 issyl0 left a comment

Choose a reason for hiding this comment

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

Thanks @dduugg, nice discovery. I have some (opinionated) comments about the corrections here.

Enabled: true
InverseMethods:
# Favor `if a != b` over `unless a == b`
:==: :!=
Copy link
Member

Choose a reason for hiding this comment

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

I'm very surprised this isn't a default.

@@ -526,7 +526,7 @@ def audit_livecheck_version
def audit_livecheck_min_os
return unless online?
return unless cask.livecheckable?
return unless cask.livecheck.strategy == :sparkle
return if cask.livecheck.strategy != :sparkle
Copy link
Member

Choose a reason for hiding this comment

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

Mmm, not sure how I feel about this when there's mixed unless and if in a row.

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

There's no easy general fix here that i can think of. Sometimes I chain these (return unless a && b && c), but i generally only use unless when rubocop makes me.

Copy link
Member

Choose a reason for hiding this comment

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

Let's keep it the way the cop wants it then.

Copy link
Member

Choose a reason for hiding this comment

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

I also prefer the cop's approach here.

@@ -57,7 +57,7 @@ def cleanup

cleanup.clean!

unless cleanup.disk_cleanup_size.zero?
if cleanup.disk_cleanup_size.nonzero?
Copy link
Member

Choose a reason for hiding this comment

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

I think I prefer this how it was? (And below in all these .nonzero? cases.)

Copy link
Sponsor Member Author

@dduugg dduugg Apr 18, 2023

Choose a reason for hiding this comment

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

That's a reasonable objection, i'll unset the entry that does this and re-apply the cop

Copy link
Member

Choose a reason for hiding this comment

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

Thanks!

@@ -473,7 +473,7 @@ def table_output(category, days, results, os_version: false, cask_install: false
"#{formatted_count} | #{formatted_percent}%"
next if index > 10
end
return unless results.length > 1
return if results.length <= 1
Copy link
Member

Choose a reason for hiding this comment

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

I think I prefer unless in all the cases where otherwise we have to replace > or < with the equals variant, the "unless" is easier to read (!) than "which way is that angle bracket going paired with that equals".

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

Not so for me (mostly bc i still have to mentally convert unless to if not, which makes comparisons like this a 🤕), but we could also unset these in the config, like for the zero? case.

Copy link
Member

Choose a reason for hiding this comment

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

I'll let a third person weigh in and maybe we'll get a majority vote one way or the other.

Copy link
Member

Choose a reason for hiding this comment

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

I also prefer the way the cop handles this.

else
remaining_root_files << pn unless pn.basename.to_s == ".DS_Store"
elsif pn.basename.to_s != ".DS_Store"
remaining_root_files << pn
Copy link
Member

Choose a reason for hiding this comment

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

Yes, else ... unless was weird!

@dduugg dduugg force-pushed the enable-InvertibleUnlessCondition branch 2 times, most recently from f5d70e9 to 6a7e67d Compare April 18, 2023 22:24
Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

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

Love this cop, enabling it on personal projects too, thanks @dduugg!

@MikeMcQuaid
Copy link
Member

MikeMcQuaid commented Apr 19, 2023

As a general note: I have on my "one day" TODO list to go through literally every disabled by default cop and try to enable them all and remove the ones I disagree with. Here's a list from a work project I've done this on, if it's useful:

# Enable some useful rules disabled by default.
Layout/ClassStructure:
  Enabled: true
Layout/EmptyLineAfterMultilineCondition:
  Enabled: true
Layout/FirstArrayElementLineBreak:
  Enabled: true
Layout/FirstHashElementLineBreak:
  Enabled: true
Layout/FirstMethodParameterLineBreak:
  Enabled: true
Layout/HeredocArgumentClosingParenthesis:
  Enabled: true
Layout/MultilineArrayLineBreaks:
  Enabled: true
Layout/MultilineHashKeyLineBreaks:
  Enabled: true
Layout/MultilineMethodParameterLineBreaks:
  Enabled: true
Layout/SingleLineBlockChain:
  Enabled: true
Lint/HeredocMethodCallPosition:
  Enabled: true
Naming/InclusiveLanguage:
  Enabled: true
Style/AutoResourceCleanup:
  Enabled: true
Style/CollectionMethods:
  Enabled: true
Style/ImplicitRuntimeError:
  Enabled: true
Style/InvertibleUnlessCondition:
  Enabled: true
Style/IpAddresses:
  Enabled: true
Style/OptionHash:
  Enabled: true
Style/ReturnNil:
  Enabled: true
Style/StringHashKeys:
  Enabled: true
Style/Send:
  Enabled: true
Style/StringMethods:
  Enabled: true
Style/TopLevelMethodDefinition:
  Enabled: true
Style/UnlessLogicalOperators:
  Enabled: true
Style/YodaExpression:
  Enabled: true
Performance/ChainArrayAllocation:
  Enabled: true
Performance/IoReadlines:
  Enabled: true
Performance/OpenStruct:
  Enabled: true
Performance/SelectMap:
  Enabled: true
Performance/CaseWhenSplat:
  Enabled: true
Rails/DefaultScope:
  Enabled: true
Rails/EnvironmentVariableAccess:
  Enabled: true
Rails/OrderById:
  Enabled: true
Rails/PluckId:
  Enabled: true
Rails/RequireDependency:
  Enabled: true
Rails/ReversibleMigrationMethodDefinition:
  Enabled: true
Rails/SaveBang:
  Enabled: true
Rails/TableNameAssignment:
  Enabled: true
RSpec/Dialect:
  Enabled: true
RSpec/MessageExpectation:
  Enabled: true
RSpec/Pending:
  Enabled: true
Sorbet/CallbackConditionalsBinding:
  Enabled: true
Sorbet/EnforceSignatures:
  Enabled: true
Sorbet/ForbidIncludeConstLiteral:
  Enabled: true
Sorbet/ForbidSuperclassConstLiteral:
  Enabled: true
Sorbet/ForbidTUnsafe:
  Enabled: true
Sorbet/OneAncestorPerLine:
  Enabled: true
Sorbet/SingleLineRbiClassModuleDefinitions:
  Enabled: true

@issyl0
Copy link
Member

issyl0 commented Apr 19, 2023

@MikeMcQuaid Don't tempt me to do your TODO list items for you. It's a good idea.

return if count <= 1

add_error "only a single postflight stanza is allowed"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return if count <= 1
add_error "only a single postflight stanza is allowed"
add_error "only a single postflight stanza is allowed" if count > 1

Copy link
Member

Choose a reason for hiding this comment

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

Unless RuboCop wants a guard-clause here.

@dduugg
Copy link
Sponsor Member Author

dduugg commented Apr 20, 2023

@MikeMcQuaid Don't tempt me to do your TODO list items for you. It's a good idea.

Note that per comment on the rubocop PR, rubocop will be enabling fewer of these kinds of cops going forward. If you'd prefer to stay on top of these as they come in, it may be worth exploring the EnabledByDefault config setting.

@MikeMcQuaid
Copy link
Member

Note that per comment on the rubocop PR, rubocop will be enabling fewer of these kinds of cops going forward. If you'd prefer to stay on top of these as they come in, it may be worth exploring the EnabledByDefault config setting.

Good idea. I knew about NewCops: enable (which we've enabled) but I do think EnabledByDefault probably makes more sense. When new cops are added and we have no violations: I think it's worth us enabling them.

@issyl0
Copy link
Member

issyl0 commented Apr 21, 2023

As long as it's not DisabledByDefault, I'm game for config changes. Bad news though, currently running brew style after setting EnabledByDefault: true reveals 1170 files inspected, 42077 offenses detected, 21649 offenses autocorrectable. 💀 But that's why Mike is wise and said "only enable new cops if no offenses" (or, I guess, minimal, sensible, easily fixable ones). I'll make an issue over the weekend for determining which ones are good/bad/enforceable.

@dduugg
Copy link
Sponsor Member Author

dduugg commented Apr 22, 2023

As long as it's not DisabledByDefault, I'm game for config changes. Bad news though, currently running brew style after setting EnabledByDefault: true reveals 1170 files inspected, 42077 offenses detected, 21649 offenses autocorrectable. 💀 But that's why Mike is wise and said "only enable new cops if no offenses" (or, I guess, minimal, sensible, easily fixable ones). I'll make an issue over the weekend for determining which ones are good/bad/enforceable.

I'm not too surprised by that. It might be more worthwhile to attempt it by department (e.g. Style) and not globally.

@dduugg dduugg force-pushed the enable-InvertibleUnlessCondition branch from 4801d7c to bf8ac8a Compare April 26, 2023 04:33
@MikeMcQuaid MikeMcQuaid merged commit eafdbb3 into Homebrew:master Apr 26, 2023
31 checks passed
@dduugg dduugg deleted the enable-InvertibleUnlessCondition branch April 26, 2023 05:08
@github-actions github-actions bot added the outdated PR was locked due to age label May 27, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 27, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated PR was locked due to age
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants