1use std::collections::HashMap;
3
4#[derive(Debug, Clone)]
5pub struct EducationalAdvice {
6 pub why_bad: String,
7 pub how_to_fix: String,
8 pub best_practice_tip: Option<String>,
9}
10
11pub struct EducationalAdvisor {
12 advice_db: HashMap<String, EducationalAdvice>,
13 lang: String,
14}
15
16impl EducationalAdvisor {
17 pub fn new(lang: &str) -> Self {
18 let mut advisor = Self {
19 advice_db: HashMap::new(),
20 lang: lang.to_string(),
21 };
22 advisor.initialize_advice_database();
23 advisor
24 }
25
26 pub fn get_advice(&self, rule_name: &str) -> Option<&EducationalAdvice> {
27 self.advice_db.get(rule_name)
28 }
29
30 fn initialize_advice_database(&mut self) {
31 self.add_advice("terrible-naming", self.create_terrible_naming_advice());
33 self.add_advice(
34 "meaningless-naming",
35 self.create_meaningless_naming_advice(),
36 );
37 self.add_advice(
38 "hungarian-notation",
39 self.create_hungarian_notation_advice(),
40 );
41 self.add_advice(
42 "abbreviation-abuse",
43 self.create_abbreviation_abuse_advice(),
44 );
45
46 self.add_advice("deep-nesting", self.create_deep_nesting_advice());
48 self.add_advice("god-function", self.create_god_function_advice());
49 self.add_advice("long-function", self.create_long_function_advice());
50
51 self.add_advice("magic-number", self.create_magic_number_advice());
53 self.add_advice("commented-code", self.create_commented_code_advice());
54 self.add_advice("dead-code", self.create_dead_code_advice());
55
56 self.add_advice("unwrap-abuse", self.create_unwrap_abuse_advice());
58 self.add_advice("string-abuse", self.create_string_abuse_advice());
59 self.add_advice("unnecessary-clone", self.create_unnecessary_clone_advice());
60 self.add_advice("iterator-abuse", self.create_iterator_abuse_advice());
61
62 self.add_advice("println-debugging", self.create_println_debugging_advice());
64 self.add_advice("panic-abuse", self.create_panic_abuse_advice());
65 self.add_advice("todo-comment", self.create_todo_comment_advice());
66
67 self.add_advice("file-too-long", self.create_file_too_long_advice());
69 self.add_advice("unordered-imports", self.create_unordered_imports_advice());
70 self.add_advice(
71 "deep-module-nesting",
72 self.create_deep_module_nesting_advice(),
73 );
74 }
75
76 fn add_advice(&mut self, rule_name: &str, advice: EducationalAdvice) {
77 self.advice_db.insert(rule_name.to_string(), advice);
78 }
79
80 fn create_terrible_naming_advice(&self) -> EducationalAdvice {
81 if self.lang == "zh-CN" {
82 EducationalAdvice {
83 why_bad: "糟糕的变量命名会严重影响代码可读性,让其他开发者(包括未来的你)难以理解代码意图。".to_string(),
84 how_to_fix: "使用描述性的、有意义的变量名,清楚地表达变量的用途和含义。".to_string(),
85 best_practice_tip: Some("变量名应该是自文档化的,读代码的人应该能从名字就理解变量的用途。".to_string()),
86 }
87 } else {
88 EducationalAdvice {
89 why_bad: "Poor variable naming severely impacts code readability, making it difficult for other developers (including future you) to understand the code's intent.".to_string(),
90 how_to_fix: "Use descriptive, meaningful variable names that clearly express the variable's purpose and meaning.".to_string(),
91 best_practice_tip: Some("Variable names should be self-documenting - readers should understand the purpose from the name alone.".to_string()),
92 }
93 }
94 }
95
96 fn create_meaningless_naming_advice(&self) -> EducationalAdvice {
97 if self.lang == "zh-CN" {
98 EducationalAdvice {
99 why_bad: "使用 foo、bar、data、temp 等占位符命名会让代码失去表达力,增加维护成本。"
100 .to_string(),
101 how_to_fix: "根据变量的实际用途选择具体的、有意义的名称。".to_string(),
102 best_practice_tip: Some(
103 "避免使用通用词汇,选择能准确描述数据性质的词汇。".to_string(),
104 ),
105 }
106 } else {
107 EducationalAdvice {
108 why_bad: "Using placeholder names like foo, bar, data, temp makes code lose expressiveness and increases maintenance cost.".to_string(),
109 how_to_fix: "Choose specific, meaningful names based on the variable's actual purpose.".to_string(),
110 best_practice_tip: Some("Avoid generic words, choose words that accurately describe the nature of the data.".to_string()),
111 }
112 }
113 }
114
115 fn create_hungarian_notation_advice(&self) -> EducationalAdvice {
116 if self.lang == "zh-CN" {
117 EducationalAdvice {
118 why_bad:
119 "匈牙利命名法在现代编程语言中已经过时,Rust 的类型系统已经提供了类型安全保障。"
120 .to_string(),
121 how_to_fix: "使用描述性名称而不是类型前缀,让 Rust 的类型系统处理类型检查。"
122 .to_string(),
123 best_practice_tip: Some(
124 "Rust 的强类型系统使得类型前缀变得多余,专注于语义而非类型。".to_string(),
125 ),
126 }
127 } else {
128 EducationalAdvice {
129 why_bad: "Hungarian notation is outdated in modern programming languages, Rust's type system already provides type safety guarantees.".to_string(),
130 how_to_fix: "Use descriptive names instead of type prefixes, let Rust's type system handle type checking.".to_string(),
131 best_practice_tip: Some("Rust's strong type system makes type prefixes redundant, focus on semantics rather than types.".to_string()),
132 }
133 }
134 }
135
136 fn create_abbreviation_abuse_advice(&self) -> EducationalAdvice {
137 if self.lang == "zh-CN" {
138 EducationalAdvice {
139 why_bad: "过度缩写会让代码变得难以理解,特别是对新团队成员或几个月后的自己。"
140 .to_string(),
141 how_to_fix: "使用完整的、清晰的单词,现代编辑器的自动补全让长名称不再是问题。"
142 .to_string(),
143 best_practice_tip: Some(
144 "清晰胜过简洁,代码被阅读的次数远超过被编写的次数。".to_string(),
145 ),
146 }
147 } else {
148 EducationalAdvice {
149 why_bad: "Excessive abbreviations make code hard to understand, especially for new team members or yourself months later.".to_string(),
150 how_to_fix: "Use complete, clear words. Modern editors' auto-completion makes long names no longer a problem.".to_string(),
151 best_practice_tip: Some("Clarity over brevity - code is read far more often than it's written.".to_string()),
152 }
153 }
154 }
155
156 fn create_deep_nesting_advice(&self) -> EducationalAdvice {
157 if self.lang == "zh-CN" {
158 EducationalAdvice {
159 why_bad: "深层嵌套增加了代码的认知复杂度,使得逻辑难以跟踪和调试。".to_string(),
160 how_to_fix: "使用早期返回、提取函数、或者 Rust 的 ? 操作符来减少嵌套层级。"
161 .to_string(),
162 best_practice_tip: Some(
163 "保持嵌套层级在 3 层以内,使用卫语句和早期返回。".to_string(),
164 ),
165 }
166 } else {
167 EducationalAdvice {
168 why_bad: "Deep nesting increases cognitive complexity, making logic hard to follow and debug.".to_string(),
169 how_to_fix: "Use early returns, extract functions, or Rust's ? operator to reduce nesting levels.".to_string(),
170 best_practice_tip: Some("Keep nesting levels within 3, use guard clauses and early returns.".to_string()),
171 }
172 }
173 }
174
175 fn create_unwrap_abuse_advice(&self) -> EducationalAdvice {
176 if self.lang == "zh-CN" {
177 EducationalAdvice {
178 why_bad:
179 "过度使用 unwrap() 会导致程序在遇到错误时直接崩溃,无法优雅地处理异常情况。"
180 .to_string(),
181 how_to_fix: "使用 match、if let、或者 ? 操作符来正确处理 Option 和 Result 类型。"
182 .to_string(),
183 best_practice_tip: Some(
184 "只在你确定不会失败的情况下使用 unwrap(),并添加注释说明原因。".to_string(),
185 ),
186 }
187 } else {
188 EducationalAdvice {
189 why_bad: "Excessive use of unwrap() causes programs to crash directly when encountering errors, unable to handle exceptions gracefully.".to_string(),
190 how_to_fix: "Use match, if let, or the ? operator to properly handle Option and Result types.".to_string(),
191 best_practice_tip: Some("Only use unwrap() when you're certain it won't fail, and add comments explaining why.".to_string()),
192 }
193 }
194 }
195
196 fn create_string_abuse_advice(&self) -> EducationalAdvice {
197 if self.lang == "zh-CN" {
198 EducationalAdvice {
199 why_bad:
200 "不必要的 String 分配会增加内存使用和性能开销,特别是在只需要读取的场景中。"
201 .to_string(),
202 how_to_fix: "在只需要读取字符串的地方使用 &str,只在需要拥有所有权时使用 String。"
203 .to_string(),
204 best_practice_tip: Some(
205 "优先使用 &str 作为函数参数,这样可以接受 String 和 &str 两种类型。"
206 .to_string(),
207 ),
208 }
209 } else {
210 EducationalAdvice {
211 why_bad: "Unnecessary String allocations increase memory usage and performance overhead, especially in read-only scenarios.".to_string(),
212 how_to_fix: "Use &str where you only need to read strings, use String only when you need ownership.".to_string(),
213 best_practice_tip: Some("Prefer &str as function parameters, this way you can accept both String and &str types.".to_string()),
214 }
215 }
216 }
217
218 fn create_println_debugging_advice(&self) -> EducationalAdvice {
219 if self.lang == "zh-CN" {
220 EducationalAdvice {
221 why_bad: "遗留的 println! 调试语句会污染输出,在生产环境中可能泄露敏感信息。"
222 .to_string(),
223 how_to_fix: "使用 log 库进行日志记录,或者使用 dbg! 宏进行临时调试(记得删除)。"
224 .to_string(),
225 best_practice_tip: Some(
226 "使用条件编译 #[cfg(debug_assertions)] 来确保调试代码不会进入生产环境。"
227 .to_string(),
228 ),
229 }
230 } else {
231 EducationalAdvice {
232 why_bad: "Leftover println! debug statements pollute output and may leak sensitive information in production.".to_string(),
233 how_to_fix: "Use the log crate for logging, or use the dbg! macro for temporary debugging (remember to remove).".to_string(),
234 best_practice_tip: Some("Use conditional compilation #[cfg(debug_assertions)] to ensure debug code doesn't reach production.".to_string()),
235 }
236 }
237 }
238
239 fn create_file_too_long_advice(&self) -> EducationalAdvice {
240 if self.lang == "zh-CN" {
241 EducationalAdvice {
242 why_bad: "过长的文件难以导航和维护,违反了单一职责原则,增加了代码复杂度。"
243 .to_string(),
244 how_to_fix: "将大文件拆分成多个小模块,每个模块负责特定的功能领域。".to_string(),
245 best_practice_tip: Some(
246 "保持文件在 500-1000 行以内,超出时考虑按功能拆分。".to_string(),
247 ),
248 }
249 } else {
250 EducationalAdvice {
251 why_bad: "Overly long files are hard to navigate and maintain, violate the single responsibility principle, and increase code complexity.".to_string(),
252 how_to_fix: "Split large files into multiple small modules, each responsible for specific functional areas.".to_string(),
253 best_practice_tip: Some("Keep files within 500-1000 lines, consider splitting by functionality when exceeded.".to_string()),
254 }
255 }
256 }
257
258 fn create_god_function_advice(&self) -> EducationalAdvice {
260 if self.lang == "zh-CN" {
261 EducationalAdvice {
262 why_bad: "做太多事情的函数违反了单一职责原则,难以测试和维护。".to_string(),
263 how_to_fix: "将大函数拆分成更小的、专注的函数,每个函数只做一件事。".to_string(),
264 best_practice_tip: Some("保持函数在 20-30 行以内,专注于单一任务。".to_string()),
265 }
266 } else {
267 EducationalAdvice {
268 why_bad: "Functions that do too much violate the single responsibility principle and are hard to test and maintain.".to_string(),
269 how_to_fix: "Break down large functions into smaller, focused functions that each do one thing well.".to_string(),
270 best_practice_tip: Some("Keep functions under 20-30 lines and focused on a single task.".to_string()),
271 }
272 }
273 }
274
275 fn create_long_function_advice(&self) -> EducationalAdvice {
276 if self.lang == "zh-CN" {
277 EducationalAdvice {
278 why_bad: "长函数更难理解、测试和维护。".to_string(),
279 how_to_fix: "将逻辑块提取到具有描述性名称的独立函数中。".to_string(),
280 best_practice_tip: Some(
281 "如果你无法在屏幕上看到整个函数,那它可能太长了。".to_string(),
282 ),
283 }
284 } else {
285 EducationalAdvice {
286 why_bad: "Long functions are harder to understand, test, and maintain.".to_string(),
287 how_to_fix:
288 "Extract logical blocks into separate functions with descriptive names."
289 .to_string(),
290 best_practice_tip: Some(
291 "If you can't see the entire function on your screen, it's probably too long."
292 .to_string(),
293 ),
294 }
295 }
296 }
297
298 fn create_magic_number_advice(&self) -> EducationalAdvice {
299 if self.lang == "zh-CN" {
300 EducationalAdvice {
301 why_bad: "魔法数字让代码难以理解和维护。".to_string(),
302 how_to_fix: "用能解释其用途的命名常量替换魔法数字。".to_string(),
303 best_practice_tip: Some("对具有语义含义的值使用 const 声明。".to_string()),
304 }
305 } else {
306 EducationalAdvice {
307 why_bad: "Magic numbers make code hard to understand and maintain.".to_string(),
308 how_to_fix:
309 "Replace magic numbers with named constants that explain their purpose."
310 .to_string(),
311 best_practice_tip: Some(
312 "Use const declarations for values that have semantic meaning.".to_string(),
313 ),
314 }
315 }
316 }
317
318 fn create_commented_code_advice(&self) -> EducationalAdvice {
319 if self.lang == "zh-CN" {
320 EducationalAdvice {
321 why_bad: "注释掉的代码会污染代码库,让人困惑哪些是真正在使用的代码。".to_string(),
322 how_to_fix: "删除注释掉的代码 - 版本控制系统会保留历史记录。".to_string(),
323 best_practice_tip: Some(
324 "相信你的版本控制系统 - 删除死代码而不是注释掉它。".to_string(),
325 ),
326 }
327 } else {
328 EducationalAdvice {
329 why_bad: "Commented-out code clutters the codebase and creates confusion about what's actually used.".to_string(),
330 how_to_fix: "Remove commented code - version control systems preserve history.".to_string(),
331 best_practice_tip: Some("Trust your version control system - delete dead code instead of commenting it out.".to_string()),
332 }
333 }
334 }
335
336 fn create_dead_code_advice(&self) -> EducationalAdvice {
337 if self.lang == "zh-CN" {
338 EducationalAdvice {
339 why_bad: "死代码增加了维护负担,会让开发者困惑。".to_string(),
340 how_to_fix: "定期删除未使用的函数、变量和导入。".to_string(),
341 best_practice_tip: Some("使用 cargo clippy 自动检测死代码。".to_string()),
342 }
343 } else {
344 EducationalAdvice {
345 why_bad: "Dead code increases maintenance burden and can confuse developers."
346 .to_string(),
347 how_to_fix: "Remove unused functions, variables, and imports regularly."
348 .to_string(),
349 best_practice_tip: Some(
350 "Use cargo clippy to detect dead code automatically.".to_string(),
351 ),
352 }
353 }
354 }
355
356 fn create_unnecessary_clone_advice(&self) -> EducationalAdvice {
357 if self.lang == "zh-CN" {
358 EducationalAdvice {
359 why_bad: "不必要的 clone 会浪费内存和 CPU 周期。".to_string(),
360 how_to_fix: "尽可能使用引用,只在需要所有权时才 clone。".to_string(),
361 best_practice_tip: Some("理解 Rust 的借用规则以减少不必要的分配。".to_string()),
362 }
363 } else {
364 EducationalAdvice {
365 why_bad: "Unnecessary clones waste memory and CPU cycles.".to_string(),
366 how_to_fix: "Use references when possible, clone only when you need ownership."
367 .to_string(),
368 best_practice_tip: Some(
369 "Understand Rust's borrowing rules to minimize unnecessary allocations."
370 .to_string(),
371 ),
372 }
373 }
374 }
375
376 fn create_iterator_abuse_advice(&self) -> EducationalAdvice {
377 if self.lang == "zh-CN" {
378 EducationalAdvice {
379 why_bad: "手动循环通常比迭代器链更低效且表达力差。".to_string(),
380 how_to_fix: "在适当的情况下使用 map、filter、fold 等迭代器方法代替手动循环。"
381 .to_string(),
382 best_practice_tip: Some(
383 "迭代器链由于惰性求值和编译器优化,通常更高效。".to_string(),
384 ),
385 }
386 } else {
387 EducationalAdvice {
388 why_bad: "Manual loops are often less efficient and expressive than iterator chains.".to_string(),
389 how_to_fix: "Use iterator methods like map, filter, fold instead of manual loops when appropriate.".to_string(),
390 best_practice_tip: Some("Iterator chains are often more efficient due to lazy evaluation and compiler optimizations.".to_string()),
391 }
392 }
393 }
394
395 fn create_panic_abuse_advice(&self) -> EducationalAdvice {
396 if self.lang == "zh-CN" {
397 EducationalAdvice {
398 why_bad: "过度使用 panic 会让程序在生产环境中不可靠且难以调试。".to_string(),
399 how_to_fix: "对可恢复的错误使用 Result 类型,仅在真正无法恢复的情况下使用 panic。"
400 .to_string(),
401 best_practice_tip: Some(
402 "Panic 应该用于编程错误,而不是预期的错误条件。".to_string(),
403 ),
404 }
405 } else {
406 EducationalAdvice {
407 why_bad: "Excessive panics make programs unreliable and hard to debug in production.".to_string(),
408 how_to_fix: "Use Result types for recoverable errors, reserve panics for truly unrecoverable situations.".to_string(),
409 best_practice_tip: Some("Panics should be used for programming errors, not for expected error conditions.".to_string()),
410 }
411 }
412 }
413
414 fn create_todo_comment_advice(&self) -> EducationalAdvice {
415 if self.lang == "zh-CN" {
416 EducationalAdvice {
417 why_bad: "过多的 TODO 注释表示代码不完整或规划不当。".to_string(),
418 how_to_fix: "要么实现这些 TODO,要么为未来的工作创建适当的问题跟踪。".to_string(),
419 best_practice_tip: Some(
420 "谨慎使用 TODO,并始终附带具体的解决方案计划。".to_string(),
421 ),
422 }
423 } else {
424 EducationalAdvice {
425 why_bad: "Too many TODO comments indicate incomplete or poorly planned code."
426 .to_string(),
427 how_to_fix:
428 "Either implement the TODOs or create proper issue tracking for future work."
429 .to_string(),
430 best_practice_tip: Some(
431 "Use TODO sparingly and always with a specific plan for resolution."
432 .to_string(),
433 ),
434 }
435 }
436 }
437
438 fn create_unordered_imports_advice(&self) -> EducationalAdvice {
439 EducationalAdvice {
440 why_bad: "Unordered imports make it hard to find and manage dependencies.".to_string(),
441 how_to_fix: "Use rustfmt to automatically sort imports, or sort them manually by: std, external crates, local modules.".to_string(),
442 best_practice_tip: Some("Configure your editor to run rustfmt on save to maintain consistent formatting.".to_string()),
443 }
444 }
445
446 fn create_deep_module_nesting_advice(&self) -> EducationalAdvice {
447 EducationalAdvice {
448 why_bad: "Deep module nesting makes code navigation difficult and indicates poor architecture.".to_string(),
449 how_to_fix: "Flatten module structure, use re-exports to maintain clean public APIs.".to_string(),
450 best_practice_tip: Some("Keep module nesting to 2-3 levels maximum, use re-exports for convenience.".to_string()),
451 }
452 }
453}