This is an archive of the discontinued LLVM Phabricator instance.

[clang-format] Add an experimental option to remove optional control statement braces in LLVM C++ code
ClosedPublic

Authored by owenpan on Dec 27 2021, 9:44 AM.

Details

Summary

See the LLVM style examples. This option can be expanded/configured to support other styles.

Diff Detail

Event Timeline

owenpan requested review of this revision.Dec 27 2021, 9:44 AM
owenpan created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptDec 27 2021, 9:45 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Could you have a look at preceding reviews and see if there wasn't a similar patch before?
I think that this option is a bit too limited.
Only removing braces doesn't seem enough.
Also, one should probably be able to decide when to add/remove them by e.g. setting the number of lines in what's considered short blocks.

clang/docs/ClangFormatStyleOptions.rst
3398

I don't think it's a good idea to make this option dependent on a particular style. Even if it works for LLVM style only for the moment.

3419

I'm not sure if the braces on the right should be removed in the for loop.
There should probably be an option to set the minimum number of lines/statements inside a control statement to control adding/removing braces.

Could you have a look at preceding reviews and see if there wasn't a similar patch before?
I think that this option is a bit too limited.
Only removing braces doesn't seem enough.
Also, one should probably be able to decide when to add/remove them by e.g. setting the number of lines in what's considered short blocks.

There is D95168.

clang/lib/Format/UnwrappedLineParser.cpp
484

This is very confusing a variable with the same name as the function.

2179

constexpr or configurable?

2351

I think it is worth to create a RAII type for that.

2946

I would like it better if you insert both arguments.
I don't really like default arguments.

clang/lib/Format/UnwrappedLineParser.h
198

I find it nicely if the order of functions in the cpp is the same as in the hpp.

199
owenpan added inline comments.Dec 28 2021, 2:09 PM
clang/docs/ClangFormatStyleOptions.rst
3419

I'm not sure if the braces on the right should be removed in the for loop.

This is the LLVM style. See also line 23086 in FormatTest.cpp below.

There should probably be an option to set the minimum number of lines/statements inside a control statement to control adding/removing braces.

If you have more than one statement inside a control statement block, the braces must stay.

owenpan updated this revision to Diff 396493.Dec 29 2021, 12:01 AM

Addresses review comments.

owenpan marked 4 inline comments as done.Dec 29 2021, 12:20 AM
owenpan added inline comments.
clang/lib/Format/UnwrappedLineParser.cpp
2179

It will be configurable when we expand removing braces to other styles.

2351

Can you explain why an RAII type would be beneficial here?

2946

I'm the opposite, and parseBlock()is a good example. However, I restored the previously non-default argument.

clang/lib/Format/UnwrappedLineParser.h
198

Me too although some of the functions (e.g. parseCSharpGenericTypeConstraint and parseCSharpAttribute) were already out of order.

owenpan marked 2 inline comments as done.Dec 29 2021, 12:48 AM

Could you have a look at preceding reviews and see if there wasn't a similar patch before?

I conversed with @MyDeveloperDay in D95168. In fact, that was one of the main reasons that I put in extra effort to get this patch done.

I think that this option is a bit too limited.
Only removing braces doesn't seem enough.

I wanted to implement as many features as possible using the limited parser of clang-format, and the LLVM style would be a very high bar to clear. Only focusing on LLVM now will actually make this option less limited if and when we are ready to support other styles. It would be mostly configuring/packaging what have already worked for LLVM.

Also, one should probably be able to decide when to add/remove them by e.g. setting the number of lines in what's considered short blocks.

Agreed, but if clang-format can't do insertion well independent of removal and vice versa, we probably will never get there.

So far, this patch has successfully applied to clang/lib/Format, i.e., it builds successfully and passes FormatTests.

MyDeveloperDay added inline comments.Dec 29 2021, 6:15 AM
clang/docs/ClangFormatStyleOptions.rst
3398

Can we agree on one set of options that can be used for both insertion and removal even if this patch only does removal

clang/unittests/Format/FormatTest.cpp
23224

any reason these can't be verifyFormats?

clang/lib/Format/UnwrappedLineParser.cpp
2351

You have a lot of push/pop pairs. There is the risk someone (in the future) may misuse it.

owenpan updated this revision to Diff 396573.Dec 29 2021, 2:37 PM

Fixed a bug and added a test case.

clang/lib/Format/UnwrappedLineParser.cpp
2303

Why null that?

owenpan added inline comments.Dec 29 2021, 4:50 PM
clang/docs/ClangFormatStyleOptions.rst
3398

I don't think it's a good idea to make this option dependent on a particular style. Even if it works for LLVM style only for the moment.

As @MyDeveloperDay said before, eliding braces was (by far?) the most frequent review comments, and the community would appreciate something like this. So it's likely that this option will get used and experimented, and we will get bug reports and other feedback to improve the functionalities. Once we think it's ready, we can easily configure/package the functionalities for other styles.

3398

Can we agree on one set of options that can be used for both insertion and removal even if this patch only does removal

One idea is to run insertion for all missing braces and then this option to remove the optional ones for LLVM, i.e., an AutomaticBraces if you will.

clang/lib/Format/UnwrappedLineParser.cpp
2351

I see. I will think about it.

clang/unittests/Format/FormatTest.cpp
23224

Did you mean to add the expected part as a separate case? I don't think it would add any value if there are no braces to remove in the first place?

owenpan added inline comments.Dec 29 2021, 5:07 PM
clang/lib/Format/UnwrappedLineParser.cpp
2303

MatchingParen is used to flag braces that may be optional. If it turns out that they should not be removed, we must reset it. Otherwise, the test case on line 23314 in FormatTest.cpp below would fail.

owenpan added inline comments.Dec 29 2021, 10:39 PM
clang/unittests/Format/FormatTest.cpp
23224

Did you mean to add the expected part as a separate case? I don't think it would add any value if there are no braces to remove in the first place?

Nvm. I think you wanted something like verifyFormat(PostformatCode, PreformatCode, Style)? Yes, I could do that, but I would have to relax the restriction to calling BracesRemover() in Format.cpp, i.e. checking isCpp() instead.

clang/lib/Format/UnwrappedLineParser.cpp
2303

Is MatchingParen for (if) braces null before this patch? Because I would expect that always to be set, if there is a matching brace and maybe base patches on that assumption.

owenpan added inline comments.Dec 30 2021, 3:31 PM
clang/lib/Format/UnwrappedLineParser.cpp
2303

Yes, it's not set until it's in the token annotator. That's why I added the assertion in the annotator.

owenpan updated this revision to Diff 397184.Jan 3 2022, 7:27 PM
  • Fixed a bug found by applying the patch on the entire clang source tree.
  • Added an exception: the braces are not removed if the right one is followed by a comment on the same line.
  • Updated an existing test case and added a new one.
owenpan updated this revision to Diff 397783.Jan 5 2022, 8:49 PM

Fixing a couple of major bugs found by running check-clang plus minor bug fixes and cleanup:

  • In parseLevel(), HasOpeningBrace and case tok::r_brace: don't necessarily mean the tokens are { and }, respectively.
  • A pair of braces may be subject to removal even if the } is followed by a non-trailing comment.
  • The newline before a wrapped { should be deleted when removing the braces.
  • precededByCommentOrPPDirective() should be a const member function.
  • The assertion that a { of a control statement block is not parsed more than once is false.

Now this patch not only successfully builds clang but also passes check-clang (by not failing more tests than the current clang-format).

MyDeveloperDay accepted this revision.Jan 6 2022, 1:32 AM

Owen I think we should push ahead with this rather than D95168: [clang-format] Add Insert/Remove Braces option as I've looked at what you've done here I'm reminded that the removal and insertion are likely mutually exclusive operations.

There is no doubt that insertion is desired (so I'd like to see us do that afterwards) but I now think that could be in a completely separate pass as you originally suggested.

LGTM

This revision is now accepted and ready to land.Jan 6 2022, 1:32 AM

Owen I think we should push ahead with this rather than D95168: [clang-format] Add Insert/Remove Braces option as I've looked at what you've done here I'm reminded that the removal and insertion are likely mutually exclusive operations.

There is no doubt that insertion is desired (so I'd like to see us do that afterwards) but I now think that could be in a completely separate pass as you originally suggested.

LGTM

Thanks! I will wait a couple of days in case other reviewers have some final requests.

curdeius accepted this revision.Jan 6 2022, 3:10 AM

LGTM with some nits.

clang/lib/Format/UnwrappedLineParser.cpp
435–458

Please remove unused code.

485

Please remove unused code.

clang/unittests/Format/FormatTest.cpp
23224

👍 you should be able to use the 2-argument version of verifyFormat, no?

owenpan added inline comments.Jan 7 2022, 1:14 AM
clang/lib/Format/UnwrappedLineParser.cpp
435–458

Will do pending D116318.

485

Will do.

clang/unittests/Format/FormatTest.cpp
23224

Will replace all EXPECT_EQs with verifyFormats. Question: when is the former preferred to the latter? It seems EXPECT_EQ is frequently used in FormatTest.cpp.

owenpan updated this revision to Diff 398231.Jan 7 2022, 1:59 PM
  • Use verifyFormat instead of EXPECT_EQ.
  • Make this option have less impact on the unwrapped line parser by checking Style.RemoveBracesLLVM.
  • Remove some unused code.
owenpan marked 3 inline comments as done.Jan 7 2022, 2:03 PM
owenpan updated this revision to Diff 398308.Jan 7 2022, 10:17 PM
  • Rebased to main.
  • Removed unused code.
  • Updated release notes.
owenpan marked an inline comment as done.Jan 7 2022, 10:22 PM
owenpan updated this revision to Diff 398415.Jan 9 2022, 4:41 AM
  • Braces should not be removed if the single-statement block might wrap or is already wrapped.
  • Added test cases.
  • Did a final round of cleanup.
owenpan updated this revision to Diff 398419.Jan 9 2022, 5:12 AM

Fixed a bug and added a test case.

owenpan planned changes to this revision.Jan 9 2022, 2:51 PM
owenpan updated this revision to Diff 398860.Jan 11 2022, 12:20 AM
  • Removed unnecessary code and cleaned up.
  • Tested on clang and check-clang again.
This revision is now accepted and ready to land.Jan 11 2022, 12:20 AM
owenpan requested review of this revision.Jan 11 2022, 2:49 AM
clang/include/clang/Format/Format.h
3055

This should be two warning blocks.

clang/lib/Format/UnwrappedLineParser.cpp
468

This should be an enum, a bool suggests that the return value is a failure/success indicator.

owenpan added inline comments.Jan 12 2022, 9:13 PM
clang/include/clang/Format/Format.h
3055

Can you elaborate? I simply copied the format of the existing warning block. The alignment of the \code block below is off by 1 though.

clang/lib/Format/UnwrappedLineParser.cpp
468

Most of the parse...() functions return void with no indication of pass/fail. Some of them return bool, e.g. parseObjCProtocol(), which doesn't indicate pass/fail according to the function header comment. I will add a similar comment.

HazardyKnusperkeks resigned from this revision.Jan 13 2022, 12:18 AM
HazardyKnusperkeks added inline comments.
clang/include/clang/Format/Format.h
3055

One Warning that the option is going to be renamed.

The other warning regarding the code changes.

clang/lib/Format/UnwrappedLineParser.cpp
468

Yeah I'm out here.

owenpan updated this revision to Diff 399632.Jan 13 2022, 4:24 AM
  • Rebased to main.
  • Addressed review comments.
owenpan marked 2 inline comments as done.Jan 13 2022, 4:26 AM
owenpan updated this revision to Diff 399869.Jan 13 2022, 7:29 PM
  • Fixed a bug that missed braces in nested blocks.
  • Added a test case.

@MyDeveloperDay @curdeius I will land this patch if you have no more comments. :)

curdeius accepted this revision.Jan 14 2022, 3:21 AM

LGTM.

clang/docs/ClangFormatStyleOptions.rst
3398

Have you agreed upon this?

This revision is now accepted and ready to land.Jan 14 2022, 3:21 AM
owenpan added inline comments.Jan 14 2022, 3:28 AM
clang/docs/ClangFormatStyleOptions.rst
3398

Not yet. We probably want to test inserting braces Always on check-clang if it's not already been done.

MyDeveloperDay accepted this revision.Jan 14 2022, 8:40 AM

LGTM go for it.