class RuboCop::Cop::Style::PerlBackrefs

Looks for uses of Perl-style regexp match backreferences and their English versions like $1, $2, $&, &+, $MATCH, $PREMATCH, etc.

@example

# bad
puts $1

# good
puts Regexp.last_match(1)

Constants

MESSAGE_FORMAT

Public Instance Methods

on_back_ref(node) click to toggle source
# File lib/rubocop/cop/style/perl_backrefs.rb, line 21
def on_back_ref(node)
  on_back_ref_or_gvar_or_nth_ref(node)
end
on_gvar(node) click to toggle source
# File lib/rubocop/cop/style/perl_backrefs.rb, line 25
def on_gvar(node)
  on_back_ref_or_gvar_or_nth_ref(node)
end
on_nth_ref(node) click to toggle source
# File lib/rubocop/cop/style/perl_backrefs.rb, line 29
def on_nth_ref(node)
  on_back_ref_or_gvar_or_nth_ref(node)
end

Private Instance Methods

constant_prefix(node) click to toggle source

@private @param [RuboCop::AST::Node] node @return [String]

# File lib/rubocop/cop/style/perl_backrefs.rb, line 99
def constant_prefix(node)
  if node.each_ancestor(:class, :module).any?
    '::'
  else
    ''
  end
end
derived_from_braceless_interpolation?(node) click to toggle source

@private @param [RuboCop::AST::Node] node @return [Boolean]

# File lib/rubocop/cop/style/perl_backrefs.rb, line 38
def derived_from_braceless_interpolation?(node)
  %i[dstr regexp xstr].include?(node.parent&.type)
end
format_message(node:, preferred_expression:) click to toggle source

@private @param [RuboCop::AST::Node] node @param [String] preferred_expression @return [String]

# File lib/rubocop/cop/style/perl_backrefs.rb, line 46
def format_message(node:, preferred_expression:)
  original_expression = original_expression_of(node)
  format(
    MESSAGE_FORMAT,
    original_expression: original_expression,
    preferred_expression: preferred_expression
  )
end
on_back_ref_or_gvar_or_nth_ref(node) click to toggle source

@private @param [RuboCop::AST::Node] node

# File lib/rubocop/cop/style/perl_backrefs.rb, line 109
def on_back_ref_or_gvar_or_nth_ref(node)
  preferred_expression = preferred_expression_to_node_with_constant_prefix(node)
  return unless preferred_expression

  add_offense(
    node,
    message: format_message(node: node, preferred_expression: preferred_expression)
  ) do |corrector|
    if derived_from_braceless_interpolation?(node)
      preferred_expression = "{#{preferred_expression}}"
    end

    corrector.replace(node, preferred_expression)
  end
end
original_expression_of(node) click to toggle source

@private @param [RuboCop::AST::Node] node @return [String]

# File lib/rubocop/cop/style/perl_backrefs.rb, line 58
def original_expression_of(node)
  first = node.to_a.first
  if first.is_a?(::Integer)
    "$#{first}"
  else
    first.to_s
  end
end
preferred_expression_to(node) click to toggle source

@private @param [RuboCop::AST::Node] node @return [String, nil]

# File lib/rubocop/cop/style/perl_backrefs.rb, line 70
def preferred_expression_to(node)
  first = node.to_a.first
  case first
  when ::Integer
    "Regexp.last_match(#{first})"
  when :$&, :$MATCH
    'Regexp.last_match(0)'
  when :$`, :$PREMATCH
    'Regexp.last_match.pre_match'
  when :$', :$POSTMATCH
    'Regexp.last_match.post_match'
  when :$+, :$LAST_PAREN_MATCH
    'Regexp.last_match(-1)'
  end
end
preferred_expression_to_node_with_constant_prefix(node) click to toggle source

@private @param [RuboCop::AST::Node] node @return [String, nil]

# File lib/rubocop/cop/style/perl_backrefs.rb, line 89
def preferred_expression_to_node_with_constant_prefix(node)
  expression = preferred_expression_to(node)
  return unless expression

  "#{constant_prefix(node)}#{expression}"
end