class RuboCop::Cop::RSpec::Yield

expect(foo).to be(:bar).and_yield(1)
# good
allow(foo).to receive(:bar) { |&block| block.call(1) }
# bad
@example
This cop checks for calling a block within a stub.

def autocorrect(node)

def autocorrect(node)
  lambda do |corrector|
    node_range = range_with_surrounding_space(
      range: block_range(node), side: :left
    )
    corrector.replace(node_range, generate_replacement(node.body))
  end
end

def block_range(node)

def block_range(node)
  node.loc.begin.with(end_pos: node.loc.end.end_pos)
end

def calling_block?(node, block)

def calling_block?(node, block)
  if node.begin_type?
    node.each_child_node.all? { |child| block_call?(child, block) }
  else
    block_call?(node, block)
  end
end

def convert_block_to_yield(node)

def convert_block_to_yield(node)
  args = node.arguments
  replacement = '.and_yield'
  replacement += "(#{args.map(&:source).join(', ')})" if args.any?
  replacement
end

def generate_replacement(node)

def generate_replacement(node)
  if node.begin_type?
    node.children.map { |child| convert_block_to_yield(child) }.join
  else
    convert_block_to_yield(node)
  end
end

def on_block(node)

def on_block(node)
  return unless method_on_stub?(node.send_node)
  block_arg(node.arguments) do |block|
    if calling_block?(node.body, block)
      add_offense(node, location: block_range(node))
    end
  end
end