Class: RuboCop::Cop::Performance::DeletePrefix

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector, TargetRubyVersion
Includes:
RegexpMetacharacter
Defined in:
lib/rubocop/cop/performance/delete_prefix.rb

Overview

In Ruby 2.5, ‘String#delete_prefix` has been added.

This cop identifies places where ‘gsub(/Aprefix/, ”)` and `sub(/Aprefix/, ”)` can be replaced by `delete_prefix(’prefix’)‘.

This cop has ‘SafeMultiline` configuration option that `true` by default because `^prefix` is unsafe as it will behave incompatible with `delete_prefix` for receiver is multiline string.

The ‘delete_prefix(’prefix’)‘ method is faster than `gsub(/Aprefix/, ”)`.

Examples:


# bad
str.gsub(/\Aprefix/, '')
str.gsub!(/\Aprefix/, '')

str.sub(/\Aprefix/, '')
str.sub!(/\Aprefix/, '')

# good
str.delete_prefix('prefix')
str.delete_prefix!('prefix')

SafeMultiline: true (default)


# good
str.gsub(/^prefix/, '')
str.gsub!(/^prefix/, '')
str.sub(/^prefix/, '')
str.sub!(/^prefix/, '')

SafeMultiline: false


# bad
str.gsub(/^prefix/, '')
str.gsub!(/^prefix/, '')
str.sub(/^prefix/, '')
str.sub!(/^prefix/, '')

Constant Summary collapse

MSG =
'Use `%<prefer>s` instead of `%<current>s`.'
RESTRICT_ON_SEND =
%i[gsub gsub! sub sub!].freeze
PREFERRED_METHODS =
{
  gsub: :delete_prefix,
  gsub!: :delete_prefix!,
  sub: :delete_prefix,
  sub!: :delete_prefix!
}.freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object Also known as: on_csend

rubocop:disable Metrics/AbcSize



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rubocop/cop/performance/delete_prefix.rb', line 71

def on_send(node)
  return unless (receiver, bad_method, regexp_str, replace_string = delete_prefix_candidate?(node))
  return unless replace_string.empty?

  good_method = PREFERRED_METHODS[bad_method]

  message = format(MSG, current: bad_method, prefer: good_method)

  add_offense(node.loc.selector, message: message) do |corrector|
    regexp_str = drop_start_metacharacter(regexp_str)
    regexp_str = interpret_string_escapes(regexp_str)
    string_literal = to_string_literal(regexp_str)

    new_code = "#{receiver.source}#{node.loc.dot.source}#{good_method}(#{string_literal})"

    corrector.replace(node, new_code)
  end
end