class RuboCop::Cop::Style::ArrayFirstLast


[-2]<br>arr = 2
arr.last
arr.first
# good

arr[-1]
arr[0]
# bad
@example
does not implement ‘first`/`last` methods.
`.first` or `.last` will return first/last tuple instead. Also, String
which returns a value for `0` or `-1` key, but changing these to use
This cop is unsafe because `[0]` or `[-1]` can be called on a Hash,
@safety
The cop is disabled by default due to safety concerns.
them to use `arr.first` and `arr.last` instead.
Identifies usages of `arr` and `arr` and suggests to change

def brace_method?(node)

def brace_method?(node)
  node.send_type? && (node.method?(:[]) || node.method?(:[]=))
end

def find_offense_range(node)

def find_offense_range(node)
  if node.loc.dot
    node.loc.selector.join(node.source_range.end)
  else
    node.loc.selector
  end
end

def innermost_braces_node(node)

def innermost_braces_node(node)
  node = node.receiver while node.receiver.send_type? && node.receiver.method?(:[])
  node
end

def on_send(node)

rubocop:disable Metrics/AbcSize
def on_send(node)
  return unless node.arguments.size == 1 && node.first_argument.int_type?
  value = node.first_argument.value
  return unless [0, -1].include?(value)
  node = innermost_braces_node(node)
  return if node.parent && brace_method?(node.parent)
  preferred = (value.zero? ? 'first' : 'last')
  offense_range = find_offense_range(node)
  add_offense(offense_range, message: format(MSG, preferred: preferred)) do |corrector|
    corrector.replace(offense_range, preferred_value(node, preferred))
  end
end

def preferred_value(node, value)

def preferred_value(node, value)
  value = ".#{value}" unless node.loc.dot
  value
end