class RuboCop::Cop::Performance::RedundantStringChars

This cop checks for redundant `String#chars`.

@example

# bad
str.chars[0..2]
str.chars.slice(0..2)

# good
str[0..2].chars

# bad
str.chars.first
str.chars.first(2)

# good
str[0]
str[0...2].chars

# bad
str.chars.take(2)
str.chars.length
str.chars.size
str.chars.empty?

# good
str[0...2].chars
str.length
str.size
str.empty?

# For example, if the receiver is a blank string, it will be incompatible.
# If a negative value is specified for the receiver, `nil` is returned.
str.chars.last    # Incompatible with `str[-1]`.
str.chars.last(2) # Incompatible with `str[-2..-1].chars`.
str.chars.drop(2) # Incompatible with `str[2..-1].chars`.

Constants

MSG
RESTRICT_ON_SEND

Public Instance Methods

on_send(node) click to toggle source
# File lib/rubocop/cop/performance/redundant_string_chars.rb, line 53
def on_send(node)
  return unless (receiver, method, args = redundant_chars_call?(node))

  range = offense_range(receiver, node)
  message = build_message(method, args)

  add_offense(range, message: message) do |corrector|
    range = correction_range(receiver, node)
    replacement = build_good_method(method, args)

    corrector.replace(range, replacement)
  end
end

Private Instance Methods

build_bad_method(method, args) click to toggle source
# File lib/rubocop/cop/performance/redundant_string_chars.rb, line 100
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
build_call_args(call_args_node) click to toggle source
# File lib/rubocop/cop/performance/redundant_string_chars.rb, line 113
def build_call_args(call_args_node)
  call_args_node.map(&:source).join(', ')
end
build_good_method(method, args) click to toggle source
# File lib/rubocop/cop/performance/redundant_string_chars.rb, line 83
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 :take
    "[0...#{args.first.source}].chars"
  else
    ".#{method}"
  end
end
build_message(method, args) click to toggle source
# File lib/rubocop/cop/performance/redundant_string_chars.rb, line 77
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
correction_range(receiver, node) click to toggle source
# File lib/rubocop/cop/performance/redundant_string_chars.rb, line 73
def correction_range(receiver, node)
  range_between(receiver.loc.dot.begin_pos, node.loc.expression.end_pos)
end
offense_range(receiver, node) click to toggle source
# File lib/rubocop/cop/performance/redundant_string_chars.rb, line 69
def offense_range(receiver, node)
  range_between(receiver.loc.selector.begin_pos, node.loc.expression.end_pos)
end