class RuboCop::Cop::Lint::OutOfRangeRegexpRef
Looks for references of Regexp captures that are out of range and thus always returns nil.
@safety
This cop is unsafe because it is naive in how it determines what references are available based on the last encountered regexp, but it cannot handle some cases, such as conditional regexp matches, which leads to false positives, such as: [source,ruby] ---- foo ? /(c)(b)/ =~ str : /(b)/ =~ str do_something if $2 # $2 is defined for the first condition but not the second, however # the cop will mark this as an offense. ---- This might be a good indication of code that should be refactored, however.
@example
/(foo)bar/ =~ 'foobar' # bad - always returns nil puts $2 # => nil # good puts $1 # => foo
Constants
- MSG
- REGEXP_ARGUMENT_METHODS
- REGEXP_CAPTURE_METHODS
- REGEXP_RECEIVER_METHODS
- RESTRICT_ON_SEND
Public Instance Methods
after_send(node)
click to toggle source
# File lib/rubocop/cop/lint/out_of_range_regexp_ref.rb, line 55 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
on_match_with_lvasgn(node)
click to toggle source
# File lib/rubocop/cop/lint/out_of_range_regexp_ref.rb, line 51 def on_match_with_lvasgn(node) check_regexp(node.children.first) end
on_new_investigation()
click to toggle source
# File lib/rubocop/cop/lint/out_of_range_regexp_ref.rb, line 47 def on_new_investigation @valid_ref = 0 end
on_nth_ref(node)
click to toggle source
# File lib/rubocop/cop/lint/out_of_range_regexp_ref.rb, line 71 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
on_when(node)
click to toggle source
# File lib/rubocop/cop/lint/out_of_range_regexp_ref.rb, line 65 def on_when(node) regexp_conditions = node.conditions.select(&:regexp_type?) @valid_ref = regexp_conditions.map { |condition| check_regexp(condition) }.compact.max end
Private Instance Methods
check_regexp(node)
click to toggle source
# File lib/rubocop/cop/lint/out_of_range_regexp_ref.rb, line 87 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
nth_ref_receiver?(send_node)
click to toggle source
# File lib/rubocop/cop/lint/out_of_range_regexp_ref.rb, line 107 def nth_ref_receiver?(send_node) send_node.receiver&.nth_ref_type? end
regexp_first_argument?(send_node)
click to toggle source
# File lib/rubocop/cop/lint/out_of_range_regexp_ref.rb, line 98 def regexp_first_argument?(send_node) send_node.first_argument&.regexp_type? \ && REGEXP_ARGUMENT_METHODS.include?(send_node.method_name) end
regexp_receiver?(send_node)
click to toggle source
# File lib/rubocop/cop/lint/out_of_range_regexp_ref.rb, line 103 def regexp_receiver?(send_node) send_node.receiver&.regexp_type? end