總覽

Fuchsia 開發人員運用多種工具,進行程式碼檢查及設定程式碼格式。本節將概略介紹每種語言的工具,並說明應如何新增其他 Lint 檢查,以及應維持的準確度標準。

請注意,這不會嘗試說明每個 Linter 和格式器的特定語言設定。雖然程式碼檢查和格式設定的目的是鼓勵並強制執行針對風格和最佳做法的建議,但每種相關語言都有專屬指南,說明做出的決策和啟用設定。

工具整合

Fuchsia 團隊提供兩種格式化和 Lint 程式碼的方法:開發人員端 fx 工具中的子指令,以及針對上傳的變更整合 Tricium 分析。此外,部分格式和程式碼檢查能夠直接納入建構中,但對於準確度有嚴格限制。

開發人員工具 (IDE 和 fx)

主要的開發人員工具套件是 fx 指令及其子指令,在此提供兩個相關的子指令:fx 格式程式碼和 fx lint。每次在檔案清單上執行相關工具,並將輸出內容列印至終端機的 stdout/stderr 中。執行 fx Lint 會假設開發人員已經執行 fx 版本;如果沒有,許多 Linter 就會產生與缺少版本建立檔案相關的錯誤。

檔案清單可透過以下三種方式之一指定:

  • 自第二次 Git 修訂版本以來,檔案清單有所變更,包括修訂、修改和快取檔案 (這是預設行為)
  • 以逗號分隔清單傳入 --files 旗標的檔案清單
  • 傳送至 --target 標記的 GN 目標來源中的檔案清單

正在進行格式化。Lint 預設為「僅有警告」狀態,但使用者可以將 --fix 旗標傳送至 fx Lint,自動修正工具提供修正的錯誤。

大多數編輯器也會整合格式設定工具和 Lint,讓開發人員能夠在鍵盤繫結時自動設定格式或進行格式繫結。在大多數情況下,設定 (如有) 是指將 IDE 指向相關的設定檔,以及 Fuchsia 分散式工具二進位檔。

整合式工具 (Tricium)

Tricium 是與 Gerrit 程式碼審查系統整合的服務,能以不會封鎖修訂版本的方式顯示相關警告。此 API 會在使用者上傳的所有 Fuchsia 存放區的修訂版本上觸發,並執行兩種工具分析套件。

格式轉換程式分析會盡可能減少檢查程序 (無「第三方」、「無預建」),並從修補程式修訂版本中擷取已變更檔案清單。這項工具會根據每個檔案的副檔名執行相關格式器。如果產生的格式化檔案與上傳修補程式中的檔案內容不同,Tricium 會在修補程式中張貼註解,說明如何執行適當的檔案格式器。

Linter 分析會進行完整的檢查,並執行最少的建構作業 (產生必要的設定檔和標頭)。這項工具會從修補程式修訂版本中擷取已變更檔案的清單,然後根據檔案副檔名執行相關 Linter。機器可讀的輸出內容是由 Linter 中要求,如果產生警告,則會剖析並收集為註解表單。三花八門後,畫面中會顯示 Linter 警告。

Tricium (如果可以的話),只會在修訂版本中變更行執行工具,但並非所有 Linter 都支援這種行為。對這類程式碼而言,這可讓原本不相關的 Lint 錯誤與變更本身無關,只會顯示直接相關的 Lint 錯誤。

分析結果通常是以經驗法則為依據。因此偶爾會產生偽陽性結果。Fuchsia 的目標是針對這些分析工具提供高標準,根據停用 Tricium 服務產生的指標,判定錯誤率超過 10% 的分析工具。

新的 Linter 通常應該加進現有的 Tricium 方案。到目前為止,這些建構作業中最昂貴的結帳/建構時間 (分析本身需要幾秒鐘的時間,且在最壞的情況下需要幾分鐘,但結帳和/建構可能需要更長的時間),因此從時間和基礎架構資源的角度來看,比起單純擴充現有的建構工具,所以效率更高。建議根據需要的資訊量選擇方案來擴充。舉例來說,如果不需要預先建構的/third_party 程式碼來執行分析,則應使用最少的結帳方案。

建構整合作業

對於提供零誤報率的 Lint 檢查,另一種替代做法是將這類檢查納入建構中。除非確定不會產生誤報,否則不建議您為這個類別新增額外的檢查項目。

這些檢查是直接在建構作業中實作 (一般稱為執行相關指令碼的動作),因此若擷取錯誤,會導致整個建構作業失敗。這些程式庫也會延長建構時間,因此建議只有在向開發人員提供寶貴且正確資訊時使用。

標準

格式設定工具

格式器應遵循相關風格指南,但格式器的輸出內容是否是樣式指南的真實資料來源,取決於語言和樣式的仲裁者。當上游社群中的格式工具有所變更 (例如 Rust 社群變更 rustfmt) 時,系統會使用工具鍊將更新後的格式程式導入 Fuchsia。這種情況並不常見,但也可能導致 Tricium 和本機工具之間的格式發生衝突,直到開發人員更新以使用新的工具鍊為止。

一般來說,Fushisia 是否支援格式工具,取決於執行格式指令的開發人員。唯一的自動化作業是來自 Tricium,會在檔案與格式器的輸出內容不同時發出警告,但不會封鎖 CL 的修訂版本。

內衣

Linter 通常應該為開發人員提供實用且可行的意見。這些函式通常以經驗法則為基礎,因此可能會產生偽陽性,但您應停用所有超過 10% 的誤報率的 Linter。新增 Linter 檢查的程序,是提交要求新檢查的錯誤,概述其值和預期的偽陽率。如要移除 Lint 檢查,可以回報錯誤,或根據要求的設定變更提交修補程式。

只有保證不會產生偽陽性的 Linter 才應在建構中實作。這些項目應同時由本機建構作業和 CQ 強制執行,這樣開發人員在嘗試提交程式碼時就不會出現任何意外狀況。

語言工具

每種支援的語言都提供了格式設定工具,以及選用的 Linter。本節說明如何將這些工具整合至 Fuchsia 工作流程。雖然格式器通常顯而易見,但這項工具在整合 Lint 的方式上仍有些複雜。在大多數情況下,開發人員不需要瞭解 fx 和 Tricium 的內部結構。

所有指令都是從 Fuchsia 結帳的根層級執行。

C/C++

C/C++ 程式碼使用 clang-formatclang-tidy。這些程式庫以 Clang 工具鍊預先建構的形式發布。兩者都使用根層級設定檔 (分別使用 .clang-format.clang-tidy)。開發人員不應在較低層級建立其他設定檔,因為這會導致樹狀結構中的不一致。

clang-format 在來源檔案上執行,如下所示:

prebuilt/third_party/clang/$HOST_PLATFORM/bin/clang-format \
-i \
-style=file \
-fallback-style=Google \
-sort-includes \
$FILES

執行 clang-tidy 前,您必須:

  • 建構產生的標頭組合。clang-tidy 工具會部分編譯原始碼,而 Fuchsia 中的大部分 C 和 C++ 程式碼都包含在建構過程中產生的標頭。

找到編譯資料庫和產生的標頭後,您就可以執行 run-clang-tidy.py 指令碼來啟動 clang-tidy 工具。這個指令碼會處理平行化和簡化錯誤,當同一個標頭包含在多個來源檔案中時。使用這個指令碼時,也必須從分散式 Fuchsia 工具鍊傳遞 clang-tidyclang-apply-replacements 二進位檔,確保使用正確的二進位檔。

export CLANG_TOOLCHAIN_PREFIX=prebuilt/third_party/clang/$HOST_PLATFORM
$CLANG_TOOLCHAIN_PREFIX/share/clang/run-clang-tidy.py \
  -clang-tidy-binary $CLANG_TOOLCHAIN_PREFIX/bin/clang-tidy \
  -clang-apply-replacements-binary $CLANG_TOOLCHAIN_PREFIX/bin/clang-apply-replacements \
  $FILES

您可以新增選用的 -fix 旗標,讓系統自動套用修正檔。您可以在開發人員端工具中取得這項資訊。

Rust

Rust 程式碼使用 rustfmtclippy。這些程式庫以透過 Rust 工具鍊預先建構的形式發布。此格式器具有根層級設定檔 (rustfmt.toml)。

rustfmt 在來源檔案上執行,如下所示:

prebuilt/third_party/rust/${HOST_PLATFORM}/bin/rustfmt \
--config-path=rustfmt.toml \
--unstable-features \
--skip-children \
$FILES

根據預設,所有 Rust 目標都會透過 fx build 執行 clippy。在預先提交期間,系統會將 clippy 警告視為建構錯誤。

如果只想執行 Linter,也可以使用我們的 fx 輔助指令碼在本機 GN 目標本機叫用該程式碼:

fx clippy TARGET
fx clippy --files FILE1 FILE2 # Filters lints for a list of specific files
fx lint # Same as --files but implicitly runs on locally changed files

啟用剪裁 Lint

如要查看目標的 Lint,您必須透過下列其中一種方式啟用:

  • 新增設定,以針對特定目標啟用預設的裁剪程式碼組合:configs += [ "//build/config/rust/lints:clippy_warn_all" ]
  • 在每個含有 gn arg 的目標,在本機啟用裁剪 Lint 做為警告:fx set core.x64 --args clippy_warn_all=true。這有助於在啟用 crate 前確認常見的 Lint 為何,或針對整個專案收集 Lint 頻率等統計資料。

這份清單列出了所有可用的裁剪 Lint 及其名稱。

針對特定程式碼停用剪裁 Lint

找出您要忽略特定 Lint 的 Rust 程式碼,新增 #[allow(clippy::LINT_NAME)]。請注意,屬性無法套用至所有運算式,有必要將該屬性套用至包含的語法元素。

查看

Go 程式碼使用 gofmtgo vet。這些模組是 Go 工具鍊建構的一部分,也可透過 Go 主機工具鍊的預先建構項目發布。

gofmt 在來源檔案上執行,如下所示:

prebuilt/third_party/go/$HOST_PLATFORM/bin/gofmt -s -w $FILES

TODO(https://fxbug.dev/42101826):等到實作細節完成後,再開始記錄。

FIDL

FIDL 代碼會使用 fidl-formatfidl-lint 工具。這些工具是以樹狀結構內的形式建構而成。執行 zircon/tools 目標之前,必須先建構二進位檔,確保二進位檔確實存在。

fidl-format 在來源檔案上執行,如下所示:

$ZIRCON_BUILD_DIR/tools/fidl-format -i $FILES

fidl-lint 在來源檔案上執行,如下所示:

$ZIRCON_BUILD_DIR/tools/fidl-lint $FILES

GN

GN 檔案使用 gn format 子指令。沒有 Linter。這項解決方案可做為 GN 預先建構的一部分發布。

可以在來源檔案上執行,如下所示:

prebuilt/third_party/gn/$HOST_PLATFORM/gn format <files>