class RuboCop::Cop::Style::FormatString

Enforces the use of a single string formatting utility. Valid options include Kernel#format, Kernel#sprintf and String#%.

The detection of String#% cannot be implemented in a reliable manner for all cases, so only two scenarios are considered - if the first argument is a string literal and if the second argument is an array literal.

@example EnforcedStyle: format (default)

# bad
puts sprintf('%10s', 'hoge')
puts '%10s' % 'hoge'

# good
puts format('%10s', 'hoge')

@example EnforcedStyle: sprintf

# bad
puts format('%10s', 'hoge')
puts '%10s' % 'hoge'

# good
puts sprintf('%10s', 'hoge')

@example EnforcedStyle: percent

# bad
puts format('%10s', 'hoge')
puts sprintf('%10s', 'hoge')

# good
puts '%10s' % 'hoge'

Constants

MSG
RESTRICT_ON_SEND

Public Instance Methods

on_send(node) click to toggle source
# File lib/rubocop/cop/style/format_string.rb, line 59
def on_send(node)
  formatter(node) do |selector|
    detected_style = selector == :% ? :percent : selector

    return if detected_style == style

    add_offense(node.loc.selector, message: message(detected_style)) do |corrector|
      autocorrect(corrector, node)
    end
  end
end

Private Instance Methods

autocorrect(corrector, node) click to toggle source
# File lib/rubocop/cop/style/format_string.rb, line 81
def autocorrect(corrector, node)
  return if variable_argument?(node)

  case node.method_name
  when :%
    autocorrect_from_percent(corrector, node)
  when :format, :sprintf
    case style
    when :percent
      autocorrect_to_percent(corrector, node)
    when :format, :sprintf
      corrector.replace(node.loc.selector, style.to_s)
    end
  end
end
autocorrect_from_percent(corrector, node) click to toggle source
# File lib/rubocop/cop/style/format_string.rb, line 97
def autocorrect_from_percent(corrector, node)
  percent_rhs = node.first_argument
  args = case percent_rhs.type
         when :array, :hash
           percent_rhs.children.map(&:source).join(', ')
         else
           percent_rhs.source
         end

  corrected = "#{style}(#{node.receiver.source}, #{args})"

  corrector.replace(node, corrected)
end
autocorrect_to_percent(corrector, node) click to toggle source
# File lib/rubocop/cop/style/format_string.rb, line 111
def autocorrect_to_percent(corrector, node)
  format_arg, *param_args = node.arguments
  format = format_arg.source

  args = if param_args.one?
           format_single_parameter(param_args.last)
         else
           "[#{param_args.map(&:source).join(', ')}]"
         end

  corrector.replace(node, "#{format} % #{args}")
end
format_single_parameter(arg) click to toggle source
# File lib/rubocop/cop/style/format_string.rb, line 124
def format_single_parameter(arg)
  source = arg.source
  return "{ #{source} }" if arg.hash_type?

  arg.send_type? && arg.operator_method? && !arg.parenthesized? ? "(#{source})" : source
end
message(detected_style) click to toggle source
# File lib/rubocop/cop/style/format_string.rb, line 73
def message(detected_style)
  format(MSG, prefer: method_name(style), current: method_name(detected_style))
end
method_name(style_name) click to toggle source
# File lib/rubocop/cop/style/format_string.rb, line 77
def method_name(style_name)
  style_name == :percent ? 'String#%' : style_name
end