class RuboCop::Cop::Style::ArgumentsForwarding

In Ruby 2.7, arguments forwarding has been added.

This cop identifies places where `do_something(*args, &block)` can be replaced by `do_something(…)`.

@example

# bad
def foo(*args, &block)
  bar(*args, &block)
end

# bad
def foo(*args, **kwargs, &block)
  bar(*args, **kwargs, &block)
end

# good
def foo(...)
  bar(...)
end

@example AllowOnlyRestArgument: true (default)

# good
def foo(*args)
  bar(*args)
end

def foo(**kwargs)
  bar(**kwargs)
end

@example AllowOnlyRestArgument: false

# bad
# The following code can replace the arguments with `...`,
# but it will change the behavior. Because `...` forwards block also.
def foo(*args)
  bar(*args)
end

def foo(**kwargs)
  bar(**kwargs)
end

Constants

MSG

Public Instance Methods

on_def(node) click to toggle source
# File lib/rubocop/cop/style/arguments_forwarding.rb, line 84
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
Also aliased as: on_defs
on_defs(node)
Alias for: on_def

Private Instance Methods

all_lvars_as_forwarding_method_arguments?(def_node, forwarding_method) click to toggle source
# File lib/rubocop/cop/style/arguments_forwarding.rb, line 115
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
allow_only_rest_arguments?() click to toggle source
# File lib/rubocop/cop/style/arguments_forwarding.rb, line 148
def allow_only_rest_arguments?
  cop_config.fetch('AllowOnlyRestArgument', true)
end
arguments_range(node) click to toggle source
# File lib/rubocop/cop/style/arguments_forwarding.rb, line 142
def arguments_range(node)
  arguments = node.arguments

  range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
end
extract_argument_names_from(args) click to toggle source
# File lib/rubocop/cop/style/arguments_forwarding.rb, line 102
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
forwarding_method?(node, rest_arg, kwargs, block_arg) click to toggle source
# File lib/rubocop/cop/style/arguments_forwarding.rb, line 109
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
register_offense_to_forwarding_method_arguments(forwarding_method) click to toggle source
# File lib/rubocop/cop/style/arguments_forwarding.rb, line 124
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
register_offense_to_method_definition_arguments(method_definition) click to toggle source
# File lib/rubocop/cop/style/arguments_forwarding.rb, line 133
def register_offense_to_method_definition_arguments(method_definition)
  add_offense(arguments_range(method_definition)) do |corrector|
    arguments_range = range_with_surrounding_space(
      method_definition.arguments.source_range, side: :left
    )
    corrector.replace(arguments_range, '(...)')
  end
end