Skip to content

Commit

Permalink
[Fix rubocop#9955] Fix Style/ExplicitBlockArgument adding a second …
Browse files Browse the repository at this point in the history
…set of parentheses.
  • Loading branch information
dvandersluis committed Aug 2, 2021
1 parent d40dfe7 commit d769f4f
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 9 deletions.
1 change: 1 addition & 0 deletions changelog/fix_fix_styleexplicitblockargument_adding_a.md
@@ -0,0 +1 @@
* [#9955](https://github.com/rubocop/rubocop/issues/9955): Fix `Style/ExplicitBlockArgument` adding a second set of parentheses. ([@dvandersluis][])
39 changes: 32 additions & 7 deletions lib/rubocop/cop/style/explicit_block_argument.rb
Expand Up @@ -93,18 +93,43 @@ def yielding_arguments?(block_args, yield_args)

def add_block_argument(node, corrector)
if node.arguments?
last_arg = node.arguments.last
arg_range = range_with_surrounding_comma(last_arg.source_range, :right)
replacement = ' &block'
replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
corrector.insert_after(arg_range, replacement) unless last_arg.blockarg_type?
elsif node.call_type? || node.zsuper_type?
corrector.insert_after(node, '(&block)')
insert_argument(node, corrector)
elsif empty_arguments?(node)
corrector.replace(node.arguments, '(&block)')
elsif call_like?(node)
correct_call_node(node, corrector)
else
corrector.insert_after(node.loc.name, '(&block)')
end
end

def empty_arguments?(node)
# Is there an arguments node with only parentheses?
node.arguments.is_a?(RuboCop::AST::Node) && node.arguments.loc.begin
end

def call_like?(node)
node.call_type? || node.zsuper_type? || node.super_type?
end

def insert_argument(node, corrector)
last_arg = node.arguments.last
arg_range = range_with_surrounding_comma(last_arg.source_range, :right)
replacement = ' &block'
replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
corrector.insert_after(arg_range, replacement) unless last_arg.blockarg_type?
end

def correct_call_node(node, corrector)
corrector.insert_after(node, '(&block)')
return unless node.parenthesized?

args_begin = Util.args_begin(node)
args_end = Util.args_end(node)
range = range_between(args_begin.begin_pos, args_end.end_pos)
corrector.remove(range)
end

def block_body_range(block_node, send_node)
range_between(send_node.loc.expression.end_pos, block_node.loc.end.end_pos)
end
Expand Down
9 changes: 7 additions & 2 deletions lib/rubocop/cop/util.rb
Expand Up @@ -46,8 +46,13 @@ def add_parentheses(node, corrector)

def args_begin(node)
loc = node.loc
selector =
node.super_type? || node.yield_type? ? loc.keyword : loc.selector
selector = if node.super_type? || node.yield_type?
loc.keyword
elsif node.def_type? || node.defs_type?
loc.name
else
loc.selector
end
selector.end.resize(1)
end

Expand Down
45 changes: 45 additions & 0 deletions spec/rubocop/cop/style/explicit_block_argument_spec.rb
Expand Up @@ -191,4 +191,49 @@ def m
end
RUBY
end

it 'does not add extra parens when correcting' do
expect_offense(<<~RUBY)
def my_method()
foo() { yield }
^^^^^^^^^^^^^^^ Consider using explicit block argument in the surrounding method's signature over `yield`.
end
RUBY

expect_correction(<<~RUBY, loop: false)
def my_method(&block)
foo(&block)
end
RUBY
end

it 'does not add extra parens to `super` when correcting' do
expect_offense(<<~RUBY)
def my_method
super() { yield }
^^^^^^^^^^^^^^^^^ Consider using explicit block argument in the surrounding method's signature over `yield`.
end
RUBY

expect_correction(<<~RUBY, loop: false)
def my_method(&block)
super(&block)
end
RUBY
end

it 'adds to the existing arguments when correcting' do
expect_offense(<<~RUBY)
def my_method(x)
foo(x) { yield }
^^^^^^^^^^^^^^^^ Consider using explicit block argument in the surrounding method's signature over `yield`.
end
RUBY

expect_correction(<<~RUBY)
def my_method(x, &block)
foo(x, &block)
end
RUBY
end
end

0 comments on commit d769f4f

Please sign in to comment.