1use std::path::Path;
9
10use semantic::classify_modification;
11
12fn main() {
13 let pairs: Vec<(&str, &str, &str, &str)> = vec![
14 (
16 "main.rs",
17 concat!(
18 "use std::collections::HashMap;\n",
19 "use std::io;\n\n",
20 "// Main entry point\n",
21 "fn main() {\n",
22 " let config = load_config();\n",
23 " let result = process(&config);\n",
24 " println!(\"Result: {}\", result);\n",
25 "}\n\n",
26 "fn load_config() -> HashMap<String, String> {\n",
27 " let mut map = HashMap::new();\n",
28 " map.insert(\"key\".to_string(), \"value\".to_string());\n",
29 " map\n",
30 "}\n\n",
31 "fn process(config: &HashMap<String, String>) -> String {\n",
32 " let key = config.get(\"key\").unwrap_or(&String::new());\n",
33 " format!(\"Processed: {}\", key)\n",
34 "}\n",
35 ),
36 concat!(
37 "use std::collections::HashMap;\n",
38 "use std::io;\n",
39 "use std::thread;\n",
40 "use std::time::Duration;\n\n",
41 "// Main entry point — now with retry support\n",
42 "fn main() {\n",
43 " let config = load_config();\n",
44 " let result = process_with_retry(&config, 3);\n",
45 " println!(\"Result: {}\", result);\n",
46 "}\n\n",
47 "fn load_config() -> HashMap<String, String> {\n",
48 " let mut map = HashMap::new();\n",
49 " map.insert(\"key\".to_string(), \"value\".to_string());\n",
50 " map\n",
51 "}\n\n",
52 "fn process_with_retry(config: &HashMap<String, String>, max_retries: u32) -> String {\n",
53 " let mut attempts = 0;\n",
54 " loop {\n",
55 " match try_process(config) {\n",
56 " Ok(result) => return result,\n",
57 " Err(e) if attempts < max_retries => {\n",
58 " attempts += 1;\n",
59 " eprintln!(\"Retry {}/{}: {}\", attempts, max_retries, e);\n",
60 " thread::sleep(Duration::from_millis(100 * attempts as u64));\n",
61 " }\n",
62 " Err(e) => return format!(\"Failed after {} retries: {}\", max_retries, e),\n",
63 " }\n",
64 " }\n",
65 "}\n\n",
66 "fn try_process(config: &HashMap<String, String>) -> Result<String, String> {\n",
67 " let key = config.get(\"key\").ok_or(\"missing key\")?;\n",
68 " Ok(format!(\"Processed: {}\", key))\n",
69 "}\n",
70 ),
71 "Logic: renamed fn + retry logic + new imports",
72 ),
73 (
75 "utils.rs",
76 "fn helper_one() {\nlet x = 1;\nlet y = 2;\nx + y\n}\n\nfn helper_two(a: i32, b: i32) -> i32 {\na * b + 1\n}\n\nfn helper_three() -> String {\n\"hello world\".to_string()\n}\n",
77 "fn helper_one() {\n let x = 1;\n let y = 2;\n x + y\n}\n\nfn helper_two(a: i32, b: i32) -> i32 {\n a * b + 1\n}\n\nfn helper_three() -> String {\n \"hello world\".to_string()\n}\n",
78 "Noise: formatting only (indentation)",
79 ),
80 (
82 "config.rs",
83 "// Configuration module\n// Handles loading and parsing config files\nuse std::path::Path;\n\nfn read_config(path: &Path) -> String {\n std::fs::read_to_string(path).unwrap_or_default()\n}\n",
84 "// Configuration module — refactored for clarity\n// Handles loading, parsing, and validating config files\n// See DESIGN.md for the full config spec\nuse std::path::Path;\n\nfn read_config(path: &Path) -> String {\n std::fs::read_to_string(path).unwrap_or_default()\n}\n",
85 "Low: comments only",
86 ),
87 (
89 "imports.rs",
90 "use std::io;\n\nfn do_work() -> i32 {\n 42\n}\n",
91 "use std::io;\nuse std::fs;\nuse std::path::PathBuf;\n\nfn do_work() -> i32 {\n 42\n}\n",
92 "Low: imports only",
93 ),
94 (
96 "script.py",
97 "def calculate(x,y):\n return x+y\n\ndef transform(data):\n result=[]\n for item in data:\n result.append(item*2)\n return result\n",
98 "def calculate(x, y):\n return x + y\n\ndef transform(data):\n result = []\n for item in data:\n result.append(item * 2)\n return result\n",
99 "Noise: Python formatting (spaces around ops)",
100 ),
101 (
103 "handler.ts",
104 concat!(
105 "function handleRequest(req: Request): Response {\n",
106 " const body = parseBody(req);\n",
107 " return new Response(JSON.stringify(body));\n",
108 "}\n\n",
109 "function parseBody(req: Request): any {\n",
110 " return JSON.parse(req.body as string);\n",
111 "}\n\n",
112 "function legacyHandler(data: string): string {\n",
113 " return data.toUpperCase();\n",
114 "}\n",
115 ),
116 concat!(
117 "function handleRequest(req: Request): Response {\n",
118 " const body = parseBody(req);\n",
119 " const validated = validateBody(body);\n",
120 " return new Response(JSON.stringify(validated));\n",
121 "}\n\n",
122 "function parseBody(req: Request): any {\n",
123 " return JSON.parse(req.body as string);\n",
124 "}\n\n",
125 "function validateBody(body: any): any {\n",
126 " if (!body || typeof body !== 'object') {\n",
127 " throw new Error('Invalid body');\n",
128 " }\n",
129 " return body;\n",
130 "}\n",
131 ),
132 "Logic: fn deleted + new fn + logic change",
133 ),
134 (
136 "server.go",
137 "package main\n\nimport \"fmt\"\n\nfunc handleHealth() string {\n\treturn \"ok\"\n}\n\nfunc handleMetrics() string {\n\treturn fmt.Sprintf(\"uptime=%d\", 42)\n}\n",
138 "package main\n\nimport \"fmt\"\n\nfunc handleHealth() string {\n\treturn \"healthy\"\n}\n\nfunc handleMetrics() string {\n\treturn fmt.Sprintf(\"uptime=%d,errors=%d\", 42, 0)\n}\n",
139 "Logic: Go return value changes",
140 ),
141 (
143 "App.java",
144 "class App {\npublic static void main(String[] args) {\nSystem.out.println(\"hello\");\n}\n}\n",
145 "class App {\n public static void main(String[] args) {\n System.out.println(\"hello\");\n }\n}\n",
146 "Noise: Java formatting (brace indentation)",
147 ),
148 (
150 "config.toml",
151 "[database]\nhost = \"localhost\"\nport = 5432\n",
152 "[database]\nhost = \"db.prod.internal\"\nport = 5432\ntimeout = 30\n",
153 "Logic: TOML config value change (token fallback)",
154 ),
155 ];
156
157 println!();
158 println!(" Heddle Semantic Diff — Classification Demo");
159 println!(" =========================================");
160 println!();
161 println!(
162 " {:<14} {:<18} {:<10} Expected",
163 "File", "Classification", "Importance"
164 );
165 println!(" {}", "─".repeat(78));
166
167 let mut noise_count = 0;
168 let mut low_count = 0;
169 let mut logic_count = 0;
170
171 for (name, old, new, expected) in &pairs {
172 let (kind, importance) = classify_modification(Path::new(name), old, new);
173 let imp_str = format!("{:?}", importance);
174 println!(
175 " {:<14} {:<18} {:<10} {}",
176 name,
177 format!("{:?}", kind),
178 imp_str,
179 expected
180 );
181 match importance {
182 objects::object::ChangeImportance::Noise => noise_count += 1,
183 objects::object::ChangeImportance::Low => low_count += 1,
184 _ => logic_count += 1,
185 }
186 }
187
188 println!(" {}", "─".repeat(78));
189 println!();
190 println!(
191 " {} files changed → {} things worth reviewing",
192 pairs.len(),
193 logic_count
194 );
195 println!(
196 " Filtered: {} noise (formatting) + {} low (imports/comments)",
197 noise_count, low_count
198 );
199 println!();
200}