[clang] c12aa69 - [clang-format] Add BracedInitializerIndentWidth option
Owen Pan via cfe-commits
cfe-commits at lists.llvm.org
Sat Apr 29 00:36:35 PDT 2023
Author: Jon Phillips
Date: 2023-04-29T00:36:19-07:00
New Revision: c12aa69a0be9acd0c751bf92318050d2b3730f9b
URL: https://github.com/llvm/llvm-project/commit/c12aa69a0be9acd0c751bf92318050d2b3730f9b
DIFF: https://github.com/llvm/llvm-project/commit/c12aa69a0be9acd0c751bf92318050d2b3730f9b.diff
LOG: [clang-format] Add BracedInitializerIndentWidth option
The option allows users to specify how many columns to use to indent
the contents of initializer lists.
Closes #51070.
Differential Revision: https://reviews.llvm.org/D146101
Added:
Modified:
clang/docs/ClangFormatStyleOptions.rst
clang/docs/ReleaseNotes.rst
clang/docs/tools/dump_format_style.py
clang/include/clang/Format/Format.h
clang/lib/Format/ContinuationIndenter.cpp
clang/lib/Format/Format.cpp
clang/unittests/Format/ConfigParseTest.cpp
clang/unittests/Format/FormatTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 2e9038933c814..bdcd1e88d2404 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1829,6 +1829,41 @@ the configuration (without a prefix: ``Auto``).
}
+.. _BracedInitializerIndentWidth:
+
+**BracedInitializerIndentWidth** (``Unsigned``) :versionbadge:`clang-format 17` :ref:`¶ <BracedInitializerIndentWidth>`
+ The number of columns to use to indent the contents of braced init lists.
+ If unset, ``ContinuationIndentWidth`` is used.
+
+ .. code-block:: c++
+
+ AlignAfterOpenBracket: AlwaysBreak
+ BracedInitializerIndentWidth: 2
+
+ void f() {
+ SomeClass c{
+ "foo",
+ "bar",
+ "baz",
+ };
+ auto s = SomeStruct{
+ .foo = "foo",
+ .bar = "bar",
+ .baz = "baz",
+ };
+ SomeArrayT a[3] = {
+ {
+ foo,
+ bar,
+ },
+ {
+ foo,
+ bar,
+ },
+ SomeArrayT{},
+ };
+ }
+
.. _BreakAfterAttributes:
**BreakAfterAttributes** (``AttributeBreakingStyle``) :versionbadge:`clang-format 16` :ref:`¶ <BreakAfterAttributes>`
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 55fc0e6c790ba..d66993b0929fb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -513,6 +513,8 @@ clang-format
- Add additional Qualifier Ordering support for special cases such
as templates, requires clauses, long qualified names.
- Fix all known issues associated with ``LambdaBodyIndentation: OuterScope``.
+- Add ``BracedInitializerIndentWidth`` which can be used to configure
+ the indentation level of the contents of braced init lists.
libclang
--------
diff --git a/clang/docs/tools/dump_format_style.py b/clang/docs/tools/dump_format_style.py
index fe6e9147ee94f..7b032894ce62c 100755
--- a/clang/docs/tools/dump_format_style.py
+++ b/clang/docs/tools/dump_format_style.py
@@ -69,9 +69,13 @@ def to_yaml_type(typestr: str):
elif typestr == 'std::string':
return 'String'
- subtype, napplied = re.subn(r'^std::vector<(.*)>$', r'\1', typestr)
- if napplied == 1:
- return 'List of ' + pluralize(to_yaml_type(subtype))
+ match = re.match(r'std::vector<(.*)>$', typestr)
+ if match:
+ return 'List of ' + pluralize(to_yaml_type(match.group(1)))
+
+ match = re.match(r'std::optional<(.*)>$', typestr)
+ if match:
+ return to_yaml_type(match.group(1))
return typestr
@@ -331,7 +335,8 @@ class State:
if option.type not in ['bool', 'unsigned', 'int', 'std::string',
'std::vector<std::string>',
'std::vector<IncludeCategory>',
- 'std::vector<RawStringFormat>']:
+ 'std::vector<RawStringFormat>',
+ 'std::optional<unsigned>']:
if option.type in enums:
option.enum = enums[option.type]
elif option.type in nested_structs:
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 980e6297fd6ac..40f1ae0b49d46 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -944,6 +944,39 @@ struct FormatStyle {
/// \version 12
BitFieldColonSpacingStyle BitFieldColonSpacing;
+ /// The number of columns to use to indent the contents of braced init lists.
+ /// If unset, ``ContinuationIndentWidth`` is used.
+ /// \code
+ /// AlignAfterOpenBracket: AlwaysBreak
+ /// BracedInitializerIndentWidth: 2
+ ///
+ /// void f() {
+ /// SomeClass c{
+ /// "foo",
+ /// "bar",
+ /// "baz",
+ /// };
+ /// auto s = SomeStruct{
+ /// .foo = "foo",
+ /// .bar = "bar",
+ /// .baz = "baz",
+ /// };
+ /// SomeArrayT a[3] = {
+ /// {
+ /// foo,
+ /// bar,
+ /// },
+ /// {
+ /// foo,
+ /// bar,
+ /// },
+ /// SomeArrayT{},
+ /// };
+ /// }
+ /// \endcode
+ /// \version 17
+ std::optional<unsigned> BracedInitializerIndentWidth;
+
/// Different ways to wrap braces after control statements.
enum BraceWrappingAfterControlStatementStyle : int8_t {
/// Never wrap braces after a control statement.
@@ -4286,6 +4319,7 @@ struct FormatStyle {
BinPackArguments == R.BinPackArguments &&
BinPackParameters == R.BinPackParameters &&
BitFieldColonSpacing == R.BitFieldColonSpacing &&
+ BracedInitializerIndentWidth == R.BracedInitializerIndentWidth &&
BreakAfterAttributes == R.BreakAfterAttributes &&
BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations &&
BreakArrays == R.BreakArrays &&
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index f5748cfc50890..fbd11a4cb48c7 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -1665,10 +1665,14 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
if (Current.opensBlockOrBlockTypeList(Style)) {
NewIndent = Style.IndentWidth +
std::min(State.Column, CurrentState.NestedBlockIndent);
+ } else if (Current.is(tok::l_brace)) {
+ NewIndent =
+ CurrentState.LastSpace + Style.BracedInitializerIndentWidth.value_or(
+ Style.ContinuationIndentWidth);
} else {
NewIndent = CurrentState.LastSpace + Style.ContinuationIndentWidth;
}
- const FormatToken *NextNoComment = Current.getNextNonComment();
+ const FormatToken *NextNonComment = Current.getNextNonComment();
bool EndsInComma = Current.MatchingParen &&
Current.MatchingParen->Previous &&
Current.MatchingParen->Previous->is(tok::comma);
@@ -1676,9 +1680,9 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
Style.Language == FormatStyle::LK_Proto ||
Style.Language == FormatStyle::LK_TextProto ||
!Style.BinPackArguments ||
- (NextNoComment &&
- NextNoComment->isOneOf(TT_DesignatedInitializerPeriod,
- TT_DesignatedInitializerLSquare));
+ (NextNonComment && NextNonComment->isOneOf(
+ TT_DesignatedInitializerPeriod,
+ TT_DesignatedInitializerLSquare));
BreakBeforeParameter = EndsInComma;
if (Current.ParameterCount > 1)
NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index dbab367bdb88c..f7c82c581bfc9 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -879,6 +879,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("BinPackArguments", Style.BinPackArguments);
IO.mapOptional("BinPackParameters", Style.BinPackParameters);
IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
+ IO.mapOptional("BracedInitializerIndentWidth",
+ Style.BracedInitializerIndentWidth);
IO.mapOptional("BraceWrapping", Style.BraceWrapping);
IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);
IO.mapOptional("BreakAfterJavaFieldAnnotations",
@@ -1337,6 +1339,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
LLVMStyle.BinPackArguments = true;
LLVMStyle.BinPackParameters = true;
+ LLVMStyle.BracedInitializerIndentWidth = std::nullopt;
LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
/*AfterClass=*/false,
/*AfterControlStatement=*/FormatStyle::BWACS_Never,
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index b2d79f4ca11e6..0e47abed12472 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -247,6 +247,8 @@ TEST(ConfigParseTest, ParsesConfiguration) {
SpacesBeforeTrailingComments, 1234u);
CHECK_PARSE("IndentWidth: 32", IndentWidth, 32u);
CHECK_PARSE("ContinuationIndentWidth: 11", ContinuationIndentWidth, 11u);
+ CHECK_PARSE("BracedInitializerIndentWidth: 34", BracedInitializerIndentWidth,
+ 34);
CHECK_PARSE("CommentPragmas: '// abc$'", CommentPragmas, "// abc$");
Style.QualifierAlignment = FormatStyle::QAS_Right;
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index c5c1f2150d3b1..5db947abff8c8 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -4855,6 +4855,191 @@ TEST_F(FormatTest, DesignatedInitializers) {
" [5] = eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee};");
}
+TEST_F(FormatTest, BracedInitializerIndentWidth) {
+ auto Style = getLLVMStyleWithColumns(60);
+ Style.BinPackArguments = true;
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.BracedInitializerIndentWidth = 6;
+
+ // Non-initializing braces are unaffected by BracedInitializerIndentWidth.
+ verifyFormat("enum class {\n"
+ " One,\n"
+ " Two,\n"
+ "};\n",
+ Style);
+ verifyFormat("class Foo {\n"
+ " Foo() {}\n"
+ " void bar();\n"
+ "};\n",
+ Style);
+ verifyFormat("void foo() {\n"
+ " auto bar = baz;\n"
+ " return baz;\n"
+ "};\n",
+ Style);
+ verifyFormat("auto foo = [&] {\n"
+ " auto bar = baz;\n"
+ " return baz;\n"
+ "};\n",
+ Style);
+ verifyFormat("{\n"
+ " auto bar = baz;\n"
+ " return baz;\n"
+ "};\n",
+ Style);
+ // Non-brace initialization is unaffected by BracedInitializerIndentWidth.
+ verifyFormat("SomeClass clazz(\n"
+ " \"xxxxxxxxxxxxxxxxxx\", \"yyyyyyyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzzzzzzz\");\n",
+ Style);
+
+ // The following types of initialization are all affected by
+ // BracedInitializerIndentWidth. Aggregate initialization.
+ verifyFormat("int LooooooooooooooooooooooooongVariable[2] = {\n"
+ " 10000000, 20000000};",
+ Style);
+ verifyFormat("SomeStruct s{\n"
+ " \"xxxxxxxxxxxxxxxx\", \"yyyyyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzzzzz\"};\n",
+ Style);
+ // Designated initializers.
+ verifyFormat("int LooooooooooooooooooooooooongVariable[1] = {\n"
+ " [0] = 10000000, [1] = 20000000};",
+ Style);
+ verifyFormat("SomeStruct s{\n"
+ " .foo = \"xxxxxxxxxxxxx\",\n"
+ " .bar = \"yyyyyyyyyyyyy\",\n"
+ " .baz = \"zzzzzzzzzzzzz\"};\n",
+ Style);
+ // List initialization.
+ verifyFormat("SomeStruct s{\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ "};\n",
+ Style);
+ verifyFormat("SomeStruct{\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ "};\n",
+ Style);
+ verifyFormat("new SomeStruct{\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ "};\n",
+ Style);
+ // Member initializer.
+ verifyFormat("class SomeClass {\n"
+ " SomeStruct s{\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ " };\n"
+ "};\n",
+ Style);
+ // Constructor member initializer.
+ verifyFormat("SomeClass::SomeClass : strct{\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ " } {}\n",
+ Style);
+ // Copy initialization.
+ verifyFormat("SomeStruct s = SomeStruct{\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ "};\n",
+ Style);
+ // Copy list initialization.
+ verifyFormat("SomeStruct s = {\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ "};\n",
+ Style);
+ // Assignment operand initialization.
+ verifyFormat("s = {\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ "};\n",
+ Style);
+ // Returned object initialization.
+ verifyFormat("return {\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ "};\n",
+ Style);
+ // Initializer list.
+ verifyFormat("auto initializerList = {\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ "};\n",
+ Style);
+ // Function parameter initialization.
+ verifyFormat("func({\n"
+ " \"xxxxxxxxxxxxx\",\n"
+ " \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\",\n"
+ "});\n",
+ Style);
+ // Nested init lists.
+ verifyFormat("SomeStruct s = {\n"
+ " {{init1, init2, init3, init4, init5},\n"
+ " {init1, init2, init3, init4, init5}}};\n",
+ Style);
+ verifyFormat("SomeStruct s = {\n"
+ " {{\n"
+ " .init1 = 1,\n"
+ " .init2 = 2,\n"
+ " .init3 = 3,\n"
+ " .init4 = 4,\n"
+ " .init5 = 5,\n"
+ " },\n"
+ " {init1, init2, init3, init4, init5}}};\n",
+ Style);
+ verifyFormat("SomeArrayT a[3] = {\n"
+ " {\n"
+ " foo,\n"
+ " bar,\n"
+ " },\n"
+ " {\n"
+ " foo,\n"
+ " bar,\n"
+ " },\n"
+ " SomeArrayT{},\n"
+ "}\n",
+ Style);
+ verifyFormat("SomeArrayT a[3] = {\n"
+ " {foo},\n"
+ " {\n"
+ " {\n"
+ " init1,\n"
+ " init2,\n"
+ " init3,\n"
+ " },\n"
+ " {\n"
+ " init1,\n"
+ " init2,\n"
+ " init3,\n"
+ " },\n"
+ " },\n"
+ " {baz},\n"
+ "}\n",
+ Style);
+
+ // Aligning after open braces unaffected by BracedInitializerIndentWidth.
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_Align;
+ verifyFormat("SomeStruct s{\"xxxxxxxxxxxxx\", \"yyyyyyyyyyyyy\",\n"
+ " \"zzzzzzzzzzzzz\"};\n",
+ Style);
+}
+
TEST_F(FormatTest, NestedStaticInitializers) {
verifyFormat("static A x = {{{}}};\n");
verifyFormat("static A x = {{{init1, init2, init3, init4},\n"
More information about the cfe-commits
mailing list