RT-Thread / RT-Thread/rt-thread

[Feature] 关于RT-Thread的编码规范

Aperta
#11,653 4 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Lingua principale
C
Stelle
12.2k
Fork
5.4k
Merge medio
4g 12h
PR unite (30g)
40

Descrizione

背景

本文以当前 masterf19da943aa)为基线,对照仓库根目录的 .clang-formatRT-Thread 编程风格,梳理仓库当前的代码格式规则。

本 Issue 的目的不是立即进行全仓库格式化,而是先确定 RT-Thread 希望长期保持的格式风格,并明确哪些规则由 clang-format 自动执行,哪些规则需要代码审查或独立检查。

一、目前基本一致的规则

以下规则在手册和根目录配置中基本一致:

  • 使用 4 个空格缩进,不使用 Tab;
  • 控制语句、函数、结构体、枚举等的大括号通常换行;
  • switch 中的 caseswitch 对齐;
  • 控制语句关键字与左括号之间保留空格;
  • 普通函数名与左括号之间不留空格;
  • 括号内部不保留多余空格;
  • 多行函数参数按照左括号位置进行续行缩进;
  • 二元运算符通常在两侧保留空格。

这些规则可以继续作为基础风格,但仍需要补充例外和边界条件。

二、手册与配置存在差异的规则

主题 手册中的描述或示例 当前 .clang-format 行为 需要确认的结论
指针符号位置 同时出现 type* nametype *name PointerAlignment: Right,通常输出 type *name 统一采用哪一种写法
自增运算符 示例使用 index ++ 通常输出 index++ 是否接受无空格形式
连续空行 建议不要连续使用两个以上空行 MaxEmptyLinesToKeep: 2,最多保留两个空行 配置是否应改为最多一个空行
大括号 倾向于每个大括号独占一行 空函数、短 lambda、extern 块和 do ... while 存在例外 是否把这些例外写入手册
预处理指令 示例没有明确说明预处理指令的缩进规则 IndentPPDirectives: None,通常顶格 #if 块内部是否需要缩进
行尾 手册要求使用 \n LineEnding: DeriveLF,会根据输入内容推导,不是无条件强制 LF 是否需要单独的 LF 检查

其中指针风格在手册内部也不完全一致,例如结构体成员和 Doxygen 示例采用了不同的写法,需要先确定意图,而不是简单地把某一个示例作为唯一标准。

三、配置已经决定、但手册没有明确规定的规则

以下行为会影响代码的最终排版,但当前编码规范没有给出明确要求:

配置项或行为 当前设置 尚未明确的问题
连续声明对齐 AlignConsecutiveDeclarations: false 函数参数、局部变量是否需要列对齐
连续赋值对齐 AlignConsecutiveAssignments: false 赋值号是否需要对齐
位域对齐 AlignConsecutiveBitFields: true 位域名称和冒号是否应对齐
宏对齐 AlignConsecutiveMacros: true 宏值是否应按列对齐
行宽 ColumnLimit: 0 是否需要统一的最大行宽
include 顺序 SortIncludes: NeverIncludeBlocks: Preserve 是否按系统头文件、组件头文件和本地头文件分组或排序
表达式换行 二元运算、三元表达式、字符串、参数打包均由配置决定 长表达式应如何换行
尾部注释 AlignTrailingComments: Leave 尾部注释是否需要统一列对齐
转义换行 AlignEscapedNewlines: Left 宏续行反斜杠是否需要对齐
C++ 语法 配置包含 namespace、lambda、template、enum 等规则 C++ 文件是否与 C 文件采用同一套风格
配置例外 仓库存在目录级 .clang-formatDisableFormat 目录 哪些目录是第三方代码例外,哪些属于项目代码

这些内容不一定都需要修改,但应该明确哪些是有意设计,避免格式结果由 clang-format 默认行为或历史配置偶然决定。

四、重点案例:函数参数与局部变量声明的对齐范围

希望多行函数定义的参数保持类型和变量名的列对齐,例如:

static rt_err_t _thread_init(struct rt_thread *thread,
                             const char       *name,
                             void              (*entry)(void *parameter),
                             void             *parameter,
                             void             *stack_start,
                             rt_uint32_t       stack_size,
                             rt_uint8_t        priority,
                             rt_uint32_t       tick)

但函数体内的局部变量希望保持普通间距,不因为类型长度不同而产生较大的空格差距:

rt_base_t critical_level;
int err;

在当前根配置下,clang-format 会保留参数的续行缩进,但不会形成参数内部的类型列和变量名列:

static rt_err_t _thread_init(struct rt_thread *thread,
                             const char *name,
                             void (*entry)(void *parameter),
                             void *parameter,
                             void *stack_start,
                             rt_uint32_t stack_size,
                             rt_uint8_t priority,
                             rt_uint32_t tick)
{
    rt_base_t critical_level;
    int err;
}

标准 clang-format 没有一个独立选项,可以同时满足以下两个条件:

  1. 只对函数参数列表启用类型和变量名的列对齐;
  2. 对函数体内的连续局部声明保持普通间距。

AlignConsecutiveDeclarations 不能限定为“仅函数参数”,AlignAfterOpenBracket 只能控制续行位置,不能产生参数内部的列对齐。如果重新开启全局声明对齐,函数参数可以得到目标效果,但局部变量也会出现类似下面的空格填充:

rt_base_t critical_level;
int       err;

需要讨论以下取舍:

  • 是否接受当前配置,即函数参数只做续行缩进对齐,局部声明不做列对齐;
  • 是否认为函数参数的类型和变量名列对齐是必须保留的风格;
  • 如果必须保留参数列对齐,是否接受局部声明也进行全局列对齐;
  • 是否允许使用少量 clang-format off/on 或额外脚本实现局部例外。

不建议在全仓库范围内使用大量 clang-format off/on 标记,因为这会降低自动格式化的连续性和可维护性。

五、手册规定但 clang-format 无法完整执行的规则

以下内容属于编码规范,但不应期待由 clang-format 单独保证:

  • 目录、文件、函数、结构体、宏和 API 的命名规则;
  • 头文件保护符的命名格式;
  • 文件头版权和 Change Log;(可以在发布版本的时候统一使用脚本刷一遍)
  • 英文注释、Doxygen 标签语义和注释位置;
  • 日志接口和日志内容要求;
  • 函数长度、对象设计和接口命名约定。

建议在手册中明确区分“自动格式化规则”和“需要人工审查或独立 lint 检查的编码规则”。

六、建议的后续方式

  1. 逐项确定上述格式风格和例外;
  2. 为指针、参数、局部声明、宏、位域、预处理指令和注释建立最小 C/C++ 示例;
  3. 用固定的 clang-format 版本验证这些示例,并将预期结果作为格式基准;
  4. 根据结论同步修改 .clang-format 和编码规范中的示例;
  5. 在规则确定前不进行全仓库格式化,避免引入难以区分的空格和换行变更。

附带问题

BSP 自查页面目前仍主要介绍 astyle,与仓库当前使用的 clang-format 不完全一致。待本 Issue 确定最终风格后,再统一更新该页面、旧命令和相关忽略规则说明。

参考

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia confrontando .clang-format nella radice del repository con documentation/7.contribution/coding_style_cn.md, quindi esamina le indicazioni referenziate per l’auto-verifica di BSP. Usa gli esempi di formattazione elencati per identificare le differenze non risolte e confermare il comportamento previsto di clang-format. Il lavoro è completo quando le regole e le eccezioni sono state definite e .clang-format e la documentazione dello stile di codifica sono stati aggiornati in modo coerente.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
c, cpp
Ambito
documentation, tooling
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Tranquilla
Chiarezza
Da chiarire
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.