From: Daniel Jasper Date: Fri, 8 Nov 2013 00:57:11 +0000 (+0000) Subject: clang-format: Make breaking before ternary operators configurable. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1a896a5a72d9af0259afe636535254c95dc6b355;p=clang clang-format: Make breaking before ternary operators configurable. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194229 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index ff6ed83353..0f2746712a 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -186,6 +186,9 @@ struct FormatStyle { /// \brief If \c true, binary operators will be placed after line breaks. bool BreakBeforeBinaryOperators; + /// \brief If \c true, ternary operators will be placed after line breaks. + bool BreakBeforeTernaryOperators; + /// \brief Different ways to attach braces to their surrounding context. enum BraceBreakingStyle { /// Always attach braces to surrounding context. @@ -261,6 +264,7 @@ struct FormatStyle { R.AlwaysBreakBeforeMultilineStrings && BinPackParameters == R.BinPackParameters && BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators && + BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators && BreakBeforeBraces == R.BreakBeforeBraces && BreakConstructorInitializersBeforeComma == R.BreakConstructorInitializersBeforeComma && diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index a80e87ddfc..442f9fa850 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -125,8 +125,11 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection) return true; if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || - Current.is(tok::question) || - (Current.Type == TT_ConditionalExpr && Previous.isNot(tok::question))) && + (Style.BreakBeforeTernaryOperators && + (Current.is(tok::question) || (Current.Type == TT_ConditionalExpr && + Previous.isNot(tok::question)))) || + (!Style.BreakBeforeTernaryOperators && + (Previous.is(tok::question) || Previous.Type == TT_ConditionalExpr))) && State.Stack.back().BreakBeforeParameter && !Current.isTrailingComment() && !Current.isOneOf(tok::r_paren, tok::r_brace)) return true; @@ -357,7 +360,9 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, } else { State.Column = State.Stack.back().CallContinuation; } - } else if (Current.Type == TT_ConditionalExpr) { + } else if (State.Stack.back().QuestionColumn != 0 && + (Current.Type == TT_ConditionalExpr || + Previous.Type == TT_ConditionalExpr)) { State.Column = State.Stack.back().QuestionColumn; } else if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0) { State.Column = State.Stack.back().VariablePos; @@ -398,14 +403,15 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, State.Column += Style.ContinuationIndentWidth; } - if (Current.is(tok::question)) - State.Stack.back().BreakBeforeParameter = true; if ((Previous.isOneOf(tok::comma, tok::semi) && !State.Stack.back().AvoidBinPacking) || Previous.Type == TT_BinaryOperator) State.Stack.back().BreakBeforeParameter = false; if (Previous.Type == TT_TemplateCloser && State.ParenLevel == 0) State.Stack.back().BreakBeforeParameter = false; + if (Current.is(tok::question) || + (PreviousNonComment && PreviousNonComment->is(tok::question))) + State.Stack.back().BreakBeforeParameter = true; if (!DryRun) { unsigned Newlines = 1; @@ -465,7 +471,10 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, if (Current.Type == TT_ArraySubscriptLSquare && State.Stack.back().StartOfArraySubscripts == 0) State.Stack.back().StartOfArraySubscripts = State.Column; - if (Current.is(tok::question)) + if ((Current.is(tok::question) && Style.BreakBeforeTernaryOperators) || + (Current.getPreviousNonComment() && Current.isNot(tok::colon) && + Current.getPreviousNonComment()->is(tok::question) && + !Style.BreakBeforeTernaryOperators)) State.Stack.back().QuestionColumn = State.Column; if (!Current.opensScope() && !Current.closesScope()) State.LowestLevelOnLine = diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 9443a60aa6..f2899345fb 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -123,6 +123,8 @@ template <> struct MappingTraits { Style.AlwaysBreakBeforeMultilineStrings); IO.mapOptional("BreakBeforeBinaryOperators", Style.BreakBeforeBinaryOperators); + IO.mapOptional("BreakBeforeTernaryOperators", + Style.BreakBeforeTernaryOperators); IO.mapOptional("BreakConstructorInitializersBeforeComma", Style.BreakConstructorInitializersBeforeComma); IO.mapOptional("BinPackParameters", Style.BinPackParameters); @@ -194,6 +196,7 @@ FormatStyle getLLVMStyle() { LLVMStyle.AlwaysBreakTemplateDeclarations = false; LLVMStyle.BinPackParameters = true; LLVMStyle.BreakBeforeBinaryOperators = false; + LLVMStyle.BreakBeforeTernaryOperators = true; LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; LLVMStyle.BreakConstructorInitializersBeforeComma = false; LLVMStyle.ColumnLimit = 80; @@ -240,6 +243,7 @@ FormatStyle getGoogleStyle() { GoogleStyle.AlwaysBreakTemplateDeclarations = true; GoogleStyle.BinPackParameters = true; GoogleStyle.BreakBeforeBinaryOperators = false; + GoogleStyle.BreakBeforeTernaryOperators = true; GoogleStyle.BreakBeforeBraces = FormatStyle::BS_Attach; GoogleStyle.BreakConstructorInitializersBeforeComma = false; GoogleStyle.ColumnLimit = 80; diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 5c70c8f914..474f6a5adb 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -1417,6 +1417,16 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, const FormatToken &Left = *Right.Previous; if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator)) return true; + if (Right.isTrailingComment()) + // We rely on MustBreakBefore being set correctly here as we should not + // change the "binding" behavior of a comment. + return false; + if (Left.is(tok::question) && Right.is(tok::colon)) + return false; + if (Right.Type == TT_ConditionalExpr || Right.is(tok::question)) + return Style.BreakBeforeTernaryOperators; + if (Left.Type == TT_ConditionalExpr || Left.is(tok::question)) + return !Style.BreakBeforeTernaryOperators; if (Right.is(tok::colon) && (Right.Type == TT_DictLiteral || Right.Type == TT_ObjCMethodExpr)) return false; @@ -1429,10 +1439,6 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, return true; if (Left.ClosesTemplateDeclaration) return true; - if ((Right.Type == TT_ConditionalExpr && - !(Right.is(tok::colon) && Left.is(tok::question))) || - Right.is(tok::question)) - return true; if (Right.Type == TT_RangeBasedForLoopColon || Right.Type == TT_OverloadedOperatorLParen || Right.Type == TT_OverloadedOperator) @@ -1442,8 +1448,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, if (Right.Type == TT_RangeBasedForLoopColon) return false; if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser || - Left.Type == TT_UnaryOperator || Left.Type == TT_ConditionalExpr || - Left.isOneOf(tok::question, tok::kw_operator)) + Left.Type == TT_UnaryOperator || Left.is(tok::kw_operator)) return false; if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl) return false; @@ -1457,10 +1462,6 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, } if (Right.Type == TT_ImplicitStringLiteral) return false; - if (Right.isTrailingComment()) - // We rely on MustBreakBefore being set correctly here as we should not - // change the "binding" behavior of a comment. - return false; if (Right.is(tok::r_paren) || Right.Type == TT_TemplateCloser) return false; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 3684e071fd..e6757c5d2a 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -3390,6 +3390,94 @@ TEST_F(FormatTest, BreaksConditionalExpressions) { NoBinPacking); } +TEST_F(FormatTest, BreaksConditionalExpressionsAfterOperator) { + FormatStyle Style = getLLVMStyle(); + Style.BreakBeforeTernaryOperators = false; + Style.ColumnLimit = 70; + verifyFormat( + "aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaa ?\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);", + Style); + verifyFormat( + "aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaa ? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);", + Style); + verifyFormat( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa ? aaaa(aaaaaa) :\n" + " aaaaaaaaaaaaa);", + Style); + verifyFormat( + "aaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaaaaa ? aaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaa);", + Style); + verifyFormat( + "aaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaaaaa ?: aaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaa);", + Style); + verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ?\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) :\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);", + Style); + verifyFormat("aaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ?\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) :\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa),\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa);", + Style); + verifyFormat("aaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ?:\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa),\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa);", + Style); + verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ?\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa :\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa;", + Style); + verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa =\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ?\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;", + Style); + verifyFormat( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa == aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ?\n" + " aaaaaaaaaaaaaaa :\n" + " aaaaaaaaaaaaaaa;", + Style); + verifyFormat("f(aaaaaaaaaaaaaaaa == // force break\n" + " aaaaaaaaa ?\n" + " b :\n" + " c);", + Style); + verifyFormat( + "unsigned Indent =\n" + " format(TheLine.First, IndentForLevel[TheLine.Level] >= 0 ?\n" + " IndentForLevel[TheLine.Level] :\n" + " TheLine * 2,\n" + " TheLine.InPPDirective, PreviousEndOfLineColumn);", + Style); + verifyFormat("bool aaaaaa = aaaaaaaaaaaaa ? //\n" + " aaaaaaaaaaaaaaa :\n" + " bbbbbbbbbbbbbbb ? //\n" + " ccccccccccccccc :\n" + " ddddddddddddddd;", + Style); + verifyFormat("bool aaaaaa = aaaaaaaaaaaaa ? //\n" + " aaaaaaaaaaaaaaa :\n" + " (bbbbbbbbbbbbbbb ? //\n" + " ccccccccccccccc :\n" + " ddddddddddddddd);", + Style); +} + TEST_F(FormatTest, DeclarationsOfMultipleVariables) { verifyFormat("bool aaaaaaaaaaaaaaaaa = aaaaaa->aaaaaaaaaaaaaaaaa(),\n" " aaaaaaaaaaa = aaaaaa->aaaaaaaaaaa();"); @@ -6660,6 +6748,7 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE_BOOL(AlwaysBreakTemplateDeclarations); CHECK_PARSE_BOOL(BinPackParameters); CHECK_PARSE_BOOL(BreakBeforeBinaryOperators); + CHECK_PARSE_BOOL(BreakBeforeTernaryOperators); CHECK_PARSE_BOOL(BreakConstructorInitializersBeforeComma); CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine); CHECK_PARSE_BOOL(DerivePointerBinding);