-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
[Fix #6969] Fix a false positive in Style/InverseMethods
#7016
Conversation
@@ -175,6 +178,15 @@ def camel_case_constant?(node) | |||
def dot_range(loc) | |||
range_between(loc.dot.begin_pos, loc.expression.end_pos) | |||
end | |||
|
|||
def contains_jump?(node) | |||
return false unless node.is_a?(RuboCop::AST::Node) |
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.
one-liner:
node.each_node(:return, :break, :next).any?
each_node starts from the receiver (node
) and recursively visits child nodes, with optional filtering by types (which is what you are checking), and yields only nodes, so no need to check for the class.
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.
ty, done!
e77f497
to
e2227c3
Compare
CHANGELOG.md
Outdated
@@ -23,7 +24,7 @@ | |||
* [#6992](https://github.com/rubocop-hq/rubocop/pull/6992): Fix unknown default configuration for `Layout/IndentFirstParameter` cop. ([@drenmi][]) | |||
* [#6972](https://github.com/rubocop-hq/rubocop/issues/6972): Fix a false positive for `Style/MixinUsage` when using inside block and `if` condition is after `include`. ([@koic][]) | |||
* [#6738](https://github.com/rubocop-hq/rubocop/issues/6738): Prevent auto-correct conflict of `Style/Next` and `Style/SafeNavigation`. ([@hoshinotsuyoshi][]) | |||
* [#6847](https://github.com/rubocop-hq/rubocop/pull/6847): Fix `Style/BlockDelimiters` to properly check if the node is chaned when `braces_for_chaining` is set. ([@att14][]) | |||
* [#6847](https://github.com/rubocop-hq/rubocop/pull/6847): Fix `Style/BlockDelimiters` to properly check if the node is chained when `braces_for_chaining` is set. ([@att14][]) |
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.
(unrelated typo fix)
e2227c3
to
157a6b0
Compare
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.
Thanks! Changes look good to me, but if break
an return
are also covered, I'd like to see this documented with unit tests. 🙂
🚀
@Drenmi thanks for the suggestion. I've withdrawn skipping blocks with |
157a6b0
to
29f7bed
Compare
@@ -76,6 +78,7 @@ def on_block(node) | |||
inverse_block?(node) do |_method_call, method, block| | |||
return unless inverse_blocks.key?(method) | |||
return if negated?(node) && negated?(node.parent) | |||
return if node.each_node(:next).any? |
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.
It was sufficient to consider
next
nodes in testing this over a large codebase, but it also guards againsbreak
andreturn
nodes, out of an abundance of caution.
I don't see any code in here that would fix this issue for break
or return
. I think this needs to look for those node types as well.
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.
@rrosenblum it's been reverted after further discussion/consideration. could i trouble you for an example of an issue caused by break
or return
?
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 missed something from an earlier conversation. It sounds like you had accounted for this and then reverted it. The comment that I quoted made it seem like we needed to account for break
and return
. These are likely edge cases because break
and return
don't make much sense inside of methods that are designed to have a return.
@@ -28,6 +28,8 @@ module Style | |||
# foo == bar | |||
# !!('foo' =~ /^\w+$/) | |||
# !(foo.class < Numeric) # Checking class hierarchy is allowed | |||
# # Blocks with guard clauses are ignored: | |||
# foo.select { |f| next if f.zero?; f != 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.
We do not recommend using semicolons within code, and we like to have our code examples follow as many best practices as possible. Please change this example to a multi-line block.
# foo.select do |f|
# next if f.zero?
# f != 1
# 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.
done!
87f7471
to
4593830
Compare
@@ -76,6 +78,7 @@ def on_block(node) | |||
inverse_block?(node) do |_method_call, method, block| | |||
return unless inverse_blocks.key?(method) | |||
return if negated?(node) && negated?(node.parent) | |||
return if node.each_node(:next).any? |
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 missed something from an earlier conversation. It sounds like you had accounted for this and then reverted it. The comment that I quoted made it seem like we needed to account for break
and return
. These are likely edge cases because break
and return
don't make much sense inside of methods that are designed to have a return.
manual/cops_style.md
Outdated
@@ -2658,6 +2658,8 @@ foo != bar | |||
foo == bar | |||
!!('foo' =~ /^\w+$/) | |||
!(foo.class < Numeric) # Checking class hierarchy is allowed | |||
# Blocks with guard clauses are ignored: | |||
foo.select { |f| next if f.zero?; f != 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.
You'll need to regenerate the documentation to update this.
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.
d'oh, done!
4593830
to
0cacc5c
Compare
@@ -50,6 +50,20 @@ | |||
expect_no_offenses('!!foo.reject { |e| !e }') | |||
end | |||
|
|||
it 'allows an inverse method in a block with next' do | |||
expect_no_offenses(<<-RUBY.strip_indent) |
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 you rebase using latest master branch and change this line to the following code?
-expect_no_offenses(<<-RUBY.strip_indent)
+expect_no_offenses(<<~RUBY)
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.
done!
…InverseMethods`
0cacc5c
to
6406543
Compare
Thank you! |
Style/InverseMethods
does not contemplate guard clauses or other jumps within block methods. This PR updates the cop to skip further evaluation in such cases.It was sufficient to consider
next
nodes in testing this over a large codebase, but it also guards againsbreak
andreturn
nodes, out of an abundance of caution.The
contains_jump?
implementation feels suboptimal, and I'd like to know if there's a better approach. I could neither find an existing helper to look for node types within an AST, nor find a validdef_node_matcher
that would do the trick.Resolves #6969
Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).and description in grammatically correct, complete sentences.
bundle exec rake default
. It executes all tests and RuboCop for itself, and generates the documentation.