garbage_code_hunter/rules/
advanced_rust.rs

1use std::path::Path;
2use syn::{File, visit::Visit, ExprClosure, ItemTrait, ItemImpl, GenericParam, Lifetime};
3
4use crate::analyzer::{CodeIssue, Severity, RoastLevel};
5use crate::rules::Rule;
6
7pub struct ComplexClosureRule;
8
9impl Rule for ComplexClosureRule {
10    fn name(&self) -> &'static str {
11        "complex-closure"
12    }
13
14    fn check(&self, file_path: &Path, syntax_tree: &File, _content: &str) -> Vec<CodeIssue> {
15        let mut visitor = ClosureVisitor::new(file_path.to_path_buf());
16        visitor.visit_file(syntax_tree);
17        visitor.issues
18    }
19}
20
21pub struct LifetimeAbuseRule;
22
23impl Rule for LifetimeAbuseRule {
24    fn name(&self) -> &'static str {
25        "lifetime-abuse"
26    }
27
28    fn check(&self, file_path: &Path, syntax_tree: &File, _content: &str) -> Vec<CodeIssue> {
29        let mut visitor = LifetimeVisitor::new(file_path.to_path_buf());
30        visitor.visit_file(syntax_tree);
31        visitor.issues
32    }
33}
34
35pub struct TraitComplexityRule;
36
37impl Rule for TraitComplexityRule {
38    fn name(&self) -> &'static str {
39        "trait-complexity"
40    }
41
42    fn check(&self, file_path: &Path, syntax_tree: &File, _content: &str) -> Vec<CodeIssue> {
43        let mut visitor = TraitVisitor::new(file_path.to_path_buf());
44        visitor.visit_file(syntax_tree);
45        visitor.issues
46    }
47}
48
49pub struct GenericAbuseRule;
50
51impl Rule for GenericAbuseRule {
52    fn name(&self) -> &'static str {
53        "generic-abuse"
54    }
55
56    fn check(&self, file_path: &Path, syntax_tree: &File, _content: &str) -> Vec<CodeIssue> {
57        let mut visitor = GenericVisitor::new(file_path.to_path_buf());
58        visitor.visit_file(syntax_tree);
59        visitor.issues
60    }
61}
62
63struct ClosureVisitor {
64    file_path: std::path::PathBuf,
65    issues: Vec<CodeIssue>,
66    closure_depth: usize,
67}
68
69impl ClosureVisitor {
70    fn new(file_path: std::path::PathBuf) -> Self {
71        Self {
72            file_path,
73            issues: Vec::new(),
74            closure_depth: 0,
75        }
76    }
77
78    fn check_closure_complexity(&mut self, closure: &ExprClosure) {
79        // Check for nested closures
80        if self.closure_depth > 2 {
81            let messages = vec![
82                "闭包套闭包?你这是在写俄罗斯套娃还是在考验读者的智商?",
83                "嵌套闭包比我的人际关系还复杂",
84                "这闭包嵌套得像洋葱一样,剥一层哭一次",
85                "闭包嵌套过深,建议拆分成独立函数",
86            ];
87
88            self.issues.push(CodeIssue {
89                file_path: self.file_path.clone(),
90                line: 1, // Simplified handling
91                column: 1,
92                rule_name: "complex-closure".to_string(),
93                message: messages[self.issues.len() % messages.len()].to_string(),
94                severity: Severity::Spicy,
95                roast_level: RoastLevel::Sarcastic,
96            });
97        }
98
99        // Check for complex closure parameters
100        if closure.inputs.len() > 5 {
101            let messages = vec![
102                "这个闭包的参数比我的借口还多",
103                "闭包参数过多,你确定不是在写函数?",
104                "这么多参数的闭包,建议改成正经函数",
105            ];
106
107            self.issues.push(CodeIssue {
108                file_path: self.file_path.clone(),
109                line: 1,
110                column: 1,
111                rule_name: "complex-closure".to_string(),
112                message: messages[self.issues.len() % messages.len()].to_string(),
113                severity: Severity::Mild,
114                roast_level: RoastLevel::Gentle,
115            });
116        }
117    }
118}
119
120impl<'ast> Visit<'ast> for ClosureVisitor {
121    fn visit_expr_closure(&mut self, closure: &'ast ExprClosure) {
122        self.closure_depth += 1;
123        self.check_closure_complexity(closure);
124        syn::visit::visit_expr_closure(self, closure);
125        self.closure_depth -= 1;
126    }
127}
128
129struct LifetimeVisitor {
130    file_path: std::path::PathBuf,
131    issues: Vec<CodeIssue>,
132    lifetime_count: usize,
133}
134
135impl LifetimeVisitor {
136    fn new(file_path: std::path::PathBuf) -> Self {
137        Self {
138            file_path,
139            issues: Vec::new(),
140            lifetime_count: 0,
141        }
142    }
143}
144
145impl<'ast> Visit<'ast> for LifetimeVisitor {
146    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
147        self.lifetime_count += 1;
148        
149        // Check for excessive lifetime usage
150        if self.lifetime_count > 5 {
151            let messages = vec![
152                "生命周期标注比我的生命还复杂",
153                "这么多生命周期,你是在写哲学论文吗?",
154                "生命周期滥用,建议重新设计数据结构",
155                "生命周期多到让人怀疑人生",
156            ];
157
158            self.issues.push(CodeIssue {
159                file_path: self.file_path.clone(),
160                line: 1,
161                column: 1,
162                rule_name: "lifetime-abuse".to_string(),
163                message: messages[self.issues.len() % messages.len()].to_string(),
164                severity: Severity::Spicy,
165                roast_level: RoastLevel::Sarcastic,
166            });
167        }
168
169        syn::visit::visit_lifetime(self, lifetime);
170    }
171}
172
173struct TraitVisitor {
174    file_path: std::path::PathBuf,
175    issues: Vec<CodeIssue>,
176}
177
178impl TraitVisitor {
179    fn new(file_path: std::path::PathBuf) -> Self {
180        Self {
181            file_path,
182            issues: Vec::new(),
183        }
184    }
185
186    fn check_trait_complexity(&mut self, trait_item: &ItemTrait) {
187        // Check for traits with too many methods
188        if trait_item.items.len() > 10 {
189            let messages = vec![
190                "这个 trait 的方法比我的借口还多",
191                "trait 方法过多,违反了单一职责原则",
192                "这个 trait 比瑞士军刀还要全能",
193                "trait 臃肿,建议拆分成多个小 trait",
194            ];
195
196            self.issues.push(CodeIssue {
197                file_path: self.file_path.clone(),
198                line: 1,
199                column: 1,
200                rule_name: "trait-complexity".to_string(),
201                message: messages[self.issues.len() % messages.len()].to_string(),
202                severity: Severity::Spicy,
203                roast_level: RoastLevel::Sarcastic,
204            });
205        }
206
207        // Check for traits with too many generic parameters
208        if trait_item.generics.params.len() > 3 {
209            let messages = vec![
210                "泛型参数比我的密码还复杂",
211                "这么多泛型,你是在写数学公式吗?",
212                "泛型滥用,建议简化设计",
213            ];
214
215            self.issues.push(CodeIssue {
216                file_path: self.file_path.clone(),
217                line: 1,
218                column: 1,
219                rule_name: "trait-complexity".to_string(),
220                message: messages[self.issues.len() % messages.len()].to_string(),
221                severity: Severity::Mild,
222                roast_level: RoastLevel::Gentle,
223            });
224        }
225    }
226}
227
228impl<'ast> Visit<'ast> for TraitVisitor {
229    fn visit_item_trait(&mut self, trait_item: &'ast ItemTrait) {
230        self.check_trait_complexity(trait_item);
231        syn::visit::visit_item_trait(self, trait_item);
232    }
233}
234
235struct GenericVisitor {
236    file_path: std::path::PathBuf,
237    issues: Vec<CodeIssue>,
238}
239
240impl GenericVisitor {
241    fn new(file_path: std::path::PathBuf) -> Self {
242        Self {
243            file_path,
244            issues: Vec::new(),
245        }
246    }
247
248    fn check_generic_abuse(&mut self, generics: &syn::Generics) {
249        if generics.params.len() > 5 {
250            let messages = vec![
251                "泛型参数比我的购物清单还长",
252                "这么多泛型,编译器都要哭了",
253                "泛型滥用,建议重新设计架构",
254                "泛型多到让人怀疑这还是 Rust 吗",
255            ];
256
257            self.issues.push(CodeIssue {
258                file_path: self.file_path.clone(),
259                line: 1,
260                column: 1,
261                rule_name: "generic-abuse".to_string(),
262                message: messages[self.issues.len() % messages.len()].to_string(),
263                severity: Severity::Spicy,
264                roast_level: RoastLevel::Sarcastic,
265            });
266        }
267
268        // Check for single-letter generic names (except T, U, V)
269        for param in &generics.params {
270            if let GenericParam::Type(type_param) = param {
271                let name = type_param.ident.to_string();
272                if name.len() == 1 && !matches!(name.as_str(), "T" | "U" | "V" | "E" | "K") {
273                    let messages = vec![
274                        format!("泛型参数 '{}' 的命名创意约等于零", name),
275                        format!("泛型 '{}' 的名字比我的耐心还短", name),
276                        format!("用 '{}' 做泛型名?建议用更有意义的名字", name),
277                    ];
278
279                    self.issues.push(CodeIssue {
280                        file_path: self.file_path.clone(),
281                        line: 1,
282                        column: 1,
283                        rule_name: "generic-abuse".to_string(),
284                        message: messages[self.issues.len() % messages.len()].clone(),
285                        severity: Severity::Mild,
286                        roast_level: RoastLevel::Gentle,
287                    });
288                }
289            }
290        }
291    }
292}
293
294impl<'ast> Visit<'ast> for GenericVisitor {
295    fn visit_item_fn(&mut self, func: &'ast syn::ItemFn) {
296        self.check_generic_abuse(&func.sig.generics);
297        syn::visit::visit_item_fn(self, func);
298    }
299
300    fn visit_item_struct(&mut self, struct_item: &'ast syn::ItemStruct) {
301        self.check_generic_abuse(&struct_item.generics);
302        syn::visit::visit_item_struct(self, struct_item);
303    }
304
305    fn visit_item_enum(&mut self, enum_item: &'ast syn::ItemEnum) {
306        self.check_generic_abuse(&enum_item.generics);
307        syn::visit::visit_item_enum(self, enum_item);
308    }
309
310    fn visit_item_impl(&mut self, impl_item: &'ast ItemImpl) {
311        self.check_generic_abuse(&impl_item.generics);
312        syn::visit::visit_item_impl(self, impl_item);
313    }
314}