class RuboCop::Cop::Lint::UnescapedBracketInRegexp

Checks for Regexpes (both literals and via ‘Regexp.new` / `Regexp.compile`) that contain unescaped `]` characters.

It emulates the following Ruby warning:

source,ruby

$ ruby -e ‘/abc]123/’ -e:1: warning: regular expression has ‘]’ without escape: /abc]123/


@example

# bad
/abc]123/
%r{abc]123}
Regexp.new('abc]123')
Regexp.compile('abc]123')

# good
/abc\]123/
%r{abc\]123}
Regexp.new('abc\]123')
Regexp.compile('abc\]123')

Constants

MSG
RESTRICT_ON_SEND

Public Instance Methods

on_regexp(node) click to toggle source
# File lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb, line 45
def on_regexp(node)
  RuboCop::Util.silence_warnings do
    node.parsed_tree&.each_expression do |expr|
      detect_offenses(node, expr)
    end
  end
end
on_send(node) click to toggle source
# File lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb, line 53
def on_send(node)
  # Ignore nodes that contain interpolation
  return if node.each_descendant(:dstr).any?

  regexp_constructor(node) do |text|
    Regexp::Parser.parse(text.value)&.each_expression do |expr|
      detect_offenses(text, expr)
    end
  end
end

Private Instance Methods

detect_offenses(node, expr) click to toggle source
# File lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb, line 66
def detect_offenses(node, expr)
  return unless expr.type?(:literal)

  expr.text.scan(/(?<!\\)\]/) do
    pos = Regexp.last_match.begin(0)
    next if pos.zero? # if the unescaped bracket is the first character, Ruby does not warn

    location = range_at_index(node, expr.ts, pos)

    add_offense(location) do |corrector|
      corrector.replace(location, '\]')
    end
  end
end
range_at_index(node, index, offset) click to toggle source
# File lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb, line 81
def range_at_index(node, index, offset)
  adjustment = index + offset
  node.loc.begin.end.adjust(begin_pos: adjustment, end_pos: adjustment + 1)
end