https://github.com/rmarker updated https://github.com/llvm/llvm-project/pull/143249
>From 212f9142a084c4d7bb11423565fb1f0eae93c35f Mon Sep 17 00:00:00 2001 From: rmarker <rmar...@outlook.com> Date: Sat, 7 Jun 2025 20:29:18 +0930 Subject: [PATCH 1/2] [clang-format] Add options to control wrapped lambda brace indent. Adds options to customise how wrapped lambda braces are indented when using custom brace wrapping. IndentBraces was recently changed to also indent wrapped lambda braces. This has been changed to be controlled separately to allow the old behaviour to be maintained. Especially 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. --- clang/docs/ClangFormatStyleOptions.rst | 34 ++++++++++ clang/docs/ReleaseNotes.rst | 2 + clang/include/clang/Format/Format.h | 32 +++++++++ clang/lib/Format/ContinuationIndenter.cpp | 17 +++-- clang/lib/Format/Format.cpp | 10 +++ clang/unittests/Format/ConfigParseTest.cpp | 2 + clang/unittests/Format/FormatTest.cpp | 78 ++++++++++++++++++++++ 7 files changed, 170 insertions(+), 5 deletions(-) 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; >From b8c94459def487429e8d8fcfb5d67d843de00d0b Mon Sep 17 00:00:00 2001 From: rmarker <rmar...@outlook.com> Date: Sat, 7 Jun 2025 22:06:27 +0930 Subject: [PATCH 2/2] Improve handling of Nested to make it cleaner. --- clang/lib/Format/ContinuationIndenter.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index d37b075da61ae..81d7ad7dd1eeb 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -1335,13 +1335,12 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { } if (Style.BraceWrapping.BeforeLambdaBody && Current.is(TT_LambdaLBrace)) { - const auto Nested = Current.NestingLevel != 0; + const auto Nested = Current.NestingLevel > 0; const auto From = Style.LambdaBodyIndentation == FormatStyle::LBI_Signature ? CurrentState.Indent : State.FirstIndent; - const auto Indent = - (Style.BraceWrapping.IndentBracesLambdaNested && Nested) || - (Style.BraceWrapping.IndentBracesLambdaUnnested && !Nested); + const auto Indent = Nested ? Style.BraceWrapping.IndentBracesLambdaNested + : Style.BraceWrapping.IndentBracesLambdaUnnested; return From + (Indent * Style.IndentWidth); } @@ -2126,10 +2125,9 @@ void ContinuationIndenter::moveStateToNewBlock(LineState &State, bool NewLine) { if (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope && State.NextToken->is(TT_LambdaLBrace) && !State.Line->MightBeFunctionDecl) { - const auto Nested = State.NextToken->NestingLevel != 0; - const auto Indent = - (Style.BraceWrapping.IndentBracesLambdaNested && Nested) || - (Style.BraceWrapping.IndentBracesLambdaUnnested && !Nested); + const auto Nested = State.NextToken->NestingLevel > 0; + const auto Indent = Nested ? Style.BraceWrapping.IndentBracesLambdaNested + : Style.BraceWrapping.IndentBracesLambdaUnnested; State.Stack.back().NestedBlockIndent = State.FirstIndent + (Indent * Style.IndentWidth); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits