-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang-format] Fix erroneous BraceWrapping.BeforeLambdaBody column calcs #76673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
0488584
346e7da
4f35985
6c55959
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22965,6 +22965,84 @@ TEST_F(FormatTest, EmptyLinesInLambdas) { | |
| "};"); | ||
| } | ||
|
|
||
| TEST_F(FormatTest, BreakBeforeLambdaBodyWrapping) { | ||
| verifyFormat("connect([]() {\n" | ||
| " foo();\n" | ||
| " bar();\n" | ||
| "});"); | ||
|
|
||
| auto Style = getLLVMStyle(); | ||
| Style.BreakBeforeBraces = FormatStyle::BS_Custom; | ||
| Style.BraceWrapping.BeforeLambdaBody = true; | ||
|
|
||
| verifyFormat("connect(\n" | ||
| " []()\n" | ||
| " {\n" | ||
| " foo();\n" | ||
| " bar();\n" | ||
| " });", | ||
| Style); | ||
|
|
||
| for (unsigned l : {0, 41}) { | ||
|
||
| Style.ColumnLimit = l; | ||
| verifyFormat("auto lambda = []() { return foo + bar; };", Style); | ||
| } | ||
| for (unsigned l : {40, 22}) { | ||
| Style.ColumnLimit = l; | ||
| verifyFormat("auto lambda = []()\n" | ||
| "{ return foo + bar; };", | ||
| Style); | ||
| } | ||
| Style.ColumnLimit = 21; | ||
| verifyFormat("auto lambda = []()\n" | ||
| "{\n" | ||
| " return foo + bar;\n" | ||
| "};", | ||
| Style); | ||
|
|
||
| for (unsigned l : {0, 67}) { | ||
| Style.ColumnLimit = l; | ||
| verifyFormat( | ||
| "auto result = [](int foo, int bar) { return foo + bar; }(foo, bar);", | ||
| Style); | ||
| } | ||
| Style.ColumnLimit = 66; | ||
| verifyFormat("auto result = [](int foo, int bar)\n" | ||
| "{ return foo + bar; }(foo, bar);", | ||
| Style); | ||
|
|
||
| Style.ColumnLimit = 36; | ||
| verifyFormat("myFunc([&]() { return foo + bar; });", Style); | ||
| Style.ColumnLimit = 35; | ||
| verifyFormat("myFunc([&]()\n" | ||
| " { return foo + bar; });", | ||
| Style); | ||
|
|
||
| Style = getGoogleStyleWithColumns(100); | ||
| Style.BreakBeforeBraces = FormatStyle::BS_Allman; | ||
| Style.IndentWidth = 4; | ||
| verifyFormat( | ||
| "void Func()\n" | ||
| "{\n" | ||
| " []()\n" | ||
| " {\n" | ||
| " return TestVeryLongThingName::TestVeryLongFunctionName()\n" | ||
| " .TestAnotherVeryVeryLongFunctionName();\n" | ||
| " }\n" | ||
| "}\n", | ||
| Style); | ||
| verifyFormat( | ||
| "void Func()\n" | ||
| "{\n" | ||
| " []()\n" | ||
| " {\n" | ||
| " return TestVeryLongThingName::TestVeryLongFunctionName()\n" | ||
| " .TestAnotherVeryVeryVeryLongFunctionName();\n" | ||
| " }\n" | ||
| "}\n", | ||
| Style); | ||
| } | ||
|
|
||
| TEST_F(FormatTest, FormatsBlocks) { | ||
| FormatStyle ShortBlocks = getLLVMStyle(); | ||
| ShortBlocks.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed there is code in
TokenAnnotatorthan can setMustBreakBeforeon the lambda left brace token:llvm-project/clang/lib/Format/TokenAnnotator.cpp
Lines 5297 to 5299 in 0e01c72
Introduced in 37c2233 seemingly for code like this:
Both before this current PR and here the
MustBreakBeforefield of theCurrenttoken is ignored. Should behavior change to observe this and thus force a break?Would seem the BraceWrapping.BeforeLambdaBody setting would then force lambda across multiple lines if on, but not if off.
Should the code in
TokenAnnotatorbe changed and maybe only setCanBreakBefore?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So as far as I put everything together we should break before the
{, ifBeforeLambdaBodyis set. Except for short lambdas, ifAllowShortLambdasOnASingleLinematches our lambda and it would fit on a single line. If the lambda has to be broken somewhere, it should break before{.What is needed to be changed I don't know, but also have not the time to investigate. I'm willing to hear your analysis, or maybe @mydeveloperday can shed some light into the issue?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@HazardyKnusperkeks - sorry late response. After looking into it, I don't believe there's an issue.
The code I was talking about above:
llvm-project/clang/lib/Format/TokenAnnotator.cpp
Lines 5297 to 5299 in 0e01c72
Results in
MustBreakBeforebeing set for the token (the left lambda brace), which therefore results inCanBreakBeforebeing set. The code exists as there's conditions (e.g.Left.is(TT_PointerOrReference)) inTokenAnnotator::canBreakBefore()which returnfalsefor the left lambda brace in lambdas like these:It's the fact it sets
CanBreakBeforethat matters so it enters the lambda section inContinuationIndenter::mustBreak().Just checking
Current.MatchingParen->MustBreakBeforeinside is sufficient asTokenAnnotator::mustBreakBefore()returnstruewhen it is called for the right lambda:llvm-project/clang/lib/Format/TokenAnnotator.cpp
Lines 5283 to 5293 in 0e01c72
Thus there is no need to look at
Current.MustBreakBefore. However the generic condition that checksCurrent.MustBreakBeforefor all tokens is in the condition for the nextif()statement down, so could move the lambdaif()statement down beneath that. But there's no need to do this at the moment.So this PR looks OK as-is with respect to this.