#[derive(Debug, Clone, Copy)]
pub enum StyleCategory {
Naming,
Structure,
Duplication,
Comments,
StaticAnalysis,
}
impl StyleCategory {
pub fn emoji(&self) -> &'static str {
match self {
StyleCategory::Naming => "🏷️",
StyleCategory::Structure => "🏗️",
StyleCategory::Duplication => "📋",
StyleCategory::Comments => "💬",
StyleCategory::StaticAnalysis => "🔍",
}
}
pub fn display_name(&self) -> &'static str {
match self {
StyleCategory::Naming => "命名风格",
StyleCategory::Structure => "代码结构",
StyleCategory::Duplication => "重复代码",
StyleCategory::Comments => "注释文档",
StyleCategory::StaticAnalysis => "静态检测",
}
}
}
static mut ROAST_COUNTER: usize = 0;
fn next_index(len: usize) -> usize {
unsafe {
ROAST_COUNTER = (ROAST_COUNTER + 1) % 10000;
ROAST_COUNTER % len
}
}
pub struct RoastGenerator;
impl Default for RoastGenerator {
fn default() -> Self {
Self::new()
}
}
impl RoastGenerator {
pub fn new() -> Self {
Self
}
pub fn naming_roast(&self, bad_name: &str, context: &str) -> String {
let roasts = [
format!(
"{} 嘿兄弟,'{}' 这个名字... 说真的,{}。建议你:{}",
StyleCategory::Naming.emoji(),
bad_name,
context,
self.naming_suggestion(bad_name)
),
format!(
"{} '{}' 是什么鬼?{}。换个名字吧,比如:{}",
StyleCategory::Naming.emoji(),
bad_name,
context,
self.naming_suggestion(bad_name)
),
format!(
"{} 我看到 '{}' 的时候,我的眼睛疼。{}。来,试试:{}",
StyleCategory::Naming.emoji(),
bad_name,
context,
self.naming_suggestion(bad_name)
),
];
roasts[next_index(roasts.len())].clone()
}
pub fn structure_roast(&self, metric: &str, value: usize, context: &str) -> String {
let roasts = [
format!(
"{} {} 达到了 {}?{}。说真的,{}",
StyleCategory::Structure.emoji(),
metric,
value,
context,
self.structure_suggestion(metric)
),
format!(
"{} 兄弟,{}={} 这数字有点离谱啊... {}。我的建议:{}",
StyleCategory::Structure.emoji(),
metric,
value,
context,
self.structure_suggestion(metric)
),
format!(
"{} {}:{} — 这是代码还是迷宫?{}。听我一句劝:{}",
StyleCategory::Structure.emoji(),
metric,
value,
context,
self.structure_suggestion(metric)
),
];
roasts[next_index(roasts.len())].clone()
}
pub fn duplication_roast(&self, dup_type: &str, count: usize, location_hint: &str) -> String {
let roasts = [
format!(
"{} 发现 {} 处{}重复!{}。Ctrl+C Ctrl+V 虽然爽,但维护的时候你会哭的",
StyleCategory::Duplication.emoji(),
count,
dup_type,
location_hint
),
format!(
"{} 又是复制粘贴?{} 已经出现 {} 次了。提取成函数吧,求你了",
StyleCategory::Duplication.emoji(),
dup_type,
count
),
format!(
"{} DRY (Don't Repeat Yourself) 原则听过没?这里 {} 重复了 {} 次。{}",
StyleCategory::Duplication.emoji(),
dup_type,
count,
location_hint
),
];
roasts[next_index(roasts.len())].clone()
}
pub fn comment_roast(&self, issue_type: &str, detail: &str) -> String {
let roasts = [
format!(
"{} {} — {}。代码写得好不好另说,但至少让别人看得懂啊",
StyleCategory::Comments.emoji(),
issue_type,
detail
),
format!(
"{} 未来的你(或者你的同事)看到这段{}会想打人的:{}",
StyleCategory::Comments.emoji(),
issue_type,
detail
),
format!(
"{} 注释不是用来道歉的({})。写清楚为什么,而不是写了什么",
StyleCategory::Comments.emoji(),
detail
),
];
roasts[next_index(roasts.len())].clone()
}
pub fn static_analysis_note(&self, rule_name: &str, detail: &str) -> String {
format!(
"{} [{}] {} — 这个不急,但有空可以看看",
StyleCategory::StaticAnalysis.emoji(),
rule_name,
detail
)
}
fn naming_suggestion(&self, _bad_name: &str) -> &'static str {
let suggestions = [
"用有意义的名词或动词组合",
"想想6个月后的自己还能看懂这个名字吗?",
"遵循项目命名规范(camelCase/snake_case/kebab-case)",
"问自己:这个变量到底代表什么?把答案写成名字",
"避免缩写,除非它是团队公认的(如 id, url, api)",
];
suggestions[next_index(suggestions.len())]
}
fn structure_suggestion(&self, metric: &str) -> &'static str {
match metric {
"nesting depth" | "嵌套深度" => {
"用早返回(early return)、提取方法、或策略模式来减少嵌套"
}
"function length" | "函数长度" | "lines" => "拆分成多个小函数,每个函数只做一件事",
"complexity" | "复杂度" => "简化逻辑、提取辅助函数、使用表驱动替代 if-else 链",
_ => "重构一下,让代码更易读、更易维护",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_naming_roast_generates_message() {
let gen = RoastGenerator::new();
let msg = gen.naming_roast("data", "太泛了,不知道存的是什么");
assert!(msg.contains("data"));
assert!(msg.contains(StyleCategory::Naming.emoji()));
}
#[test]
fn test_structure_roast_generates_message() {
let gen = RoastGenerator::new();
let msg = gen.structure_roast("嵌套深度", 8, "这代码嵌套得比俄罗斯套娃还深");
assert!(msg.contains("8"));
assert!(msg.contains(StyleCategory::Structure.emoji()));
}
#[test]
fn test_duplication_roast_generates_message() {
let gen = RoastGenerator::new();
let msg = gen.duplication_roast("代码块", 5, "出现在第10行和第50行");
assert!(msg.contains("5"));
assert!(msg.contains(StyleCategory::Duplication.emoji()));
}
#[test]
fn test_comment_roast_generates_message() {
let gen = RoastGenerator::new();
let msg = gen.comment_roast("TODO", "TODO: fix this later");
assert!(msg.contains("TODO"));
assert!(msg.contains(StyleCategory::Comments.emoji()));
}
#[test]
fn test_static_analysis_note_is_mild() {
let gen = RoastGenerator::new();
let msg = gen.static_analysis_note("magic-number", "Found magic number 42");
assert!(msg.contains(StyleCategory::StaticAnalysis.emoji()));
assert!(msg.contains("不急"));
}
#[test]
fn test_category_emoji_and_names() {
assert_eq!(StyleCategory::Naming.emoji(), "🏷️");
assert_eq!(StyleCategory::Naming.display_name(), "命名风格");
assert_eq!(StyleCategory::Structure.emoji(), "🏗️");
assert_eq!(StyleCategory::Duplication.emoji(), "📋");
assert_eq!(StyleCategory::Comments.emoji(), "💬");
assert_eq!(StyleCategory::StaticAnalysis.emoji(), "🔍");
}
}