123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Cop::Performance::Casecmp

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, AutoCorrector, Base
Instance Chain:
self, Base
Inherits: Base
  • Object
Defined in: lib/rubocop/cop/performance/casecmp.rb

Overview

Identifies places where a case-insensitive string comparison can better be implemented using casecmp.

This cop is disabled by default because String#casecmp only works with ASCII characters. See https://github.com/rubocop/rubocop/issues/9753.

If you are working only with ASCII characters, then this cop can be safely enabled.

Examples:

# bad
str.downcase == 'abc'
str.upcase.eql? 'ABC'
'abc' == str.downcase
'ABC'.eql? str.upcase
str.downcase == str.downcase

# good
str.casecmp('ABC').zero?
'abc'.casecmp(str).zero?

Cop Safety Information:

  • This cop is unsafe because String#casecmp and String#casecmp? behave differently when using Non-ASCII characters.

Constant Summary

Instance Method Summary

Instance Method Details

#autocorrect(corrector, node, replacement) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/performance/casecmp.rb', line 90

def autocorrect(corrector, node, replacement)
  corrector.replace(node, replacement)
end

#build_good_method(method, arg, variable) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/performance/casecmp.rb', line 94

def build_good_method(method, arg, variable)
  bang = method == :!= ? '!' : ''

  # We want resulting call to be parenthesized
  # if arg already includes one or more sets of parens, don't add more
  # or if method call already used parens, again, don't add more
  if arg.send_type? || !parentheses?(arg)
    "#{bang}#{variable.source}.casecmp(#{arg.source}).zero?"
  else
    "#{bang}#{variable.source}.casecmp#{arg.source}.zero?"
  end
end

#on_send(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/performance/casecmp.rb', line 58

def on_send(node)
  return unless downcase_eq(node) || eq_downcase(node)
  return unless (parts = take_method_apart(node))

  _receiver, method, arg, variable = parts
  good_method = build_good_method(method, arg, variable)

  message = format(MSG, good: good_method, bad: node.source)
  add_offense(node, message: message) do |corrector|
    autocorrect(corrector, node, good_method)
  end
end

#take_method_apart(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/performance/casecmp.rb', line 73

def take_method_apart(node)
  if downcase_downcase(node)
    receiver, method, rhs = *node
    arg, = *rhs
  elsif downcase_eq(node)
    receiver, method, arg = *node
  elsif eq_downcase(node)
    arg, method, receiver = *node
  else
    return
  end

  variable, = *receiver

  [receiver, method, arg, variable]
end