Skip to content

Commit

Permalink
Merge pull request #10064 from casperisfine/explicit-block-corrector
Browse files Browse the repository at this point in the history
Style/ExplicitBlockArgument: do not assume the block parameter name
  • Loading branch information
koic committed Sep 8, 2021
2 parents 8585c75 + e44b0a8 commit b9de8e8
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 14 deletions.
1 change: 1 addition & 0 deletions changelog/fix_hardcoded_block_parameter_name.md
@@ -0,0 +1 @@
* [#10064](https://github.com/rubocop/rubocop/pull/10064): Fix `Style/ExplicitBlockArgument` corrector assuming any existing block argument was named `block`. ([@byroot][])
32 changes: 21 additions & 11 deletions lib/rubocop/cop/style/explicit_block_argument.rb
Expand Up @@ -67,17 +67,27 @@ def on_yield(node)
# so this can cause crashes in haml_lint
return unless def_node

block_name = extract_block_name(def_node)

add_offense(block_node) do |corrector|
corrector.remove(block_body_range(block_node, send_node))

add_block_argument(send_node, corrector)
add_block_argument(def_node, corrector) if @def_nodes.add?(def_node)
add_block_argument(send_node, corrector, block_name)
add_block_argument(def_node, corrector, block_name) if @def_nodes.add?(def_node)
end
end
end

private

def extract_block_name(def_node)
if def_node.block_argument?
def_node.arguments.last.name
else
'block'
end
end

def yielding_arguments?(block_args, yield_args)
yield_args = yield_args.dup.fill(
nil,
Expand All @@ -91,15 +101,15 @@ def yielding_arguments?(block_args, yield_args)
end
end

def add_block_argument(node, corrector)
def add_block_argument(node, corrector, block_name)
if node.arguments?
insert_argument(node, corrector)
insert_argument(node, corrector, block_name)
elsif empty_arguments?(node)
corrector.replace(node.arguments, '(&block)')
corrector.replace(node.arguments, "(&#{block_name})")
elsif call_like?(node)
correct_call_node(node, corrector)
correct_call_node(node, corrector, block_name)
else
corrector.insert_after(node.loc.name, '(&block)')
corrector.insert_after(node.loc.name, "(&#{block_name})")
end
end

Expand All @@ -112,16 +122,16 @@ def call_like?(node)
node.call_type? || node.zsuper_type? || node.super_type?
end

def insert_argument(node, corrector)
def insert_argument(node, corrector, block_name)
last_arg = node.arguments.last
arg_range = range_with_surrounding_comma(last_arg.source_range, :right)
replacement = ' &block'
replacement = " &#{block_name}"
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)')
def correct_call_node(node, corrector, block_name)
corrector.insert_after(node, "(&#{block_name})")
return unless node.parenthesized?

args_begin = Util.args_begin(node)
Expand Down
6 changes: 3 additions & 3 deletions spec/rubocop/cop/style/explicit_block_argument_spec.rb
Expand Up @@ -41,15 +41,15 @@ def m

it 'correctly corrects when method already has an explicit block argument' do
expect_offense(<<~RUBY)
def m(&block)
def m(&blk)
items.something { |i| yield i }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Consider using explicit block argument in the surrounding method's signature over `yield`.
end
RUBY

expect_correction(<<~RUBY)
def m(&block)
items.something(&block)
def m(&blk)
items.something(&blk)
end
RUBY
end
Expand Down

0 comments on commit b9de8e8

Please sign in to comment.