I - 前言
clang-format 用于快速格式化代码风格,集成开发环境一般内置支持,如 Visual Studio 。由于使用 Visual Studio 2019 内置的较旧的版本,网上查到很多 clang-format 配置选项不支持,如 AlignConsecutiveMacros 连续的宏对齐 选项,报错如下。
YAML:17:25: error: unknown key 'AlignConsecutiveMacros'
AlignConsecutiveMacros: true
^~~~
Error reading d:\Code.clang-format: invalid argument
集体升级成本又太高,所以使用了旧版 8.0.0。
clang 自 9.0.0 开始支持 AlignConsecutiveMacros 这个选项。
II - 获取和使用配置
.clang-format 文件使用 YAML 格式:
key1: value1
key2: value2
# 注释
不希望被格式化的代码可以通过特定注释 隔离出来。如下
// clang-format off
// clang-format on
使用举例:
some code
// clang-format off
不希望被格式化的代码
// clang-format on
some code
关于如何获取 .clang-format 文件, Visual Studio 如何使用和配置 ,查看以下链接:
《 Visual Studio 2019 设置手动触发 clang-format 格式化 》
https://blog.csdn.net/weixin_44488341/article/details/130292730
示例
# Google C/C++ Code Style settings
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
# Author: Kehan Xue, kehan.xue (at) gmail.com
Language: Cpp
BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: None
AlignOperands: Align
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never # To avoid conflict, set this "Never" and each "if statement" should include brace when coding
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterStruct: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 80
CompactNamespaces: false
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false # Make sure the * or & align on the left
EmptyLineBeforeAccessModifier: LogicalBlock
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Left
ReflowComments: false
# SeparateDefinitionBlocks: Always # Only support since clang-format 14
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++11
TabWidth: 4
UseTab: Never
III - 格式风格可配置选项
此章节仅分享与 C++ 有关的选项, 略去了 Java / Objective-C 及其他语言相关的选项。
clang-format 中的数据类型表
数据类型 | 含义 |
---|---|
string | 字符串 |
bool | 布尔值 |
unsigned | 非负整数 |
int | 整数 |
enum | clang-format 自身的选项 |
vector<string> | 字符串数组 |
3.1 - BasedOnStyle (string)
使用举例
BasedOnStyle: Google
3.2 - AccessModifierOffset (int)
使用举例
AccessModifierOffset: -4
访问标识 (public
, protected
, private
) 的额外缩进或反缩进,设置为 -4 时效果如下,
class Random
{
public:
设置正数 n ,就是额外缩进 n 个字符位,负数就是反向缩进 。
3.3 - Align 对齐
3.3.1 - AlignAfterOpenBracket (enum)
左括号后的参数对齐,这个影响到 小括号、中括号和 大括号。
可以取值:
- Align 在左括号处对齐参数
someLongFunction(argument1, argument2);
- DontAlign 不对齐,换行后根据参数 ContinuationIndentWidth 缩进。
someLongFunction(argument1, argument2);
- AlwaysBreak 如果参数放一行不下,则总是换行。
使用举例someLongFunction( argument1, argument2);
AlignAfterOpenBracket: Align
3.3.2 - AlignConsecutiveAssignments (bool)
对齐连续赋值语句的等号, true 的情况下格式如下int rrrr = 12; int p = 22; int cc = 23;
使用举例:
AlignConsecutiveAssignments: true
3.3.3 - AlignConsecutiveDeclarations (bool)
对齐连续的声明语句的变量名称,为 true 时格式如下
int aaaa = 12;
float b = 23;
std::string str = 23;
使用方法同 3.4
3.3.4 - AlignEscapedNewlines (enum)
对齐语句换行的反斜杠 \
,可取值:
- DontAlign 不对齐
#define A \ int aaaa; \ int b; \ int dddddddddd;
- Left 尽可能靠左对齐
#define A \ int aaaa; \ int b; \ int dddddddddd
- Right 尽可能靠右对齐
#define A \ int aaaa; \ int b; \ int dddddddddd;
3.3.5 - AlignOperands (bool)
对齐操作数,如果为 true,水平对齐二元和三元表达式的操作数。
具体来说,这对齐需要分割成多行的单个表达式的操作数,格式如下int aaa = bbbbbbbbbbbbbbb + ccccccccccccccc;
3.3.6 - AlignTrailingComments (bool)
对齐尾部注释,格式如下true: int a; // My comment a int b = 2; // comment b false: int a; // My comment a int b = 2; // comment about b
3.4 - AllowAllParametersOfDeclarationOnNextLine (bool)
如果函数声明不能放进一行中,允许将函数声明的所有参数放到下一行中,即使BinPackParameters 参数 为 false 。
true:
void myFunction(
int a, int b, int c, int d, int e);
false:
void myFunction(int a,
int b,
int c,
int d,
int e);
3.5 - AllowShort 允许同行短语句
3.5.1 - AllowShortBlocksOnASingleLine (bool)
允许将简单的大括号语句收缩到单行。例如,这允许将以下代码放置在一行中。
if (nullptr == ptr) {
return false; }
3.5.2 - AllowShortCaseLabelsOnASingleLine (bool)
允许将短的 case
语句防置在一行
true: false:
switch (a) {
vs. switch (a) {
case 1: x = 1; break; case 1:
case 2: return; x = 1;
} break;
case 2:
return;
}
3.5.3 - AllowShortFunctionsOnASingleLine (enum)
允许将短的函数放置在同一行
- None
- InineOnly 只合并在类中定义的函数。与 Inline 选项相同,只是它不牵扯到 Empty:即顶层的空函数也不被合并。
class Foo { void f() { foo(); } }; void f() { foo(); } void f() { }
- Empty 仅合并空函数
void f() { } void f2() { bar2(); }
- Inline 仅合并类中定义的函数,牵涉到 Empty
class Foo { void f() { foo(); } }; void f() { foo(); } void f() { }
- All 合并所有的函数放在同一行
class Foo { void f() { foo(); } }; void f() { bar(); }
3.5.4 - AllowShortIfStatementsOnASingleLine (bool)
允许短的 if 语句放置在同一行
if (condition) return;
3.5.5 - AllowShortLoopsOnASingleLine (bool)
允许短的循环放置在同一行
while (condition) continue;
3.6 - AlwaysBreak 总是断行/换行
3.6.1 - AlwaysBreakAfterDefinitionReturnType (enum)
总是在函数定义的返回类型后换行。此选项已被废弃,保留它是为了对旧版本向下兼容。
- None 在返回类型后自动换行。设置后,PenaltyReturnTypeOnItsOwnLine 选项会在格式化时纳入考虑。
- All 总是在返回类型之后换行。
- TopLevel 总是在顶层函数的返回类型之后换行。
3.6.2 - AlwaysBreakAfterReturnType (enum)
总是在返回类型后换行
- None,自动在返回类型后换行,PenaltyReturnTypeOnItsOwnLine会被考虑。
class A { int f() { return 0; }; }; int f(); int f() { return 1; }
- All,总是在返回类型后换行
class A { int f() { return 0; }; }; int f(); int f() { return 1; }
- TopLevel,只在顶层函数返回类型后换行
class A { int f() { return 0; }; }; int f(); int f() { return 1; }
- AllDefinitions,总是在函数定义的返回类型后换行
class A { int f() { return 0; }; }; int f(); int f() { return 1; }
- TopLevelDefinitions,总是在顶层函数定义的返回类型后换行
class A { int f() { return 0; }; }; int f(); int f() { return 1; }
3.6.3 - AlwaysBreakBeforeMultilineStrings (bool)
总是在多行字符串前换行,为 ture 时,总是在多行字符串字面量前换行。
这个标志是为了使文件中存在多个多行字符串的情况看起来更加一致。因此,只有当在字符串从行首缩进 ContinuationIndentWidth 空格时,它才会生效。true: false: aaaa = vs. aaaa = "bbbb" "bbbb" "cccc"; "cccc";
3.6.4 - AlwaysBreakTemplateDeclarations (enum)
总是在模板声明处换行,可设置为: - No,不在声明前强制换行。PenaltyBreakTemplateDeclaration选项会被考虑。
template <typename T> T foo() { } template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbbbbbbbbbb) { }
- MultiLine,仅当模板后的声明跨越多行时,在模板声明后强制换行。
template <typename T> T foo() { } template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbbbbbbbbbb) { }
- Yes,总是在模板声明后换行
template <typename T> T foo() { } template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbbbbbbbbbb) { }
3.7 - BinPack
3.7.1 - BinPackArguments (bool)
打包实参
为 false 时,一个函数调用的参数将全部在同一行,或者每个参数一行。
true:
void f() {
f(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);
}
false:
void f() {
f(aaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);
}
3.7.2 - BinPackParameters (bool)
打包形参
为 false 时,一个函数声明或定义的参数将全部在同一行,或者每行一个。
true:
void f(int aaaaaaaaaaaaaaaaaaaa, int aaaaaaaaaaaaaaaaaaaa,
int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {
}
false:
void f(int aaaaaaaaaaaaaaaaaaaa,
int aaaaaaaaaaaaaaaaaaaa,
int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {
}
3.8 - BraceWrapping (enum)
控制每种单独类型的大括号换行
如果 BreakBeforeBraces 选项设置为 Custom 时,指定此选项来处理每种大括号换行,其他情况下,将忽略此选项。
# Example of usage:
BreakBeforeBraces: Custom
BraceWrapping:
AfterEnum: true
AfterStruct: false
SplitEmptyFunction: false
内部需要配置的标志
- AfterClass(bool),换行类定义
true:
class foo {
};
false:
class foo
{
};
- AfterControlStatement(bool),换行控制语句 (
if/while/for/switch/...
)
true:
if (foo())
{
} else
{
}
for (int i = 0; i < 10; ++i)
{
}
false:
if (foo()) {
} else {
}
for (int i = 0; i < 10; ++i) {
}
- AfterEnum(bool), 枚举定义换行
true:
enum X : int
{
B
};
false:
enum X : int {
B };
- AfterFunction(bool),换行函数定义
true:
void foo()
{
bar();
bar2();
}
false:
void foo() {
bar();
bar2();
}
- AfterNamespace(bool),换行命名空间定义
true:
namespace
{
int foo();
int bar();
}
false:
namespace {
int foo();
int bar();
}
- AfterObjCDeclaration(bool),Objective-C/C++ 相关略去
- AfterStruct(bool),结构体定义换行
true:
struct foo
{
int x;
};
false:
struct foo {
int x;
};
- AfterUnion(bool),联合体定义换行
true:
union foo
{
int x;
}
false:
union foo {
int x;
}
- AfterExternBlock(bool),
extern
语句块换行
true:
extern "C"
{
int foo();
}
false:
extern "C" {
int foo();
}
- BeforeCatch(bool),
catch
前换行
true:
try {
foo();
}
catch () {
}
false:
try {
foo();
} catch () {
}
- BeforeElse(bool),
else
前换行
true:
if (foo()) {
}
else {
}
false:
if (foo()) {
} else {
}
- IndentBraces(bool),缩进换行的大括号
- SplitEmptyFunction(bool)
为 false 时,空函数体可以放置在单行。这个选项只有在函数的开头括号已经被换行,即 AfterFunction 括号换行被设置,并且函数不能/不应该被放在单行上时才会使用(根据 AllowShortFunctionsOnASingleLine 和构造函数格式化选项)。int f() vs. inf f() { } { }
- SplitEmptyRecord(bool),空的记录(例如类、结构或联合体)的主体可以放在单行。这个选项只有在记录的开头大括号已经被换行的情况下使用,即设置了 AfterClass(针对类)大括号换行模式。
class Foo vs. class Foo { } { }
- SplitEmptyNamespace(bool),为 false 时,空的命名空间体可以放在单行上。这个选项只有在命名空间的开头大括号已经被换行,即设置了 AfterNamespace 大括号换行模式时才会使用。
namespace Foo vs. namespace Foo { } { }
3.9 - Break 断行/换行
3.9.1 - BreakAfterJavaFieldAnnotations (bool)
略去3.9.2 - BreakBeforeBinaryOperators (enum)
双目操作符前的换行。 - None,在操作符后换行
LooooooooooongType loooooooooooooooooooooongVariable =
someLooooooooooooooooongFunction();
bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ==
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >
ccccccccccccccccccccccccccccccccccccccccc;
- NonAssignment,在非赋值的操作符前换行
LooooooooooongType loooooooooooooooooooooongVariable =
someLooooooooooooooooongFunction();
bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
== aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
&& aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> ccccccccccccccccccccccccccccccccccccccccc;
- All,在操作符前换行
LooooooooooongType loooooooooooooooooooooongVariable
= someLooooooooooooooooongFunction();
bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
== aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
&& aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> ccccccccccccccccccccccccccccccccccccccccc;
3.9.3 - BreakBeforeBraces (enum)
大括号前的换行风格,可设置为:
- Attach 总是将大括号附加到围绕附近的上下文
try { foo(); } catch () { } void foo() { bar(); } class foo { }; if (foo()) { } else { } enum X : int { A, B };
- Linux,类似 Attach,但在函数、命名空间和类定义的大括号前换行。
try { foo(); } catch () { } void foo() { bar(); } class foo { }; if (foo()) { } else { } enum X : int { A, B };
- Mozilla,类似 Attach,但在枚举、函数和实现定义的大括号前要换行。
try { foo(); } catch () { } void foo() { bar(); } class foo { }; if (foo()) { } else { } enum X : int { A, B };
- Stroustrup,类似 Attach,但在函数定义,
catch
和else
处换行try { foo(); } catch () { } void foo() { bar(); } class foo { }; if (foo()) { } else { } enum X : int { A, B };
- Allman ,总是在大括号前换行
try { foo(); } catch () { } void foo() { bar(); } class foo { }; if (foo()) { } else { } enum X : int { A, B };
- GNU,始终在大括号前换行,并对控制语句的大括号添加额外的缩进,而不对类、函数或其他定义的大括号缩进。
try { foo(); } catch () { } void foo() { bar(); } class foo { }; if (foo()) { } else { } enum X : int { A, B };
- Webkit,类似 Attach,但始终在函数前换行。
try { foo(); } catch () { } void foo() { bar(); } class foo { }; if (foo()) { } else { } enum X : int { A, B };
- Custom 在 BraceWrapping 中配置每个单独的大括号
3.9.4 - BreakBeforeTernaryOperators (bool)
三元操作符之前换行,为 true 时,三元操作符将被放在换行符之后。
true:
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription
? firstValue
: SecondValueVeryVeryVeryVeryLong;
false:
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription ?
firstValue :
SecondValueVeryVeryVeryVeryLong;
3.9.5 - BreakConstructorInitializers (enum)
换行构造函数初始化列表
- BeforeColon在冒号前和逗号后换行构造函数初始化列表。
Constructor() : initializer1(), initializer2()
- BeforeComma 在冒号和逗号之前断行构造函数初始化列表,并将逗号与冒号对齐。
Constructor() : initializer1() , initializer2()
- AfterColon在冒号和逗号之后换行构造函数初始化列表。
Constructor() : initializer1(), initializer2()
3.9.6 - BreakInheritanceList (enum)
断行继承列表,继承列表的样式。 - BeforeColon 在冒号之前和逗号之后换行继承列表。
class Foo : Base1, Base2 { };
- BeforeComma在冒号和逗号之前换行继承列表,并将逗号与冒号对齐。
class Foo : Base1 , Base2 { };
- AfterColon在冒号和逗号之后换行继承列表。
class Foo : Base1, Base2 { };
3.9.7 - BreakStringLiterals (bool)
允许格式化时对字符串字面值换行,个人建议设置为 false。
3.10 - ColumnLimit (unsigned)
一行代码的最大字符数。
为 0 时意味着没有最大字符数限制。在这种情况下,clang-format 将保持输入的语句中的断行形式,除非它们与其他规则相矛盾。
3.11 - CommentPragmas (string)
不修改的注释前缀正则表达式。
一个正则表达式描述具有特殊意义的注释,这个注释不应该被分割换行或以其他方式改变。
// CommentPragmas: '^ FOOBAR pragma:'
// 如下此行不受影响
#include <vector> // FOOBAR pragma: keep
3.12 - CompactNamespaces (bool)
紧凑命名空间
如果为 true,连续的命名空间声明将放置在同一行。如果为 false,每个命名空间将在一个新行中声明。
true:
namespace Foo {
namespace Bar {
}}
false:
namespace Foo {
namespace Bar {
}
}
如果无法放在一行中,多出的命名空间会换行:
namespace Foo {
namespace Bar {
namespace Extra {
}}}
3.13 - Constructor Initializer 构造函数初始化列表
3.13.1 - ConstructorInitializerAllOnOneLineOrOnePerLine (bool)
构造函数初始化列表都在同一行或每行一个,如果一行放不下所有的初始化,把初始化放到适当的行。
true:
SomeClass::Constructor()
: aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa) {
return 0;
}
false:
SomeClass::Constructor()
: aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa),
aaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa) {
return 0;
}
3.13.2 - ConstructorInitializerIndentWidth (unsigned)
构造函数初始化列表缩进宽度。用于缩进构造函数初始化列表以及继承列表的字符数。
3.14 - ContinuationIndentWidth (unsigned)
续行缩进的宽度。
ContinuationIndentWidth: 2
int i = // VeryVeryVeryVeryVeryLongComment
longFunction( // Again a long comment
arg);
3.15 - Cpp11BracedListStyle (bool)
C++11 大括号列表风格。
为 true 时,将格式化括号内的列表为最适合C++11的大括号列表风格。
重要的区别:
- 大括号列表内没有空格。
- 大括号结束前没有换行。
- 使用延续缩进,不使用块缩进。
基本上,C++11的括号列表的格式与函数调用的格式几乎完全相同。如果括号内的列表后面有一个名称(例如一个类型或变量的名字),clang-format 即格式化{}为一个带有该名称的函数调用的括号形式。如果没有名称,则假定有一个零长度的名称。
true: false:
vector<int> x{
1, 2, 3, 4}; vs. vector<int> x{
1, 2, 3, 4 };
vector<T> x{
{
}, {
}, {
}, {
}}; vector<T> x{
{
}, {
}, {
}, {
} };
f(MyMap[{
composite, key}]); f(MyMap[{
composite, key }]);
new int[3]{
1, 2, 3}; new int[3]{
1, 2, 3 };
3.16 - DerivePointerAlignment (bool)
继承点对齐方式。
为 true 时,clang-format 会分析格式化文件中最常用的 &
和 *
的对齐方式。指针和引用的对齐方式将根据文件中发现的偏好进行更新。PointerAlignment 选项仅作为备用。
3.17 - DisableFormat (bool)
是否完全禁用格式化。
3.18 - ExperimentalAutoDetectBinPacking (bool)
如果为 true,clang-format 会检测函数的调用和定义是否格式化为每行一个参数的情况。
每个调用可以是“整体打包”,每行一个或不确定的。如果是不确定的,例如完全在一行上,但需要做出决定,clang-format 会分析输入文件中是否有其他整体打包的情况,并使用相应的格式化。
注:这是一个实验性的标志,可能会弃用或重命名。请不要在配置文件中使用这个标志。使用时需自己评价风险。
3.19 - FixNamespaceComments (bool)
修复命名空间注释,为 true 时,会对命名空间添加丢失的“名称空间的结束注释”并修复无效的现有注释。
true
namespace a {
foo();
} // namespace a;
false
namespace a {
foo();
}
3.20 - ForEachMacros (vector\)
foreach 宏,一个宏的数组,应该被解释为 foreach
循环而不是函数调用。
这些宏应该有以下格式
FOREACH(<variable-declaration>, ...)
<loop-body>
在 .clang-format 文件,此配置项可如下格式设置
ForEachMacros: ['RANGES_FOR', 'FOREACH']
3.21 - Include 头文件
3.21.1 - IncludeBlocks (enum)
include 块,多个#include 块可以作为一个整体进行排序,并根据类别进行分组。
- Preserve每个
#include
块单独排序
#include "b.h" into #include "b.h"
#include <lib/main.h> #include "a.h"
#include "a.h" #include <lib/main.h>
- Merge将多个
#include
块合并为一个整体进行排序
#include "b.h" into #include "a.h"
#include "b.h"
#include <lib/main.h> #include <lib/main.h>
#include "a.h"
- Regroup将多个
#include
块合并在一起,作为一个整体进行排序。然后根据类别的优先级拆分成若干分组。参见 IncludeCategories。
#include "b.h" into #include "a.h"
#include "b.h"
#include <lib/main.h>
#include "a.h" #include <lib/main.h>
3.21.2 - IncludeCategories (vector\)
正则表达式表示不同的 #include 类别,用于排序 #include。
支持POSIX扩展正则表达式。
这些正则表达式与包括的文件名(包括<>或"")依次匹配。属于第一个匹配的正则表达式的值被分配,#include 首先根据增加的类别编号进行排序,然后在每个类别中按字母顺序排序。
如果没有一个正则表达式匹配,INT_MAX 将被指定为类别。一个源文件的主头自动获得类别0。因此它一般被保留在 #include 的开头https://llvm.org/docs/CodingStandards.html#include-style。然而,如果你有某些头文件总是需要放在前面,你也可以指定负的优先级(Priority)。
要在.clang-format文件中配置这个,请使用:
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '<[[:alnum:].]+>'
Priority: 4
- Regex: '.*'
Priority: 1
3.21.3 - IncludeIsMainRegex (string)
主包含的正则表达式。
指定一个后缀名的正则表达式,其表明了文件到主包含映射中允许的后缀名。
当猜测一个 #include 语句是否为“main(主)” include 时 (分配 Category 0,见上文) ,使用这个允许后缀的头文件干的重合词。会进行部分匹配,因此:
""
表示“任意后缀”"$"
表示“无后缀”
例如,如果配置为“(_test)?$ “,则头文件 a.h 将被视为 a.cc 和 a_test.cc 中的"主包含”。
3.22 - Indent 缩进
3.22.1 - IndentCaseLabels (bool)
case
标签的缩进,是否相对 switch
语句多一层次的缩进。
为 false 时,case
标签后面的语句块使用与 switch
标签相同的缩进级别。
false: true:
switch (fool) {
vs. switch (fool) {
case 1: case 1:
bar(); bar();
break; break;
default: default:
plop(); plop();
} }
3.22.2 - IndentPPDirectives (enum)
预处理指令的缩进
- None 不缩进预处理指令
#if FOO #if BAR #include <foo> #endif #endif
- AfterHash
#
符号之后缩进#if FOO # if BAR # include <foo> # endif #endif
3.22.3 - IndentWidth (unsigned)
用于缩进的个列数
3.22.4 - IndentWrappedFunctionNames (bool)
换行的函数名缩进,如果函数定义或声明在类型之后换行,则缩进
true:
LoooooooooooooooooooooooooooooooooooooooongReturnType
LoooooooooooooooooooooooooooooooongFunctionDeclaration();
false:
LoooooooooooooooooooooooooooooooooooooooongReturnType
LoooooooooooooooooooooooooooooooongFunctionDeclaration();
3.23- JavaImportGroups (vector\)
Java import 相关
3.24 - JavaScript
3.24.1 - JavaScriptQuotes (enum)
JavaScript 引号
3.24.2 - JavaScriptWrapImports (bool)
略
3.25- KeepEmptyLinesAtTheStartOfBlocks (bool)
语句块开始前预留一个空行
为 true 时,会在语句块前放置一个空行
true: false:
if (foo) {
vs. if (foo) {
bar();
bar(); }
}
3.26 - Language (enum)
格式化的目标语言
选项值 | 描述 |
---|---|
None | 不使用 |
Cpp | 用于 C, C++. |
Java | 用于 Java. |
JavaScript | 用于 JavaScript. |
ObjC | 用于 Objective-C, Objective-C++. |
Proto | 用于 Protocol Buffers https://developers.google.com/protocol-buffers/. |
TableGen | 用于 TableGen 代码 |
TextProto | 用于 文本格式的 Protocol Buffer 信息 |
3.27 - Macro Block 宏定义块
匹配开始和结束语句块的宏定义正则表达式,用于缩进
3.27.1 - MacroBlockBegin (string)
3.27.2 - MacroBlockEnd (string)
# With:
MacroBlockBegin: "^NS_MAP_BEGIN|\
NS_TABLE_HEAD$"
MacroBlockEnd: "^\
NS_MAP_END|\
NS_TABLE_.*_END$"
NS_MAP_BEGIN
foo();
NS_MAP_END
NS_TABLE_HEAD
bar();
NS_TABLE_FOO_END
# Without:
NS_MAP_BEGIN
foo();
NS_MAP_END
NS_TABLE_HEAD
bar();
NS_TABLE_FOO_END
3.28 - MaxEmptyLinesToKeep (unsigned)
保留连续空行的最大数目
MaxEmptyLinesToKeep: 1 vs. MaxEmptyLinesToKeep: 0
int f() {
int f() {
int = 1; int i = 1;
i = foo();
i = foo(); return i;
}
return i;
}
3.29 - NamespaceIndentation (enum)
命名空间缩进
- None 不缩进命名空间
namespace out { int i; namespace in { int i; } }
- Inner 仅缩进内部的命名空间
namespace out { int i; namespace in { int i; } }
- All 缩进所有的命名空间
namespace out { int i; namespace in { int i; } }
3.30 - Objective-C
略去3.30.1 - ObjCBinPackProtocolList (enum)
3.30.2 - ObjCBlockIndentWidth (unsigned)
3.30.3 - ObjCSpaceAfterProperty (bool)
3.30.4 - ObjCSpaceBeforeProtocolList (bool)
3.31 - Penalty
不同选项换行的罚值,数值越高,优先级越高。
3.31.1 - PenaltyBreakAssignment (unsigned)
赋值断行
3.31.2 - PenaltyBreakBeforeFirstCallParameter (unsigned)
调用函数的第一个参数断行
3.31.3 - PenaltyBreakComment (unsigned)
注释断行
3.31.4 - PenaltyBreakFirstLessLess (unsigned)
<<
字符断行
3.31.5 - PenaltyBreakString (unsigned)
字符串断行
3.31.6 - PenaltyBreakTemplateDeclaration (unsigned)
模板声明断行
3.31.7 - PenaltyExcessCharacter (unsigned)
超出 ColumnLimit 的个字符断行
3.31.8 - PenaltyReturnTypeOnItsOwnLine (unsigned)
返回类型断行
3.32 - PointerAlignment (enum)
指针和引用的对齐风格,即 *
和 &
字符的对齐。
可用值:
- Left 左对齐
char* a;
- Right 右对齐
char *a;
- Middle 居中对齐
char * a;
3.33 - RawStringFormats (vector\)
原生字符串格式,定义用于检测原生字符串中支持的语言代码块的提示。
具有匹配的分隔符或匹配的包围函数名的原始字符串将根据 .clang-format 文件中为该语言设置的样式重新格式化。如果在 .clang-format 文件中没有为特定的语言设置样式,将使用由 BasedOnStyle 选项给出的预定义样式。如果没有找到 BasedOnStyle 选项,将基于 llvm 风格格式化。在确定原始字符串内容的语言时,匹配的分隔符优先于匹配的包围函数名。
如果指定了一个标准的分隔符,可能的话,同一语言出现的其他分隔符将被更新为标准的分隔符。
每种语言最多只能有一个规范,同样的分隔符和包围函数不应出现在多个规范中。
要在 .clang-format 文件中配置这一点,使用:
RawStringFormats:
- Language: TextProto
Delimiters:
- 'pb'
- 'proto'
EnclosingFunctions:
- 'PARSE_TEXT_PROTO'
BasedOnStyle: google
- Language: Cpp
Delimiters:
- 'cc'
- 'cpp'
BasedOnStyle: llvm
CanonicalDelimiter: 'cc'
3.34 - ReflowComments (bool)
为 true 时,clang-format 将尝试续行排版注释。
false:
// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
true:
// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
// information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
* information */
3.35 - Sort 排序
3.35.1 - SortIncludes (bool)
排序 #include
,为 true 时,排序所有头文件包含语句
false: true:
#include "b.h" vs. #include "a.h"
#include "a.h" #include "b.h"
3.35.2 - SortUsingDeclarations (bool)
对 using 声明排序,
为 true 时,会对 using 声明排序。
using 声明的排序定义如下: 用"::"分割字符串,并丢弃所有初始为空的字符串。每个列表的最后一个元素是非命名空间的字符串;所有其他元素是命名空间的字符串。
对字符串列表进行排序,首先排序所有非命名空间,然后排序所有命名空间,在这些组中,排序按照不区分大小写的词典顺序。
false: true:
using std::cout; vs. using std::cin;
using std::cin; using std::cout;
3.36 - Space 空格
3.36.1 - SpaceAfterCStyleCast (bool)
C 风格强转后的空格,为 true 时,会在 )
和 被转换的变量之间插入一个空格。
true: false:
(int) a; vs. (int)a;
3.36.2 - SpaceAfterTemplateKeyword (bool)
template
关键字后的空格,为 true 时,template
关键字之后会插入一个空格。
true: false:
template <int> void Get(); vs. template<int> void Get();
3.36.3 - SpaceBeforeAssignmentOperators (bool)
赋值操作符前的空格,为 false 时,赋值操作符前的空格会被移除。
true: false:
int a = 5; vs. int a=5;
a += 42 a+=42;
3.36.4 - SpaceBeforeCpp11BracedList (bool)
C++11 大括号列表前的空格,C++11 大括号列表用于初始化一个对象
为 true 时,在此种大括号前会添加一个空格。
true: false:
Foo foo {
bar }; vs. Foo foo{
bar };
Foo {
}; Foo{
};
vector<int> {
1, 2, 3 }; vector<int>{
1, 2, 3 };
new int[3] {
1, 2, 3 }; new int[3]{
1, 2, 3 };
3.36.5 - SpaceBeforeCtorInitializerColon (bool)
构造函数初始化冒号前的空格,
为 false 时,将会移除构造函数初始化列表冒号符前的空格。
true: false:
Foo::Foo() : a(a) {
} Foo::Foo(): a(a) {
}
3.36.6 - SpaceBeforeInheritanceColon (bool)
继承冒号前的空格,是否在继承冒号符前加空格
true: false:
class Foo : Bar {
} vs. class Foo: Bar {
}
3.36.7 - SpaceBeforeParens (enum)
小括号前的空格,Parens 简写自 Parentheses (小括号) , 定义在何种情况下,左小括号前会添加一个空格。
- Never 左括号前永远不添加空格。
void f() { if(true) { f(); } }
- ControlStatements 仅对于控制语句 (
for / if / while ...
)后的左括号前添加空格。void f() { if (true) { f(); } }
- Always 除非语法规则禁止(在类似函数的宏定义中)或由其他风格规则决定(在单目运算符后,左括号后,等),否则总是在左括号前加一个空格。
void f () { if (true) { f (); } }
3.36.8 - SpaceBeforeRangeBasedForLoopColon (bool)
基于范围的 for 循环冒号符:
前的空格,示例true: false: for (auto v : values) { } vs. for(auto v: values) { }
3.36.9 - SpaceInEmptyParentheses (bool)
空 (小) 括号中的空格,为 true 时 会在()
之间插入空格
true: false:
void f( ) {
vs. void f() {
int x[] = {
foo( ), bar( )}; int x[] = {
foo(), bar()};
if (true) {
if (true) {
f( ); f();
} }
} }
3.36.10 - SpacesBeforeTrailingComments (unsigned)
语句后的单行注释前的空格数量,非负整数。不影响多行注释 (/*
)。
SpacesBeforeTrailingComments: 3
void f() {
if (true) {
// foo1
f(); // bar
} // foo
}
3.36.11 - SpacesInAngles (bool)
尖括号中的空格,为 true 时,在模板参数列表 <
之后 和 >
之前插入空格。
static_cast< int >(arg); vs. static_cast<int>(arg);
std::function< void(int) > fct; std::function<void(int)> fct;
3.36.12 - SpacesInCStyleCastParentheses (bool)
C 风格转换括号中的空格,为 true 时,会在 C 风格转换的括号中插入空格。
true: false:
x = ( int32 )y vs. x = (int32)y
3.36.13 - SpacesInContainerLiterals (bool)
容器字面量中的空格,为 true 时,在容器字面量之间中插入空格 (例如 ObjC 和Javascript 数组和 dict 字面量)。
true: false:
var arr = [ 1, 2, 3 ]; vs. var arr = [1, 2, 3];
f({
a : 1, b : 2, c : 3}); f({
a: 1, b: 2, c: 3});
3.36.14 - SpacesInParentheses (bool)
小括号中的空格,
为 true 时,在 (
之后 和 )
之前插入空格。
true: false:
t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
3.36.15 - SpacesInSquareBrackets (bool)
方括号中的空格,
为 true 时,则在 [
之后 和 ]
之前插入空格。Lambda 表达式或未指定大小的数组声明不受影响。
true: false:
int a[ 5 ]; vs. int a[5];
std::unique_ptr<int[]> foo() {
} // 不受影响
3.37 - Standard (Enum)
- Cpp03 使用 C++03 适配的语法。
- Cpp11 使用 C++11, C++14 和 C++1z 的特性 如
// 使用 std::vector<std::vector<int>> // 替代 std::vector<std::vector<int> >
- Auto 根据输入自动检测
3.38 - StatementMacros (vector\)
应该被认为是完整语句的宏向量。
通常宏是表达式,需要添加分号;
有时情况并非如此,这需要使 clang-format 将这些未加分号的宏视作一个完整语句来处理。
StatementMacros:["Q_UNUSED",...]
3.39 - TabWidth (unsigned)
制表符宽度,用于替换为多少个空格或 在 3.40 - UseTab 使用制表符时,替换的空白数量。
3.40 - UseTab (enum)
格式化是否使用制表符 即 \t
, 可用值
- Never 从不使用制表符。
- ForIndentation 仅缩进时使用制表符。
- ForContinuationAndIndentation 仅在语句换行继续和缩进时使用制表符。
- Always 每当需要填充空白时,至少从一处空白到下一处空白之间的位置足够容纳下一个制表符时,就使用制表符。
参考链接:https://releases.llvm.org/8.0.0/tools/clang/docs/ClangFormatStyleOptions.html