From: Francois Ferrand Date: Thu, 23 Apr 2020 13:56:47 +0000 (+0200) Subject: clang-format: support aligned nested conditionals formatting X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4db94094b469b4715d08ef37f1799bf3ea7ca8ea;p=platform%2Fupstream%2Fllvm.git clang-format: support aligned nested conditionals formatting Summary: When multiple ternary operators are chained, e.g. like an if/else-if/ else-if/.../else sequence, clang-format will keep aligning the colon with the question mark, which increases the indent for each conditionals: int a = condition1 ? result1 : condition2 ? result2 : condition3 ? result3 : result4; This patch detects the situation (e.g. conditionals used in false branch of another conditional), to avoid indenting in that case: int a = condition1 ? result1 : condition2 ? result2 : condition3 ? result3 : result4; When BreakBeforeTernaryOperators is false, this will format like this: int a = condition1 ? result1 : condition2 ? result2 : conditino3 ? result3 : result4; This formatting style is referenced here: https://www.fluentcpp.com/2018/02/27/replace-else-if-ternary-operator/ and here: https://marcmutz.wordpress.com/2010/10/14/top-5-reasons-you-should-love-your-ternary-operator/ Reviewers: krasimir, djasper, klimek, MyDeveloperDay Reviewed By: MyDeveloperDay Subscribers: hokein, dyung, MyDeveloperDay, acoomans, cfe-commits Tags: #clang, #clang-format Differential Revision: https://reviews.llvm.org/D50078 --- diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index cf88524..5dc4573 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -367,6 +367,12 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { State.Stack.back().BreakBeforeParameter && !Current.isTrailingComment() && !Current.isOneOf(tok::r_paren, tok::r_brace)) return true; + if (State.Stack.back().IsChainedConditional && + ((Style.BreakBeforeTernaryOperators && Current.is(TT_ConditionalExpr) && + Current.is(tok::colon)) || + (!Style.BreakBeforeTernaryOperators && Previous.is(TT_ConditionalExpr) && + Previous.is(tok::colon)))) + return true; if (((Previous.is(TT_DictLiteral) && Previous.is(tok::l_brace)) || (Previous.is(TT_ArrayInitializerLSquare) && Previous.ParameterCount > 1) || @@ -1022,8 +1028,23 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { if (State.Stack.back().QuestionColumn != 0 && ((NextNonComment->is(tok::colon) && NextNonComment->is(TT_ConditionalExpr)) || - Previous.is(TT_ConditionalExpr))) + Previous.is(TT_ConditionalExpr))) { + if (((NextNonComment->is(tok::colon) && NextNonComment->Next && + !NextNonComment->Next->FakeLParens.empty() && + NextNonComment->Next->FakeLParens.back() == prec::Conditional) || + (Previous.is(tok::colon) && !Current.FakeLParens.empty() && + Current.FakeLParens.back() == prec::Conditional)) && + !State.Stack.back().IsWrappedConditional) { + // NOTE: we may tweak this slightly: + // * not remove the 'lead' ContinuationIndentWidth + // * always un-indent by the operator when + // BreakBeforeTernaryOperators=true + unsigned Indent = + State.Stack.back().Indent - Style.ContinuationIndentWidth; + return Indent; + } return State.Stack.back().QuestionColumn; + } if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0) return State.Stack.back().VariablePos; if ((PreviousNonComment && @@ -1144,6 +1165,11 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, if (Current.is(TT_ArraySubscriptLSquare) && State.Stack.back().StartOfArraySubscripts == 0) State.Stack.back().StartOfArraySubscripts = State.Column; + if (Current.is(TT_ConditionalExpr) && Current.is(tok::question) && + ((Current.MustBreakBefore) || + (Current.getNextNonComment() && + Current.getNextNonComment()->MustBreakBefore))) + State.Stack.back().IsWrappedConditional = true; if (Style.BreakBeforeTernaryOperators && Current.is(tok::question)) State.Stack.back().QuestionColumn = State.Column; if (!Style.BreakBeforeTernaryOperators && Current.isNot(tok::colon)) { @@ -1284,6 +1310,8 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, NewParenState.Tok = nullptr; NewParenState.ContainsLineBreak = false; NewParenState.LastOperatorWrapped = true; + NewParenState.IsChainedConditional = false; + NewParenState.IsWrappedConditional = false; NewParenState.NoLineBreak = NewParenState.NoLineBreak || State.Stack.back().NoLineBreakInOperand; @@ -1316,14 +1344,20 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign) NewParenState.StartOfFunctionCall = State.Column; - // Always indent conditional expressions. Never indent expression where - // the 'operator' is ',', ';' or an assignment (i.e. *I <= - // prec::Assignment) as those have different indentation rules. Indent - // other expression, unless the indentation needs to be skipped. - if (*I == prec::Conditional || - (!SkipFirstExtraIndent && *I > prec::Assignment && - !Current.isTrailingComment())) + // Indent conditional expressions, unless they are chained "else-if" + // conditionals. Never indent expression where the 'operator' is ',', ';' or + // an assignment (i.e. *I <= prec::Assignment) as those have different + // indentation rules. Indent other expression, unless the indentation needs + // to be skipped. + if (*I == prec::Conditional && Previous && Previous->is(tok::colon) && + Previous->is(TT_ConditionalExpr) && I == Current.FakeLParens.rbegin() && + !State.Stack.back().IsWrappedConditional) { + NewParenState.IsChainedConditional = true; + } else if (*I == prec::Conditional || + (!SkipFirstExtraIndent && *I > prec::Assignment && + !Current.isTrailingComment())) { NewParenState.Indent += Style.ContinuationIndentWidth; + } if ((Previous && !Previous->opensScope()) || *I != prec::Comma) NewParenState.BreakBeforeParameter = false; State.Stack.push_back(NewParenState); diff --git a/clang/lib/Format/ContinuationIndenter.h b/clang/lib/Format/ContinuationIndenter.h index 5ad4548..28180cd 100644 --- a/clang/lib/Format/ContinuationIndenter.h +++ b/clang/lib/Format/ContinuationIndenter.h @@ -209,7 +209,8 @@ struct ParenState { ContainsLineBreak(false), ContainsUnwrappedBuilder(false), AlignColons(true), ObjCSelectorNameFound(false), HasMultipleNestedBlocks(false), NestedBlockInlined(false), - IsInsideObjCArrayLiteral(false), IsCSharpGenericTypeConstraint(false) {} + IsInsideObjCArrayLiteral(false), IsCSharpGenericTypeConstraint(false), + IsChainedConditional(false), IsWrappedConditional(false) {} /// \brief The token opening this parenthesis level, or nullptr if this level /// is opened by fake parenthesis. @@ -335,6 +336,14 @@ struct ParenState { bool IsCSharpGenericTypeConstraint : 1; + /// \brief true if the current \c ParenState represents the false branch of + /// a chained conditional expression (e.g. else-if) + bool IsChainedConditional : 1; + + /// \brief true if there conditionnal was wrapped on the first operator (the + /// question mark) + bool IsWrappedConditional : 1; + bool operator<(const ParenState &Other) const { if (Indent != Other.Indent) return Indent < Other.Indent; @@ -376,6 +385,10 @@ struct ParenState { return NestedBlockInlined; if (IsCSharpGenericTypeConstraint != Other.IsCSharpGenericTypeConstraint) return IsCSharpGenericTypeConstraint; + if (IsChainedConditional != Other.IsChainedConditional) + return IsChainedConditional; + if (IsWrappedConditional != Other.IsWrappedConditional) + return IsWrappedConditional; return false; } }; diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index e641f10..000141a 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -40,7 +40,8 @@ WhitespaceManager::Change::Change(const FormatToken &Tok, ContinuesPPDirective(ContinuesPPDirective), Spaces(Spaces), IsInsideToken(IsInsideToken), IsTrailingComment(false), TokenLength(0), PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0), - StartOfBlockComment(nullptr), IndentationOffset(0) {} + StartOfBlockComment(nullptr), IndentationOffset(0), ConditionalsLevel(0) { +} void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines, unsigned Spaces, @@ -95,6 +96,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() { alignConsecutiveMacros(); alignConsecutiveDeclarations(); alignConsecutiveAssignments(); + alignChainedConditionals(); alignTrailingComments(); alignEscapedNewlines(); generateChanges(); @@ -227,6 +229,33 @@ void WhitespaceManager::calculateLineBreakInformation() { LastBlockComment = nullptr; } } + + // Compute conditional nesting level + // Level is increased for each conditional, unless this conditional continues + // a chain of conditional, i.e. starts immediately after the colon of another + // conditional. + SmallVector ScopeStack; + int ConditionalsLevel = 0; + for (auto &Change : Changes) { + for (unsigned i = 0, e = Change.Tok->FakeLParens.size(); i != e; ++i) { + bool isNestedConditional = + Change.Tok->FakeLParens[e - 1 - i] == prec::Conditional && + !(i == 0 && Change.Tok->Previous && + Change.Tok->Previous->is(TT_ConditionalExpr) && + Change.Tok->Previous->is(tok::colon)); + if (isNestedConditional) + ++ConditionalsLevel; + ScopeStack.push_back(isNestedConditional); + } + + Change.ConditionalsLevel = ConditionalsLevel; + + for (unsigned i = Change.Tok->FakeRParens; i > 0 && ScopeStack.size(); + --i) { + if (ScopeStack.pop_back_val()) + --ConditionalsLevel; + } + } } // Align a single sequence of tokens, see AlignTokens below. @@ -248,6 +277,7 @@ AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F &&Matches, // double z); // In the above example, we need to take special care to ensure that // 'double z' is indented along with it's owning function 'b'. + // Special handling is required for 'nested' ternary operators. SmallVector ScopeStack; for (unsigned i = Start; i != End; ++i) { @@ -288,7 +318,10 @@ AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F &&Matches, unsigned ScopeStart = ScopeStack.back(); if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName) || (ScopeStart > Start + 1 && - Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))) + Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)) || + Changes[i].Tok->is(TT_ConditionalExpr) || + (Changes[i].Tok->Previous && + Changes[i].Tok->Previous->is(TT_ConditionalExpr))) Changes[i].Spaces += Shift; } @@ -341,7 +374,7 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, // abort when we hit any token in a higher scope than the starting one. auto IndentAndNestingLevel = StartAt < Changes.size() ? Changes[StartAt].indentAndNestingLevel() - : std::pair(0, 0); + : std::tuple(); // Keep track of the number of commas before the matching tokens, we will only // align a sequence of matching tokens if they are preceded by the same number @@ -411,8 +444,8 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, StartOfSequence = i; unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn; - int LineLengthAfter = -Changes[i].Spaces; - for (unsigned j = i; j != e && Changes[j].NewlinesBefore == 0; ++j) + int LineLengthAfter = Changes[i].TokenLength; + for (unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength; unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter; @@ -610,6 +643,50 @@ void WhitespaceManager::alignConsecutiveDeclarations() { Changes, /*StartAt=*/0); } +void WhitespaceManager::alignChainedConditionals() { + if (Style.BreakBeforeTernaryOperators) { + AlignTokens( + Style, + [](Change const &C) { + // Align question operators and last colon + return C.Tok->is(TT_ConditionalExpr) && + ((C.Tok->is(tok::question) && !C.NewlinesBefore) || + (C.Tok->is(tok::colon) && C.Tok->Next && + (C.Tok->Next->FakeLParens.size() == 0 || + C.Tok->Next->FakeLParens.back() != prec::Conditional))); + }, + Changes, /*StartAt=*/0); + } else { + static auto AlignWrappedOperand = [](Change const &C) { + auto Previous = C.Tok->getPreviousNonComment(); // Previous; + return C.NewlinesBefore && Previous && Previous->is(TT_ConditionalExpr) && + (Previous->is(tok::question) || + (Previous->is(tok::colon) && + (C.Tok->FakeLParens.size() == 0 || + C.Tok->FakeLParens.back() != prec::Conditional))); + }; + // Ensure we keep alignment of wrapped operands with non-wrapped operands + // Since we actually align the operators, the wrapped operands need the + // extra offset to be properly aligned. + for (Change &C : Changes) { + if (AlignWrappedOperand(C)) + C.StartOfTokenColumn -= 2; + } + AlignTokens( + Style, + [this](Change const &C) { + // Align question operators if next operand is not wrapped, as + // well as wrapped operands after question operator or last + // colon in conditional sequence + return (C.Tok->is(TT_ConditionalExpr) && C.Tok->is(tok::question) && + &C != &Changes.back() && (&C + 1)->NewlinesBefore == 0 && + !(&C + 1)->IsTrailingComment) || + AlignWrappedOperand(C); + }, + Changes, /*StartAt=*/0); + } +} + void WhitespaceManager::alignTrailingComments() { unsigned MinColumn = 0; unsigned MaxColumn = UINT_MAX; diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h index a9f8392..87f24e9 100644 --- a/clang/lib/Format/WhitespaceManager.h +++ b/clang/lib/Format/WhitespaceManager.h @@ -19,6 +19,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Format/Format.h" #include +#include namespace clang { namespace format { @@ -158,11 +159,16 @@ public: const Change *StartOfBlockComment; int IndentationOffset; - // A combination of indent level and nesting level, which are used in - // tandem to compute lexical scope, for the purposes of deciding + // Depth of conditionals. Computed from tracking fake parenthesis, except + // it does not increase the indent for "chained" conditionals. + int ConditionalsLevel; + + // A combination of indent, nesting and conditionals levels, which are used + // in tandem to compute lexical scope, for the purposes of deciding // when to stop consecutive alignment runs. - std::pair indentAndNestingLevel() const { - return std::make_pair(Tok->IndentLevel, Tok->NestingLevel); + std::tuple indentAndNestingLevel() const { + return std::make_tuple(Tok->IndentLevel, Tok->NestingLevel, + ConditionalsLevel); } }; @@ -181,6 +187,9 @@ private: /// Align consecutive declarations over all \c Changes. void alignConsecutiveDeclarations(); + /// Align consecutive declarations over all \c Changes. + void alignChainedConditionals(); + /// Align trailing comments over all \c Changes. void alignTrailingComments(); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 1308487..62f3cbb 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -5975,6 +5975,124 @@ TEST_F(FormatTest, BreaksConditionalExpressions) { " // comment\n" " ? a = b\n" " : a;"); + + // Chained conditionals + FormatStyle Style = getLLVMStyle(); + Style.ColumnLimit = 70; + Style.AlignOperands = true; + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111\n" + " : bbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaa ? 1111111111111111\n" + " : bbbbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111\n" + " : bbbbbbbbbbbbbb ? 222222\n" + " : 333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : cccccccccccccc ? 3333333333333333\n" + " : 4444444444444444;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? (aaa ? bbb : ccc)\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : (aaa ? bbb : ccc);", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : cccccccccccccccccc)\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaa ? (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : cccccccccccccccccc)\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaa ? a = (aaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : dddddddddddddddddd)\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaa ? a + (aaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : dddddddddddddddddd)\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaa ? 1111111111111111\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : a + (aaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : dddddddddddddddddd)\n", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? 1111111111111111\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : cccccccccccccccccc);", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : ccccccccccccccc ? dddddddddddddddddd\n" + " : eeeeeeeeeeeeeeeeee)\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? (aaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : ccccccccccccccc ? dddddddddddddddddd\n" + " : eeeeeeeeeeeeeeeeee)\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : cccccccccccc ? dddddddddddddddddd\n" + " : eeeeeeeeeeeeeeeeee)\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? aaaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : cccccccccccccccccc\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? aaaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : cccccccccccccccc ? dddddddddddddddddd\n" + " : eeeeeeeeeeeeeeeeee\n" + " : bbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaaaaaaa\n" + " ? (aaaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : cccccccccccccccccc ? dddddddddddddddddd\n" + " : eeeeeeeeeeeeeeeeee)\n" + " : bbbbbbbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaaaaaaaaaaa\n" + " ? aaaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb\n" + " : cccccccccccccccc ? dddddddddddddddddd\n" + " : eeeeeeeeeeeeeeeeee\n" + " : bbbbbbbbbbbbbbbbbbbbbbb ? 2222222222222222\n" + " : 3333333333333333;", + Style); } TEST_F(FormatTest, BreaksConditionalExpressionsAfterOperator) { @@ -6080,6 +6198,121 @@ TEST_F(FormatTest, BreaksConditionalExpressionsAfterOperator) { " aaaaa :\n" " bbbbbbbbbbbbbbb + cccccccccccccccc;", Style); + + // Chained conditionals + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111 :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111 :\n" + " bbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaa ? 1111111111111111 :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111 :\n" + " bbbbbbbbbbbbbbbb ? 222222 :\n" + " 333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111 :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " cccccccccccccccc ? 3333333333333333 :\n" + " 4444444444444444;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? (aaa ? bbb : ccc) :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaa ? 1111111111111111 :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " (aaa ? bbb : ccc);", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " cccccccccccccccccc) :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaa ? (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " cccccccccccccccccc) :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaa ? a = (aaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " dddddddddddddddddd) :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaa ? a + (aaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " dddddddddddddddddd) :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaa ? 1111111111111111 :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " a + (aaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " dddddddddddddddddd)\n", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? 1111111111111111 :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " cccccccccccccccccc);", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " ccccccccccccccccc ? dddddddddddddddddd :\n" + " eeeeeeeeeeeeeeeeee) :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? (aaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " ccccccccccccc ? dddddddddddddddddd :\n" + " eeeeeeeeeeeeeeeeee) :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? (aaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " ccccccccccccccccc ? dddddddddddddddddd :\n" + " eeeeeeeeeeeeeeeeee) :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? aaaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " cccccccccccccccccc :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat( + "return aaaaaaaaaaaaaaaa ? aaaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " cccccccccccccccccc ? dddddddddddddddddd :\n" + " eeeeeeeeeeeeeeeeee :\n" + " bbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaaaaaaa ?\n" + " (aaaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " cccccccccccccccccc ? dddddddddddddddddd :\n" + " eeeeeeeeeeeeeeeeee) :\n" + " bbbbbbbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); + verifyFormat("return aaaaaaaaaaaaaaaaaaaaa ?\n" + " aaaaaaaaaaaaaaaaaaaa ? bbbbbbbbbbbbbbbbbb :\n" + " cccccccccccccccccccc ? dddddddddddddddddd :\n" + " eeeeeeeeeeeeeeeeee :\n" + " bbbbbbbbbbbbbbbbbbbbb ? 2222222222222222 :\n" + " 3333333333333333;", + Style); } TEST_F(FormatTest, DeclarationsOfMultipleVariables) {