Clang-Format

最后更新: 2021-04-23 07:23:47 +0800 +0800
原文以英文撰写。您正在阅读AI翻译版本。

clang-format 将源代码布局变为仓库策略,而不是每位作者的个人偏好。它根据语法令牌流格式化受支持的语言,因此缩进、换行以及许多空格决策都可以复现。它不会规定命名、API、所有权或行为正确性;因此,代码评审仍然必须检查这些语义问题。

建立仓库策略 #

在仓库根目录提交 .clang-format 文件。使用 --style=file 时,clang-format 会从每个输入文件所在位置向其祖先目录搜索,并选择距离最近的 .clang-format 或 _clang-format。因此,嵌套目录可以有意覆盖根目录策略,但意外放置的嵌套文件也会改变该子树的格式化结果。

使用显式 YAML,即使预设样式提供了默认值,也要包含基础样式:

yaml
---
BasedOnStyle: LLVM
IndentWidth: 4
ColumnLimit: 100
SortIncludes: CaseSensitive

LLVM、Google、Chromium、Mozilla、WebKit、Microsoft 和 GNU 是内置的基础样式。预设名称并不是稳定的仓库策略,因为新版 clang-format 可能会添加选项或修改默认值。使用 clang-format --style=LLVM --dump-config 生成特定版本的完整起始配置,审核后提交预期的选项。当要求输出按字节完全一致时,应在开发环境和 CI 环境中固定格式化工具的版本;显式配置可以减少版本之间的格式差异,但无法完全消除这些差异。

Language: 部分会针对特定语言扩展默认部分:

yaml
---
BasedOnStyle: LLVM
IndentWidth: 4
---
Language: Cpp
PointerAlignment: Left

对于标准输入或没有扩展名的文件,传入 --assume-filename=example.cc,使语言检测和仓库发现过程与目标源文件保持一致。

调用格式化工具 #

每次调用都使用已提交的策略:

bash
# 重写由构建系统或文件列表选中的完整文件。
clang-format --style=file -i src/widget.cc include/widget.h

# 仅重写发生变更的行。此调用中的偏移量以字节为单位。
clang-format --style=file -i --offset=120 --length=400 src/widget.cc

# 在不修改文件的情况下检查 CI 文件集。
clang-format --style=file --dry-run --Werror src/widget.cc include/widget.h

编辑器应在保存时或执行显式格式化命令时,使用 --style=file 调用 clang-format。CI 应运行相同版本的可执行文件,并且只检查与项目相关的已跟踪文件;Shell 通配符会遗漏嵌套目录中的文件,并且结果可能因 Shell 而异。可供审核的 CI 脚本可以从 Git 或构建系统获取文件列表,并在格式化会产生差异时失败。

--style=file:/absolute/path/to/.clang-format 会选择一个已知文件,并避免搜索父目录。对于生成工具,或不应因子目录而变化的单体仓库策略,应使用此选项。

分离布局与评审 #

对于特定的格式化工具版本、源代码、配置和请求范围,格式化结果是确定性的。在创建补丁前运行格式化工具,并将采用格式化策略时的整体重格式化与功能变更分开。这样,评审者可以忽略布局噪声,从而更容易阅读语义差异。

不要将格式化输出视为编译器检查或安全检查。clang-format 可以对 include 进行排序并重写换行位置,但它不会解析 include,也不会验证编译结果。只有当生成形式或表格形式无法由策略表达时,才使用文档化的 clang-format off 和 clang-format on 注释来保护特殊布局;并在指令旁说明例外原因。

评论

在 GitHub 上阅读或评论(发表评论需要登录)