Skip to main content

代码风格检测规则知识库

文档说明

本知识库面向开源社区三维基础几何引擎的代码风格检测场景,整理了项目平台所采用的 Google C++ 代码风格clang-formatclang-tidy 工具链下的可执行检测规则、Google 预设的关键配置取值,以及对应的违规知识条目。

工具边界(重要)

  • clang-format 只负责排版/格式(缩进、空格、换行、大括号、对齐、#include 排序),不检查命名、不改语义
  • 命名约定、头文件保护宏、语义性可读性clang-tidyreadability-identifier-naminggoogle-*llvm-header-guardreadability-* 等检查负责。
  • 因此本文按"检测器(detector)"维度标注每条规则归属的工具,避免误以为 clang-format 能拦截命名问题。

规则结构概览

模块规则范围主检测器条目数说明
命名约定CF-N.xclang-tidy readability-identifier-naming / google-*8类型/函数/变量/成员/常量/命名空间/宏/文件名
缩进与空白CF-I.xclang-format5缩进宽度、Tab、访问修饰符、case、行尾空白
列宽与换行CF-W.xclang-format380 列、参数打包、模板换行
大括号与控制流CF-B.xclang-format3大括号附着、短语句单行、初始化列表
指针与空格CF-S.xclang-format3指针左对齐、控制语句空格、行尾注释空格
头文件组织CF-H.xclang-format / clang-tidy3include 顺序与分组、保护宏
注释风格CF-C.xclang-format / clang-tidy2// 注释、行尾注释对齐
合计CF-*27风格检测规则与知识条目统一来源

目录

  • 1 工具链与流水线
  • 2 Google 预设关键配置取值(clang-format -style=google -dump-config
  • 3 命名约定(CF-N)
  • 4 缩进与空白(CF-I)
  • 5 列宽与换行(CF-W)
  • 6 大括号与控制流(CF-B)
  • 7 指针与空格(CF-S)
  • 8 头文件组织(CF-H)
  • 9 注释风格(CF-C)
  • 10 标准知识条目列表

1 工具链与流水线

环节工具职责CI 命令(示例)
格式校验clang-format排版一致性,差异即违规clang-format --dry-run --Werror -style=file <files>
格式修复clang-format自动重排clang-format -i -style=file <files>
命名/语义clang-tidy命名、保护宏、可读性clang-tidy -p build <files>
增量校验git-clang-format仅校验改动行git clang-format --diff <base>
  • 规则配置以仓库根目录 .clang-formatBasedOnStyle: Google)与 .clang-tidy唯一事实来源,CI 与本地共用同一份配置。
  • 检测日志中 clang-format统一 diff呈现违规;clang-tidyfile:line:col: warning: ... [check-name] 呈现,方括号内即规则编号。

2 Google 预设关键配置取值

以下为 BasedOnStyle: Google 的代表性取值;权威取值可用 clang-format -style=google -dump-config 重新导出。部分取值随 LLVM 版本演进(例如 AllowShortIfStatementsOnASingleLineStandard),CI 应锁定 clang 版本。

选项Google 取值含义
BasedOnStyleGoogle继承 Google 预设
ColumnLimit80行宽上限 80 列
IndentWidth2缩进 2 空格
ContinuationIndentWidth4续行缩进 4 空格
UseTabNever禁用 Tab
TabWidth8Tab 视觉宽度(仅展示用)
AccessModifierOffset-1public:/private: 相对类体回退 1
NamespaceIndentationNone命名空间体不额外缩进
IndentCaseLabelstruecase 标签缩进
PointerAlignmentLeftint* p* 贴类型)
DerivePointerAlignmenttrue从现有代码推断指针对齐(覆盖 PointerAlignment
SpaceBeforeParensControlStatementsif ( 有空格,foo( 无空格
BreakBeforeBracesAttach左大括号与声明同行
AllowShortFunctionsOnASingleLineAll允许短函数写成单行
AllowShortIfStatementsOnASingleLineWithoutElse(新版)/true(旧版)允许短 if 单行
AllowShortLoopsOnASingleLinetrue允许短循环单行
BinPackParameterstrue形参尽量同行打包
BinPackArgumentstrue实参尽量同行打包
Cpp11BracedListStyletrue{} 列表无多余内侧空格
SortIncludesCaseSensitive#include 排序
IncludeBlocksRegroupinclude 分组重排
AlignAfterOpenBracketAlign括号后续行对齐
AlignTrailingCommentstrue行尾注释对齐
SpacesBeforeTrailingComments2行尾注释前 2 空格
AlwaysBreakTemplateDeclarationsYestemplate<...> 单独成行
StandardAuto语言标准自动探测

3 命名约定(CF-N)

clang-tidyreadability-identifier-naming 配合 Google 风格选项强制;clang-format 不检查命名。

编号对象Google 约定正例反例
CF-N.1类型(class/struct/enum/typedef/别名/类型模板参数)UpperCamelCase,无下划线class GeometryEngine;class geometry_engine;
CF-N.2普通函数UpperCamelCaseComputeNormal()compute_normal()
CF-N.3变量(局部/全局/形参)snake_caseint face_count;int faceCount;
CF-N.4类的非静态数据成员snake_case + 尾随下划线int vertex_count_;int vertexCount;
CF-N.5常量(constexpr/const 静态存储期)k + UpperCamelCaseconst int kMaxFaces = 1000;const int MAX_FACES;
CF-N.6命名空间全小写 snake_casenamespace geom_kernel {namespace GeomKernel {
CF-N.7全大写 + 下划线(且应尽量避免宏)#define PI_VALUE 3.14#define piValue 3.14
CF-N.8文件名全小写 + 下划线,.cc/.h(非头部包含用 .incmesh_builder.ccMeshBuilder.cpp

4 缩进与空白(CF-I)

编号选项Google 取值检测要点
CF-I.1IndentWidth2每级缩进 2 空格
CF-I.2UseTabNever一律空格,禁止 Tab
CF-I.3AccessModifierOffset-1访问修饰符相对类体回退 1 列
CF-I.4IndentCaseLabelstrueswitchcase 缩进
CF-I.5行尾空白 / 文件末换行删除行尾空白,文件以单个换行结尾

5 列宽与换行(CF-W)

编号选项Google 取值检测要点
CF-W.1ColumnLimit80单行不超过 80 列
CF-W.2BinPackParameters/BinPackArgumentstrue参数打包策略一致
CF-W.3AlwaysBreakTemplateDeclarationsYestemplate<...> 独占一行

6 大括号与控制流(CF-B)

编号选项Google 取值检测要点
CF-B.1BreakBeforeBracesAttach左大括号紧贴声明同一行
CF-B.2AllowShortIfStatementsOnASingleLineWithoutElseif 可单行,带 else 不可
CF-B.3Cpp11BracedListStyletrue花括号初始化列表无多余内侧空格

7 指针与空格(CF-S)

编号选项Google 取值检测要点
CF-S.1PointerAlignment/DerivePointerAlignmentLeft/trueint* p(同文件保持一致)
CF-S.2SpaceBeforeParensControlStatementsif (/for ( 有空格,函数调用无
CF-S.3SpacesBeforeTrailingComments2行尾注释前 2 空格

8 头文件组织(CF-H)

编号选项/检查约定检测要点
CF-H.1SortIncludes/IncludeBlocksCaseSensitive/Regroupinclude 按组排序
CF-H.2include 顺序关联头→C 系统→C++ 标准库→第三方→本项目组间空行分隔,组内字母序
CF-H.3头文件保护(llvm-header-guard#pragma once<PROJECT>_<PATH>_<FILE>_H_保护宏命名规范

9 注释风格(CF-C)

编号选项/检查约定检测要点
CF-C.1注释语法优先 // 行注释实现内避免成块 /* */
CF-C.2AlignTrailingCommentstrue同块行尾注释对齐

10 标准知识条目列表

10.1 条目字段说明

每条规则采用统一字段:规则编号、规则名称、类别、检测器、漏洞描述、产生原因、影响范围、典型输入、日志特征、修复建议、相关案例、关联规则。其中规则编号优先采用工具原生标识clang-format 选项名 / clang-tidy 检查名),以便检测日志直接映射到本条目。

10.2 条目明细

命名约定类

CF-N.1 - 类型命名应使用 UpperCamelCase
  • 规则编号:CF-N.1
  • 规则名称:类型命名应使用 UpperCamelCase
  • 类别:命名约定
  • 检测器clang-tidy readability-identifier-namingClassCase: CamelCase 等)
  • 漏洞描述:类、结构体、枚举、typedef/类型别名、类型模板参数未采用首字母大写的驼峰,破坏 Google 命名一致性,降低类型与变量在阅读时的可区分度。
  • 影响范围:全部 C++ 头文件与源文件中的类型声明。
  • 日志特征clang-tidy 输出 invalid case style for class 'xxx' [readability-identifier-naming],携带文件、行列号与建议名。
  • 产生原因
    • 沿用 snake_case 类型命名习惯
    • 从历史代码复制类型未改名
    • 评审只看功能,忽略命名风格
  • 典型输入
    class geometry_engine {};       // 违规:snake_case
    struct meshData {}; // 违规:首字母小写
    typedef std::map<int,int> int_map; // 违规
  • 修复建议
    • 统一改为 UpperCamelCase:GeometryEngineMeshDataIntMap
    • .clang-tidy 启用 readability-identifier-naming 并设定各类大小写
  • 相关案例
    • 案例编号:CF-N.1-01
    • 违规场景:模块从其他代码库迁移,保留 <prefix>_<class> 式带下划线类型命名,与 Google 风格不符。
    • 修复结果:重命名为 Curve2d 并置于 geom::math2d 命名空间,clang-tidy 通过。
  • 关联规则:CF-N.3、CF-N.6
CF-N.3 - 变量命名应使用 snake_case
  • 规则编号:CF-N.3
  • 规则名称:变量命名应使用 snake_case
  • 类别:命名约定
  • 检测器clang-tidy readability-identifier-namingVariableCase: lower_case
  • 漏洞描述:局部变量、全局变量与函数形参使用驼峰或匈牙利前缀,违反 Google 的全小写下划线约定。
  • 影响范围:所有函数体与形参列表。
  • 日志特征invalid case style for variable 'xxx' [readability-identifier-naming]
  • 产生原因
    • 沿用 aWidthOfBox/myFlag 等他项目习惯
    • IDE 模板默认驼峰
  • 典型输入
    int faceCount = 0;     // 违规
    double aTolerance; // 违规(带冗余前缀)
  • 修复建议
    • 改为 face_counttolerance
    • 形参同样 snake_case
  • 相关案例
    • 案例编号:CF-N.3-01
    • 违规场景:求解器内大量 myXxx 成员与局部混用,难以一眼区分成员与局部。
    • 修复结果:局部改 snake_case、成员改 snake_case_(见 CF-N.4),可读性显著提升。
  • 关联规则:CF-N.4
CF-N.4 - 类数据成员应使用尾随下划线
  • 规则编号:CF-N.4
  • 规则名称:类数据成员应使用 snake_case 加尾随下划线
  • 类别:命名约定
  • 检测器clang-tidy readability-identifier-namingClassMemberCase: lower_caseClassMemberSuffix: _
  • 漏洞描述:类的非静态数据成员缺少尾随下划线,无法与局部变量、形参区分,易引发遮蔽与误赋值。
  • 影响范围:所有含数据成员的类。
  • 日志特征invalid case style for member 'xxx',提示应加 _ 后缀。
  • 产生原因
    • 沿用 myField 式成员命名习惯
    • 未配置成员后缀规则
  • 典型输入
    class Mesh {
    int vertexCount; // 违规:应为 vertex_count_
    bool myReady; // 违规
    };
  • 修复建议
    • 改为 vertex_count_ready_
    • struct(被动数据聚合)的成员不加尾随下划线
  • 相关案例
    • 案例编号:CF-N.4-01
    • 违规场景:构造函数 Mesh(int vertex_count): vertexCount(vertex_count) 形参与成员仅大小写之差,易写错。
    • 修复结果:成员改 vertex_count_,消除歧义。
  • 关联规则:CF-N.3、CF-S.1
CF-N.5 - 常量应使用 k 前缀驼峰
  • 规则编号:CF-N.5
  • 规则名称:常量应使用 k 前缀 UpperCamelCase
  • 类别:命名约定
  • 检测器clang-tidy readability-identifier-namingConstexprVariableCaseGlobalConstantCase + Prefix: k
  • 漏洞描述:编译期常量(constexpr/静态存储期 const)使用全大写或普通驼峰,与宏混淆或与变量混淆。
  • 影响范围:常量定义、枚举值。
  • 日志特征:提示常量应以 k 开头的驼峰命名。
  • 产生原因
    • 沿用 C 风格 MAX_FACES 宏式常量名
  • 典型输入
    const int MAX_FACES = 1000;   // 违规
    constexpr double TOL = 1e-9; // 违规
  • 修复建议
    • 改为 kMaxFaceskTolerance
    • 枚举值同样 kEnumName
  • 相关案例
    • 案例编号:CF-N.5-01
    • 违规场景#define 与全大写 const 混用,难以区分宏与常量。
    • 修复结果:宏改 constexpr kXxx,统一为常量命名。
  • 关联规则:CF-N.7、CF-N.1
CF-N.8 - 文件名应使用小写下划线与 .cc/.h 扩展名
  • 规则编号:CF-N.8
  • 规则名称:文件命名与扩展名
  • 类别:命名约定
  • 检测器:仓库约定 + CI 脚本(文件名正则);clang-tidy 不直接检查
  • 漏洞描述:源文件使用 .cpp 等非 Google 约定扩展名或大写驼峰文件名,违反 Google 的小写下划线 .cc/.h 约定,破坏跨平台与构建一致性。
  • 影响范围:全部源码文件命名。
  • 日志特征:CI 文件名检查脚本报告非法扩展名/大小写。
  • 产生原因
    • 直接迁移其他工程的命名习惯
  • 典型输入
    MeshBuilder.cpp    // 违规:大写驼峰 + 非 .cc
    GeometryEngine.H // 违规:大写 + 大写扩展名
  • 修复建议
    • 改为 mesh_builder.ccgeometry_engine.h
    • 内联实现头用 .inc(非直接包含的代码片段)
  • 相关案例
    • 案例编号:CF-N.8-01
    • 违规场景:仓库混用 .cpp.cc,构建脚本 glob 漏掉部分文件。
    • 修复结果:统一 .cc/.h,构建与 IDE 识别一致。
  • 关联规则:CF-H.2

缩进与空白类

CF-I.1 - 缩进宽度为 2 空格
  • 规则编号:CF-I.1(IndentWidth
  • 规则名称:缩进宽度为 2 空格
  • 类别:缩进与空白
  • 检测器clang-format
  • 漏洞描述:缩进非 2 空格(如沿用 4 空格或 Tab),破坏 Google 排版一致性,导致 diff 噪声。
  • 影响范围:所有代码块缩进。
  • 日志特征clang-format --dry-run --Werror 报告缩进相关的格式 diff。
  • 产生原因
    • 编辑器默认 4 空格/Tab
    • 未启用 .clang-format
  • 典型输入
    void Foo() {
    DoSomething(); // 违规:4 空格
    }
  • 修复建议
    • clang-format -i;编辑器对接 .clang-format
  • 相关案例
    • 案例编号:CF-I.1-01
    • 违规场景:混入 4 空格缩进,PR diff 全是空白变更。
    • 修复结果:统一 2 空格,diff 仅剩逻辑变更。
  • 关联规则:CF-I.2
CF-I.2 - 禁用 Tab,一律空格
  • 规则编号:CF-I.2(UseTab: Never
  • 规则名称:禁用 Tab 缩进
  • 类别:缩进与空白
  • 检测器clang-format
  • 漏洞描述:使用 Tab 缩进导致不同编辑器显示宽度不一,行内对齐错乱。
  • 影响范围:所有缩进与对齐。
  • 日志特征:格式 diff 中出现 \t → 空格的替换。
  • 产生原因
    • 编辑器未设置"Tab 转空格"
  • 典型输入
    →int x = 0;   // 违规:制表符缩进
  • 修复建议
    • 设置编辑器 expandtab;clang-format -i
  • 相关案例
    • 案例编号:CF-I.2-01
    • 违规场景:Tab/空格混用,注释对齐在他人机器上错位。
    • 修复结果:全部转空格后对齐稳定。
  • 关联规则:CF-I.1、CF-I.5
CF-I.5 - 删除行尾空白并保留文件末换行
  • 规则编号:CF-I.5
  • 规则名称:行尾空白与文件末换行
  • 类别:缩进与空白
  • 检测器clang-format(行尾空白);clang-tidy/CI(文件末换行)
  • 漏洞描述:行尾遗留空白与缺失文件末换行造成无意义 diff、部分工具告警。
  • 影响范围:所有文本行。
  • 日志特征:格式 diff 标注尾随空白被删除、文件末补换行。
  • 产生原因
    • 编辑器未开启"保存时清理"
  • 典型输入
    int x = 0;····      // 行尾空白(且文件末缺少换行符)
  • 修复建议
    • 开启保存清理;clang-format -i
  • 相关案例
    • 案例编号:CF-I.5-01
    • 违规场景:大量行尾空白污染 blame 与 diff。
    • 修复结果:清理后历史可读性提升。
  • 关联规则:CF-I.2

列宽与换行类

CF-W.1 - 行宽不超过 80 列
  • 规则编号:CF-W.1(ColumnLimit: 80
  • 规则名称:行宽上限 80 列
  • 类别:列宽与换行
  • 检测器clang-format
  • 漏洞描述:单行超过 80 列,降低分屏与代码评审可读性,触发自动换行。
  • 影响范围:所有源码行。
  • 日志特征:格式 diff 在超长行处自动断行。
  • 产生原因
    • 长链式调用、长字符串、深层嵌套
  • 典型输入
    result = ComputeIntersection(surface_a, surface_b, tolerance, max_iterations, enable_cache);
  • 修复建议
    • clang-format 自动换行;必要时抽取局部变量缩短表达式
  • 相关案例
    • 案例编号:CF-W.1-01
    • 违规场景:求解器调用单行 120 列,评审需横向滚动。
    • 修复结果:换行 + 参数对齐后宽度合规。
  • 关联规则:CF-W.2

大括号与控制流类

CF-B.1 - 左大括号与声明同行(Attach)
  • 规则编号:CF-B.1(BreakBeforeBraces: Attach
  • 规则名称:左大括号附着
  • 类别:大括号与控制流
  • 检测器clang-format
  • 漏洞描述:左大括号另起一行(Allman 风格)违反 Google 的附着式大括号,导致排版不一致。
  • 影响范围:函数、类、控制语句的大括号。
  • 日志特征:格式 diff 将 { 上移至声明行尾。
  • 产生原因
    • 沿用 Allman/GNU 大括号风格
  • 典型输入
    void Foo()
    { // 违规:应附着到 Foo() 行尾
    }
  • 修复建议
    • clang-format -i 自动附着
  • 相关案例
    • 案例编号:CF-B.1-01
    • 违规场景:团队成员混用 Allman 与 Attach。
    • 修复结果:统一 Attach。
  • 关联规则:CF-B.2

指针与空格类

CF-S.1 - 指针/引用符号左对齐
  • 规则编号:CF-S.1(PointerAlignment: Left / DerivePointerAlignment: true
  • 规则名称:指针/引用符号左对齐
  • 类别:指针与空格
  • 检测器clang-format
  • 漏洞描述*/& 贴变量(int *p)或同文件风格不一致,违反 Google 的 int* p 左对齐惯例(DerivePointerAlignment 会按文件主流风格推断并统一)。
  • 影响范围:所有指针/引用声明。
  • 日志特征:格式 diff 调整 */& 位置。
  • 产生原因
    • 沿用 C 风格 int *p
  • 典型输入
    int *p;     // 违规(Google 倾向 int* p)
    Mesh & m; // 违规
  • 修复建议
    • clang-format -i;保持单文件一致
  • 相关案例
    • 案例编号:CF-S.1-01
    • 违规场景:同文件 int* aint *b 混用。
    • 修复结果:统一左对齐。
  • 关联规则:CF-N.4
CF-S.2 - 控制语句关键字后加空格、函数调用不加
  • 规则编号:CF-S.2(SpaceBeforeParens: ControlStatements
  • 规则名称:控制语句空格规则
  • 类别:指针与空格
  • 检测器clang-format
  • 漏洞描述if(/for( 缺空格或 foo () 多空格,违反 Google 空格约定。
  • 影响范围:控制语句与函数调用。
  • 日志特征:格式 diff 调整括号前空格。
  • 产生原因
    • 个人习惯不一致
  • 典型输入
    if(x > 0) {}    // 违规:应为 if (x > 0)
    Foo (); // 违规:应为 Foo()
  • 修复建议
    • clang-format -i
  • 相关案例
    • 案例编号:CF-S.2-01
    • 违规场景while(true)if (x) 混用。
    • 修复结果:统一 ControlStatements 规则。
  • 关联规则:CF-B.1

头文件组织类

CF-H.2 - #include 分组与排序
  • 规则编号:CF-H.2(SortIncludes / IncludeBlocks: Regroup
  • 规则名称:include 顺序与分组
  • 类别:头文件组织
  • 检测器clang-format
  • 漏洞描述#include 未按"关联头→C 系统头→C++ 标准库→第三方库→本项目"分组并字母排序,易出现隐式依赖与重复包含。
  • 影响范围:所有源文件头部。
  • 日志特征:格式 diff 重排 include 顺序、插入空行分组。
  • 产生原因
    • 随手追加 include
  • 典型输入
    #include "geom/mesh.h"
    #include <vector>
    #include "geom/curve.h"
    #include <stdio.h>
  • 修复建议
    • clang-format -i;将关联头(如 mesh.cc 对应 mesh.h)置于首位
  • 相关案例
    • 案例编号:CF-H.2-01
    • 违规场景:本项目头排在标准库前,掩盖了缺失的传递包含。
    • 修复结果:Regroup 后暴露并补齐缺失 include。
  • 关联规则:CF-H.3、CF-N.8
CF-H.3 - 头文件保护宏命名规范
  • 规则编号:CF-H.3(llvm-header-guard#pragma once
  • 规则名称:头文件保护
  • 类别:头文件组织
  • 检测器clang-tidy llvm-header-guard
  • 漏洞描述:缺失或命名不规范的头文件保护宏会导致重复包含或宏冲突。Google 形式为 <PROJECT>_<PATH>_<FILE>_H_
  • 影响范围:所有头文件。
  • 日志特征header guard does not follow preferred style [llvm-header-guard]
  • 产生原因
    • 手写宏名不一致、复制粘贴未改宏
  • 典型输入
    #ifndef MESH_H   // 违规:未含项目/路径前缀
    #define MESH_H
  • 修复建议
    • 改为 OPEN3DGMBE_GEOM_MESH_H_,或统一改用 #pragma once
  • 相关案例
    • 案例编号:CF-H.3-01
    • 违规场景:两个不同目录的 mesh.h 使用相同 MESH_H 宏,触发漏包含。
    • 修复结果:加入路径前缀后冲突消除。
  • 关联规则:CF-H.2

注释风格类

CF-C.1 - 优先使用 // 行注释
  • 规则编号:CF-C.1
  • 规则名称:注释语法与语言
  • 类别:注释风格
  • 检测器clang-format(注释重排)/ 评审约定
  • 漏洞描述:实现代码中大量使用 /* */ 块注释或非英文注释,违反 Google 与项目国际化约定。
  • 影响范围:所有注释。
  • 日志特征:格式 diff 调整注释缩进;评审标注非英文注释。
  • 产生原因
    • 沿用 C 风格块注释
  • 典型输入
    /* 计算法线 */   // 违规:块注释 + 中文
  • 修复建议
    • 改为 // Compute the normal.
    • 保持注释为英文(符合项目国际化约定)
  • 相关案例
    • 案例编号:CF-C.1-01
    • 违规场景:混合中英文块注释,外部贡献者难读。
    • 修复结果:统一英文 // 注释。
  • 关联规则:CF-C.2

版本与时效说明:本文 Google 预设取值依据 LLVM clang-format/clang-tidy 文档与 Google C++ Style Guide 整理。clang-format 选项默认值随 LLVM 大版本可能微调,CI 应固定 clang 版本并以仓库 .clang-format/.clang-tidy 为唯一事实来源;权威取值用 clang-format -style=google -dump-configclang-tidy --dump-config 导出核对。