clang-format配置
Table of Contents
前言
简介
Clang-format 是一种代码格式化的工具,可以用来格式化各种代码,支持的语言如下
- C/C++
- Java
- JavaScript
- Objective-C
- Protobuf
- C#
Clang-format 的配置文件可以取名为 .clang-format 或者 _clang-format ,该文件被放在项目的根目录下,一般来说 Clang-format 会自己去寻找配置文件的
安装
windows
直接从上述网站上找到一个对应的发行版安装即可
然后在命令行中输入如下指令来查看是否安装完成,一般来说安装完成之后需要重新启动一下
| |
ubuntu
根据该文章的内容来安装
安装最新版 LLVM,需要注意,该指令只能在 bash 中使用
| |
安装 Clang-format
| |
之后可以验证
| |
原文地址
Clang-Format Style Options — Clang 20.0.0git documentation (llvm.org)
原理
Clang-format 的底层原理是基于 Clang 编译器的前端技术,包括一下几个步骤
- 词法分析:Clang-format 使用 Clange 的词法分析器,将源代码分解成标记,这些标记是代码的基本构建块,如关键词,标识符,运算符和分隔符
- 语法分析:Clang-format 解析代码的语法结构,生成抽象语法树,抽象语法树是代码结构的树形表示形式,用于进一步分析和转换
- 格式化规则应用:Clang-format 根据用户定义的格式化规则,对 AST 进行遍历和调整。规则涵盖了代码缩进,空格,换行和代码块布局等各个方面
- 代码生成:Clang-format 将调整之后的 AST 转换回源代码文本,并且输出格式化之后的代码
vscode 配置 Clang-format
需要下载插件 C/C++,但是需要注意的是,下载的插件的版本必须是 1.17.4 以及之前的版本(后面更新的新版本好像用不了)
然后在设置里找到 format-enbale 并且将其打开即可
然后可以在项目的根目录下添加 .clang-format 文件,里面就可以写配置了,然后在格式化时 C/C++ 插件会自动寻找 .clang-format 文件的,一般来说会在该项目的根目录中寻找
命令行语法
| |
常用的选项如下
-i直接修改文件而不是输出到标准输出-style指定格式化风格,如下几种预定风格-assume-filename指定文件类型,以便应用相应的格式化规则
配置文件语法
在进行配置时,可以一次使用多个语言配置,如下
| |
可以在源代码中进行如下注释,表示这一段代码不需要被格式化
| |
编写规则
- 配置文件名必须为
.clang-format - 该文件必须位于项目的根目录或者编译目录下
- 文件采用
YAML语法
配置字段解释
Language语言,可以指定当前配置文件为那些文件配置的- Cpp
- Java
- JavaScript
- ObjC
- Proto
- TableGen
- TextPorto
- CSharp
BaseOnStyle基础风格,指定基本的风格样式- LLVM
- Chromium
- Mozilla
- WebKit
- Microsoft
- GNU
AccessModifierOffset访问性修饰符偏移,这个偏移量是相对于原来已有的缩进而言的,需要在原来就有的偏移基础上进行的偏移AlignAfterOpenBracket开括号之后的对齐Align开阔号之后对齐变量DontAlign不对齐,换行后使用缩进AlwaysBreak一行放不下时,总是在一个开括号之后换行BlockIndext一行放不下时,总是在一个开括号之后换行,并且在新行关闭尾括号,但是仅限于圆括号
AlignArrayOfStructures对齐结构体数组,当数组列数相等时,会对齐每行的文本Left向左对齐Right向右对齐None不对齐
AlignConsecutiveAssignments连续赋值对齐,连续几行的赋值语句中,等号对齐。其中有几个变量来控制bool Enabled是否使能对齐bool AcrossEmptyLines可以跨越空白行进行对齐bool AcrossComments可以跨越注释行进行对齐bool AlignCompound对于混合运算+=会对齐于=bool PadOperators混合运算符填补对齐到所有左值的最右边界,仅限于连续赋值
AlignConsecutiveBitFields位段对齐,主要用于结构体位阈段的对齐。由如下几个变量控制Enabled使能对齐AcrossEmptyLines可以跨越空行进行对齐AcrossComments可以跨越注释进行对齐
AlignConsecutiveDeclarations连续对齐声明,可以对齐变量等连续声明的语句。需要注意的是,这个对齐尽量不要跨越空白行,容易把函数定义也对齐了。由如下几个变量控制Enabled使能对齐AcrossEmptyLines可以跨越空行进行对齐AcrossComments可以跨越注释进行对齐
AlignEscapedNewlines对齐分割语法行的斜杠DontAlign不对齐Left左对齐,尽可能向左对齐Right右对齐,对齐到列的最右边
AlignOperands竖直对齐表达式的操作数,竖直对齐二元或三元表达式的操作数DontAlign不对齐Align对齐AlignAfterOperators在操作符之后对齐,也就是是否对齐操作数- 外部属性
BreakBeforeBinaryOperators在二元操作符之前打断,如果配置文件中设置了这个属性,操作符也会换行
AlignTrailingComments对齐尾部注释KindLeave不做格式化Always对齐尾部注释Never不对齐,但是进行缩进之类的操作
OverEmptyLines跨越空白行的行数,超过这个行数的注释不会对齐
AllowAllArgumentsOnNextLine允许参数在下一行上,如果函数调用或者带括号的函数初始化列表不在一行中,允许所有参数放到下一行AllowAllParametersOfDeclarationOnNextLine允许声明的参数在下一行上,函数声明无法放在一行中,允许将所有变量放在下一行上****
AllowShortBlocksOnASingleLine允许短语法块在单行上Never从不合并到单行上Always只合并空的块到单行上Empty总是合并短块到单行上
AllowShortEnumsOnASingleLine允许短的枚举类到单行上AllowShortFunctionsOnASingleLine允许短函数在单行上None从不合并InlineOnly仅合并被定义在类里面的短函数Empty只合并空函数inline合并在类里面的短函数和外部的空函数ALL合并所有合适的短函数在单行上
AllowShortIfStatementsOnASingleLine允许if块在单行上Never从不把if放在单行上WithoutElse没有else时放在单行上OnlyFirstIf只把第一个if语句放在单行上,后面的else if和else都不放在单行上AllIfsAndElse短语句放在单行上
AllowShortLambdasOnASingleLine允许短匿名函数lambda放在单行上None从不合并Empty只合并空的匿名函数Inline当匿名函数作为实参时,合并在单行上All合并所有短的匿名函数
AllowShortLoopsOnASingleLine允许合并短循环到单行上AlwaysBreakAfterReturnType函数声明返回类型的换行风格None从不在返回类型之后自动换行All总是在返回类型之后自动换行TopLevel在顶级函数顶级返回类型处换行AllDefinitions在函数定义的返回类型处换行TopLevelDefinitions在顶级函数定义的返回类型处换行
AlwaysBreakBeforeMultilineStrings多行字符串换行,在多行字符串字面量之前换行AlwaysBreakTemplateDeclarations模板声明换行No不会强制在模板声明处换行MultiLine仅在接下来的函数/类声明参数需要跨行时才会在模板处换行Yes总是在模板声明之后换行
AttributeMacros属性宏,这个对于语言扩展或静态分析器注释非常有用BinPackArguments装箱变量false变量要么都在同一行,要么每个变量单独一行true会把变量合理打包放在一行上,更紧凑一点
BitFieldColonSpacing位阈冒号的空格风格Both在冒号每边都增加一个空格None不添加任何空格Before在冒号之前添加空格After在冒号之后添加空格
BraceWrapping大括号换行风格。必须将BreakBeforeBraces设置为Custom时才有效,否则被忽略。由以下几个参数来定义bool AfterCaseLabel在case之后的大括号换行bool AfterClass类定义之后换行AfterControlStatement控制语句之后换行Never从不换行MultiLine只在一个多行控制语句之后换行Always总是换行
bool AfterEnum在枚举类之后换行bool AfterFunction在函数定义之后大括号换行bool AfterNamespace命名空间之后换行bool AfterStruct在结构体之后换行bool AfterUnion在联合定义之后换行bool AfterExternBlock在extern声明之后换行bool BeforeCatch在catch之前换行bool BeforeElse在else之前换行bool BeforeLambdaBody在匿名函数表达式块之前换行bool BeforeWhile在while之前换行bool IndentBraces对换行的大括号缩进bool SplitEmptyFunction如果为false,空函数体可以放在单行上。此选项仅在函数的左大括号已经被换行的情况下使用,即设置了AfterFunction大括号换行模式,并且函数不应该放在单行上bool SplitEmptyRecord如果为false,空的类,结构体和联合体的主体可以放在单行上。此选项仅在记录的开始大括号已经被换行的情况下使用,即设置了AfterClass(用于类)大括号换行模式bool SplitEmptyNamespace如果为false,空的namespace主体可以放在单行上。此选项仅在命名空间的开始大括号已经被换行的情况下使用,即设置了AfterNamespace大括号换行模式bool AfterObjCDeclaration在 ObjC 定义之后换行
BreakAfterJavaFieldAnnotations在修饰器之后换行,适用于 JavaBreakArrays仅用于支持 Json 数组换行BreakBeforeBinaryOperators二元操作符换行None在操作符之后换行NonAssignment只在非赋值操作之前换行All在操作符之前换行
BreakBeforeBraces大括号换行格式Attach总是将大括号附加到周围上下文Linux与上述类似,但是会在函数,命名空间和类定义处换行Mozilla与Attach类似,但是会在枚举和函数定义处换行Stroustrup与Attach类似,但是会在函数定义,catch,else处换行Allman总是会在大括号处换行Whitesmiths与Allman类似,但是始终要缩进大括号并使用大括号排列代码GNU总是在大括号之前换行,并在控制语句的大括号中增加额外的缩进级别,而在类、函数或其他定义的大括号中不会缩进大括号WebKit与Attach类似,但是会在函数定义处换行Custom客制化配置每个大括号情况
BreakBeforeConceptDeclarations概念声明换行风格Never保持模板声明行和concept在一行Allowed允许模板声明和concept之间换行,实际的表现取决于上下文和换行规则Always永远在concept之前换行,并且将改行放在模板声明之前
BreakBeforeTernaryOperators三元操作符换行规则true在三元操作符之前换行false在三元操作符之后换行
BreakConstructorInitializers构造函数换行风格BeforeColon冒号前和逗号之后换行BeforeComma逗号和冒号之前换行,并且对齐AfterColon在冒号和逗号之后换行AfterComma仅在逗号之后进行换行
BreakInheritanceList继承换行风格BeforeColon冒号前和逗号之后换行BeforeComma逗号和冒号之前换行,并且对齐AfterColon在冒号和逗号之后换行AfterComma仅在逗号之后进行换行
BreakStringLiterals字符串常量换行,允许对字符串字面量进行断行ColumnLimit列数限制,设置为 0 表示没有限制,不会在一行太长的语句中换行CommentPragmas注释表示。值为字符串,含有正则表达式,其描述具有特殊含义的注释,这些注释不应被分割成行或以其他方式更改CompactNamespaces紧凑命名空间true将连续的命名空间声明在一行中false每个命名空间在新行中声明
ConstructorInitializerIndentWidth构造初始化缩进宽度,用于构造函数初始化列表和继承列表缩进的字符数,无符号整数ContinuationIndentWidth延续下一行缩进宽度,原来一行放不下时,换行后,新行缩进的字符数Cpp11BracedListStyle大括号列表风格,其中大括号列表中没有空格false就是大括号内有空格与变量分隔
DeriveLineEnding提取行结尾DerivePointerAlignment提取指针对齐true分析格式化文件中的&和*最常见的对齐方式,然后指针和引用对齐将根据在文件中找到的对齐样式进行更新
DisableFormat禁用格式化EmptyLineAfterAccessModifier定义何时在访问修饰符之后放置空行Never移除访问修饰符之后所有的空行Leave在访问修饰符之后保持现有的空行Always如果访问修饰符之后没有空行,总是在后面添加空行
EmptyLineBeforeAccessModifier访问修饰符前空行Never移除访问修饰符之前所有的空行Leave在访问修饰符之前保持现有的空行Always如果访问修饰符之前没有空行,总是在后面添加空行,除非访问修饰符位于结构或类定义的开头LogicalBlock有当访问修饰符开始一个新的逻辑块时才添加空行。逻辑块是由一个或多个成员字段或函数组成的一组
ExperimentalAutoDetectBinPacking实验性的功能,不要在配置文件中使用,使用风险自负FixNamespaceComments修复命名空间描述trueClang-format 将为短命名空间添加丢失的命名空间结束注释,并且修复无效的现有注释
ForEachMacros迭代循环宏,被解释为foreach循环而不是函数调用的宏向量IfMacros条件判断宏,被解释为条件语句而不是函数调用的宏向量IncludeBlocksinclude块风格Preserve每个include块单独排序Merge合并多个include块,并且整体排序Regroup合并多个include块,并且整体排序,根据类别优先级分组,可参考IncludeCategories
IncludeCategoriesinclude种类,正则表达式表示不同的include类别,然后进行排序。支持 POSIX 扩展正则表达式,每个分类都包含如下四个参数,下面是一个示例Regex正则表达式Priority优先级SortPriority默认优先级CaseSensitive是否区分大小写
1 2 3 4 5 6 7 8 9 10 11 12IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 SortPriority: 2 CaseSensitive: true # 字段标记为区分大小写,默认情况下不区分大小写 - Regex: '^((<|")(gtest|gmock|isl|json)/)' Priority: 3 - Regex: '<[[:alnum:].]+>' Priority: 4 - Regex: '.*' Priority: 1 SortPriority: 0IncludeIsMainRegex指定一个正则表达式,其表明了文件到主包含映射中被允许的后缀名IncludeIsMainSourceRegex判断源文件的正则表达式。为被格式化的文件指定正则表达式,匹配正则表达式的这些文件允许在文件到main-include映射中被视为mainIndentAccessModifiers访问修饰符缩进,用于指定访问修饰符是否应该有自己的缩进级别false访问修饰符相对于成员缩进(或向外缩进),根据AccessModifierOffset。记录成员的缩进位置比记录低一级true访问修饰符获得自己的缩进级别,而且成员的缩进是在此基础上的
IndentCaseBlockscase块的缩进falsecase标签之后的块与case有着相同的缩进级别truecase标签之后的缩进为作用域块,相对于case还有一级缩进
IndentCaseLabelscase label标签缩进falsecase标签与switch标签有着相同的缩进等级truecase标签在switch基础上有一级缩进
IndentExternBlockExtern扩展块缩进NoIndent不缩进Indent缩进
IndentGotoLabels缩进goto跳转符号IndentPPDirectives预处理指令缩进None不缩进任何预处理指令AfterHash缩进#之后的内容BeforeHash缩进时包括#
IndentRequiresClause是否缩进模板中的require子句。这只适用于RequiresClausePosition为OwnLine或WithFollowing时IndentWidth缩进宽度,用于缩进的列数IndentWrappedFunctionNames如果函数定义或声明在类型之后换行,则函数名缩进InsertBraces插入括号。在控制语句之后插入大括号,除非控制语句位于宏定义中,或者大括号包含预处理指令。但是需要注意的是,设置之后有可能会导致错误的代码格式,需要小心使用InsertTrailingCommas插入尾部冒号Wrapped会在跨多行换行的容器字面量(数组和对象)中插入尾随逗号。但是使用之后将禁用BinPackArgumentsNone不插入
JavaImportGroups为 Java 导入按照所需组排序的前缀向量JavaScriptQuotesJava 的引号风格Leave保持原样Single总是使用单引号Double总是使用双引号
JavaScriptWrapImportsJava 中import/export语句换行KeepEmptyLinesAtTheStartOfBlocks在一个语法块的开始刘空行LambdaBodyIndentation匿名函数表达式主体缩进样式Signature将匿名函数主体相对于 该匿名函数签名对齐OuterScope相对于匿名函数签名所在的外部作用域的缩进级别对齐匿名函数主体
MacroBlockBegin开始块的宏,匹配启动块的宏的正则表达式MacroBlockEnd结束块的宏MaxEmptyLinesToKeep最大持续空行,就是保留的最大空行数NamespaceIndentation命名空间内部是否缩进None不缩进Inner只缩进嵌套的命名空间(最外层命名空间内部不缩进)All所有命名空间都缩进
NamespaceMacro命名空间宏,用于打开名称空间块的宏向量ObjCBinPackProtocolListObjC 的打包风格Never/Auto(BinPackParameters=false)则在超出ColumnLimit时将Objective-C协议一致性列表项布局到单独的行上Always/Auto(BinPackParameters=true)当代码长度超过ColumnLimit时,就会将Objective-C协议一致性列表项打包成尽可能少的行
ObjCBlockIndentWidth用于 ObjC 块缩进的字符数ObjCBreakBeforeNestedBlockParam当函数调用中有嵌套的块参数时,将参数列表分解成行ObjCSpaceAfterProperty在 ObjC 的属性之后添加一个空格ObjCSpaceBeforeProtocolList在 ObjC 协议列表前面添加一个空格PPIndentWidth用于预处理器语句缩进的列数PackConstructorInitializers打包构造函数初始化列表Never总是将每个构造函数初始化列表放在一个单独的行中BinPack打包构造函数初始化列表CurrentLine如果合适,将所有构造函数初始化式放在当前行中,否则将每一个放在单独的一行上NextLine与上述相似,如果所有的构造函数初始化式都不适合当前行,则尝试将它们适合下一行
PenaltyXxxx各类情况惩罚PointerAlignment指针对齐风格Left向左对齐Right向右对齐Middle中间对齐
QualifierAlignment限定符对齐,不同的排列说明符和限定符的方法,主要是针对const和volatileLeave保持原状,不强制Left左对齐说明符或者限定符Right右对齐说明符或者限定符Custom将说明符/限定符更改为基于QualifierOrder对齐
QualifierOrder说明符和限定符的顺序,限定符出现的顺序- 包括
const, inline, static, constexpr, volatile, restrict, type - 必须包含
type。在type左边的项目将被放置在类型的左边,并按提供的顺序排列。type右侧的项目将被放置在类型的右侧,并按提供的顺序排列 - 例子
QualifierOrder: ['inline', 'static', 'const', 'volatile', 'type']
- 包括
RawStringFormats原始字符串格式ReferenceAlignment引用格式对齐Left向左对齐Right向右对齐Middle中间对齐
ReflowComments是否重新排版注释RemoveBracesLLVM移除括号,用来移除部分可以去掉的括号(大括号),即if/else/for/while等语句。通过 LLVM 风格实现。可能导致未知错误,小心使用RemoveSemicolon移除分号,移除非空函数的分号。有可能带来未知风险RequiresClausePositionrequire子句位置OwnLine总是把要求子句放在单独一行上WithPreceding试着把从句和声明的前面部分放在一起WithFollowing尝试把requires子句和函数声明放在一起SingleLine如果可能的话,尽量把所有内容放在同一行。否则正常的断行规则就会被取代
RequiresExpressionIndentationrequire表达式缩进OuterScope相对于require表达式所在的外部范围的缩进级别Keyword相对于require关键字的缩进
SeparateDefinitionBlocks分离定义语句块,指定使用空行分隔定义块,包括类、结构、枚举和函数Leave保持原样Always在定义块之间插入空行Never在定义块之间移除空行
ShortNamespaceLines短命名空间行数,这通过计算未换行行(即既不包含开始名称空间也不包含结束名称空间大括号)来确定短名称空间的最大长度,并使FixNamespaceComments忽略为这些名称空间添加结束注释SortIncludes对include排序Never不进行排序CaseSensitive区分大小写,按照 ascii 排序CaseInsensitive不区分大小写,按照字母顺序排序
SortJavaStaticImport排序 Java 静态导入Before静态导入被放在非静态导入前面After静态导入被放在非静态导入前面
SortUsingDeclarations对using声明进行排序,按照字母顺序排序SpaceAfterCStyleCastC 风格类型转换,是否在 C 风格的类型转换之后插入空白符SpaceAfterLogicalNot是否在逻辑非操作符之后插入空格SpaceAfterTemplateKeyword是否在模板关键字之后插入空格SpaceAroundPointerQualifiers定义在什么情况下在指针限定符之前或之后放置空格Default不用确保指针限定符周围的空格,而是使用PointerAlignment代替Before确保在指针限定符之前有一个空格After确保在指针限定符之后有一个空格Both确保在指针限定符之后和之前都有一个空格
SpaceBeforeAssignmentOperators赋值操作符控空格,赋值操作符之前是否插入空格SpaceBeforeCaseColoncase之后的冒号前是否插入空格SpaceBeforeCpp11BracedList大括号列表空格,是否在大括号列表之前插入空格SpaceBeforeCtorInitializerColon构造函数初始化中的冒号前是否插入空格SpaceBeforeInheritanceColon继承冒号前是否插入空格SpaceBeforeParens圆括号空格,圆括号前是否插入空格Never从不在一个开圆括号之前放一个空格ControlStatement只在控制语句关键字之后的开括号前加空格ControlStatementsExceptControlMacros与上一个类似,但是排除宏定义NonEmptyParentheses只有当圆括号非空时Always总是在开括号之前放一个空格Custom自定义
SpaceBeforeParensOptions圆括号前空格控制,控制括号前的个别空格,必须在SpaceBeforeParens设置为Custom时才有效bool AfterControlStatements在控制语句关键字和圆括号之间插入空格bool AfterForeachMacros在foreach宏和圆括号之间插入空格bool AfterFunctionDeclarationName在函数声明和开圆括号之前放置空格bool AfterFunctionDefinitionName在函数定义名称和开圆括号之间用空格隔开bool AfterIfMacros在if宏和开圆括号之间放空格bool AfterOverloadedOperator在操作符重载和开括号之间放一个空格bool AfterRequiresInClause在required子句中的required关键字和开括号(如果有的话)之间放空格bool AfterRequiresInExpression在required表达式中的required关键字和开括号之间放空格bool BeforeNonEmptyParentheses只有当圆括号不是空的时候,才在圆括号前放空格
SpaceBeforeRangeBasedForLoopColon是否在循环范围里的冒号前插入空格SpaceBeforeSquareBrackets方括号前插入空格,匿名函数不受影响,只有第一个方括号才会收到影响(如果有多个的话)SpaceInEmptyBlock空块中是否插入空格SpaceInEmptyParentheses空圆括号之间是否插入空格SpacesBeforeTrailingComments尾部注释前的空格数,不影响块注释SpacesInAngles角括号是否插入空格Never不插入Always在角括号之间插入空格Leave如果有空格,则在<之后和>之前保留且只保留一个空格
SpacesInCStyleCastParentheses是否向 C 类型转换中插入空格SpacesInConditionalStatement条件表达式中的空格SpacesInContainerLiterals容器中的空格,在容器中插入空格(方括号和花括号中初始化数组之类的)SpacesInLineCommentPrefix行注释的开头允许有多少空格,要禁用最大值,请将其设置为-1,除此之外,最大值优先于最小值。在行注释区中,后面的行保持相对缩进。有两个参数Minimum最小值Maximum最大值
SpacesInParentheses在圆括号里的空格SpacesInSquareBrackets方括号中的空格StandardC++ 标准,可以为c++03解析格式化为c++03c++11c++14c++17c++20Latest解析和格式化为最新的支持版本Auto根据输入和输出自动检测语言
StatementAttributeLikeMacros在语句前被忽略的宏,就像它们是一个属性一样。这样它们就不会被解析为标识符StatementMacros完整语句的宏向量TabWidthTab 的宽度TypenameMacros类型名宏定义,类型声明而不是函数调用的宏向量UseCRLF换行时使用\r\n而不是\n。如果DeriveLineEnding为真,也可用作回退UseTab在文件中使用制表符的情况Never从不使用ForIndentation仅用于缩进ForContinuationAndIndentation用制表符填充所有前导空白,并使用空格对齐出现在一行内AlignWithSpaces使用制表符进行行继续和缩进,使用空格进行对齐Always每当需要填充至少跨越一个制表位到下一个制表位的空白时,就使用制表符
WhitespaceSensitiveMacros对空白敏感且不应被触及的宏向量
一个可供参考的版本
| |