garbage_code_hunter/rules/
advanced_rust.rs

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