From f21c704553a8af7012eaf1ab777e2aa1a55cc86d Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Sun, 26 Apr 2020 14:04:45 +0200 Subject: [PATCH] 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 --- clang/docs/ClangFormatStyleOptions.rst | 13 +++++++++++++ clang/include/clang/Format/Format.h | 11 +++++++++++ clang/lib/Format/Format.cpp | 2 ++ clang/lib/Format/TokenAnnotator.cpp | 4 ++++ clang/unittests/Format/FormatTest.cpp | 11 +++++++++++ 5 files changed, 41 insertions(+) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index ce26b06..3ea503a 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -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. '()' diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 011cf59..f8f2903 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -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 diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 961cb92..1fd7d61 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -329,6 +329,8 @@ struct ScalarEnumerationTraits { 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); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 734dbdc..408f68e 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -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, diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 9fdf2e7..aba209b 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -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" -- 2.7.4