From fcebf22ae59c58fe1d0eb39caaf00c0aaa7359d5 Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Mon, 26 May 2014 13:10:39 +0000 Subject: [PATCH] clang-format: Split up moveStateToNextToken. No functional changes intended. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209626 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/ContinuationIndenter.cpp | 271 ++++++++++++++++------------ lib/Format/ContinuationIndenter.h | 12 ++ 2 files changed, 163 insertions(+), 120 deletions(-) diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index e1a559d0df..7485e0d40a 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -559,8 +559,8 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, bool DryRun, bool Newline) { - const FormatToken &Current = *State.NextToken; assert(State.Stack.size()); + const FormatToken &Current = *State.NextToken; if (Current.Type == TT_InheritanceColon) State.Stack.back().AvoidBinPacking = true; @@ -633,6 +633,44 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, State.Stack.back().JSFunctionInlined = !Newline; } + moveStatePastFakeLParens(State, Newline); + moveStatePastScopeOpener(State, Newline); + moveStatePastScopeCloser(State); + moveStatePastFakeRParens(State); + + if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) { + State.StartOfStringLiteral = State.Column; + } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) && + !Current.isStringLiteral()) { + State.StartOfStringLiteral = 0; + } + + State.Column += Current.ColumnWidth; + State.NextToken = State.NextToken->Next; + unsigned Penalty = breakProtrudingToken(Current, State, DryRun); + if (State.Column > getColumnLimit(State)) { + unsigned ExcessCharacters = State.Column - getColumnLimit(State); + Penalty += Style.PenaltyExcessCharacter * ExcessCharacters; + } + + if (Current.Role) + Current.Role->formatFromToken(State, this, DryRun); + // If the previous has a special role, let it consume tokens as appropriate. + // It is necessary to start at the previous token for the only implemented + // role (comma separated list). That way, the decision whether or not to break + // after the "{" is already done and both options are tried and evaluated. + // FIXME: This is ugly, find a better way. + if (Previous && Previous->Role) + Penalty += Previous->Role->formatAfterToken(State, this, DryRun); + + return Penalty; +} + +void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, + bool Newline) { + const FormatToken &Current = *State.NextToken; + const FormatToken *Previous = Current.getPreviousNonComment(); + // Don't add extra indentation for the first fake parenthesis after // 'return', assignments or opening <({[. The indentation for these cases // is special cased. @@ -696,97 +734,91 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, State.Stack.push_back(NewParenState); SkipFirstExtraIndent = false; } +} - // If we encounter an opening (, [, { or <, we add a level to our stacks to - // prepare for the following tokens. - if (Current.opensScope()) { - unsigned NewIndent; - unsigned NewIndentLevel = State.Stack.back().IndentLevel; - bool AvoidBinPacking; - bool BreakBeforeParameter = false; - if (Current.is(tok::l_brace) || - Current.Type == TT_ArrayInitializerLSquare) { - if (Current.MatchingParen && Current.BlockKind == BK_Block && - State.Stack.back().LambdasFound <= 1) { - // If this is an l_brace starting a nested block, we pretend (wrt. to - // indentation) that we already consumed the corresponding r_brace. - // Thus, we remove all ParenStates caused by fake parentheses that end - // at the r_brace. The net effect of this is that we don't indent - // relative to the l_brace, if the nested block is the last parameter of - // a function. For example, this formats: - // - // SomeFunction(a, [] { - // f(); // break - // }); - // - // instead of: - // SomeFunction(a, [] { - // f(); // break - // }); - // - // If we have already found more than one lambda introducers on this - // level, we opt out of this because similarity between the lambdas is - // more important. - for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i) { - assert(State.Stack.size() > 1); - if (State.Stack.size() == 1) { - // Do not pop the last element. - break; - } - State.Stack.pop_back(); - } - // For some reason, ObjC blocks are indented like continuations. - NewIndent = - State.Stack.back().LastSpace + (Current.Type == TT_ObjCBlockLBrace - ? Style.ContinuationIndentWidth - : Style.IndentWidth); - ++NewIndentLevel; - BreakBeforeParameter = true; - } else { - NewIndent = State.Stack.back().LastSpace; - if (Current.opensBlockTypeList(Style)) { - NewIndent += Style.IndentWidth; - NewIndent = std::min(State.Column + 2, NewIndent); - ++NewIndentLevel; - } else { - NewIndent += Style.ContinuationIndentWidth; - NewIndent = std::min(State.Column + 1, NewIndent); - } +void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) { + const FormatToken &Current = *State.NextToken; + + // Remove scopes created by fake parenthesis. + if (Current.isNot(tok::r_brace) || + (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) { + // Don't remove FakeRParens attached to r_braces that surround nested blocks + // as they will have been removed early (see above). + for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) { + unsigned VariablePos = State.Stack.back().VariablePos; + assert(State.Stack.size() > 1); + if (State.Stack.size() == 1) { + // Do not pop the last element. + break; } - const FormatToken *NextNoComment = Current.getNextNonComment(); - AvoidBinPacking = Current.BlockKind == BK_Block || - Current.Type == TT_ArrayInitializerLSquare || - Current.Type == TT_DictLiteral || - Style.Language == FormatStyle::LK_Proto || - !Style.BinPackParameters || - (NextNoComment && - NextNoComment->Type == TT_DesignatedInitializerPeriod); - } else { - NewIndent = Style.ContinuationIndentWidth + - std::max(State.Stack.back().LastSpace, - State.Stack.back().StartOfFunctionCall); - AvoidBinPacking = !Style.BinPackParameters || - (Style.ExperimentalAutoDetectBinPacking && - (Current.PackingKind == PPK_OnePerLine || - (!BinPackInconclusiveFunctions && - Current.PackingKind == PPK_Inconclusive))); - // If this '[' opens an ObjC call, determine whether all parameters fit - // into one line and put one per line if they don't. - if (Current.Type == TT_ObjCMethodExpr && Style.ColumnLimit != 0 && - getLengthToMatchingParen(Current) + State.Column > - getColumnLimit(State)) - BreakBeforeParameter = true; + State.Stack.pop_back(); + State.Stack.back().VariablePos = VariablePos; } + } +} + +void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, + bool Newline) { + const FormatToken &Current = *State.NextToken; + if (!Current.opensScope()) + return; - bool NoLineBreak = State.Stack.back().NoLineBreak || - (Current.Type == TT_TemplateOpener && - State.Stack.back().ContainsUnwrappedBuilder); - State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, - State.Stack.back().LastSpace, - AvoidBinPacking, NoLineBreak)); - State.Stack.back().BreakBeforeParameter = BreakBeforeParameter; + if (Current.MatchingParen && Current.BlockKind == BK_Block) { + moveStateToNewBlock(State); + return; } + unsigned NewIndent; + unsigned NewIndentLevel = State.Stack.back().IndentLevel; + bool AvoidBinPacking; + bool BreakBeforeParameter = false; + if (Current.is(tok::l_brace) || Current.Type == TT_ArrayInitializerLSquare) { + NewIndent = State.Stack.back().LastSpace; + if (Current.opensBlockTypeList(Style)) { + NewIndent += Style.IndentWidth; + NewIndent = std::min(State.Column + 2, NewIndent); + ++NewIndentLevel; + } else { + NewIndent += Style.ContinuationIndentWidth; + NewIndent = std::min(State.Column + 1, NewIndent); + } + const FormatToken *NextNoComment = Current.getNextNonComment(); + AvoidBinPacking = Current.Type == TT_ArrayInitializerLSquare || + Current.Type == TT_DictLiteral || + Style.Language == FormatStyle::LK_Proto || + !Style.BinPackParameters || + (NextNoComment && + NextNoComment->Type == TT_DesignatedInitializerPeriod); + } else { + NewIndent = Style.ContinuationIndentWidth + + std::max(State.Stack.back().LastSpace, + State.Stack.back().StartOfFunctionCall); + AvoidBinPacking = !Style.BinPackParameters || + (Style.ExperimentalAutoDetectBinPacking && + (Current.PackingKind == PPK_OnePerLine || + (!BinPackInconclusiveFunctions && + Current.PackingKind == PPK_Inconclusive))); + // If this '[' opens an ObjC call, determine whether all parameters fit + // into one line and put one per line if they don't. + if (Current.Type == TT_ObjCMethodExpr && Style.ColumnLimit != 0 && + getLengthToMatchingParen(Current) + State.Column > + getColumnLimit(State)) + BreakBeforeParameter = true; + } + bool NoLineBreak = State.Stack.back().NoLineBreak || + (Current.Type == TT_TemplateOpener && + State.Stack.back().ContainsUnwrappedBuilder); + State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, + State.Stack.back().LastSpace, + AvoidBinPacking, NoLineBreak)); + State.Stack.back().BreakBeforeParameter = BreakBeforeParameter; +} + +void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) { + const FormatToken &Current = *State.NextToken; + if (!Current.closesScope()) + return; + // If we encounter a closing ), ], } or >, we can remove a level from our // stacks. if (State.Stack.size() > 1 && @@ -801,50 +833,49 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, if (NextNonComment && NextNonComment->isNot(tok::l_square)) State.Stack.back().StartOfArraySubscripts = 0; } +} - // Remove scopes created by fake parenthesis. - if (Current.isNot(tok::r_brace) || - (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) { - // Don't remove FakeRParens attached to r_braces that surround nested blocks - // as they will have been removed early (see above). - for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) { - unsigned VariablePos = State.Stack.back().VariablePos; +void ContinuationIndenter::moveStateToNewBlock(LineState &State) { + // If this is an l_brace starting a nested block, we pretend (wrt. to + // indentation) that we already consumed the corresponding r_brace. Thus, we + // remove all ParenStates caused by fake parentheses that end at the r_brace. + // The net effect of this is that we don't indent relative to the l_brace, if + // the nested block is the last parameter of a function. For example, this + // formats: + // + // SomeFunction(a, [] { + // f(); // break + // }); + // + // instead of: + // SomeFunction(a, [] { + // f(); // break + // }); + // + // If we have already found more than one lambda introducers on this level, we + // opt out of this because similarity between the lambdas is more important. + if (State.Stack.back().LambdasFound <= 1) { + for (unsigned i = 0; i != State.NextToken->MatchingParen->FakeRParens; + ++i) { assert(State.Stack.size() > 1); if (State.Stack.size() == 1) { // Do not pop the last element. break; } State.Stack.pop_back(); - State.Stack.back().VariablePos = VariablePos; } } - if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) { - State.StartOfStringLiteral = State.Column; - } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) && - !Current.isStringLiteral()) { - State.StartOfStringLiteral = 0; - } - - State.Column += Current.ColumnWidth; - State.NextToken = State.NextToken->Next; - unsigned Penalty = breakProtrudingToken(Current, State, DryRun); - if (State.Column > getColumnLimit(State)) { - unsigned ExcessCharacters = State.Column - getColumnLimit(State); - Penalty += Style.PenaltyExcessCharacter * ExcessCharacters; - } - - if (Current.Role) - Current.Role->formatFromToken(State, this, DryRun); - // If the previous has a special role, let it consume tokens as appropriate. - // It is necessary to start at the previous token for the only implemented - // role (comma separated list). That way, the decision whether or not to break - // after the "{" is already done and both options are tried and evaluated. - // FIXME: This is ugly, find a better way. - if (Previous && Previous->Role) - Penalty += Previous->Role->formatAfterToken(State, this, DryRun); - - return Penalty; + // For some reason, ObjC blocks are indented like continuations. + unsigned NewIndent = State.Stack.back().LastSpace + + (State.NextToken->Type == TT_ObjCBlockLBrace + ? Style.ContinuationIndentWidth + : Style.IndentWidth); + State.Stack.push_back(ParenState( + NewIndent, /*NewIndentLevel=*/State.Stack.back().IndentLevel + 1, + State.Stack.back().LastSpace, /*AvoidBinPacking=*/true, + State.Stack.back().NoLineBreak)); + State.Stack.back().BreakBeforeParameter = true; } unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current, diff --git a/lib/Format/ContinuationIndenter.h b/lib/Format/ContinuationIndenter.h index dc3e3086fd..4733bda0a0 100644 --- a/lib/Format/ContinuationIndenter.h +++ b/lib/Format/ContinuationIndenter.h @@ -73,6 +73,18 @@ private: /// accordingly. unsigned moveStateToNextToken(LineState &State, bool DryRun, bool Newline); + /// \brief Update 'State' according to the next token's fake left parentheses. + void moveStatePastFakeLParens(LineState &State, bool Newline); + /// \brief Update 'State' according to the next token's fake r_parens. + void moveStatePastFakeRParens(LineState &State); + + /// \brief Update 'State' according to the next token being one of "(<{[". + void moveStatePastScopeOpener(LineState &State, bool Newline); + /// \brief Update 'State' according to the next token being one of ")>}]". + void moveStatePastScopeCloser(LineState &State); + /// \brief Update 'State' with the next token opening a nested block. + void moveStateToNewBlock(LineState &State); + /// \brief If the current token sticks out over the end of the line, break /// it if possible. /// -- 2.40.0