code-simplifier

code-simplifier

熱門

審查 RTK Rust 程式碼,找出慣用簡化方式。偵測過度工程、不必要的記憶體配置、冗長模式。在不改變行為的前提下套用 Rust 慣用語法。

7.8萬星標
4906分支
更新於 2026/8/30
SKILL.md
唯讀
名稱
code-simplifier
描述

審查 RTK Rust 程式碼,找出慣用簡化方式。偵測過度工程、不必要的記憶體配置、冗長模式。在不改變行為的前提下套用 Rust 慣用語法。

RTK 程式碼簡化器

審查並簡化 RTK 中的 Rust 程式碼,同時尊重專案的限制。

限制(絕不可簡化掉)

  • LazyLock 正規表達式 — 即使「更簡單」也不能移到函式內
  • 每個 ? 上的 .context() — 冗長但必須
  • 回退到原始指令 — 即使看起來像死碼也絕不能移除
  • 結束碼傳遞 — 絕不可簡化成 Ok(())
  • #[cfg(test)] mod tests — 絕不可移除測試模組

簡化模式

1. 疊代器鏈取代手動迴圈

// ❌ 冗長
let mut result = Vec::new();
for line in input.lines() {
    let trimmed = line.trim();
    if !trimmed.is_empty() && trimmed.starts_with("error") {
        result.push(trimmed.to_string());
    }
}

// ✅ 慣用
let result: Vec<String> = input.lines()
    .map(|l| l.trim())
    .filter(|l| !l.is_empty() && l.starts_with("error"))
    .map(str::to_string)
    .collect();

2. 字串建構

// ❌ 冗長的 push 迴圈
let mut out = String::new();
for (i, line) in lines.iter().enumerate() {
    out.push_str(line);
    if i < lines.len() - 1 {
        out.push('\n');
    }
}

// ✅ join
let out = lines.join("\n");

3. Option/Result 鏈式呼叫

// ❌ 巢狀 match
let result = match maybe_value {
    Some(v) => match transform(v) {
        Ok(r) => r,
        Err(_) => default,
    },
    None => default,
};

// ✅ 鏈式
let result = maybe_value
    .and_then(|v| transform(v).ok())
    .unwrap_or(default);

4. 結構解構

// ❌ 重複欄位存取
fn process(args: &MyArgs) -> String {
    format!("{} {}", args.command, args.subcommand)
}

// ✅ 解構
fn process(&MyArgs { ref command, ref subcommand, .. }: &MyArgs) -> String {
    format!("{} {}", command, subcommand)
}

5. 提早回傳取代巢狀

// ❌ 深度巢狀
fn filter(input: &str) -> Option<String> {
    if !input.is_empty() {
        if let Some(line) = input.lines().next() {
            if line.starts_with("error") {
                return Some(line.to_string());
            }
        }
    }
    None
}

// ✅ 提早回傳
fn filter(input: &str) -> Option<String> {
    if input.is_empty() { return None; }
    let line = input.lines().next()?;
    if !line.starts_with("error") { return None; }
    Some(line.to_string())
}

6. 避免多餘的 clone

// ❌ 不必要的 clone
fn filter_output(input: &str) -> String {
    let s = input.to_string();  // 無意義的 clone
    s.lines().filter(|l| !l.is_empty()).collect::<Vec<_>>().join("\n")
}

// ✅ 直接使用 &str
fn filter_output(input: &str) -> String {
    input.lines().filter(|l| !l.is_empty()).collect::<Vec<_>>().join("\n")
}

7. 單一變體的 match 使用 if let

// ❌ 只為一個變體寫完整 match
match output {
    Ok(s) => process(&s),
    Err(_) => {},
}

// ✅ if let(但在 RTK 中仍要處理錯誤 — 不要靜默丟棄)
if let Ok(s) = output {
    process(&s);
}
// 注意:在 RTK 過濾器中,務必用 eprintln! 處理 Err 並加上回退

RTK 特定檢查

簡化後執行以下檢查:

# 確認沒有回歸
cargo fmt --all && cargo clippy --all-targets && cargo test

# 確認函式中沒有新增正規表達式
grep -n "Regex::new" src/<file>.rs
# 固定且重複使用的模式應放在 `LazyLock<Regex>` 靜態變數中

# 確認生產程式碼中沒有新增 unwrap
grep -n "\.unwrap()" src/<file>.rs
# 只應出現在 #[cfg(test)] 區塊內

不要簡化的項目

  • static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(...).unwrap()); — 這裡的 .unwrap() 可接受,因為是初始化時
  • .context("description")? 鏈 — 冗長但必要
  • 回退的 match 分支 Err(e) => { eprintln!(...); raw_output } — 看似多餘但這是安全網
  • std::process::exit(code) 在 run() 結尾 — 看似可以改成 Ok(()) 但其實不行