[clang] [clang-format] Add options to control wrapped lambda brace indent. (PR #143249)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 7 04:23:37 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (rmarker)
<details>
<summary>Changes</summary>
Adds options to customise how wrapped lambda braces are indented when using custom brace wrapping.
`IndentBraces` was recently updated to also indent wrapped lambda braces. This has been changed to be controlled separately to allow the old behaviour to be maintained. Ideally before a release is made with the new behaviour.
In order to further increase flexibility, the indentation can be controlled separately for both nested and unnested lambdas.
Resolves #<!-- -->143248
---
Full diff: https://github.com/llvm/llvm-project/pull/143249.diff
7 Files Affected:
- (modified) clang/docs/ClangFormatStyleOptions.rst (+34)
- (modified) clang/docs/ReleaseNotes.rst (+2)
- (modified) clang/include/clang/Format/Format.h (+32)
- (modified) clang/lib/Format/ContinuationIndenter.cpp (+12-5)
- (modified) clang/lib/Format/Format.cpp (+10)
- (modified) clang/unittests/Format/ConfigParseTest.cpp (+2)
- (modified) clang/unittests/Format/FormatTest.cpp (+78)
``````````diff
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 83716cc049ee3..5294c77020945 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -2541,6 +2541,40 @@ the configuration (without a prefix: ``Auto``).
* ``bool IndentBraces`` Indent the wrapped braces themselves.
+ * ``bool IndentBracesLambdaNested`` Indent nested wrapped lambda braces.
+
+ .. code-block:: c++
+
+ false:
+ function(
+ []()
+ {
+ return true;
+ });
+
+ true:
+ function(
+ []()
+ {
+ return true;
+ });
+
+ * ``bool IndentBracesLambdaUnnested`` Indent unnested wrapped lambda braces.
+
+ .. code-block:: c++
+
+ false:
+ auto foo = []()
+ {
+ return true;
+ };
+
+ true:
+ auto foo = []()
+ {
+ return true;
+ };
+
* ``bool SplitEmptyFunction`` If ``false``, empty function body can be put on a single line.
This option is used only if the opening brace of the function has
already been wrapped, i.e. the ``AfterFunction`` brace wrapping mode is
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9ab69320f0368..03e33c4fcdc49 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -988,6 +988,8 @@ clang-format
``enum`` enumerator lists.
- Add ``OneLineFormatOffRegex`` option for turning formatting off for one line.
- Add ``SpaceAfterOperatorKeyword`` option.
+- Add ``IndentBracesLambdaNested`` and ``IndentBracesLambdaUnnested`` to
+ ``BraceWrapping`` options for controlling wrapped lambda brace indentation.
clang-refactor
--------------
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 127b1d08919de..86291d6fa845c 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -1547,6 +1547,38 @@ struct FormatStyle {
bool BeforeWhile;
/// Indent the wrapped braces themselves.
bool IndentBraces;
+ /// Indent nested wrapped lambda braces.
+ /// \code
+ /// false:
+ /// function(
+ /// []()
+ /// {
+ /// return true;
+ /// });
+ ///
+ /// true:
+ /// function(
+ /// []()
+ /// {
+ /// return true;
+ /// });
+ /// \endcode
+ bool IndentBracesLambdaNested;
+ /// Indent unnested wrapped lambda braces.
+ /// \code
+ /// false:
+ /// auto foo = []()
+ /// {
+ /// return true;
+ /// };
+ ///
+ /// true:
+ /// auto foo = []()
+ /// {
+ /// return true;
+ /// };
+ /// \endcode
+ bool IndentBracesLambdaUnnested;
/// If ``false``, empty function body can be put on a single line.
/// This option is used only if the opening brace of the function has
/// already been wrapped, i.e. the ``AfterFunction`` brace wrapping mode is
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 4e4e48f90a89f..d37b075da61ae 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -1334,12 +1334,15 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
Style.IndentWidth;
}
- if (Style.BraceWrapping.BeforeLambdaBody &&
- Style.BraceWrapping.IndentBraces && Current.is(TT_LambdaLBrace)) {
+ if (Style.BraceWrapping.BeforeLambdaBody && Current.is(TT_LambdaLBrace)) {
+ const auto Nested = Current.NestingLevel != 0;
const auto From = Style.LambdaBodyIndentation == FormatStyle::LBI_Signature
? CurrentState.Indent
: State.FirstIndent;
- return From + Style.IndentWidth;
+ const auto Indent =
+ (Style.BraceWrapping.IndentBracesLambdaNested && Nested) ||
+ (Style.BraceWrapping.IndentBracesLambdaUnnested && !Nested);
+ return From + (Indent * Style.IndentWidth);
}
if ((NextNonComment->is(tok::l_brace) && NextNonComment->is(BK_Block)) ||
@@ -2123,8 +2126,12 @@ void ContinuationIndenter::moveStateToNewBlock(LineState &State, bool NewLine) {
if (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope &&
State.NextToken->is(TT_LambdaLBrace) &&
!State.Line->MightBeFunctionDecl) {
- const auto Indent = Style.IndentWidth * Style.BraceWrapping.IndentBraces;
- State.Stack.back().NestedBlockIndent = State.FirstIndent + Indent;
+ const auto Nested = State.NextToken->NestingLevel != 0;
+ const auto Indent =
+ (Style.BraceWrapping.IndentBracesLambdaNested && Nested) ||
+ (Style.BraceWrapping.IndentBracesLambdaUnnested && !Nested);
+ State.Stack.back().NestedBlockIndent =
+ State.FirstIndent + (Indent * Style.IndentWidth);
}
unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
// ObjC block sometimes follow special indentation rules.
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index bdaf264e9adce..db0f9f87eeb0a 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -196,6 +196,10 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
+ IO.mapOptional("IndentBracesLambdaNested",
+ Wrapping.IndentBracesLambdaNested);
+ IO.mapOptional("IndentBracesLambdaUnnested",
+ Wrapping.IndentBracesLambdaUnnested);
IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
@@ -1382,6 +1386,8 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
/*BeforeLambdaBody=*/false,
/*BeforeWhile=*/false,
/*IndentBraces=*/false,
+ /*IndentBracesLambdaNested=*/false,
+ /*IndentBracesLambdaUnnested=*/false,
/*SplitEmptyFunction=*/true,
/*SplitEmptyRecord=*/true,
/*SplitEmptyNamespace=*/true};
@@ -1452,6 +1458,8 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
/*BeforeLambdaBody=*/true,
/*BeforeWhile=*/true,
/*IndentBraces=*/true,
+ /*IndentBracesLambdaNested=*/true,
+ /*IndentBracesLambdaUnnested=*/true,
/*SplitEmptyFunction=*/true,
/*SplitEmptyRecord=*/true,
/*SplitEmptyNamespace=*/true};
@@ -1552,6 +1560,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
/*BeforeLambdaBody=*/false,
/*BeforeWhile=*/false,
/*IndentBraces=*/false,
+ /*IndentBracesLambdaNested=*/false,
+ /*IndentBracesLambdaUnnested=*/false,
/*SplitEmptyFunction=*/true,
/*SplitEmptyRecord=*/true,
/*SplitEmptyNamespace=*/true};
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index aedfdd151d6d3..4436e5ef4904f 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -236,6 +236,8 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeLambdaBody);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeWhile);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBracesLambdaNested);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBracesLambdaUnnested);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunction);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyRecord);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyNamespace);
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index c0633ba3c29b3..fa06554ed584c 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -24358,6 +24358,84 @@ TEST_F(FormatTest, LambdaBracesInGNU) {
Style);
}
+TEST_F(FormatTest, LambdaBracesIndentationNested) {
+ auto Style = getLLVMStyle();
+ EXPECT_EQ(Style.LambdaBodyIndentation, FormatStyle::LBI_Signature);
+
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.BeforeLambdaBody = true;
+ verifyFormat("function(\n"
+ " [&]()\n"
+ " {\n"
+ " for (int i = 0; i < y; ++i)\n"
+ " return 97;\n"
+ " });",
+ Style);
+
+ Style.BraceWrapping.IndentBracesLambdaNested = true;
+ verifyFormat("function(\n"
+ " [&]()\n"
+ " {\n"
+ " for (int i = 0; i < y; ++i)\n"
+ " return 97;\n"
+ " });",
+ Style);
+
+ Style.LambdaBodyIndentation = FormatStyle::LBI_OuterScope;
+ verifyFormat("function([&]()\n"
+ " {\n"
+ " for (int i = 0; i < y; ++i)\n"
+ " return 97;\n"
+ " });",
+ Style);
+
+ Style.BraceWrapping.IndentBracesLambdaNested = false;
+ verifyFormat("function([&]()\n"
+ "{\n"
+ " for (int i = 0; i < y; ++i)\n"
+ " return 97;\n"
+ "});",
+ Style);
+}
+
+TEST_F(FormatTest, LambdaBracesIndentationUnnested) {
+ auto Style = getLLVMStyle();
+ EXPECT_EQ(Style.LambdaBodyIndentation, FormatStyle::LBI_Signature);
+
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.BeforeLambdaBody = true;
+ verifyFormat("auto x = [&]()\n"
+ "{\n"
+ " for (int i = 0; i < y; ++i)\n"
+ " return 97;\n"
+ "};",
+ Style);
+
+ Style.BraceWrapping.IndentBracesLambdaUnnested = true;
+ verifyFormat("auto x = [&]()\n"
+ " {\n"
+ " for (int i = 0; i < y; ++i)\n"
+ " return 97;\n"
+ " };",
+ Style);
+
+ Style.LambdaBodyIndentation = FormatStyle::LBI_OuterScope;
+ verifyFormat("auto x = [&]()\n"
+ " {\n"
+ " for (int i = 0; i < y; ++i)\n"
+ " return 97;\n"
+ " };",
+ Style);
+
+ Style.BraceWrapping.IndentBracesLambdaUnnested = false;
+ verifyFormat("auto x = [&]()\n"
+ "{\n"
+ " for (int i = 0; i < y; ++i)\n"
+ " return 97;\n"
+ "};",
+ Style);
+}
+
TEST_F(FormatTest, FormatsBlocks) {
FormatStyle ShortBlocks = getLLVMStyle();
ShortBlocks.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always;
``````````
</details>
https://github.com/llvm/llvm-project/pull/143249
More information about the cfe-commits
mailing list