ryo_executor/engine/impls/
bool_simplify.rs1use ryo_analysis::SymbolKind;
10use ryo_mutations::idiom::BoolSimplifyMutation;
11use ryo_mutations::{Mutation, MutationResult};
12use ryo_source::pure::{PureImplItem, PureItem};
13
14use crate::engine::{ASTMutationContext, ASTRegApply};
15
16impl ASTRegApply for BoolSimplifyMutation {
17 fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
18 let mut total_changes = 0;
19
20 if let Some(target_id) = self.target_fn {
21 if let Some(PureItem::Fn(f)) = ctx.ast_registry.get_mut(target_id) {
23 total_changes += self.transform_block(&mut f.body);
24 }
25 } else {
26 let fn_ids: Vec<_> = ctx
28 .symbol_registry
29 .iter()
30 .filter(|(id, _)| {
31 matches!(ctx.symbol_registry.kind(*id), Some(SymbolKind::Function))
32 })
33 .map(|(id, _)| id)
34 .collect();
35
36 for id in fn_ids {
37 if let Some(PureItem::Fn(f)) = ctx.ast_registry.get_mut(id) {
38 total_changes += self.transform_block(&mut f.body);
39 }
40 }
41
42 let impl_ids: Vec<_> = ctx
44 .symbol_registry
45 .iter()
46 .filter(|(id, _)| matches!(ctx.symbol_registry.kind(*id), Some(SymbolKind::Impl)))
47 .map(|(id, _)| id)
48 .collect();
49
50 for id in impl_ids {
51 if let Some(PureItem::Impl(imp)) = ctx.ast_registry.get_mut(id) {
52 for impl_item in &mut imp.items {
53 if let PureImplItem::Fn(f) = impl_item {
54 total_changes += self.transform_block(&mut f.body);
55 }
56 }
57 }
58 }
59 }
60
61 MutationResult {
62 mutation_type: self.mutation_type().to_string(),
63 changes: total_changes,
64 description: if total_changes > 0 {
65 format!("Simplified {} boolean comparison(s)", total_changes)
66 } else {
67 "No boolean comparisons simplified".to_string()
68 },
69 }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use crate::engine::ASTMutationEngine;
77 use ryo_analysis::testing::ContextBuilder;
78
79 #[test]
80 fn test_v2_bool_simplify_eq_true() {
81 let mut ctx = ContextBuilder::new()
82 .with_file(
83 "src/lib.rs",
84 r#"
85fn check(x: bool) -> bool {
86 x == true
87}
88"#,
89 )
90 .build();
91
92 let mutation = BoolSimplifyMutation::new();
93 let result = ASTMutationEngine::execute_ast_reg(&mutation, &mut ctx);
94
95 assert_eq!(result.result.changes, 1);
96 }
97
98 #[test]
99 fn test_v2_bool_simplify_eq_false() {
100 let mut ctx = ContextBuilder::new()
101 .with_file(
102 "src/lib.rs",
103 r#"
104fn check(x: bool) -> bool {
105 x == false
106}
107"#,
108 )
109 .build();
110
111 let mutation = BoolSimplifyMutation::new();
112 let result = ASTMutationEngine::execute_ast_reg(&mutation, &mut ctx);
113
114 assert_eq!(result.result.changes, 1);
115 }
116
117 #[test]
118 fn test_v2_bool_simplify_in_if() {
119 let mut ctx = ContextBuilder::new()
120 .with_file(
121 "src/lib.rs",
122 r#"
123fn process(flag: bool) {
124 if flag == true {
125 println!("yes");
126 }
127}
128"#,
129 )
130 .build();
131
132 let mutation = BoolSimplifyMutation::new();
133 let result = ASTMutationEngine::execute_ast_reg(&mutation, &mut ctx);
134
135 assert_eq!(result.result.changes, 1);
136 }
137
138 #[test]
139 fn test_v2_bool_simplify_no_changes() {
140 let mut ctx = ContextBuilder::new()
141 .with_file(
142 "src/lib.rs",
143 r#"
144fn check(x: bool) -> bool {
145 x
146}
147"#,
148 )
149 .build();
150
151 let mutation = BoolSimplifyMutation::new();
152 let result = ASTMutationEngine::execute_ast_reg(&mutation, &mut ctx);
153
154 assert_eq!(result.result.changes, 0);
155 }
156}