class RuboCop::Cop::Style::ArgumentsForwarding


end
bar(**kwargs)
def foo(**kwargs)
end
bar(*args)
def foo(*args)
# but it will change the behavior. Because ‘…` forwards block also.
# The following code can replace the arguments with `…`,
# bad
@example AllowOnlyRestArgument: false
end
bar(**kwargs)
def foo(**kwargs)
end
bar(*args)
def foo(*args)
# good
@example AllowOnlyRestArgument: true (default)
end
bar(…)
def foo(…)
# good
end
bar(*args, **kwargs, &block)
def foo(*args, **kwargs, &block)
# bad
end
bar(*args, &block)
def foo(*args, &block)
# bad
@example
can be replaced by `do_something(…)`.
This cop identifies places where `do_something(*args, &block)`
In Ruby 2.7, arguments forwarding has been added.

def all_lvars_as_forwarding_method_arguments?(def_node, forwarding_method)

def all_lvars_as_forwarding_method_arguments?(def_node, forwarding_method)
  lvars = def_node.body.each_descendant(:lvar, :lvasgn)
  begin_pos = forwarding_method.source_range.begin_pos
  end_pos = forwarding_method.source_range.end_pos
  lvars.all? { |lvar| lvar.source_range.begin_pos.between?(begin_pos, end_pos) }
end

def allow_only_rest_arguments?

def allow_only_rest_arguments?
  cop_config.fetch('AllowOnlyRestArgument', true)
end

def arguments_range(node)

def arguments_range(node)
  arguments = node.arguments
  range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
end

def extract_argument_names_from(args)

def extract_argument_names_from(args)
  kwargs_name = args.first.source.delete('**') if args.first&.kwrestarg_type?
  block_arg_name = args.last.source.delete('&') if args.last&.blockarg_type?
  [kwargs_name, block_arg_name].map { |name| name&.to_sym }
end

def forwarding_method?(node, rest_arg, kwargs, block_arg)

def forwarding_method?(node, rest_arg, kwargs, block_arg)
  return only_rest_arguments?(node, rest_arg) unless allow_only_rest_arguments?
  forwarding_method_arguments?(node, rest_arg, block_arg, kwargs)
end

def on_def(node)

def on_def(node)
  return unless node.body
  return unless (rest_args_name, args = use_rest_arguments?(node.arguments))
  node.each_descendant(:send) do |send_node|
    kwargs_name, block_name = extract_argument_names_from(args)
    next unless forwarding_method?(send_node, rest_args_name, kwargs_name, block_name) &&
                all_lvars_as_forwarding_method_arguments?(node, send_node)
    register_offense_to_forwarding_method_arguments(send_node)
    register_offense_to_method_definition_arguments(node)
  end
end

def register_offense_to_forwarding_method_arguments(forwarding_method)

def register_offense_to_forwarding_method_arguments(forwarding_method)
  add_offense(arguments_range(forwarding_method)) do |corrector|
    range = range_between(
      forwarding_method.loc.selector.end_pos, forwarding_method.source_range.end_pos
    )
    corrector.replace(range, '(...)')
  end
end

def register_offense_to_method_definition_arguments(method_definition)

def register_offense_to_method_definition_arguments(method_definition)
  add_offense(arguments_range(method_definition)) do |corrector|
    arguments_range = range_with_surrounding_space(
      range: method_definition.arguments.source_range, side: :left
    )
    corrector.replace(arguments_range, '(...)')
  end
end