Skip to content

Commit

Permalink
[Fix rubocop#12807] Fix false positives for Naming/BlockForwarding
Browse files Browse the repository at this point in the history
Fixes rubocop#12807.

This PR fixes false positives for `Naming/BlockForwarding`
when using explicit block forwarding in block method and others.
  • Loading branch information
koic committed Mar 22, 2024
1 parent 2386409 commit e1ea4db
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#12807](https://github.com/rubocop/rubocop/issues/12807): Fix false positives for `Naming/BlockForwarding` when using explicit block forwarding in block method and others. ([@koic][])
43 changes: 31 additions & 12 deletions lib/rubocop/cop/naming/block_forwarding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,25 @@ def self.autocorrect_incompatible_with
[Lint::AmbiguousOperator, Style::ArgumentsForwarding]
end

# rubocop:disable Metrics/CyclomaticComplexity
def on_def(node)
return if node.arguments.empty?

last_argument = node.last_argument
return if expected_block_forwarding_style?(node, last_argument)

invalid_syntax = false
node.each_descendant(:block_pass) do |block_pass_node|
next if block_pass_node.children.first&.sym_type? ||
last_argument.source != block_pass_node.source
forwarded_args = node.each_descendant(:block_pass).with_object([]) do |block_pass, result|
return nil if invalid_syntax?(block_pass)
next unless block_argument_name_matched?(block_pass, last_argument)

if block_pass_node.each_ancestor(:block, :numblock).any?
invalid_syntax = true
next
end
result << block_pass
end

register_offense(block_pass_node, node)
forwarded_args.each do |forwarded_arg|
register_offense(forwarded_arg, node)
end

register_offense(last_argument, node) unless invalid_syntax
register_offense(last_argument, node)
end
# rubocop:enable Metrics/CyclomaticComplexity
alias on_defs on_def

private
Expand All @@ -88,6 +84,29 @@ def expected_block_forwarding_style?(node, last_argument)
end
end

def block_argument_name_matched?(block_pass_node, last_argument)
return false if block_pass_node.children.first&.sym_type?

last_argument.source == block_pass_node.source
end

# Prevents the following syntax error:
#
# # foo.rb
# def foo(&)
# block_method do
# bar(&)
# end
# end
#
# $ ruby -vc foo.rb
# ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22]
# foo.rb: foo.rb:4: anonymous block parameter is also used within block (SyntaxError)
#
def invalid_syntax?(block_pass_node)
block_pass_node.each_ancestor(:block, :numblock).any?
end

def use_kwarg_in_method_definition?(node)
node.arguments.each_descendant(:kwarg, :kwoptarg).any?
end
Expand Down
48 changes: 48 additions & 0 deletions spec/rubocop/cop/naming/block_forwarding_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,54 @@ def foo(&block)
RUBY
end

it 'does not register an offense when using explicit block forwarding in block method and after' do
# Prevents the following syntax error:
#
# # foo.rb
# def foo(&)
# block_method do
# bar(&)
# end
# end
#
# $ ruby -vc foo.rb
# ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22]
# foo.rb: foo.rb:4: anonymous block parameter is also used within block (SyntaxError)
#
expect_no_offenses(<<~RUBY)
def foo(&block)
block_method do
bar(&block)
end
baz(&block)
end
RUBY
end

it 'does not register an offense when using explicit block forwarding in block method and before' do
# Prevents the following syntax error:
#
# # foo.rb
# def foo(&)
# block_method do
# bar(&)
# end
# end
#
# $ ruby -vc foo.rb
# ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22]
# foo.rb: foo.rb:4: anonymous block parameter is also used within block (SyntaxError)
#
expect_no_offenses(<<~RUBY)
def foo(&block)
bar(&block)
block_method do
baz(&block)
end
end
RUBY
end

it 'does not register an offense when defining no arguments method' do
expect_no_offenses(<<~RUBY)
def foo
Expand Down

0 comments on commit e1ea4db

Please sign in to comment.