From e5321c400c76517f10ee6090556f6d87c150b826 Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Tue, 1 Oct 2013 14:41:18 +0000 Subject: [PATCH] Refactoring: split addTokenToState into two methods. Summary: Pure refactoring, should be no semantic changes. Reviewers: djasper Reviewed By: djasper CC: cfe-commits, klimek Differential Revision: http://llvm-reviews.chandlerc.com/D1796 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191772 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/ContinuationIndenter.cpp | 425 ++++++++++++++-------------- lib/Format/ContinuationIndenter.h | 19 ++ 2 files changed, 237 insertions(+), 207 deletions(-) diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index cc12fc9d81..6a5f8763d9 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -191,13 +191,6 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, bool DryRun, unsigned ExtraSpaces) { const FormatToken &Current = *State.NextToken; - const FormatToken &Previous = *State.NextToken->Previous; - const FormatToken *PreviousNonComment = - State.NextToken->getPreviousNonComment(); - - // Extra penalty that needs to be added because of the way certain line - // breaks are chosen. - unsigned Penalty = 0; if (State.Stack.size() == 0 || Current.Type == TT_ImplicitStringLiteral) { // FIXME: Is this correct? @@ -210,220 +203,238 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, return 0; } + unsigned Penalty = 0; + if (Newline) + Penalty = addTokenOnNewLine(State, DryRun); + else + addTokenOnCurrentLine(State, DryRun, ExtraSpaces); + + return moveStateToNextToken(State, DryRun, Newline) + Penalty; +} + +void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, + unsigned ExtraSpaces) { + const FormatToken &Current = *State.NextToken; + const FormatToken &Previous = *State.NextToken->Previous; + if (Current.is(tok::equal) && + (State.Line->First->is(tok::kw_for) || State.ParenLevel == 0) && + State.Stack.back().VariablePos == 0) { + State.Stack.back().VariablePos = State.Column; + // Move over * and & if they are bound to the variable name. + const FormatToken *Tok = &Previous; + while (Tok && State.Stack.back().VariablePos >= Tok->ColumnWidth) { + State.Stack.back().VariablePos -= Tok->ColumnWidth; + if (Tok->SpacesRequiredBefore != 0) + break; + Tok = Tok->Previous; + } + if (Previous.PartOfMultiVariableDeclStmt) + State.Stack.back().LastSpace = State.Stack.back().VariablePos; + } + + unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces; + + if (!DryRun) + Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, /*IndentLevel=*/0, + Spaces, State.Column + Spaces); + + if (Current.Type == TT_ObjCSelectorName && State.Stack.back().ColonPos == 0) { + if (State.Stack.back().Indent + Current.LongestObjCSelectorName > + State.Column + Spaces + Current.ColumnWidth) + State.Stack.back().ColonPos = + State.Stack.back().Indent + Current.LongestObjCSelectorName; + else + State.Stack.back().ColonPos = State.Column + Spaces + Current.ColumnWidth; + } + + if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr && + Current.Type != TT_LineComment) + State.Stack.back().Indent = State.Column + Spaces; + if (Previous.is(tok::comma) && !Current.isTrailingComment() && + State.Stack.back().AvoidBinPacking) + State.Stack.back().NoLineBreak = true; + if (startsSegmentOfBuilderTypeCall(Current)) + State.Stack.back().ContainsUnwrappedBuilder = true; + + State.Column += Spaces; + if (Current.is(tok::l_paren) && Previous.isOneOf(tok::kw_if, tok::kw_for)) + // Treat the condition inside an if as if it was a second function + // parameter, i.e. let nested calls have an indent of 4. + State.Stack.back().LastSpace = State.Column + 1; // 1 is length of "(". + else if (Previous.is(tok::comma)) + State.Stack.back().LastSpace = State.Column; + else if ((Previous.Type == TT_BinaryOperator || + Previous.Type == TT_ConditionalExpr || + Previous.Type == TT_UnaryOperator || + Previous.Type == TT_CtorInitializerColon) && + (Previous.getPrecedence() != prec::Assignment || + Current.StartsBinaryExpression)) + // Always indent relative to the RHS of the expression unless this is a + // simple assignment without binary expression on the RHS. Also indent + // relative to unary operators and the colons of constructor initializers. + State.Stack.back().LastSpace = State.Column; + else if (Previous.Type == TT_InheritanceColon) + State.Stack.back().Indent = State.Column; + else if (Previous.opensScope()) { + // If a function has a trailing call, indent all parameters from the + // opening parenthesis. This avoids confusing indents like: + // OuterFunction(InnerFunctionCall( // break + // ParameterToInnerFunction)) // break + // .SecondInnerFunctionCall(); + bool HasTrailingCall = false; + if (Previous.MatchingParen) { + const FormatToken *Next = Previous.MatchingParen->getNextNonComment(); + HasTrailingCall = Next && Next->isMemberAccess(); + } + if (HasTrailingCall && + State.Stack[State.Stack.size() - 2].CallContinuation == 0) + State.Stack.back().LastSpace = State.Column; + } +} + +unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, + bool DryRun) { + const FormatToken &Current = *State.NextToken; + const FormatToken &Previous = *State.NextToken->Previous; // If we are continuing an expression, we want to indent an extra 4 spaces. unsigned ContinuationIndent = std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) + 4; - if (Newline) { - // The first line break on any ParenLevel causes an extra penalty in order - // prefer similar line breaks. - if (!State.Stack.back().ContainsLineBreak) - Penalty += 15; - State.Stack.back().ContainsLineBreak = true; - - Penalty += State.NextToken->SplitPenalty; - - // Breaking before the first "<<" is generally not desirable if the LHS is - // short. - if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0 && - State.Column <= Style.ColumnLimit / 2) - Penalty += Style.PenaltyBreakFirstLessLess; - - if (Current.is(tok::l_brace) && Current.BlockKind == BK_Block) { + // Extra penalty that needs to be added because of the way certain line + // breaks are chosen. + unsigned Penalty = 0; + + const FormatToken *PreviousNonComment = + State.NextToken->getPreviousNonComment(); + // The first line break on any ParenLevel causes an extra penalty in order + // prefer similar line breaks. + if (!State.Stack.back().ContainsLineBreak) + Penalty += 15; + State.Stack.back().ContainsLineBreak = true; + + Penalty += State.NextToken->SplitPenalty; + + // Breaking before the first "<<" is generally not desirable if the LHS is + // short. + if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0 && + State.Column <= Style.ColumnLimit / 2) + Penalty += Style.PenaltyBreakFirstLessLess; + + if (Current.is(tok::l_brace) && Current.BlockKind == BK_Block) { + State.Column = State.FirstIndent; + } else if (Current.is(tok::r_brace)) { + if (Current.MatchingParen && + (Current.MatchingParen->BlockKind == BK_BracedInit || + !Current.MatchingParen->Children.empty())) + State.Column = State.Stack[State.Stack.size() - 2].LastSpace; + else State.Column = State.FirstIndent; - } else if (Current.is(tok::r_brace)) { - if (Current.MatchingParen && - (Current.MatchingParen->BlockKind == BK_BracedInit || - !Current.MatchingParen->Children.empty())) - State.Column = State.Stack[State.Stack.size() - 2].LastSpace; - else - State.Column = State.FirstIndent; - } else if (Current.is(tok::string_literal) && - State.StartOfStringLiteral != 0) { - State.Column = State.StartOfStringLiteral; - State.Stack.back().BreakBeforeParameter = true; - } else if (Current.is(tok::lessless) && - State.Stack.back().FirstLessLess != 0) { - State.Column = State.Stack.back().FirstLessLess; - } else if (Current.isMemberAccess()) { - if (State.Stack.back().CallContinuation == 0) { - State.Column = ContinuationIndent; - State.Stack.back().CallContinuation = State.Column; - } else { - State.Column = State.Stack.back().CallContinuation; - } - } else if (Current.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; - } else if ((PreviousNonComment && - PreviousNonComment->ClosesTemplateDeclaration) || - ((Current.Type == TT_StartOfName || - Current.is(tok::kw_operator)) && - State.ParenLevel == 0 && - (!Style.IndentFunctionDeclarationAfterType || - State.Line->StartsDefinition))) { - State.Column = State.Stack.back().Indent; - } else if (Current.Type == TT_ObjCSelectorName) { - if (State.Stack.back().ColonPos > Current.ColumnWidth) { - State.Column = State.Stack.back().ColonPos - Current.ColumnWidth; - } else { - State.Column = State.Stack.back().Indent; - State.Stack.back().ColonPos = State.Column + Current.ColumnWidth; - } - } else if (Current.is(tok::l_square) && Current.Type != TT_ObjCMethodExpr && - Current.Type != TT_LambdaLSquare) { - if (State.Stack.back().StartOfArraySubscripts != 0) - State.Column = State.Stack.back().StartOfArraySubscripts; - else - State.Column = ContinuationIndent; - } else if (Current.Type == TT_StartOfName || - Previous.isOneOf(tok::coloncolon, tok::equal) || - Previous.Type == TT_ObjCMethodExpr) { + } else if (Current.is(tok::string_literal) && + State.StartOfStringLiteral != 0) { + State.Column = State.StartOfStringLiteral; + State.Stack.back().BreakBeforeParameter = true; + } else if (Current.is(tok::lessless) && + State.Stack.back().FirstLessLess != 0) { + State.Column = State.Stack.back().FirstLessLess; + } else if (Current.isMemberAccess()) { + if (State.Stack.back().CallContinuation == 0) { State.Column = ContinuationIndent; - } else if (Current.Type == TT_CtorInitializerColon) { - State.Column = - State.FirstIndent + Style.ConstructorInitializerIndentWidth; - } else if (Current.Type == TT_CtorInitializerComma) { - State.Column = State.Stack.back().Indent; + State.Stack.back().CallContinuation = State.Column; } else { - State.Column = State.Stack.back().Indent; - // Ensure that we fall back to indenting 4 spaces instead of just - // flushing continuations left. - if (State.Column == State.FirstIndent) - State.Column += 4; - } - - 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 (!DryRun) { - unsigned Newlines = 1; - if (Current.is(tok::comment)) - Newlines = std::max(Newlines, std::min(Current.NewlinesBefore, - Style.MaxEmptyLinesToKeep + 1)); - Whitespaces.replaceWhitespace(Current, Newlines, State.Line->Level, - State.Column, State.Column, - State.Line->InPPDirective); - } - - if (!Current.isTrailingComment()) - State.Stack.back().LastSpace = State.Column; - if (Current.isMemberAccess()) - State.Stack.back().LastSpace += Current.ColumnWidth; - State.StartOfLineLevel = State.ParenLevel; - State.LowestLevelOnLine = State.ParenLevel; - - // Any break on this level means that the parent level has been broken - // and we need to avoid bin packing there. - for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) { - State.Stack[i].BreakBeforeParameter = true; + State.Column = State.Stack.back().CallContinuation; } - const FormatToken *TokenBefore = Current.getPreviousNonComment(); - if (TokenBefore && !TokenBefore->isOneOf(tok::comma, tok::semi) && - TokenBefore->Type != TT_TemplateCloser && - TokenBefore->Type != TT_BinaryOperator && !TokenBefore->opensScope()) - State.Stack.back().BreakBeforeParameter = true; - - // If we break after {, we should also break before the corresponding }. - if (Previous.is(tok::l_brace)) - State.Stack.back().BreakBeforeClosingBrace = true; - - if (State.Stack.back().AvoidBinPacking) { - // If we are breaking after '(', '{', '<', this is not bin packing - // unless AllowAllParametersOfDeclarationOnNextLine is false. - if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) || - Previous.Type == TT_BinaryOperator) || - (!Style.AllowAllParametersOfDeclarationOnNextLine && - State.Line->MustBeDeclaration)) - State.Stack.back().BreakBeforeParameter = true; + } else if (Current.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; + } else if ((PreviousNonComment && + PreviousNonComment->ClosesTemplateDeclaration) || + ((Current.Type == TT_StartOfName || + Current.is(tok::kw_operator)) && + State.ParenLevel == 0 && + (!Style.IndentFunctionDeclarationAfterType || + State.Line->StartsDefinition))) { + State.Column = State.Stack.back().Indent; + } else if (Current.Type == TT_ObjCSelectorName) { + if (State.Stack.back().ColonPos > Current.ColumnWidth) { + State.Column = State.Stack.back().ColonPos - Current.ColumnWidth; + } else { + State.Column = State.Stack.back().Indent; + State.Stack.back().ColonPos = State.Column + Current.ColumnWidth; } - + } else if (Current.is(tok::l_square) && Current.Type != TT_ObjCMethodExpr && + Current.Type != TT_LambdaLSquare) { + if (State.Stack.back().StartOfArraySubscripts != 0) + State.Column = State.Stack.back().StartOfArraySubscripts; + else + State.Column = ContinuationIndent; + } else if (Current.Type == TT_StartOfName || + Previous.isOneOf(tok::coloncolon, tok::equal) || + Previous.Type == TT_ObjCMethodExpr) { + State.Column = ContinuationIndent; + } else if (Current.Type == TT_CtorInitializerColon) { + State.Column = State.FirstIndent + Style.ConstructorInitializerIndentWidth; + } else if (Current.Type == TT_CtorInitializerComma) { + State.Column = State.Stack.back().Indent; } else { - if (Current.is(tok::equal) && - (State.Line->First->is(tok::kw_for) || State.ParenLevel == 0) && - State.Stack.back().VariablePos == 0) { - State.Stack.back().VariablePos = State.Column; - // Move over * and & if they are bound to the variable name. - const FormatToken *Tok = &Previous; - while (Tok && State.Stack.back().VariablePos >= Tok->ColumnWidth) { - State.Stack.back().VariablePos -= Tok->ColumnWidth; - if (Tok->SpacesRequiredBefore != 0) - break; - Tok = Tok->Previous; - } - if (Previous.PartOfMultiVariableDeclStmt) - State.Stack.back().LastSpace = State.Stack.back().VariablePos; - } + State.Column = State.Stack.back().Indent; + // Ensure that we fall back to indenting 4 spaces instead of just + // flushing continuations left. + if (State.Column == State.FirstIndent) + State.Column += 4; + } - unsigned Spaces = State.NextToken->SpacesRequiredBefore + ExtraSpaces; + 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 (!DryRun) - Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, /*IndentLevel=*/0, - Spaces, State.Column + Spaces); - - if (Current.Type == TT_ObjCSelectorName && - State.Stack.back().ColonPos == 0) { - if (State.Stack.back().Indent + Current.LongestObjCSelectorName > - State.Column + Spaces + Current.ColumnWidth) - State.Stack.back().ColonPos = - State.Stack.back().Indent + Current.LongestObjCSelectorName; - else - State.Stack.back().ColonPos = - State.Column + Spaces + Current.ColumnWidth; - } + if (!DryRun) { + unsigned Newlines = 1; + if (Current.is(tok::comment)) + Newlines = std::max(Newlines, std::min(Current.NewlinesBefore, + Style.MaxEmptyLinesToKeep + 1)); + Whitespaces.replaceWhitespace(Current, Newlines, State.Line->Level, + State.Column, State.Column, + State.Line->InPPDirective); + } - if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr && - Current.Type != TT_LineComment) - State.Stack.back().Indent = State.Column + Spaces; - if (Previous.is(tok::comma) && !Current.isTrailingComment() && - State.Stack.back().AvoidBinPacking) - State.Stack.back().NoLineBreak = true; - if (startsSegmentOfBuilderTypeCall(Current)) - State.Stack.back().ContainsUnwrappedBuilder = true; - - State.Column += Spaces; - if (Current.is(tok::l_paren) && Previous.isOneOf(tok::kw_if, tok::kw_for)) - // Treat the condition inside an if as if it was a second function - // parameter, i.e. let nested calls have an indent of 4. - State.Stack.back().LastSpace = State.Column + 1; // 1 is length of "(". - else if (Previous.is(tok::comma)) - State.Stack.back().LastSpace = State.Column; - else if ((Previous.Type == TT_BinaryOperator || - Previous.Type == TT_ConditionalExpr || - Previous.Type == TT_UnaryOperator || - Previous.Type == TT_CtorInitializerColon) && - (Previous.getPrecedence() != prec::Assignment || - Current.StartsBinaryExpression)) - // Always indent relative to the RHS of the expression unless this is a - // simple assignment without binary expression on the RHS. Also indent - // relative to unary operators and the colons of constructor initializers. - State.Stack.back().LastSpace = State.Column; - else if (Previous.Type == TT_InheritanceColon) - State.Stack.back().Indent = State.Column; - else if (Previous.opensScope()) { - // If a function has a trailing call, indent all parameters from the - // opening parenthesis. This avoids confusing indents like: - // OuterFunction(InnerFunctionCall( // break - // ParameterToInnerFunction)) // break - // .SecondInnerFunctionCall(); - bool HasTrailingCall = false; - if (Previous.MatchingParen) { - const FormatToken *Next = Previous.MatchingParen->getNextNonComment(); - HasTrailingCall = Next && Next->isMemberAccess(); - } - if (HasTrailingCall && - State.Stack[State.Stack.size() - 2].CallContinuation == 0) - State.Stack.back().LastSpace = State.Column; - } + if (!Current.isTrailingComment()) + State.Stack.back().LastSpace = State.Column; + if (Current.isMemberAccess()) + State.Stack.back().LastSpace += Current.ColumnWidth; + State.StartOfLineLevel = State.ParenLevel; + State.LowestLevelOnLine = State.ParenLevel; + + // Any break on this level means that the parent level has been broken + // and we need to avoid bin packing there. + for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) { + State.Stack[i].BreakBeforeParameter = true; + } + const FormatToken *TokenBefore = Current.getPreviousNonComment(); + if (TokenBefore && !TokenBefore->isOneOf(tok::comma, tok::semi) && + TokenBefore->Type != TT_TemplateCloser && + TokenBefore->Type != TT_BinaryOperator && !TokenBefore->opensScope()) + State.Stack.back().BreakBeforeParameter = true; + + // If we break after {, we should also break before the corresponding }. + if (Previous.is(tok::l_brace)) + State.Stack.back().BreakBeforeClosingBrace = true; + + if (State.Stack.back().AvoidBinPacking) { + // If we are breaking after '(', '{', '<', this is not bin packing + // unless AllowAllParametersOfDeclarationOnNextLine is false. + if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) || + Previous.Type == TT_BinaryOperator) || + (!Style.AllowAllParametersOfDeclarationOnNextLine && + State.Line->MustBeDeclaration)) + State.Stack.back().BreakBeforeParameter = true; } - return moveStateToNextToken(State, DryRun, Newline) + Penalty; + return Penalty; } unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, diff --git a/lib/Format/ContinuationIndenter.h b/lib/Format/ContinuationIndenter.h index 608a827194..c3642d24c4 100644 --- a/lib/Format/ContinuationIndenter.h +++ b/lib/Format/ContinuationIndenter.h @@ -84,6 +84,25 @@ private: unsigned breakProtrudingToken(const FormatToken &Current, LineState &State, bool DryRun); + /// \brief Appends the next token to \p State and updates information + /// necessary for indentation. + /// + /// Puts the token on the current line. + /// + /// If \p DryRun is \c false, also creates and stores the required + /// \c Replacement. + void addTokenOnCurrentLine(LineState &State, bool DryRun, + unsigned ExtraSpaces); + + /// \brief Appends the next token to \p State and updates information + /// necessary for indentation. + /// + /// Adds a line break and necessary indentation. + /// + /// If \p DryRun is \c false, also creates and stores the required + /// \c Replacement. + unsigned addTokenOnNewLine(LineState &State, bool DryRun); + /// \brief Adds a multiline token to the \p State. /// /// \returns Extra penalty for the first line of the literal: last line is -- 2.40.0