Skip to content

Commit

Permalink
[Fix rubocop#9304] Do not register an offense for `Style/ExplicitBloc…
Browse files Browse the repository at this point in the history
…kArgument` when the `yield` arguments are not an exact match with the block arguments.
  • Loading branch information
dvandersluis committed Jan 10, 2021
1 parent 41242be commit 3ef4f0f
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 8 deletions.
1 change: 1 addition & 0 deletions changelog/fix_do_not_register_offense_for.md
@@ -0,0 +1 @@
* [#9304](https://github.com/rubocop-hq/rubocop/issues/9304): Do not register an offense for `Style/ExplicitBlockArgument` when the `yield` arguments are not an exact match with the block arguments. ([@dvandersluis][])
3 changes: 1 addition & 2 deletions config/default.yml
Expand Up @@ -3271,9 +3271,8 @@ Style/ExplicitBlockArgument:
that just passes its arguments to another block.
StyleGuide: '#block-argument'
Enabled: true
# May change the yielding arity.
Safe: false
VersionAdded: '0.89'
VersionChanged: <<next>>

Style/ExponentialNotation:
Description: 'When using exponential notation, favor a mantissa between 1 (inclusive) and 10 (exclusive).'
Expand Down
10 changes: 10 additions & 0 deletions lib/rubocop/cop/style/explicit_block_argument.rb
Expand Up @@ -6,6 +6,9 @@ module Style
# This cop enforces the use of explicit block argument to avoid writing
# block literal that just passes its arguments to another block.
#
# NOTE: This cop only registers an offense if the block args match the
# yield args exactly.
#
# @example
# # bad
# def with_tmp_dir
Expand Down Expand Up @@ -75,7 +78,14 @@ def on_yield(node)
private

def yielding_arguments?(block_args, yield_args)
yield_args = yield_args.dup.fill(
nil,
yield_args.length, block_args.length - yield_args.length
)

yield_args.zip(block_args).all? do |yield_arg, block_arg|
next false unless yield_arg && block_arg

block_arg && yield_arg.children.first == block_arg.children.first
end
end
Expand Down
28 changes: 22 additions & 6 deletions spec/rubocop/cop/style/explicit_block_argument_spec.rb
Expand Up @@ -18,17 +18,25 @@ def m(&block)
RUBY
end

it 'registers an offense and corrects when block yields several first its arguments' do
it 'registers an offense and corrects when multiple arguments are yielded' do
expect_offense(<<~RUBY)
def m
items.something { |i, j| yield i }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Consider using explicit block argument in the surrounding method's signature over `yield`.
items.something(first_arg) { |i, j| yield i, j }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Consider using explicit block argument in the surrounding method's signature over `yield`.
end
RUBY

expect_correction(<<~RUBY)
def m(&block)
items.something(&block)
items.something(first_arg, &block)
end
RUBY
end

it 'does not register an offense when arguments are yielded in a different order' do
expect_no_offenses(<<~RUBY)
def m
items.something(first_arg) { |i, j| yield j, i }
end
RUBY
end
Expand Down Expand Up @@ -92,8 +100,8 @@ def m
3.times { yield }
^^^^^^^^^^^^^^^^^ Consider using explicit block argument in the surrounding method's signature over `yield`.
else
other_items.something { |i, j| yield i }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Consider using explicit block argument in the surrounding method's signature over `yield`.
other_items.something { |i, j| yield i, j }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Consider using explicit block argument in the surrounding method's signature over `yield`.
end
end
RUBY
Expand Down Expand Up @@ -155,6 +163,14 @@ def m
RUBY
end

it 'does not register an offense when there is more than one block argument and not all are yielded' do
expect_no_offenses(<<~RUBY)
def m
items.something { |i, j| yield i }
end
RUBY
end

it 'does not register an offense when code is called outside of a method' do
expect_no_offenses(<<~RUBY)
render("partial") do
Expand Down

0 comments on commit 3ef4f0f

Please sign in to comment.