Class: Mutineer::Mutators::RegexLiteral
- Defined in:
- lib/mutineer/mutators/regex_literal.rb
Overview
Regular-expression literal mutator (Tier-2).
Conservative, clearly-safe textual swaps inside a plain regex literal:
drop a leading ^ anchor, drop a trailing $ anchor, and swap the +
and * quantifiers. Interpolated regexes use a different node type and are
never visited. Escaped tokens (preceded by a backslash) are left alone.
Instance Method Summary collapse
-
#emit(start_offset, end_offset, replacement) ⇒ void
private
Emits a regex mutation.
-
#scan(content, base) ⇒ void
private
Scans the pattern bytes and emits anchor/quantifier mutations.
-
#trailing_anchor?(content) ⇒ Boolean
private
Whether the pattern ends with an unescaped
$anchor. -
#visit_regular_expression_node(node) ⇒ void
Visits regular-expression literals.
Methods inherited from Base
Instance Method Details
#emit(start_offset, end_offset, replacement) ⇒ void (private)
This method returns an undefined value.
Emits a regex mutation.
62 63 64 65 66 67 68 69 |
# File 'lib/mutineer/mutators/regex_literal.rb', line 62 def emit(start_offset, end_offset, replacement) @mutations << Mutation.new( start_offset: start_offset, end_offset: end_offset, replacement: replacement, operator: :regex ) end |
#scan(content, base) ⇒ void (private)
This method returns an undefined value.
Scans the pattern bytes and emits anchor/quantifier mutations.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/mutineer/mutators/regex_literal.rb', line 32 def scan(content, base) emit(base, base + 1, "") if content.start_with?("^") emit(base + content.bytesize - 1, base + content.bytesize, "") if trailing_anchor?(content) escaped = false offset = base content.each_char do |ch| unless escaped emit(offset, offset + 1, "*") if ch == "+" emit(offset, offset + 1, "+") if ch == "*" end escaped = ch == "\\" && !escaped offset += ch.bytesize end end |
#trailing_anchor?(content) ⇒ Boolean (private)
Whether the pattern ends with an unescaped $ anchor.
52 53 54 |
# File 'lib/mutineer/mutators/regex_literal.rb', line 52 def trailing_anchor?(content) content.end_with?("$") && !content.end_with?("\\$") end |
#visit_regular_expression_node(node) ⇒ void
This method returns an undefined value.
Visits regular-expression literals.
18 19 20 21 22 23 |
# File 'lib/mutineer/mutators/regex_literal.rb', line 18 def visit_regular_expression_node(node) loc = node.content_loc content = @source.byteslice(loc.start_offset...loc.end_offset) scan(content, loc.start_offset) super end |