class RuboCop::Cop::Style::ConcatArrayLiterals

Enforces the use of ‘Array#push(item)` instead of `Array#concat()` to avoid redundant array literals.

@safety

This cop is unsafe, as it can produce false positives if the receiver
is not an `Array` object.

@example

# bad
list.concat([foo])
list.concat([bar, baz])
list.concat([qux, quux], [corge])

# good
list.push(foo)
list.push(bar, baz)
list.push(qux, quux, corge)

Constants

MSG
MSG_FOR_PERCENT_LITERALS
RESTRICT_ON_SEND

Public Instance Methods

on_csend(node)

rubocop:enable Metrics

Alias for: on_send
on_send(node) click to toggle source

rubocop:disable Metrics

# File lib/rubocop/cop/style/concat_array_literals.rb, line 34
def on_send(node)
  return if node.arguments.empty?
  return unless node.arguments.all?(&:array_type?)

  offense = offense_range(node)
  current = offense.source

  if (use_percent_literal = node.arguments.any?(&:percent_literal?))
    if percent_literals_includes_only_basic_literals?(node)
      prefer = preferred_method(node)
      message = format(MSG, prefer: prefer, current: current)
    else
      message = format(MSG_FOR_PERCENT_LITERALS, current: current)
    end
  else
    prefer = preferred_method(node)
    message = format(MSG, prefer: prefer, current: current)
  end

  add_offense(offense, message: message) do |corrector|
    if use_percent_literal
      corrector.replace(offense, prefer)
    else
      corrector.replace(node.loc.selector, 'push')
      node.arguments.each do |argument|
        corrector.remove(argument.loc.begin)
        corrector.remove(argument.loc.end)
      end
    end
  end
end
Also aliased as: on_csend

Private Instance Methods

offense_range(node) click to toggle source
# File lib/rubocop/cop/style/concat_array_literals.rb, line 70
def offense_range(node)
  node.loc.selector.join(node.source_range.end)
end
percent_literals_includes_only_basic_literals?(node) click to toggle source
# File lib/rubocop/cop/style/concat_array_literals.rb, line 87
def percent_literals_includes_only_basic_literals?(node)
  node.arguments.select(&:percent_literal?).all? do |arg|
    arg.children.all? { |child| child.str_type? || child.sym_type? }
  end
end
preferred_method(node) click to toggle source
# File lib/rubocop/cop/style/concat_array_literals.rb, line 74
def preferred_method(node)
  new_arguments =
    node.arguments.map do |arg|
      if arg.percent_literal?
        arg.children.map { |child| child.value.inspect }
      else
        arg.children.map(&:source)
      end
    end.join(', ')

  "push(#{new_arguments})"
end