clang-format: Add ControlStatementsExceptForEachMacros option to SpaceBeforeParens

Summary: systemd recently added a clang-format file. One issue I
encountered in using clang-format on systemd is that systemd does
not add a space before the parens of their foreach macros but
clang-format always adds a space. This does not seem to be
configurable in clang-format. This revision adds the
ControlStatementsExceptForEachMacros option to SpaceBeforeParens
which puts a space before all control statement parens except
ForEach macros. This drastically reduces the amount of changes
when running clang-format on systemd's source code.

Reviewers: MyDeveloperDay, krasimir, mitchell-stellar

Reviewed By: MyDeveloperDay

Subscribers: cfe-commits

Tags: #clang-format, #clang

Differential Revision: https://reviews.llvm.org/D78869
This commit is contained in:
Daan De Meyer 2020-04-26 14:04:45 +02:00
parent 7fa5abd343
commit f21c704553
5 changed files with 41 additions and 0 deletions

View File

@ -2336,6 +2336,19 @@ the configuration (without a prefix: ``Auto``).
}
}
* ``SBPO_ControlStatementsExceptForEachMacros`` (in configuration: ``ControlStatementsExceptForEachMacros``)
Same as ``SBPO_ControlStatements`` except this option doesn't apply to
ForEach macros. This is useful in projects where ForEach macros are
treated as function calls instead of control statements.
.. code-block:: c++
void f() {
Q_FOREACH(...) {
f();
}
}
* ``SBPO_NonEmptyParentheses`` (in configuration: ``NonEmptyParentheses``)
Put a space before opening parentheses only if the parentheses are not
empty i.e. '()'

View File

@ -1983,6 +1983,17 @@ struct FormatStyle {
/// }
/// \endcode
SBPO_ControlStatements,
/// Same as ``SBPO_ControlStatements`` except this option doesn't apply to
/// ForEach macros. This is useful in projects where ForEach macros are
/// treated as function calls instead of control statements.
/// \code
/// void f() {
/// Q_FOREACH(...) {
/// f();
/// }
/// }
/// \endcode
SBPO_ControlStatementsExceptForEachMacros,
/// Put a space before opening parentheses only if the parentheses are not
/// empty i.e. '()'
/// \code

View File

@ -329,6 +329,8 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
IO.enumCase(Value, "ControlStatements",
FormatStyle::SBPO_ControlStatements);
IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
FormatStyle::SBPO_ControlStatementsExceptForEachMacros);
IO.enumCase(Value, "NonEmptyParentheses",
FormatStyle::SBPO_NonEmptyParentheses);
IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);

View File

@ -2900,6 +2900,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
(Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
return true;
if (Style.SpaceBeforeParens ==
FormatStyle::SBPO_ControlStatementsExceptForEachMacros &&
Left.is(TT_ForEachMacro))
return false;
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
(Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while,

View File

@ -972,6 +972,17 @@ TEST_F(FormatTest, ForEachLoops) {
" UNKNOWN_FORACH(Item * item, itemlist) {}\n"
"}");
FormatStyle Style = getLLVMStyle();
Style.SpaceBeforeParens =
FormatStyle::SBPO_ControlStatementsExceptForEachMacros;
verifyFormat("void f() {\n"
" foreach(Item *item, itemlist) {}\n"
" Q_FOREACH(Item *item, itemlist) {}\n"
" BOOST_FOREACH(Item *item, itemlist) {}\n"
" UNKNOWN_FORACH(Item * item, itemlist) {}\n"
"}",
Style);
// As function-like macros.
verifyFormat("#define foreach(x, y)\n"
"#define Q_FOREACH(x, y)\n"