Author: Mitchell Balan Date: 2019-12-03T12:20:54-05:00 New Revision: 26748a321e20a7aa952ce8daa4f030c384ae7032
URL: https://github.com/llvm/llvm-project/commit/26748a321e20a7aa952ce8daa4f030c384ae7032 DIFF: https://github.com/llvm/llvm-project/commit/26748a321e20a7aa952ce8daa4f030c384ae7032.diff LOG: [clang-format] Add new option to add spaces around conditions Summary: This diff adds a new option SpacesAroundConditions that inserts spaces inside the braces for conditional statements. Reviewers: klimek, owenpan, mitchell-stellar, MyDeveloperDay Patch by: timwoj Subscribers: rsmmr, cfe-commits Tags: clang, clang-format Differential Revision: https://reviews.llvm.org/D68346 Added: Modified: clang/docs/ClangFormatStyleOptions.rst clang/include/clang/Format/Format.h clang/lib/Format/Format.cpp clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index f438ec7f871b..2f7483435fd4 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2328,6 +2328,9 @@ the configuration (without a prefix: ``Auto``). true: false: x = ( int32 )y vs. x = (int32)y +**SpacesInConditionalStatement** (``bool``) + If ``true``, spaces will be inserted around if/for/while (and similar) conditions. + **SpacesInContainerLiterals** (``bool``) If ``true``, spaces are inserted inside container literals (e.g. ObjC and Javascript array and dict literals). diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 604a935f3a28..f17a10c7f5c8 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1953,6 +1953,15 @@ struct FormatStyle { /// \endcode bool SpacesInAngles; + /// If ``true``, spaces will be inserted around if/for/switch/while + /// conditions. + /// \code + /// true: false: + /// if ( a ) { ... } vs. if (a) { ... } + /// while ( i < 5 ) { ... } while (i < 5) { ... } + /// \endcode + bool SpacesInConditionalStatement; + /// If ``true``, spaces are inserted inside container literals (e.g. /// ObjC and Javascript array and dict literals). /// \code{.js} @@ -2155,6 +2164,7 @@ struct FormatStyle { SpaceInEmptyParentheses == R.SpaceInEmptyParentheses && SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments && SpacesInAngles == R.SpacesInAngles && + SpacesInConditionalStatement == R.SpacesInConditionalStatement && SpacesInContainerLiterals == R.SpacesInContainerLiterals && SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses && SpacesInParentheses == R.SpacesInParentheses && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 4e42bab56182..f12bca48c630 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -537,6 +537,8 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("SpacesBeforeTrailingComments", Style.SpacesBeforeTrailingComments); IO.mapOptional("SpacesInAngles", Style.SpacesInAngles); + IO.mapOptional("SpacesInConditionalStatement", + Style.SpacesInConditionalStatement); IO.mapOptional("SpacesInContainerLiterals", Style.SpacesInContainerLiterals); IO.mapOptional("SpacesInCStyleCastParentheses", @@ -817,6 +819,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.SpaceBeforeCpp11BracedList = false; LLVMStyle.SpaceBeforeSquareBrackets = false; LLVMStyle.SpacesInAngles = false; + LLVMStyle.SpacesInConditionalStatement = false; LLVMStyle.PenaltyBreakAssignment = prec::Assignment; LLVMStyle.PenaltyBreakComment = 300; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 74ff5b531496..93cb36961ee5 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2592,6 +2592,13 @@ bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const { Right.ParameterCount > 0); } +/// Returns \c true if the token is followed by a boolean condition, \c false +/// otherwise. +static bool isKeywordWithCondition(const FormatToken &Tok) { + return Tok.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch, + tok::kw_constexpr); +}; + bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left, const FormatToken &Right) { @@ -2610,6 +2617,15 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, (Left.is(tok::l_brace) && Left.BlockKind != BK_Block && Right.is(tok::r_brace) && Right.BlockKind != BK_Block)) return Style.SpaceInEmptyParentheses; + if (Style.SpacesInConditionalStatement) { + if (Left.is(tok::l_paren) && Left.Previous && + isKeywordWithCondition(*Left.Previous)) + return true; + if (Right.is(tok::r_paren) && Right.MatchingParen && + Right.MatchingParen->Previous && + isKeywordWithCondition(*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))) @@ -3044,7 +3060,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, // 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 index e6fa829e7ff9..069542683c0d 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -12555,6 +12555,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(SpacesInParentheses); CHECK_PARSE_BOOL(SpacesInSquareBrackets); CHECK_PARSE_BOOL(SpacesInAngles); + CHECK_PARSE_BOOL(SpacesInConditionalStatement); CHECK_PARSE_BOOL(SpaceInEmptyBlock); CHECK_PARSE_BOOL(SpaceInEmptyParentheses); CHECK_PARSE_BOOL(SpacesInContainerLiterals); @@ -14880,6 +14881,22 @@ TEST_F(FormatTest, AmbersandInLamda) { verifyFormat("auto lambda = [&a = a]() { a = 2; };", AlignStyle); } + TEST_F(FormatTest, SpacesInConditionalStatement) { + FormatStyle Spaces = getLLVMStyle(); + Spaces.SpacesInConditionalStatement = true; + verifyFormat("for ( int i = 0; i; i++ )\n continue;", Spaces); + verifyFormat("if ( !a )\n return;", Spaces); + verifyFormat("if ( a )\n return;", Spaces); + verifyFormat("if constexpr ( a )\n return;", Spaces); + verifyFormat("switch ( a )\ncase 1:\n return;", Spaces); + verifyFormat("while ( a )\n return;", Spaces); + verifyFormat("while ( (a && b) )\n return;", Spaces); + verifyFormat("do {\n} while ( 1 != 0 );", Spaces); + // Check that space on the left of "::" is inserted as expected at beginning + // of condition. + verifyFormat("while ( ::func() )\n return;", Spaces); +} + TEST_F(FormatTest, AlternativeOperators) { // Test case for ensuring alternate operators are not // combined with their right most neighbour. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits