ryo_mutations/basic/stmt/insert_statement.rs
1//! InsertStatementMutation: Insert statements at specific positions
2//!
3//! Insert a statement at the start, end, or relative to another statement:
4//! ```ignore
5//! fn example() {
6//! // <- Insert at Start
7//! do_work();
8//! // <- Insert at End
9//! }
10//! ```
11//!
12//! # Matching strategy (BeforePattern / AfterPattern)
13//!
14//! `reference_stmt` (PureStmt) に対して PartialEq で厳密比較する。
15//! これは RemoveStatement の `stmt_matches_pattern`(文字列パターン照合)とは
16//! 意図的に異なる方式である。
17//!
18//! - **InsertStatement**: 「この特定の文の隣に挿入」→ 正確な位置特定が必要 → PartialEq
19//! - **RemoveStatement**: 「パターンに合う文を除去」→ 柔軟な照合が必要 → 文字列パターン
20//!
21//! `reference_stmt` は converter 側で `syn::parse_str` → `to_pure()` により生成される。
22//! 元ソースコードも同じ `syn::parse_file` → `to_pure()` パイプラインを経由するため、
23//! 同一の Rust コード文字列からは同一の PureStmt が生成される。
24
25use ryo_source::pure::PureStmt;
26use ryo_symbol::SymbolId;
27
28use crate::Mutation;
29
30/// Position for inserting statements
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
32pub enum InsertPosition {
33 /// At the start of the function body
34 Start,
35 /// At the end of the function body (before return statement if any)
36 #[default]
37 End,
38 /// Before a statement matching the reference pattern
39 BeforePattern,
40 /// After a statement matching the reference pattern
41 AfterPattern,
42}
43
44/// Insert a statement at a specific position
45#[derive(Debug, Clone)]
46pub struct InsertStatementMutation {
47 /// Statement to insert
48 pub stmt: PureStmt,
49 /// Target function SymbolId
50 pub target_fn: SymbolId,
51 /// Insert position
52 pub position: InsertPosition,
53 /// Reference statement for BeforePattern/AfterPattern.
54 /// Matched via PartialEq (exact structural match).
55 pub reference_stmt: Option<PureStmt>,
56}
57
58impl InsertStatementMutation {
59 pub fn new(stmt: PureStmt, target_fn: SymbolId) -> Self {
60 Self {
61 stmt,
62 target_fn,
63 position: InsertPosition::End,
64 reference_stmt: None,
65 }
66 }
67
68 /// Insert at the start of the function
69 pub fn at_start(mut self) -> Self {
70 self.position = InsertPosition::Start;
71 self
72 }
73
74 /// Insert at the end of the function
75 pub fn at_end(mut self) -> Self {
76 self.position = InsertPosition::End;
77 self
78 }
79
80 /// Insert before a statement matching the reference
81 pub fn before(mut self, reference_stmt: PureStmt) -> Self {
82 self.position = InsertPosition::BeforePattern;
83 self.reference_stmt = Some(reference_stmt);
84 self
85 }
86
87 /// Insert after a statement matching the reference
88 pub fn after(mut self, reference_stmt: PureStmt) -> Self {
89 self.position = InsertPosition::AfterPattern;
90 self.reference_stmt = Some(reference_stmt);
91 self
92 }
93}
94
95impl Mutation for InsertStatementMutation {
96 fn describe(&self) -> String {
97 format!(
98 "Insert statement in function '{}' at {:?}",
99 self.target_fn, self.position
100 )
101 }
102
103 fn mutation_type(&self) -> &'static str {
104 "InsertStatement"
105 }
106
107 fn box_clone(&self) -> Box<dyn Mutation> {
108 Box::new(self.clone())
109 }
110}