Skip to content

[clang-format] Weird line breaks with AlignAfterOpenBracket: BlockIndent #103306

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

Closed
lukasberbuer opened this issue Aug 13, 2024 · 4 comments · Fixed by #124998
Closed

[clang-format] Weird line breaks with AlignAfterOpenBracket: BlockIndent #103306

lukasberbuer opened this issue Aug 13, 2024 · 4 comments · Fixed by #124998
Labels
clang-format confirmed Verified by a second party

Comments

@lukasberbuer
Copy link

Following example showcases weird line-breaking choices with AlignAfterOpenBracket: BlockIndent:

  • Pure LLVM style:

    auto result = std::optional<int>(123)
                    .transform([](int n) { return n + 100; })
                    .transform([](int n) {
                        // multiline lambda
                        return std::to_string(n);
                    });
  • With AlignAfterOpenBracket: BlockIndent 💥:

    auto result = std::optional<int>(123).transform([](int n) { return n + 100; }
    ).transform([](int n) {
        // multiline lambda
        return std::to_string(n);
    });
  • Desired output:

    auto result = std::optional<int>(123)
        .transform([](int n) { return n + 100; })
        .transform([](int n) {
            // multiline lambda
            return std::to_string(n);
        });

Any ideas how to fix this? Can it be done just via the config?

.clang-format

---
BasedOnStyle: LLVM
AlignAfterOpenBracket: BlockIndent
AlignOperands: DontAlign
@owenca owenca added the bug Indicates an unexpected problem or unintended behavior label Aug 13, 2024
@llvmbot
Copy link
Member

llvmbot commented Aug 13, 2024

@llvm/issue-subscribers-bug

Author: Lukas Berbuer (lukasberbuer)

Following example showcases weird line-breaking choices with `AlignAfterOpenBracket: BlockIndent`:
  • Pure LLVM style:

    auto result = std::optional&lt;int&gt;(123)
                    .transform([](int n) { return n + 100; })
                    .transform([](int n) {
                        // multiline lambda
                        return std::to_string(n);
                    });
  • With AlignAfterOpenBracket: BlockIndent 💥:

    auto result = std::optional&lt;int&gt;(123).transform([](int n) { return n + 100; }
    ).transform([](int n) {
        // multiline lambda
        return std::to_string(n);
    });
  • Desired output:

    auto result = std::optional&lt;int&gt;(123)
        .transform([](int n) { return n + 100; })
        .transform([](int n) {
            // multiline lambda
            return std::to_string(n);
        });

Any ideas how to fix this? Can it be done just via the config?

.clang-format

---
BasedOnStyle: LLVM
AlignAfterOpenBracket: BlockIndent
AlignOperands: DontAlign

@owenca owenca added confirmed Verified by a second party and removed bug Indicates an unexpected problem or unintended behavior labels Dec 16, 2024
gedare added a commit to gedare/llvm-project that referenced this issue Jan 29, 2025
Near the ColumnLimit a break could be inserted before a right parens with
BlockIndent without a break after the matching left parens. Avoid these
hanging right parens by disallowing breaks before right parens unless
there was a break after the left parens.

Fixes llvm#103306
@gedare
Copy link
Contributor

gedare commented Jan 29, 2025

You can achieve this with the style option from #118409 to reduce the penalty for breaking before the member access, and the fix (pending) from #124998 to avoid breaking the right parens of 123).

You need to set a penalty much lower than the default. 30 seemed to do the trick:

$ cat 103306.c 
auto result = std::optional<int>(123)
                .transform([](int n) { return n + 100; })
                .transform([](int n) {
                    // multiline lambda
                    return std::to_string(n);
                });

$ clang-format --style="{BasedOnStyle: llvm, AlignAfterOpenBracket: BlockIndent, PenaltyBreakBeforeMemberAccess: 30}" 103306.c
auto result = std::optional<int>(123)
                  .transform([](int n) { return n + 100; })
                  .transform([](int n) {
                    // multiline lambda
                    return std::to_string(n);
                  });

@lukasberbuer
Copy link
Author

lukasberbuer commented Jan 31, 2025

Thanks @gedare, this solves most of this formatting issue.
Is there any way to control the indentation of member access after a line break?

- auto result = std::optional<int>(123)
-                 .transform([](int n) { return n + 100; });
+ auto result = std::optional<int>(123)
+     .transform([](int n) { return n + 100; });

@gedare
Copy link
Contributor

gedare commented Jan 31, 2025

Thanks @gedare, this solves most of this formatting issue. Is there any way to control the indentation of member access after a line break?

  • auto result = std::optional(123)
  •             .transform([](int n) { return n + 100; });
    
  • auto result = std::optional(123)
  • .transform([](int n) { return n + 100; });
    

The BlockIndent option uses the ContinuationIndent. I think this might interact withAlignOperands

swift-ci pushed a commit to swiftlang/llvm-project that referenced this issue Apr 25, 2025
Near the ColumnLimit a break could be inserted before a right parens
with BlockIndent without a break after the matching left parens. Avoid
these hanging right parens by disallowing breaks before right parens
unless there was a break after the left parens.

Fixes llvm#103306

(cherry picked from commit b873479)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang-format confirmed Verified by a second party
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants