Add Ruby language support - #55
Conversation
| severity: MutationSeverity::Medium, | ||
| }, | ||
| Mutation { | ||
| slug: "RBR", |
There was a problem hiding this comment.
We added a custom RBR (Range Bound Replacement) slug to swap Ruby's inclusive (..) and exclusive (...) range operators.
9760eb8 to
40b0887
Compare
| /// (method/do_block/block) are intentionally excluded so that the | ||
| /// outermost-match logic in `patterns` keeps producing one mutant per | ||
| /// inner statement rather than a single mutant for the whole body. | ||
| const STATEMENT_KINDS: &[&str] = &[ |
There was a problem hiding this comment.
We include nodes::CASE and nodes::CASE_MATCH but exclude top-level containers like method and class bodies. This creates isolated mutations for innermost statements rather than replacing the entire container.
| } | ||
| }); | ||
| } | ||
| "UF" => { |
There was a problem hiding this comment.
We added custom mutation slugs (UF/UT and ULF/ULT) for Ruby's unless and until statements. Standard IF/IT logic creates the opposite behavior because replacing an unless condition with false differs semantically from replacing an if condition with false.
| ); | ||
| } | ||
| } | ||
| "UP" => { |
There was a problem hiding this comment.
We created the UP (Unpin Pattern) slug to handle unpinning variables in pattern matching expressions. Removing the ^ pin operator (in ^var) changes the match from an exact-value match to a variable reassignment. We use a dedicated slug for this instead of reusing the NR (Negation Removal) slug, as the caret does not function as a logical negation in this context.
| mutants | ||
| } | ||
|
|
||
| pub fn swap_named_children(root: Node, source: &str, node_kinds: &[&str]) -> Vec<PartialMutant> { |
There was a problem hiding this comment.
We added this function to support mutating Ruby array patterns (e.g., in [a, b, c]). Tree-sitter treats array elements as standalone named children rather than wrapping them in an arguments list. This prevents the existing swap_args function from traversing them.
| info!( | ||
| " {:<9} | {}", | ||
| &outcome.status.display(), | ||
| outcome.status.display(), |
There was a problem hiding this comment.
Removed the unnecessary reference (&) here since .display() already returns a type that implements Display. This was done to resolve a clippy::useless_borrow warning.
| ) -> AppResult<()> { | ||
| // If mutant_id is provided, special handling | ||
| if filters.id.is_some() { | ||
| if let Some(id) = filters.id { |
There was a problem hiding this comment.
Refactored the if is_some() check that was followed by an unwrap() into an if let Some(id) binding to satisfy clippy::unnecessary_unwrap.
|
|
||
| # "varaint" is a typo in the upstream tree-sitter-ruby grammar's comment | ||
| # ("command varaint") in grammar.js. We do not control this vendored file. | ||
| varaint = "varaint" |
There was a problem hiding this comment.
Added varaint to the typos ignore list because this typo exists in a comment within the vendored tree-sitter-ruby grammar file, which we do not maintain.
fe669e5 to
f3fe683
Compare
nsmmrs
left a comment
There was a problem hiding this comment.
Just noticed it said I have an unfinished review, so I think my comments have been invisible this whole time.
|
Not sure why, but I'm suddenly getting a bunch of notifications about failed CI runs on this PR. |
Summary
Adds Ruby support. Introduces a
RubyLanguageEnginethat parses and mutates Ruby code using thetree-sitter-rubygrammar.Mutations
We mapped Mewt's standard mutation operators to Ruby AST nodes and created new operators to support Ruby-specific syntax and control flow.
1. Ruby-Specific Operators (New)
unlessconditions andunless_guardnodes withfalseortrue.untilloop conditions withfalseortrue.^pin operator in pattern matching expressions (in ^varbecomesin var)...) and exclusive (...) range operators.&.becomes.).||=and&&=operators.=~and!~).===) with the standard equality operator (==)."",[],{}).2. Core Operators (Mapped to Ruby)
if,elsif,if_guard, and ternary conditional expressions.nilorraise "mewt". Applies to top-level expressions, method calls,yield,super,redo,retry,break,next,rescue_modifier(inline rescue), andcase_match(inclauses).!operator and thenotkeyword (e.g.,not valid?).in [a, b, c]).redoandretrykeywords, and replacesbreakandnextwithredoorretry.Testing
tests/ruby/mutations/to verify mutant generation across different syntax scenarios.just pre-commitformatting and linter checks (cargo fmt,clippy, andtypos).