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
Add Hash#each_value and Hash#each_key cop #7677
Add Hash#each_value and Hash#each_key cop #7677
Conversation
cc77cae
to
8bb305b
Compare
config/default.yml
Outdated
Style/HashEachMethods: | ||
Description: 'Use Hash#each_key and Hash#each_value.' | ||
StyleGuide: '#hash-each' | ||
Enabled: 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 this to pending
. We're no longer enabling any new cops by default.
lib/rubocop/config_loader.rb
Outdated
@@ -55,7 +55,7 @@ def load_file(file) | |||
end | |||
|
|||
def add_missing_namespaces(path, hash) | |||
hash.keys.each do |key| | |||
hash.keys.each do |key| # rubocop:disable Style/HashEachMethods |
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 guess we can just update this, right?
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 actually don't think we can in this case. Due to the hash[q] = hash.delete(key)
line below, we'll get a RuntimeError: can't add a new key into hash during iteration
if we try do a hash.each_key
here.
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.
Ops. my bad. Should have read the code more carefully. :-)
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.
Could this whole issue be sidestepped with a
hash.transform_keys { |key| Cop::Cop.qualified_cop_name(key, path) }
? Or do we need to support rubies < 2.5?
The code looks solid to me. Thanks for tackling this! I guess we should mark the cop as unsafe, though, as there's definitely some potential for false positives. |
Thanks for looking, I've pushed another commit where I marked it as unsafe, and also pending! |
CHANGELOG.md
Outdated
@@ -99,6 +100,7 @@ | |||
* [#7446](https://github.com/rubocop-hq/rubocop/issues/7446): Add `merge` to list of non-mutating methods. ([@cstyles][]) | |||
* [#7077](https://github.com/rubocop-hq/rubocop/issues/7077): **(Breaking)** Rename `Unneeded*` cops to `Redundant*` (e.g., `Style/UnneededPercentQ` becomes `Style/RedundantPercentQ`). ([@scottmatthewman][]) | |||
* [#7396](https://github.com/rubocop-hq/rubocop/issues/7396): Display assignments, branches, and conditions values with the offense. ([@avmnu-sng][]) | |||
* [#7434](https://github.com/rubocop-hq/rubocop/issues/7434): Fix an incorrect autocorrect for `Style/MultilineWhenThen` when the body of `when` branch starts with `then`. ([@koic][]) |
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.
Looks like this might be a rebase artifact? The same line appears above in the Bug Fixes
section.
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.
Yeah, this change is not the difference in this PR.
config/default.yml
Outdated
Description: 'Use Hash#each_key and Hash#each_value.' | ||
StyleGuide: '#hash-each' | ||
Enabled: pending | ||
VersionAdded: '0.79' |
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.
Should this be updated to '0.80'
? Looks like 0.79
was released already.
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.
Sure.
|
||
MSG = 'Use `%<prefer>s` instead of `%<current>s`.' | ||
|
||
def_node_matcher :kv_each, <<-PATTERN |
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.
Can you update this entire PR with squiggly heredoc? (<<~
)
it 'auto-corrects foo#keys.each with foo#each_key' do | ||
new_source = autocorrect_source('foo.keys.each { |k| p k }') | ||
expect(new_source).to eq('foo.each_key { |k| p k }') | ||
end |
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.
Can you use expect_correction
for test an automatic correction? The following address will be helpful.
#7650
I knew this cop sounded familiar to me. We have I also think we may have tried to implement this same cop in the past. I don't think this change is safe if you are mutating the keys or values while using This code does not work if you change def add_missing_namespaces(path, hash)
hash.keys.each do |key|
q = Cop::Cop.qualified_cop_name(key, path)
next if q == key
hash[q] = hash.delete(key)
end
end |
We used to have Performance/HashEach. Not sure what happened to it. Update: Found the removal of the cop |
Yup, and there was an issue filed where it was suggested to instead by a Style PR. I didn't link it as part of the commit message because it's in a different repo and so I think the link would break. Let me know if I should be doing something differently here! |
@jemmaissroff Just address the failing build and I think we're good here. |
Actually - it might be cool to also make the cop configurable, so that people could decide whether they prefer |
If we are classifying this as a Style Cop, then I completely agree that it would be cool for this to be configurable. If we were to classify it as a Performance Cop then I don't think the configuration makes sense. |
8f5ce66
to
a9381e9
Compare
@bbatsov build is fixed! |
.rubocop.yml
Outdated
@@ -28,6 +28,9 @@ Style/FormatStringToken: | |||
Exclude: | |||
- spec/**/* | |||
|
|||
Style/HashEachMethods: | |||
Enabled: false |
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.
This setting looks unnecessary.
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 had a build failing that prompted me to add it here. Can you tell me more about why this looks unnecessary?
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.
By default, it is better to use the setting in config/default.yml.
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 think I'm getting confused around what pending
will do. It appears that breaks builds also. Are you suggesting to leave it as pending
and then remove it from here?
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.
Yeah, config/default.yml leaves the specification of Enabled: pending
. OTOH, I expect this setting to be removed from .rubocop.yml.
It appears that breaks builds
Can you show me what build error is occurring?
config/default.yml
Outdated
Style/HashEachMethods: | ||
Description: 'Use Hash#each_key and Hash#each_value.' | ||
StyleGuide: '#hash-each' | ||
Enabled: false |
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.
Can you update to Enabled: pending
status?
#7677 (comment)
CHANGELOG.md
Outdated
@@ -8,6 +8,7 @@ | |||
* [#7663](https://github.com/rubocop-hq/rubocop/pull/7663): Add new `Style/HashTransformKeys` and `Style/HashTransformValues` cops. ([@djudd][], [@eugeneius][]) | |||
* [#7619](https://github.com/rubocop-hq/rubocop/issues/7619): Support autocorrect of legacy cop names for `Migration/DepartmentName`. ([@koic][]) | |||
* [#7659](https://github.com/rubocop-hq/rubocop/pull/7659): Layout/LineLength autocorrect now breaks up long lines with blocks. ([@maxh][]) | |||
* Add a cop for `Hash#each_key` and `Hash#each_value`. ([@jemmaissroff][]) |
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.
Can you add the PR link to this changelog entry?
It seems you need to rebase to |
9f8a426
to
1d3bdaf
Compare
🎉 Thanks for working on this! 🙇 |
Added a cop to match the style guide's recommendations around
hash-each
.This cop enforces correct usage of
Hash#each_key
andHash#each_value
as opposed to
Hash#keys.each
andHash#values.each
.Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).bundle exec rake default
. It executes all tests and RuboCop for itself, and generates the documentation.