class RuboCop::Cop::Lint::OutOfRangeRegexpRef


puts $1 # => foo
# good
puts $2 # => nil
# bad - always returns nil
/(foo)bar/ =~ ‘foobar’
@example
however.
This might be a good indication of code that should be refactored,
—-
# the cop will mark this as an offense.
# $2 is defined for the first condition but not the second, however
do_something if $2
foo ? /©(b)/ =~ str : /(b)/ =~ str
—-
[source,ruby]

leads to false positives, such as:
it cannot handle some cases, such as conditional regexp matches, which
references are available based on the last encountered regexp, but
This cop is unsafe because it is naive in how it determines what
@safety
and thus always returns nil.
Looks for references of Regexp captures that are out of range

def after_send(node)

def after_send(node)
  @valid_ref = nil
  if regexp_first_argument?(node)
    check_regexp(node.first_argument)
  elsif regexp_receiver?(node)
    check_regexp(node.receiver)
  end
end

def check_regexp(node)

def check_regexp(node)
  return if node.interpolation?
  named_capture = node.each_capture(named: true).count
  @valid_ref = if named_capture.positive?
                 named_capture
               else
                 node.each_capture(named: false).count
               end
end

def nth_ref_receiver?(send_node)

def nth_ref_receiver?(send_node)
  send_node.receiver&.nth_ref_type?
end

def on_in_pattern(node)

def on_in_pattern(node)
  regexp_patterns = regexp_patterns(node)
  @valid_ref = regexp_patterns.filter_map { |pattern| check_regexp(pattern) }.max
end

def on_match_with_lvasgn(node)

def on_match_with_lvasgn(node)
  check_regexp(node.children.first)
end

def on_new_investigation

def on_new_investigation
  @valid_ref = 0
end

def on_nth_ref(node)

def on_nth_ref(node)
  backref, = *node
  return if @valid_ref.nil? || backref <= @valid_ref
  message = format(
    MSG,
    backref: backref,
    count: @valid_ref.zero? ? 'no' : @valid_ref,
    group: @valid_ref == 1 ? 'group' : 'groups'
  )
  add_offense(node, message: message)
end

def on_when(node)

def on_when(node)
  regexp_conditions = node.conditions.select(&:regexp_type?)
  @valid_ref = regexp_conditions.filter_map { |condition| check_regexp(condition) }.max
end

def regexp_first_argument?(send_node)

def regexp_first_argument?(send_node)
  send_node.first_argument&.regexp_type? \
    && REGEXP_ARGUMENT_METHODS.include?(send_node.method_name)
end

def regexp_patterns(in_node)

def regexp_patterns(in_node)
  pattern = in_node.pattern
  if pattern.regexp_type?
    [pattern]
  else
    pattern.each_descendant(:regexp).to_a
  end
end

def regexp_receiver?(send_node)

def regexp_receiver?(send_node)
  send_node.receiver&.regexp_type?
end