diff options
Diffstat (limited to 'clang/lib/Format/ContinuationIndenter.cpp')
-rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 45522a82322..778ffe30f62 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -135,6 +135,12 @@ bool ContinuationIndenter::canBreak(const LineState &State) { return false; } + // If binary operators are moved to the next line (including commas for some + // styles of constructor initializers), that's always ok. + if (!Current.isOneOf(TT_BinaryOperator, tok::comma) && + State.Stack.back().NoLineBreakInOperand) + return false; + return !State.Stack.back().NoLineBreak; } @@ -395,6 +401,27 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, State.Stack.back().NoLineBreak = true; } + // Don't allow the RHS of an operator to be split over multiple lines unless + // there is a line-break right after the operator. + // Exclude relational operators, as there, it is always more desirable to + // have the LHS 'left' of the RHS. + const FormatToken *P = Current.getPreviousNonComment(); + if (!Current.is(tok::comment) && P && + (P->isOneOf(TT_BinaryOperator, tok::comma) || + (P->is(TT_ConditionalExpr) && P->is(tok::colon))) && + !P->isOneOf(TT_OverloadedOperator, TT_CtorInitializerComma) && + P->getPrecedence() != prec::Assignment && + P->getPrecedence() != prec::Relational) { + bool BreakBeforeOperator = + P->is(tok::lessless) || + (P->is(TT_BinaryOperator) && + Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None) || + (P->is(TT_ConditionalExpr) && Style.BreakBeforeTernaryOperators); + if (!BreakBeforeOperator || + (!State.Stack.back().LastOperatorWrapped && BreakBeforeOperator)) + State.Stack.back().NoLineBreakInOperand = true; + } + State.Column += Spaces; if (Current.isNot(tok::comment) && Previous.is(tok::l_paren) && Previous.Previous && @@ -716,6 +743,8 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, assert(State.Stack.size()); const FormatToken &Current = *State.NextToken; + if (Current.isOneOf(tok::comma, TT_BinaryOperator)) + State.Stack.back().NoLineBreakInOperand = false; if (Current.is(TT_InheritanceColon)) State.Stack.back().AvoidBinPacking = true; if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator)) { @@ -724,8 +753,10 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, else State.Stack.back().LastOperatorWrapped = Newline; } - if ((Current.is(TT_BinaryOperator) && Current.isNot(tok::lessless)) || - Current.is(TT_ConditionalExpr)) + if (Current.is(TT_BinaryOperator) && Current.isNot(tok::lessless)) + State.Stack.back().LastOperatorWrapped = Newline; + if (Current.is(TT_ConditionalExpr) && Current.Previous && + !Current.Previous->is(TT_ConditionalExpr)) State.Stack.back().LastOperatorWrapped = Newline; if (Current.is(TT_ArraySubscriptLSquare) && State.Stack.back().StartOfArraySubscripts == 0) @@ -848,6 +879,8 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, I != E; ++I) { ParenState NewParenState = State.Stack.back(); NewParenState.ContainsLineBreak = false; + NewParenState.NoLineBreak = + NewParenState.NoLineBreak || State.Stack.back().NoLineBreakInOperand; // Indent from 'LastSpace' unless these are fake parentheses encapsulating // a builder type call after 'return' or, if the alignment after opening @@ -862,24 +895,6 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, std::max(std::max(State.Column, NewParenState.Indent), State.Stack.back().LastSpace); - // Don't allow the RHS of an operator to be split over multiple lines unless - // there is a line-break right after the operator. - // Exclude relational operators, as there, it is always more desirable to - // have the LHS 'left' of the RHS. - if (Previous && Previous->getPrecedence() != prec::Assignment && - Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr, tok::comma) && - Previous->getPrecedence() != prec::Relational) { - bool BreakBeforeOperator = - Previous->is(tok::lessless) || - (Previous->is(TT_BinaryOperator) && - Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None) || - (Previous->is(TT_ConditionalExpr) && - Style.BreakBeforeTernaryOperators); - if ((!Newline && !BreakBeforeOperator) || - (!State.Stack.back().LastOperatorWrapped && BreakBeforeOperator)) - NewParenState.NoLineBreak = true; - } - // Do not indent relative to the fake parentheses inserted for "." or "->". // This is a special case to make the following to statements consistent: // OuterFunction(InnerFunctionCall( // break @@ -1003,15 +1018,13 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, // Generally inherit NoLineBreak from the current scope to nested scope. // However, don't do this for non-empty nested blocks, dict literals and // array literals as these follow different indentation rules. - const FormatToken *Previous = Current.getPreviousNonComment(); bool NoLineBreak = Current.Children.empty() && !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) && (State.Stack.back().NoLineBreak || + State.Stack.back().NoLineBreakInOperand || (Current.is(TT_TemplateOpener) && - State.Stack.back().ContainsUnwrappedBuilder) || - (Current.is(tok::l_brace) && !Newline && Previous && - Previous->is(tok::comma))); + State.Stack.back().ContainsUnwrappedBuilder)); State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, LastSpace, AvoidBinPacking, NoLineBreak)); State.Stack.back().NestedBlockIndent = NestedBlockIndent; |