class RuboCop::Cop::Style::RedundantRegexpEscape

/[+-]d/
# good<br><br>/d/
# bad
/a-b/
# good
/a-b/
# bad
%r!foo!bar!
# good
%r/foo/bar/
# good
/foo/bar/
# good
%r{foo/bar}
# good
%r{foo/bar}
# bad
@example
This cop checks for redundant escapes inside Regexp literals.

def allowed_escape?(node, char, within_character_class)

def allowed_escape?(node, char, within_character_class)
  # Strictly speaking a few single-letter metachars are currently
  # unnecessary to "escape", e.g. i, E, F, but enumerating them is
  # rather difficult, and their behaviour could change over time with
  # different versions of Ruby so that e.g. /\i/ != /i/
  return true if /[[:alnum:]]/.match?(char)
  return true if ALLOWED_ALWAYS_ESCAPES.include?(char) || delimiter?(node, char)
  if within_character_class
    ALLOWED_WITHIN_CHAR_CLASS_METACHAR_ESCAPES.include?(char)
  else
    ALLOWED_OUTSIDE_CHAR_CLASS_METACHAR_ESCAPES.include?(char)
  end
end

def delimiter?(node, char)

def delimiter?(node, char)
  delimiters = [node.loc.begin.source[-1], node.loc.end.source[0]]
  delimiters.include?(char)
end

def each_escape(node)

def each_escape(node)
  node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
    yield(expr.text[1], expr.ts, !char_class_depth.zero?) if expr.type == :escape
    if expr.type == :set
      char_class_depth + (event == :enter ? 1 : -1)
    else
      char_class_depth
    end
  end
end

def each_escape(node)

def each_escape(node)
  node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
    yield(expr.text[1], expr.start_index, !char_class_depth.zero?) if expr.type == :escape
    if expr.type == :set
      char_class_depth + (event == :enter ? 1 : -1)
    else
      char_class_depth
    end
  end
end

def escape_range_at_index(node, index)

def escape_range_at_index(node, index)
  regexp_begin = node.loc.begin.end_pos
  start = regexp_begin + index
  range_between(start, start + 2)
end

def on_regexp(node)

def on_regexp(node)
  each_escape(node) do |char, index, within_character_class|
    next if allowed_escape?(node, char, within_character_class)
    location = escape_range_at_index(node, index)
    add_offense(location, message: MSG_REDUNDANT_ESCAPE) do |corrector|
      corrector.remove_leading(escape_range_at_index(node, index), 1)
    end
  end
end