This is an archive of the discontinued LLVM Phabricator instance.

[clang-format] Avoid unnecessarily aggressive line-breaking when using "LambdaBodyIndentation: OuterScope" with argument bin-packing.
ClosedPublic

Authored by jp4a50 on Apr 12 2023, 7:28 AM.

Details

Summary

The pre-existing logic dictating indentation of function arguments (one or more of which are lambdas) has been heavily tailored towards the default (and historically, the only available) indentation of lambda bodies: "LambdaBodyIndentation: Signature".

Much of that logic has been geared towards avoiding inconsistent, over-indentation of lambdas when passed to functions. See https://reviews.llvm.org/D52676 for context.

When this logic is applied with "LambdaBodyIndentation: OuterScope", it mostly serves to introduce an unnecessary number of line breaks and actually misalign arguments with preceding or proceeding lambdas. This is particularly noticeable when using BinPackArguments: true. The benefits of the pre-existing logic are effectively non-existent when using OuterScope because lambda bodies are *already* consistently and minimally indented by the behaviour of OuterScope.

As such, my aim here is to, for OuterScope only, disable the aforementioned logic.

I'm aware that some of these changes are a little subjective so I am expecting and open to discussion on them! That being said, it's worth bearing in mind that I am acting on behalf of the maintainers/users of the KJ style guide whose preferred style motivated the implementation of OuterScope in the first place. We are attempting to fit to our preferred style (but not overfit to the extent that we contravene behaviour that can be reasonably expected).

Diff Detail

Event Timeline

jp4a50 created this revision.Apr 12 2023, 7:28 AM
Herald added projects: Restricted Project, Restricted Project, Restricted Project. · View Herald TranscriptApr 12 2023, 7:28 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
jp4a50 requested review of this revision.Apr 12 2023, 7:28 AM
jp4a50 edited the summary of this revision. (Show Details)Apr 12 2023, 7:40 AM
jp4a50 edited the summary of this revision. (Show Details)
jp4a50 edited the summary of this revision. (Show Details)Apr 12 2023, 7:43 AM
jp4a50 added inline comments.Apr 12 2023, 7:51 AM
clang/lib/Format/ContinuationIndenter.cpp
342

AFAICT, this only matters when using OuterScope, but it seems like a sensible exception to make in the general case, so I haven't included a check for OuterScope here.

1089

So I genuinely think that the original implementation here (which I've left intact *except* for when OuterScope is enabled) does not match up to the intention expressed in the comment in line 1018.

It effectively seems to assume that the parenthesis level entry which is second from the top is the 'parent' parenthesis level, but this ignores the fact that there are often "fake parens" entries in the parenthesis state stack which presumably should be ignored (as I have done in my implementation for OuterScope).

As such, there are a lot of cases where (when OuterScope is not enabled) we apply BreakBeforeParameter to the *existing* parenthesis level rather than the parent parenthesis level. So when I tried to "fix" this behaviour in the general case it broke a lot of tests, even though I think the behaviour may be what was originally intended.

Happy to discuss this and be proven wrong, but I thought I'd explain why I've added a special case here for OuterScope in even greater detail than I have in the comment.

jp4a50 edited the summary of this revision. (Show Details)Apr 13 2023, 1:50 PM

Hey @MyDeveloperDay @owenpan . I'd appreciate if you guys have time to consider this change. It's the last significant issue my team and I are tracking that's blocking our adoption of clang-format for multiple codebases that use KJ :)

Hey @MyDeveloperDay @owenpan . I'd appreciate if you guys have time to consider this change. It's the last significant issue my team and I are tracking that's blocking our adoption of clang-format for multiple codebases that use KJ :)

We probably should fix https://github.com/llvm/llvm-project/issues/44486 first.

Hey @MyDeveloperDay @owenpan . I'd appreciate if you guys have time to consider this change. It's the last significant issue my team and I are tracking that's blocking our adoption of clang-format for multiple codebases that use KJ :)

We probably should fix https://github.com/llvm/llvm-project/issues/44486 first.

Hi @owenpan . Thanks for your reply. Sorry that I missed it for a while - I stopped monitoring the review after a while and missed the email notification because I hadn't figured out how to make my LLVM email notifications only send me notifications related to my reviews.

I've had a bit of a look into https://github.com/llvm/llvm-project/issues/44486 and I can see why it's happening. It is caused by the unconditional, aggressive line-breaking introduced by https://reviews.llvm.org/D52676 as mkurdej notes on the github issue.

Unfortunately I think the fact that the changes in https://reviews.llvm.org/D52676 were implemented in the TokenAnnotator (rather than ContinuationIndenter) means this will be a non-trivial fix - I don't think the decision to force these line breaks should have been implemented here as there is not enough context to handle edge cases like the one raised in https://github.com/llvm/llvm-project/issues/44486.

I'll have a go at moving the implementation of this behaviour into ContinuationIndenter to see if it allows me to fix the issue. My rough idea is to get the OptimizingLineFormatter to consider either breaking or not breaking before the first argument, but when we don't break before the first argument, disallow line-breaking before any other arguments (in all cases that we have lambda arguments except when there is a single lambda that is the last argument).

Hopefully that should allow us to maintain the same logic as we currently have but also consider the additional case of having all arguments (including the lambdas) on the same line. I doubt it will be as simple as that but thought I'd give you a heads up.

@owenpan I've put up a patch for the bug you mentioned here: https://reviews.llvm.org/D156259

I'll rebase this change on top of that if you like the look of it. It should be fairly trivial to do.

Hello @owenpan , @HazardyKnusperkeks . Now that https://reviews.llvm.org/D156259 is merged, please can you take a look at this change?

clang/docs/ReleaseNotes.rst
169 ↗(On Diff #546004)

Owens comment holds, no bug fix in release notes.

clang/lib/Format/ContinuationIndenter.cpp
1080

I don't know if LLVM has any policy in this regard, but I prefer this.

1103

see above

1110

Drop the if, the loop does the checking.

1111–1112

Would be consistent with the code base.

1125
jp4a50 updated this revision to Diff 554704.Aug 30 2023, 7:08 AM

Address review comments.

jp4a50 marked 6 inline comments as done.Aug 30 2023, 7:09 AM

All comments addressed.

But please wait for other opinions.

This revision is now accepted and ready to land.Aug 30 2023, 8:54 AM
jp4a50 added a comment.Sep 1 2023, 5:49 AM

But please wait for other opinions.

OK sure. @owenpan, any thoughts?

owenpan accepted this revision.Sep 6 2023, 3:10 AM

LG with a couple of minor comments.

clang/lib/Format/ContinuationIndenter.cpp
342

To be consistent with line 1116 below.

clang/unittests/Format/FormatTest.cpp
22576

If so, we should put the test case below in a #if 0-#endif block with a FIXME comment?

jp4a50 updated this revision to Diff 556262.Sep 8 2023, 8:00 AM

Minor review comments.

jp4a50 marked 2 inline comments as done.Sep 8 2023, 8:01 AM

Thanks all. All comments addressed now. Please merge for me once ready.

owenpan added inline comments.Sep 8 2023, 2:20 PM
clang/unittests/Format/FormatTest.cpp
22575

This line is too long. Will fix it before merging.

owenpan retitled this revision from Avoid unnecessarily aggressive line-breaking when using "LambdaBodyIndentation: OuterScope" with argument bin-packing. to [clang-format] Avoid unnecessarily aggressive line-breaking when using "LambdaBodyIndentation: OuterScope" with argument bin-packing..Sep 8 2023, 2:30 PM
This revision was landed with ongoing or failed builds.Sep 8 2023, 2:34 PM
This revision was automatically updated to reflect the committed changes.