diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2287,6 +2287,9 @@ int a[ 5 ]; vs. int a[5]; std::unique_ptr foo() {} // Won't be affected +**SpacesAroundConditions** (``bool``) + If ``true``, spaces will be inserted around if/for/while (and similar) conditions. + **Standard** (``LanguageStandard``) Format compatible with this standard, e.g. use ``A >`` instead of ``A>`` for ``LS_Cpp03``. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1945,6 +1945,10 @@ /// \endcode bool SpacesInSquareBrackets; + /// \brief If ``true``, spaces will be inserted around if/for/while (and + /// similar) conditions. + bool SpacesAroundConditions; + /// Supported language standards. enum LanguageStandard { /// Use C++03-compatible syntax. @@ -2081,6 +2085,7 @@ SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses && SpacesInParentheses == R.SpacesInParentheses && SpacesInSquareBrackets == R.SpacesInSquareBrackets && + SpacesAroundConditions == R.SpacesAroundConditions && Standard == R.Standard && TabWidth == R.TabWidth && StatementMacros == R.StatementMacros && UseTab == R.UseTab && TypenameMacros == R.TypenameMacros; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -517,6 +517,7 @@ Style.SpacesInCStyleCastParentheses); IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses); IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); + IO.mapOptional("SpacesAroundConditions", Style.SpacesAroundConditions); IO.mapOptional("Standard", Style.Standard); IO.mapOptional("StatementMacros", Style.StatementMacros); IO.mapOptional("TabWidth", Style.TabWidth); @@ -775,6 +776,7 @@ LLVMStyle.SpaceBeforeAssignmentOperators = true; LLVMStyle.SpaceBeforeCpp11BracedList = false; LLVMStyle.SpacesInAngles = false; + LLVMStyle.SpacesAroundConditions = false; LLVMStyle.PenaltyBreakAssignment = prec::Assignment; LLVMStyle.PenaltyBreakComment = 300; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2505,6 +2505,18 @@ return Right.is(tok::hash); if (Left.is(tok::l_paren) && Right.is(tok::r_paren)) return Style.SpaceInEmptyParentheses; + if (Style.SpacesAroundConditions) { + const auto is_cond_kw = [&](const FormatToken *t) { + return t->isOneOf(tok::kw_if, tok::pp_elif, tok::kw_for, tok::kw_while, + tok::kw_switch, tok::kw_constexpr, TT_ForEachMacro); + }; + if (Left.is(tok::l_paren) && Left.Previous && is_cond_kw(Left.Previous)) + return true; + if (Right.is(tok::r_paren) && Right.MatchingParen && + Right.MatchingParen->Previous && + is_cond_kw(Right.MatchingParen->Previous)) + return true; + } if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) return (Right.is(TT_CastRParen) || (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen))) @@ -2903,7 +2915,8 @@ // The identifier might actually be a macro name such as ALWAYS_INLINE. If // this turns out to be too lenient, add analysis of the identifier itself. return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd(); - if (Right.is(tok::coloncolon) && !Left.isOneOf(tok::l_brace, tok::comment)) + if (Right.is(tok::coloncolon) && + !Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren)) return (Left.is(TT_TemplateOpener) && Style.Standard < FormatStyle::LS_Cpp11) || !(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square, diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -12177,6 +12177,7 @@ CHECK_PARSE_BOOL(SpaceBeforeCtorInitializerColon); CHECK_PARSE_BOOL(SpaceBeforeInheritanceColon); CHECK_PARSE_BOOL(SpaceBeforeRangeBasedForLoopColon); + CHECK_PARSE_BOOL(SpacesAroundConditions); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterCaseLabel); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass); @@ -14373,6 +14374,16 @@ verifyFormat("auto lambda = [&a = a]() { a = 2; };", AlignStyle); } +TEST_F(FormatTest, SpacesAroundConditions) { + FormatStyle Spaces = getLLVMStyle(); + Spaces.SpacesAroundConditions = true; + verifyFormat("if ( !a )\n return;", Spaces); + verifyFormat("if ( a )\n return;", Spaces); + verifyFormat("while ( a )\n return;", Spaces); + verifyFormat("while ( (a && b) )\n return;", Spaces); + verifyFormat("do {\n} while ( 1 != 0 );", Spaces); +} + } // end namespace } // end namespace format } // end namespace clang