diff options
author | dim <dim@FreeBSD.org> | 2015-05-27 18:47:56 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-05-27 18:47:56 +0000 |
commit | 3191b2b32a96e1a6ee833fcca73e5c8e0c67ba65 (patch) | |
tree | dbbd4047878da71c1a706e26ce05b4e7791b14cc /lib/Format/ContinuationIndenter.cpp | |
parent | 38d6f2e7f2ce51a5b3836d26596c6c34a3288752 (diff) | |
download | FreeBSD-src-3191b2b32a96e1a6ee833fcca73e5c8e0c67ba65.zip FreeBSD-src-3191b2b32a96e1a6ee833fcca73e5c8e0c67ba65.tar.gz |
Vendor import of clang trunk r238337:
https://llvm.org/svn/llvm-project/cfe/trunk@238337
Diffstat (limited to 'lib/Format/ContinuationIndenter.cpp')
-rw-r--r-- | lib/Format/ContinuationIndenter.cpp | 184 |
1 files changed, 123 insertions, 61 deletions
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 4cc92b0..4e8f5af 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -143,11 +143,10 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection) return true; if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || - (Style.BreakBeforeTernaryOperators && - (Current.is(tok::question) || - (Current.is(TT_ConditionalExpr) && Previous.isNot(tok::question)))) || + (Style.BreakBeforeTernaryOperators && Current.is(TT_ConditionalExpr) && + Previous.isNot(tok::question)) || (!Style.BreakBeforeTernaryOperators && - (Previous.is(tok::question) || Previous.is(TT_ConditionalExpr)))) && + Previous.is(TT_ConditionalExpr))) && State.Stack.back().BreakBeforeParameter && !Current.isTrailingComment() && !Current.isOneOf(tok::r_paren, tok::r_brace)) return true; @@ -166,10 +165,17 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { ((Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All) || Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0)) return true; + if (Current.is(TT_SelectorName) && State.Stack.back().ObjCSelectorNameFound && + State.Stack.back().BreakBeforeParameter) + return true; if (State.Column < getNewLineColumn(State)) return false; - if (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None) { + + // Using CanBreakBefore here and below takes care of the decision whether the + // current style uses wrapping before or after operators for the given + // operator. + if (Previous.is(TT_BinaryOperator) && Current.CanBreakBefore) { // If we need to break somewhere inside the LHS of a binary expression, we // should also break after the operator. Otherwise, the formatting would // hide the operator precedence, e.g. in: @@ -185,16 +191,13 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { Previous.Previous->isNot(TT_BinaryOperator); // For >>. bool LHSIsBinaryExpr = Previous.Previous && Previous.Previous->EndsBinaryExpression; - if (Previous.is(TT_BinaryOperator) && (!IsComparison || LHSIsBinaryExpr) && - Current.isNot(TT_BinaryOperator) && // For >>. - !Current.isTrailingComment() && !Previous.is(tok::lessless) && + if ((!IsComparison || LHSIsBinaryExpr) && !Current.isTrailingComment() && Previous.getPrecedence() != prec::Assignment && State.Stack.back().BreakBeforeParameter) return true; - } else { - if (Current.is(TT_BinaryOperator) && Previous.EndsBinaryExpression && - State.Stack.back().BreakBeforeParameter) - return true; + } else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore && + State.Stack.back().BreakBeforeParameter) { + return true; } // Same as above, but for the first "<<" operator. @@ -203,12 +206,14 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { State.Stack.back().FirstLessLess == 0) return true; - if (Current.is(TT_SelectorName) && State.Stack.back().ObjCSelectorNameFound && - State.Stack.back().BreakBeforeParameter) - return true; if (Current.NestingLevel == 0 && !Current.isTrailingComment()) { + // Always break after "template <...>" and leading annotations. This is only + // for cases where the entire line does not fit on a single line as a + // different LineFormatter would be used otherwise. if (Previous.ClosesTemplateDeclaration) return true; + if (Previous.is(TT_FunctionAnnotationRParen)) + return true; if (Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) && Current.isNot(TT_LeadingJavaAnnotation)) return true; @@ -221,8 +226,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { if (startsSegmentOfBuilderTypeCall(Current) && (State.Stack.back().CallContinuation != 0 || - (State.Stack.back().BreakBeforeParameter && - State.Stack.back().ContainsUnwrappedBuilder))) + State.Stack.back().BreakBeforeParameter)) return true; // The following could be precomputed as they do not depend on the state. @@ -232,6 +236,10 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { Previous.is(tok::l_brace) && !Current.isOneOf(tok::r_brace, tok::comment)) return true; + if (Current.is(tok::lessless) && Previous.is(tok::identifier) && + Previous.TokenText == "endl") + return true; + return false; } @@ -245,12 +253,18 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, (Current.Previous->Tok.getIdentifierInfo() == nullptr || Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() == tok::pp_not_keyword))) { - // FIXME: Is this correct? - int WhitespaceLength = SourceMgr.getSpellingColumnNumber( - State.NextToken->WhitespaceRange.getEnd()) - - SourceMgr.getSpellingColumnNumber( - State.NextToken->WhitespaceRange.getBegin()); - State.Column += WhitespaceLength; + unsigned EndColumn = + SourceMgr.getSpellingColumnNumber(Current.WhitespaceRange.getEnd()); + if (Current.LastNewlineOffset != 0) { + // If there is a newline within this token, the final column will solely + // determined by the current end column. + State.Column = EndColumn; + } else { + unsigned StartColumn = + SourceMgr.getSpellingColumnNumber(Current.WhitespaceRange.getBegin()); + assert(EndColumn >= StartColumn); + State.Column += EndColumn - StartColumn; + } moveStateToNextToken(State, DryRun, /*Newline=*/false); return 0; } @@ -297,7 +311,9 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, else if (State.Stack.back().Indent + Current.LongestObjCSelectorName > State.Column + Spaces + Current.ColumnWidth) State.Stack.back().ColonPos = - State.Stack.back().Indent + Current.LongestObjCSelectorName; + std::max(State.FirstIndent + Style.ContinuationIndentWidth, + State.Stack.back().Indent) + + Current.LongestObjCSelectorName; else State.Stack.back().ColonPos = State.Column + Spaces + Current.ColumnWidth; } @@ -308,9 +324,12 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, State.Stack.back().Indent = State.Column + Spaces; if (State.Stack.back().AvoidBinPacking && startsNextParameter(Current, Style)) State.Stack.back().NoLineBreak = true; - if (startsSegmentOfBuilderTypeCall(Current)) + if (startsSegmentOfBuilderTypeCall(Current) && + State.Column > getNewLineColumn(State)) State.Stack.back().ContainsUnwrappedBuilder = true; + if (Current.is(TT_LambdaArrow)) + State.Stack.back().NoLineBreak = true; if (Current.isMemberAccess() && Previous.is(tok::r_paren) && (Previous.MatchingParen && (Previous.TotalLength - Previous.MatchingParen->TotalLength > 10))) { @@ -359,7 +378,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, const FormatToken *Next = Previous.MatchingParen->getNextNonComment(); HasTrailingCall = Next && Next->isMemberAccess(); } - if (HasTrailingCall && + if (HasTrailingCall && State.Stack.size() > 1 && State.Stack[State.Stack.size() - 2].CallContinuation == 0) State.Stack.back().LastSpace = State.Column; } @@ -406,7 +425,11 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, State.Stack.back().AlignColons = false; } else { State.Stack.back().ColonPos = - State.Stack.back().Indent + NextNonComment->LongestObjCSelectorName; + (Style.IndentWrappedFunctionNames + ? std::max(State.Stack.back().Indent, + State.FirstIndent + Style.ContinuationIndentWidth) + : State.Stack.back().Indent) + + NextNonComment->LongestObjCSelectorName; } } else if (State.Stack.back().AlignColons && State.Stack.back().ColonPos <= NextNonComment->ColumnWidth) { @@ -468,8 +491,9 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, !PreviousNonComment->isOneOf(tok::comma, tok::semi) && (PreviousNonComment->isNot(TT_TemplateCloser) || Current.NestingLevel != 0) && - !PreviousNonComment->isOneOf(TT_BinaryOperator, TT_JavaAnnotation, - TT_LeadingJavaAnnotation) && + !PreviousNonComment->isOneOf( + TT_BinaryOperator, TT_FunctionAnnotationRParen, TT_JavaAnnotation, + TT_LeadingJavaAnnotation) && Current.isNot(TT_BinaryOperator) && !PreviousNonComment->opensScope()) State.Stack.back().BreakBeforeParameter = true; @@ -516,7 +540,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block) return Current.NestingLevel == 0 ? State.FirstIndent : State.Stack.back().Indent; - if (Current.isOneOf(tok::r_brace, tok::r_square)) { + if (Current.isOneOf(tok::r_brace, tok::r_square) && State.Stack.size() > 1) { if (Current.closesBlockTypeList(Style)) return State.Stack[State.Stack.size() - 2].NestedBlockIndent; if (Current.MatchingParen && @@ -529,6 +553,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { return State.Stack.back().Indent; if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0) return State.StartOfStringLiteral; + if (NextNonComment->is(TT_ObjCStringLiteral) && + State.StartOfStringLiteral != 0) + return State.StartOfStringLiteral - 1; if (NextNonComment->is(tok::lessless) && State.Stack.back().FirstLessLess != 0) return State.Stack.back().FirstLessLess; @@ -546,8 +573,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { return State.Stack.back().VariablePos; if ((PreviousNonComment && (PreviousNonComment->ClosesTemplateDeclaration || - PreviousNonComment->isOneOf(TT_AttributeParen, TT_JavaAnnotation, - TT_LeadingJavaAnnotation))) || + PreviousNonComment->isOneOf( + TT_AttributeParen, TT_FunctionAnnotationRParen, TT_JavaAnnotation, + TT_LeadingJavaAnnotation))) || (!Style.IndentWrappedFunctionNames && NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName))) return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent); @@ -555,7 +583,10 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { if (!State.Stack.back().ObjCSelectorNameFound) { if (NextNonComment->LongestObjCSelectorName == 0) return State.Stack.back().Indent; - return State.Stack.back().Indent + + return (Style.IndentWrappedFunctionNames + ? std::max(State.Stack.back().Indent, + State.FirstIndent + Style.ContinuationIndentWidth) + : State.Stack.back().Indent) + NextNonComment->LongestObjCSelectorName - NextNonComment->ColumnWidth; } @@ -570,10 +601,16 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { return State.Stack.back().StartOfArraySubscripts; return ContinuationIndent; } - if (NextNonComment->is(TT_StartOfName) || - Previous.isOneOf(tok::coloncolon, tok::equal)) { + + // This ensure that we correctly format ObjC methods calls without inputs, + // i.e. where the last element isn't selector like: [callee method]; + if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 && + NextNonComment->Next && NextNonComment->Next->is(TT_ObjCMethodExpr)) + return State.Stack.back().Indent; + + if (NextNonComment->isOneOf(TT_StartOfName, TT_PointerOrReference) || + Previous.isOneOf(tok::coloncolon, tok::equal)) return ContinuationIndent; - } if (PreviousNonComment && PreviousNonComment->is(tok::colon) && PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) return ContinuationIndent; @@ -621,7 +658,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, std::min(State.LowestLevelOnLine, Current.NestingLevel); if (Current.isMemberAccess()) State.Stack.back().StartOfFunctionCall = - Current.LastOperator ? 0 : State.Column + Current.ColumnWidth; + Current.LastOperator ? 0 : State.Column; if (Current.is(TT_SelectorName)) State.Stack.back().ObjCSelectorNameFound = true; if (Current.is(TT_CtorInitializerColon)) { @@ -637,12 +674,9 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, State.Stack.back().AvoidBinPacking = true; State.Stack.back().BreakBeforeParameter = false; } - - // In ObjC method declaration we align on the ":" of parameters, but we need - // to ensure that we indent parameters on subsequent lines by at least our - // continuation indent width. - if (Current.is(TT_ObjCMethodSpecifier)) - State.Stack.back().Indent += Style.ContinuationIndentWidth; + if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline) + State.Stack.back().NestedBlockIndent = + State.Column + Current.ColumnWidth + 1; // Insert scopes created by fake parenthesis. const FormatToken *Previous = Current.getPreviousNonComment(); @@ -675,12 +709,13 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, moveStatePastScopeCloser(State); moveStatePastFakeRParens(State); - if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) { + if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) State.StartOfStringLiteral = State.Column; - } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) && - !Current.isStringLiteral()) { + if (Current.is(TT_ObjCStringLiteral) && State.StartOfStringLiteral == 0) + State.StartOfStringLiteral = State.Column + 1; + else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) && + !Current.isStringLiteral()) State.StartOfStringLiteral = 0; - } State.Column += Current.ColumnWidth; State.NextToken = State.NextToken->Next; @@ -712,7 +747,8 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, // 'return', assignments or opening <({[. The indentation for these cases // is special cased. bool SkipFirstExtraIndent = - (Previous && (Previous->opensScope() || Previous->is(tok::kw_return) || + (Previous && (Previous->opensScope() || + Previous->isOneOf(tok::semi, tok::kw_return) || (Previous->getPrecedence() == prec::Assignment && Style.AlignOperands) || Previous->is(TT_ObjCMethodExpr))); @@ -783,7 +819,6 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) { for (unsigned i = 0, e = State.NextToken->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; @@ -806,6 +841,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, unsigned NewIndent; unsigned NewIndentLevel = State.Stack.back().IndentLevel; + unsigned LastSpace = State.Stack.back().LastSpace; bool AvoidBinPacking; bool BreakBeforeParameter = false; if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) { @@ -815,17 +851,28 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, ++NewIndentLevel; } else { NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth; - NewIndent = std::min(State.Column + 1, NewIndent); } const FormatToken *NextNoComment = Current.getNextNonComment(); AvoidBinPacking = Current.isOneOf(TT_ArrayInitializerLSquare, TT_DictLiteral) || - Style.Language == FormatStyle::LK_Proto || !Style.BinPackParameters || + Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments || (NextNoComment && NextNoComment->is(TT_DesignatedInitializerPeriod)); } else { NewIndent = Style.ContinuationIndentWidth + std::max(State.Stack.back().LastSpace, State.Stack.back().StartOfFunctionCall); + + // Ensure that different different brackets force relative alignment, e.g.: + // void SomeFunction(vector< // break + // int> v); + // FIXME: We likely want to do this for more combinations of brackets. + // Verify that it is wanted for ObjC, too. + if (Current.Tok.getKind() == tok::less && + Current.ParentBracket == tok::l_paren) { + NewIndent = std::max(NewIndent, State.Stack.back().Indent); + LastSpace = std::max(LastSpace, State.Stack.back().Indent); + } + AvoidBinPacking = (State.Line->MustBeDeclaration && !Style.BinPackParameters) || (!State.Line->MustBeDeclaration && !Style.BinPackArguments) || @@ -833,19 +880,33 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, (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.is(TT_ObjCMethodExpr) && Style.ColumnLimit != 0 && - getLengthToMatchingParen(Current) + State.Column > + if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen) { + if (Style.ColumnLimit) { + // If this '[' opens an ObjC call, determine whether all parameters fit + // into one line and put one per line if they don't. + if (getLengthToMatchingParen(Current) + State.Column > getColumnLimit(State)) - BreakBeforeParameter = true; + BreakBeforeParameter = true; + } else { + // For ColumnLimit = 0, we have to figure out whether there is or has to + // be a line break within this call. + for (const FormatToken *Tok = &Current; + Tok && Tok != Current.MatchingParen; Tok = Tok->Next) { + if (Tok->MustBreakBefore || + (Tok->CanBreakBefore && Tok->NewlinesBefore > 0)) { + BreakBeforeParameter = true; + break; + } + } + } + } } bool NoLineBreak = State.Stack.back().NoLineBreak || (Current.is(TT_TemplateOpener) && State.Stack.back().ContainsUnwrappedBuilder); - unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent; - State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, - State.Stack.back().LastSpace, + unsigned NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall, + State.Stack.back().NestedBlockIndent); + State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, LastSpace, AvoidBinPacking, NoLineBreak)); State.Stack.back().NestedBlockIndent = NestedBlockIndent; State.Stack.back().BreakBeforeParameter = BreakBeforeParameter; @@ -1082,8 +1143,9 @@ bool ContinuationIndenter::nextIsMultilineString(const LineState &State) { if (Current.getNextNonComment() && Current.getNextNonComment()->isStringLiteral()) return true; // Implicit concatenation. - if (State.Column + Current.ColumnWidth + Current.UnbreakableTailLength > - Style.ColumnLimit) + if (Style.ColumnLimit != 0 && + State.Column + Current.ColumnWidth + Current.UnbreakableTailLength > + Style.ColumnLimit) return true; // String will be split. return false; } |