class RuboCop::Cop::Lint::RedundantSplatExpansion

Checks for unneeded usages of splat expansion.

@example

# bad
a = *[1, 2, 3]
a = *'a'
a = *1
['a', 'b', *%w(c d e), 'f', 'g']

# good
c = [1, 2, 3]
a = *c
a, b = *c
a, *b = *c
a = *1..10
a = ['a']
['a', 'b', 'c', 'd', 'e', 'f', 'g']

# bad
do_something(*['foo', 'bar', 'baz'])

# good
do_something('foo', 'bar', 'baz')

# bad
begin
  foo
rescue *[StandardError, ApplicationError]
  bar
end

# good
begin
  foo
rescue StandardError, ApplicationError
  bar
end

# bad
case foo
when *[1, 2, 3]
  bar
else
  baz
end

# good
case foo
when 1, 2, 3
  bar
else
  baz
end

@example AllowPercentLiteralArrayArgument: true (default)

# good
do_something(*%w[foo bar baz])

@example AllowPercentLiteralArrayArgument: false

# bad
do_something(*%w[foo bar baz])

Constants

ARRAY_PARAM_MSG
ASSIGNMENT_TYPES
MSG
PERCENT_CAPITAL_I
PERCENT_CAPITAL_W
PERCENT_I
PERCENT_W

Public Instance Methods

on_splat(node) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 95
def on_splat(node)
  redundant_splat_expansion(node) do
    if array_splat?(node) && (method_argument?(node) || part_of_an_array?(node))
      return if allow_percent_literal_array_argument? &&
                use_percent_literal_array_argument?(node)

      add_offense(node, message: ARRAY_PARAM_MSG) do |corrector|
        autocorrect(corrector, node)
      end
    else
      add_offense(node) { |corrector| autocorrect(corrector, node) }
    end
  end
end

Private Instance Methods

allow_percent_literal_array_argument?() click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 203
def allow_percent_literal_array_argument?
  cop_config.fetch('AllowPercentLiteralArrayArgument', true)
end
array_new_inside_array_literal?(array_new_node) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 131
def array_new_inside_array_literal?(array_new_node)
  return false unless array_new?(array_new_node)

  grandparent = array_new_node.parent.parent
  grandparent.array_type? && grandparent.children.size > 1
end
array_splat?(node) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 155
def array_splat?(node)
  node.children.first.array_type?
end
autocorrect(corrector, node) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 112
def autocorrect(corrector, node)
  range, content = replacement_range_and_content(node)

  corrector.replace(range, content)
end
method_argument?(node) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 159
def method_argument?(node)
  node.parent.send_type?
end
part_of_an_array?(node) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 163
def part_of_an_array?(node)
  # The parent of a splat expansion is an array that does not have
  # `begin` or `end`
  parent = node.parent
  parent.array_type? && parent.loc.begin && parent.loc.end
end
redundant_brackets?(node) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 170
def redundant_brackets?(node)
  parent = node.parent
  grandparent = node.parent.parent

  parent.when_type? || parent.send_type? || part_of_an_array?(node) ||
    grandparent&.resbody_type?
end
redundant_splat_expansion(node) { || ... } click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 118
def redundant_splat_expansion(node)
  literal_expansion(node) do |expanded_item|
    if expanded_item.send_type?
      return if array_new_inside_array_literal?(expanded_item)

      grandparent = node.parent.parent
      return if grandparent && !ASSIGNMENT_TYPES.include?(grandparent.type)
    end

    yield
  end
end
remove_brackets(array) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 178
def remove_brackets(array)
  array_start = array.loc.begin.source
  elements = *array
  elements = elements.map(&:source)

  if array_start.start_with?(PERCENT_W)
    "'#{elements.join("', '")}'"
  elsif array_start.start_with?(PERCENT_CAPITAL_W)
    %("#{elements.join('", "')}")
  elsif array_start.start_with?(PERCENT_I)
    ":#{elements.join(', :')}"
  elsif array_start.start_with?(PERCENT_CAPITAL_I)
    %(:"#{elements.join('", :"')}")
  else
    elements.join(', ')
  end
end
replacement_range_and_content(node) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 138
def replacement_range_and_content(node)
  variable, = *node
  loc = node.loc
  expression = loc.expression

  if array_new?(variable)
    expression = node.parent.source_range if node.parent.array_type?
    [expression, variable.source]
  elsif !variable.array_type?
    [expression, "[#{variable.source}]"]
  elsif redundant_brackets?(node)
    [expression, remove_brackets(variable)]
  else
    [loc.operator, '']
  end
end
use_percent_literal_array_argument?(node) click to toggle source
# File lib/rubocop/cop/lint/redundant_splat_expansion.rb, line 196
def use_percent_literal_array_argument?(node)
  argument = node.children.first

  node.parent.send_type? &&
    (argument.percent_literal?(:string) || argument.percent_literal?(:symbol))
end