如何用 Clippy 檢測 Rust 代碼
如果你在一個開發團隊中工作,需要經常與彼此的代碼交互,那麼你就知道編寫乾淨和符合編程習慣的代碼是多麼重要。
有時,開發人員通過學習語法來學習一種新的編程語言。然後,他們用它來構建非常棒的系統,但是,如果不按照該語言的編程習慣編寫,對團隊其他人是一種糟糕的體驗。檢測代碼是檢查編程習慣的最佳方法之一,所以讓我們看看如何在 Rust 中做到這一點。
本文將具體討論 Rust 中代碼檢測的重要性和結果,研究如何在 Rust 代碼庫中進行檢測。然後,我們安裝 Clippy 並演示如何使用它來檢測 Rust 代碼。
什麼是代碼檢測?
檢測是通過檢查代碼來檢測潛在的錯誤、bug 和不遵循編程語言標準約定的樣式。
檢測在動態語言 (如 Python 和 JavaScript) 中更流行,因爲靜態類型語言具有執行大多數檢測操作的編譯器。檢測代碼的工具稱爲 linter,它執行以下操作:
-
檢查潛在的 bug
-
檢查錯誤
-
檢查代碼的複雜性
-
檢查代碼氣味
-
檢查程序是否遵循慣用的和乾淨的代碼風格
-
檢查不匹配的命名約定
-
提供安全警告
-
檢查內存泄漏、索引溢出和空指針解引用
-
檢查非法數據類型組合
在項目早期引入檢測很重要,因爲檢測舊的遺留代碼庫可能很困難 (甚至不可能)。
檢測如何改進 Rust 代碼?
Rust 編譯器在構建時考慮了靜態代碼分析,它有自己內置的 lint 檢查集合,在編譯期間評估代碼。
要查看這些內置 lints(被稱爲默認允許的 lints) 的列表,運行以下命令:
rustc -W help
這些 lints 分爲以下幾組,稱爲檢測級別:
-
allow:忽略違反 lints 的檢測
-
warn:如果 lints 被違反產生一個警告
-
force-warn:與 warn 相同,但不能被覆蓋
-
deny:如果 lints 被違反,產生一個錯誤
-
forbid:與 deny 相同,但不能被覆蓋
要使用 Rust 編譯器的內置檢測功能對 Rust 程序運行檢查,請使用以下命令:
cargo check
在編譯或檢查期間拋出錯誤的 Rust 代碼在警告中提供了 lint 類別:
在這裏,警告顯示了 warn 級別。我們可以通過在代碼頂部添加 lint 級別屬性來防止 lint 拋出警告,如下所示:
#![allow(unused_variables)]
這允許 Rust 編譯器用 (unused_variables) 覆蓋所有代碼。如果我們運行檢查或嘗試再次編譯,這個特殊的警告將不存在。
覆蓋 lints 在測試或創建應用程序原型而不需要遵循慣用標準的情況下非常有用。當你想要運行通常會在編譯時拋出檢測錯誤的代碼塊時,這特別有用。
我們已經對 Rust 的內置編譯器有了更好的理解,現在讓我們來學習更多關於 Clippy 的知識。
Clippy 是什麼?
Clippy 是一個庫,提供超過 550 個 lint,分爲 10 個 lint 級別:
-
cargo:幫助你改善 Cargo.toml 清單文件
-
complexity:用於可以簡化的複雜代碼
-
correctness:正確代碼的檢測,不能包含 #![allow]
-
deprecated:用於已棄用的代碼或庫
-
nursery:仍在開發中的新的 lints
-
pedantic:嚴格的 lints
-
perf:對如何提高代碼的速度和性能給出建議的 lint
-
restriction:對特定情況有用的限制
-
style:加強慣用風格的 lint
-
suspicious:檢測可疑代碼,這些代碼應該被修復,但如果是故意的,可以保留。
現在,讓我們看看如何安裝和運行 Clippy。
安裝和運行 Clippy
Rust 工具鏈的新版本預裝了 Clippy。如果你想手動安裝 Clippy,你可以使用 rustup 工具鏈安裝程序:
rustup update
rustup component add clippy
Clippy 可以作爲項目文件夾中的 cargo 子命令運行:
cargo clippy
Clippy 檢查並編譯項目文件夾中的依賴項和代碼,如下所示:
使用 Clippy 進行代碼分析
一些 Rust 代碼可以在編譯時沒有編譯錯誤,但這並不意味着代碼是乾淨的。Clippy 可以在你的代碼中捕捉你或 Rust 編譯器無法檢測到的次優實踐。例如,下面的代碼可以正常編譯,但它實際上有一個問題:
fn add(x: i32, y: i32) -> i32 {
return x + y
}
fn main() {
println!("Summation result is: {}", add(3, 7));
}
// Returns: 10
現在,讓我們使用 Clippy 來檢查和發現問題:
cargo clippy
檢查的結果返回以下警告:
提示從代碼中刪除 return 語句,只留下 x + y。如果再次執行 cargo clippy,將不會發現任何問題。
雖然這是一個非常簡單的示例,但是 Clippy 功能強大,能夠捕捉真正嚴重的錯誤。在 Rust 項目中應該總是使用 Clippy。
配置 Clippy
你不需要接受 Clippy 提供的每一個 lint。事實上,當你不同意一個 lint 時,你可以自由地在你的代碼中添加幾個 #![allow(…)]lint 屬性。還可以使用特定的子命令定製 Clippy,使其具有你喜歡的某些行爲。
例如,可以使用 - D 選項來啓用或禁用特定的檢測,或者使用 - W 選項來控制 Clippy 生成的警告級別。此外,還可以使用 - A 選項在項目中的所有依賴項上運行 Clippy,而不僅僅是你自己的代碼。
要允許特定的 lint 運行,使用 - A 選項:
cargo clippy -- -A clippy::lint_name
如果想對特定的 lint 發出警告,可以使用 - W 選項,如下所示:
cargo clippy -- -W clippy::lint_name
你也可以在 lint 分類中嘗試這些屬性。例如,你可以運行 Clippy,並對所有啓用的 lints 發出警告:
cargo clippy --W clippy::correctness
持續集成
在生產環境中,建議在持續集成 (CI) 上運行 Clippy。如果你使用 GitHub Actions,那麼將這段代碼附加到你的配置腳本:
on: push
name: Clippy check
# Make sure CI fails on all warnings, including Clippy lints
env:
RUSTFLAGS: "-Dwarnings"
jobs:
clippy_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Clippy
run: cargo clippy --all-targets --all-features
-Dwarnings 標誌阻止 CI 進行處理。環境變量 RUSTFLAGS 被設置爲 - Dwarnings 以使所有 cargo 命令服從 Clippy 警告。
如果你的 CI 提供商是 Travis CI,你可以添加這個:
language: rust
rust:
- stable
- beta
before_script:
- rustup component add clippy
script:
- cargo clippy
# if you want the build job to fail when encountering warnings, use
- cargo clippy -- -D warnings
# in order to also check tests and non-default crate features, use
- cargo clippy --all-targets --all-features -- -D warnings
- cargo test
# etc.
進一步的建議
在本文中,我們研究了檢測和檢測級別,並討論了檢測如何改進 Rust 代碼。演示瞭如何安裝 Clippy 並使用它來檢查代碼是否符合規範,還演示瞭如何在持續集成中包含 Clippy。
在使用 Clippy 時,應該記住兩件事。首先,你可以不時地反對 Clippy 的建議。其次,Clippy 不會以任何方式使內置編譯器的安全性和錯誤檢查工具變得可替換或無用。相反,Clippy 提供了一個廣泛的附加 lint 集合,可以用來使 Rust 代碼更高效。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/qcD9_9MCzgN92Luca1LbAQ