Skip to content

[clang-format] Stop moving lambda to new line only to indent it more. #141576

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

rmarker
Copy link
Contributor

@rmarker rmarker commented May 27, 2025

Hanging indents are minimised for lambdas by pushing them onto a new line. However, it could still do this even if it would cause even more hanging indents than it otherwise would.

The handling has been expanded to check for this case and avoid moving the lambda to a new line.

Fix #141575

@llvmbot
Copy link
Member

llvmbot commented May 27, 2025

@llvm/pr-subscribers-clang-format

Author: None (rmarker)

Changes

Hanging indents are minimised for lambdas by pushing them onto a new line. However, it could still do this even if it would cause even more hanging indents than it otherwise would.

The handling has been expanded to check for this case and avoid moving the lambda to a new line.

Fix #141575


Full diff: https://github.com/llvm/llvm-project/pull/141576.diff

2 Files Affected:

  • (modified) clang/lib/Format/ContinuationIndenter.cpp (+21-4)
  • (modified) clang/unittests/Format/FormatTest.cpp (+14)
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 4e4e48f90a89f..c6c21c4a5ffcd 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -325,13 +325,30 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
   if (Current.isMemberAccess() && CurrentState.ContainsUnwrappedBuilder)
     return false;
 
-  // Don't create a 'hanging' indent if there are multiple blocks in a single
-  // statement and we are aligning lambda blocks to their signatures.
-  if (Previous.is(tok::l_brace) && State.Stack.size() > 1 &&
+  // Force a lambda onto a new line so that we don't create a 'hanging' indent
+  // if there are multiple blocks in a single statement and we are aligning
+  // lambda blocks to their signatures.
+  if (Previous.is(tok::l_brace) && State.Stack.size() > 2 &&
       State.Stack[State.Stack.size() - 2].NestedBlockInlined &&
       State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks &&
       Style.LambdaBodyIndentation == FormatStyle::LBI_Signature) {
-    return false;
+    if (!Style.isCpp())
+      return false;
+
+    // Make sure to push lambdas to a new line when they are an argument with
+    // other arguments preceding them.
+    if (State.Stack[State.Stack.size() - 2].StartOfFunctionCall > 0)
+      return false;
+
+    // Only force a new line if it is not just going to create a worse hanging
+    // indent. Otherwise, based on the ContinuationIndentWidth, we could end up
+    // more indented than we would've been. To avoid odd looking breaks, make
+    // sure we save at least IndentWidth.
+    if (State.Stack[State.Stack.size() - 3].Indent +
+            Style.ContinuationIndentWidth + Style.IndentWidth <
+        State.Stack[State.Stack.size() - 2].Indent) {
+      return false;
+    }
   }
 
   // Don't break after very short return types (e.g. "void") as that is often
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index c0633ba3c29b3..e55d82ca82c8b 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -23814,6 +23814,20 @@ TEST_F(FormatTest, FormatsLambdas) {
                "}",
                LLVMWithBeforeLambdaBody);
 
+  // Make sure we don't put the lambda on a new line when it would be indented
+  // more than where it would be otherwise.
+  verifyFormat("if ([]()\n"
+               "    {\n"
+               "      return true;\n"
+               "    }()) {\n"
+               "}",
+               LLVMWithBeforeLambdaBody);
+  verifyFormat("fun([]()\n"
+               "    {\n"
+               "      return 17;\n"
+               "    });",
+               LLVMWithBeforeLambdaBody);
+
   LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
       FormatStyle::ShortLambdaStyle::SLS_Empty;
   verifyFormat("FctWithOneNestedLambdaInline_SLS_Empty(\n"

Copy link
Contributor

@HazardyKnusperkeks HazardyKnusperkeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please wait for @owenca or @mydeveloperday.

@rmarker
Copy link
Contributor Author

rmarker commented Jun 10, 2025

Ping @owenca, @mydeveloperday.

Style.LambdaBodyIndentation == FormatStyle::LBI_Signature) {
return false;
if (!Style.isCpp())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems weird as LambdaBodyIndentation only applies to C++.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is weird.
Without it though, the test FormatTestJava.FormatsInnerBlocks fails.
It looks like formatting for other languages ended up inadvertently depending on it.
I figured that this was the least risky way of changing any existing formatting.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hanging indents are minimised for lambdas by pushing them onto a new
line. However, it could still do this even if it would cause even more
hanging indents than it otherwise would.

The handling has been expanded to check for this case and avoid moving
the lambda to a new line.
@rmarker
Copy link
Contributor Author

rmarker commented Jun 16, 2025

Updated to address merge conflict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clang-format] Lambda hanging indent increased by moving to a new line
4 participants