class RuboCop::Cop::Performance::RedundantStringChars


.chars<br>str.chars
# good
str.chars.empty?
str.chars.size
str.chars.length
str.chars.drop(2)
str.chars.take(2)
# bad<br><br>str.chars<br>str[-1]<br>str.chars
str[0]
# good
str.chars.last(2)
str.chars.last
str.chars.first(2)
str.chars.first
# bad<br><br>str.chars
# good

str.chars.slice(0..2)
str.chars[0..2]
# bad
@example
This cop checks for redundant ‘String#chars`.

def autocorrect(node)

def autocorrect(node)
  redundant_chars_call?(node) do |receiver, method, args|
    range = correction_range(receiver, node)
    replacement = build_good_method(method, args)
    lambda do |corrector|
      corrector.replace(range, replacement)
    end
  end
end

def build_bad_method(method, args)

def build_bad_method(method, args)
  case method
  when :[]
    "chars[#{build_call_args(args)}]"
  else
    if args.any?
      "chars.#{method}(#{build_call_args(args)})"
    else
      "chars.#{method}"
    end
  end
end

def build_call_args(call_args_node)

def build_call_args(call_args_node)
  call_args_node.map(&:source).join(', ')
end

def build_good_method(method, args)

rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
def build_good_method(method, args)
  case method
  when :[], :slice
    "[#{build_call_args(args)}].chars"
  when :first
    if args.any?
      "[0...#{args.first.source}].chars"
    else
      '[0]'
    end
  when :last
    if args.any?
      "[-#{args.first.source}..-1].chars"
    else
      '[-1]'
    end
  when :take
    "[0...#{args.first.source}].chars"
  when :drop
    "[#{args.first.source}..-1].chars"
  else
    ".#{method}"
  end
end

def build_message(method, args)

def build_message(method, args)
  good_method = build_good_method(method, args)
  bad_method = build_bad_method(method, args)
  format(MSG, good_method: good_method, bad_method: bad_method)
end

def correction_range(receiver, node)

def correction_range(receiver, node)
  range_between(receiver.loc.dot.begin_pos, node.loc.expression.end_pos)
end

def offense_range(receiver, node)

def offense_range(receiver, node)
  range_between(receiver.loc.selector.begin_pos, node.loc.expression.end_pos)
end

def on_send(node)

def on_send(node)
  redundant_chars_call?(node) do |receiver, method, args|
    range = offense_range(receiver, node)
    message = build_message(method, args)
    add_offense(node, location: range, message: message)
  end
end

def replaceable_method?(method_name)

def replaceable_method?(method_name)
  REPLACEABLE_METHODS.include?(method_name)
end