agentic_evolve_core/crystallization/
variable_detector.rs1use crate::types::pattern::{Language, PatternVariable};
4
5#[derive(Debug, Default)]
7pub struct VariableDetector;
8
9impl VariableDetector {
10 pub fn new() -> Self {
11 Self
12 }
13
14 pub fn detect(&self, code: &str, language: &Language) -> Vec<PatternVariable> {
15 let mut variables = Vec::new();
16
17 let string_re = regex::Regex::new(r#""([^"]{3,})""#).unwrap();
19 for (i, cap) in string_re.captures_iter(code).enumerate() {
20 variables.push(PatternVariable {
21 name: format!("STRING_{}", i),
22 var_type: "string".to_string(),
23 pattern: None,
24 default: Some(cap[1].to_string()),
25 });
26 }
27
28 let num_re = regex::Regex::new(r"\b(\d{2,})\b").unwrap();
30 for (i, cap) in num_re.captures_iter(code).enumerate() {
31 variables.push(PatternVariable {
32 name: format!("NUMBER_{}", i),
33 var_type: "number".to_string(),
34 pattern: Some(r"\d+".to_string()),
35 default: Some(cap[1].to_string()),
36 });
37 }
38
39 match language {
41 Language::Rust => {
42 let type_re = regex::Regex::new(r"\b([A-Z][a-zA-Z0-9]+)\b").unwrap();
43 let mut seen = std::collections::HashSet::new();
44 for cap in type_re.captures_iter(code) {
45 let name = &cap[1];
46 if !is_common_type(name) && seen.insert(name.to_string()) {
47 variables.push(PatternVariable {
48 name: format!("TYPE_{name}"),
49 var_type: "type".to_string(),
50 pattern: Some(r"[A-Z]\w+".to_string()),
51 default: Some(name.to_string()),
52 });
53 }
54 }
55 }
56 Language::Python => {
57 let type_re = regex::Regex::new(r"\b([A-Z][a-zA-Z0-9]+)\b").unwrap();
58 let mut seen = std::collections::HashSet::new();
59 for cap in type_re.captures_iter(code) {
60 let name = &cap[1];
61 if !is_common_python_type(name) && seen.insert(name.to_string()) {
62 variables.push(PatternVariable {
63 name: format!("TYPE_{name}"),
64 var_type: "type".to_string(),
65 pattern: Some(r"[A-Z]\w+".to_string()),
66 default: Some(name.to_string()),
67 });
68 }
69 }
70 }
71 _ => {}
72 }
73
74 variables
75 }
76}
77
78fn is_common_type(name: &str) -> bool {
79 matches!(
80 name,
81 "String"
82 | "Vec"
83 | "HashMap"
84 | "HashSet"
85 | "Option"
86 | "Result"
87 | "Box"
88 | "Arc"
89 | "Rc"
90 | "Mutex"
91 | "RwLock"
92 | "Cell"
93 | "RefCell"
94 | "Self"
95 | "Ok"
96 | "Err"
97 | "Some"
98 | "None"
99 | "Default"
100 | "Debug"
101 | "Clone"
102 | "Copy"
103 | "Send"
104 | "Sync"
105 | "Display"
106 | "Error"
107 | "Serialize"
108 | "Deserialize"
109 | "Value"
110 | "Path"
111 | "PathBuf"
112 )
113}
114
115fn is_common_python_type(name: &str) -> bool {
116 matches!(
117 name,
118 "True"
119 | "False"
120 | "None"
121 | "List"
122 | "Dict"
123 | "Set"
124 | "Tuple"
125 | "Optional"
126 | "Union"
127 | "Any"
128 | "Type"
129 | "Callable"
130 | "Iterator"
131 | "Exception"
132 | "ValueError"
133 | "TypeError"
134 | "KeyError"
135 )
136}