lint最早用於C語言,是一種用來檢查程式碼的工具,現在的主流程式語言幾乎都有lint可以使用,尤其是JavaScript、Python等直譯式程式語言,因為它們的程式碼不會經過編譯,所以特別需要使用lint來檢查原始碼。藉由lint,我們可以寫出疑慮較少、效能更好或是更容易閱讀的程式碼。Rust程式語言雖然是靜態型別的程式語言,而且擁有十分嚴謹的編譯器,但官方還是提供了一個lint工具──Clippy。
使用clippy
clippy
的使用方法很簡單,建議透過以下指令來執行:
替cargo clippy
指令加上--tests
參數,可以讓它去檢查測試用的Rust程式碼,如果需要的話,也可以加上--features
、--all-features
或--no-default-features
參數來啟用特色。clippy
工具本身的-W
參數可以用來設定要將哪一個的lint分類或是規則改設為「警告」(warn)層級,就會輸出不符合該規則的位置,但不影響行程執行結束後回傳的Exit Status;-A
參數可以用來設定要將哪一個的lint分類或是規則改設為「允許」(allow)層級,就不會輸出不符合該規則的位置;-D
參數可以用來設定要將哪一個的lint分類或是規則改設為「拒絕」(deny)層級,就會輸出不符合該規則的位置,且影響行程執行結束後回傳的Exit Status。
clippy
的lint規則分類有以下幾項:
clippy::correctness
:錯誤或是無用的程式碼,預設為「拒絕」層級。clippy::style
:不合乎(官方)習慣的程式碼,預設為「警告」層級。clippy::complexity
:可以被簡化的程式碼,預設為「警告」層級。clippy::perf
:可以被加速的程式碼,預設為「警告」層級。clippy::all
:即表示以上四個分類。方便整體控制層級用的,例如-D clippy::all
就是-D clippy::correctness -D clippy::style -D clippy::complexity -D clippy::perf
。clippy::restriction
:程式碼語法結構與風格的規則,預設為「允許」層級。可能會與以上分類的規則有所衝突。clippy::cargo
:Cargo設定檔(即Cargo.toml
),預設為「允許」層級。Clippy可以檢查Cargo設定檔中缺失的設定項目,和相依crate的版本問題。clippy::pedantic
:其它比較嚴格的規則,預設為「允許」層級。clippy::nursery
:尚未穩定的規則,預設為「允許」層級。
所有的lint規則,以及規定原因都可以來這個網頁查詢。
利用巨集來設定lint規則
藉由#[allow(...)]
、#[warn(...)]
、#[deny(...)]
屬性,我們可以在Rust程式碼中臨時設定lint規則。
例如:
fn main(){
let x: u64 = 61864918973511;
println!("{}", x);
}
以上程式的第二行敘述會觸犯clippy::unreadable_literal
規則,如果要針對這個x
變數避免Clippy出現警告,可以對其加上#[allow(clippy::unreadable_literal)]
屬性。如下:
fn main(){
#[allow(clippy::unreadable_literal)]
let x: u64 = 61864918973511;
println!("{}", x);
}
可配置的lint規則
有些lint規則可以透過Clippy的設定檔來指定參數。cargo cargo
指令在執行的時候,首先會尋找工作目錄中是否有.clippy.toml
檔案,如果有的話就會將其作為clippy
的設定檔,如果沒有的話就會再尋找工作目錄中是否有clippy.toml
檔案,如果還是沒有的話,就會去尋找上層目錄是否有.clippy.toml
和clippy.toml
檔案,依此類推。
可以被配置的lint規則如下:
blacklisted-names = ["foo", "bar", "baz", "quux"] # clippy::blacklisted_name
cognitive-complexity-threshold = 25 # clippy::cognitive_complexity
doc-valid-idents = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "JavaScript", "NaN", "NaNs", "OAuth", "OpenGL", "OpenSSH", "OpenSSL", "OpenStreetMap", "TrueType", "iOS", "macOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"] # clippy::doc_markdown
enum-variant-name-threshold = 3 # clippy::enum_variant_names
enum-variant-size-threshold = 200 # clippy::large_enum_variant
single-char-binding-names-threshold = 5 # clippy::many_single_char_names
too-large-for-stack = 200 # clippy::boxed_local
too-many-arguments-threshold = 7 # clippy::too_many_arguments
trivial-copy-size-limit = 1 # clippy::trivially_copy_pass_by_ref
type-complexity-threshold = 250 # clippy::type_complexity
verbose-bit-mask-threshold = 1 # clippy::verbose_bit_mask
# too_many_lines = 100 # clippy::too_many_lines (pedantic)