ContinuationIndenter.cpp revision 276479
1259701Sdim//===--- ContinuationIndenter.cpp - Format C++ code -----------------------===// 2259701Sdim// 3259701Sdim// The LLVM Compiler Infrastructure 4259701Sdim// 5259701Sdim// This file is distributed under the University of Illinois Open Source 6259701Sdim// License. See LICENSE.TXT for details. 7259701Sdim// 8259701Sdim//===----------------------------------------------------------------------===// 9259701Sdim/// 10259701Sdim/// \file 11259701Sdim/// \brief This file implements the continuation indenter. 12259701Sdim/// 13259701Sdim//===----------------------------------------------------------------------===// 14259701Sdim 15259701Sdim#include "BreakableToken.h" 16259701Sdim#include "ContinuationIndenter.h" 17259701Sdim#include "WhitespaceManager.h" 18259701Sdim#include "clang/Basic/OperatorPrecedence.h" 19259701Sdim#include "clang/Basic/SourceManager.h" 20259701Sdim#include "clang/Format/Format.h" 21259701Sdim#include "llvm/Support/Debug.h" 22259701Sdim#include <string> 23259701Sdim 24276479Sdim#define DEBUG_TYPE "format-formatter" 25276479Sdim 26259701Sdimnamespace clang { 27259701Sdimnamespace format { 28259701Sdim 29259701Sdim// Returns the length of everything up to the first possible line break after 30259701Sdim// the ), ], } or > matching \c Tok. 31259701Sdimstatic unsigned getLengthToMatchingParen(const FormatToken &Tok) { 32276479Sdim if (!Tok.MatchingParen) 33259701Sdim return 0; 34259701Sdim FormatToken *End = Tok.MatchingParen; 35259701Sdim while (End->Next && !End->Next->CanBreakBefore) { 36259701Sdim End = End->Next; 37259701Sdim } 38259701Sdim return End->TotalLength - Tok.TotalLength + 1; 39259701Sdim} 40259701Sdim 41259701Sdim// Returns \c true if \c Tok is the "." or "->" of a call and starts the next 42259701Sdim// segment of a builder type call. 43259701Sdimstatic bool startsSegmentOfBuilderTypeCall(const FormatToken &Tok) { 44259701Sdim return Tok.isMemberAccess() && Tok.Previous && Tok.Previous->closesScope(); 45259701Sdim} 46259701Sdim 47259701Sdim// Returns \c true if \c Current starts a new parameter. 48259701Sdimstatic bool startsNextParameter(const FormatToken &Current, 49259701Sdim const FormatStyle &Style) { 50259701Sdim const FormatToken &Previous = *Current.Previous; 51259701Sdim if (Current.Type == TT_CtorInitializerComma && 52259701Sdim Style.BreakConstructorInitializersBeforeComma) 53259701Sdim return true; 54259701Sdim return Previous.is(tok::comma) && !Current.isTrailingComment() && 55259701Sdim (Previous.Type != TT_CtorInitializerComma || 56259701Sdim !Style.BreakConstructorInitializersBeforeComma); 57259701Sdim} 58259701Sdim 59259701SdimContinuationIndenter::ContinuationIndenter(const FormatStyle &Style, 60259701Sdim SourceManager &SourceMgr, 61259701Sdim WhitespaceManager &Whitespaces, 62259701Sdim encoding::Encoding Encoding, 63259701Sdim bool BinPackInconclusiveFunctions) 64259701Sdim : Style(Style), SourceMgr(SourceMgr), Whitespaces(Whitespaces), 65259701Sdim Encoding(Encoding), 66276479Sdim BinPackInconclusiveFunctions(BinPackInconclusiveFunctions), 67276479Sdim CommentPragmasRegex(Style.CommentPragmas) {} 68259701Sdim 69259701SdimLineState ContinuationIndenter::getInitialState(unsigned FirstIndent, 70259701Sdim const AnnotatedLine *Line, 71259701Sdim bool DryRun) { 72259701Sdim LineState State; 73259701Sdim State.FirstIndent = FirstIndent; 74259701Sdim State.Column = FirstIndent; 75259701Sdim State.Line = Line; 76259701Sdim State.NextToken = Line->First; 77259701Sdim State.Stack.push_back(ParenState(FirstIndent, Line->Level, FirstIndent, 78259701Sdim /*AvoidBinPacking=*/false, 79259701Sdim /*NoLineBreak=*/false)); 80259701Sdim State.LineContainsContinuedForLoopSection = false; 81259701Sdim State.StartOfStringLiteral = 0; 82276479Sdim State.StartOfLineLevel = 0; 83276479Sdim State.LowestLevelOnLine = 0; 84259701Sdim State.IgnoreStackForComparison = false; 85259701Sdim 86259701Sdim // The first token has already been indented and thus consumed. 87259701Sdim moveStateToNextToken(State, DryRun, /*Newline=*/false); 88259701Sdim return State; 89259701Sdim} 90259701Sdim 91259701Sdimbool ContinuationIndenter::canBreak(const LineState &State) { 92259701Sdim const FormatToken &Current = *State.NextToken; 93259701Sdim const FormatToken &Previous = *Current.Previous; 94259701Sdim assert(&Previous == Current.Previous); 95259701Sdim if (!Current.CanBreakBefore && !(State.Stack.back().BreakBeforeClosingBrace && 96259701Sdim Current.closesBlockTypeList(Style))) 97259701Sdim return false; 98259701Sdim // The opening "{" of a braced list has to be on the same line as the first 99259701Sdim // element if it is nested in another braced init list or function call. 100259701Sdim if (!Current.MustBreakBefore && Previous.is(tok::l_brace) && 101276479Sdim Previous.Type != TT_DictLiteral && Previous.BlockKind == BK_BracedInit && 102276479Sdim Previous.Previous && 103259701Sdim Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma)) 104259701Sdim return false; 105259701Sdim // This prevents breaks like: 106259701Sdim // ... 107259701Sdim // SomeParameter, OtherParameter).DoSomething( 108259701Sdim // ... 109259701Sdim // As they hide "DoSomething" and are generally bad for readability. 110276479Sdim if (Previous.opensScope() && Previous.isNot(tok::l_brace) && 111276479Sdim State.LowestLevelOnLine < State.StartOfLineLevel && 112276479Sdim State.LowestLevelOnLine < Current.NestingLevel) 113259701Sdim return false; 114259701Sdim if (Current.isMemberAccess() && State.Stack.back().ContainsUnwrappedBuilder) 115259701Sdim return false; 116276479Sdim 117276479Sdim // Don't create a 'hanging' indent if there are multiple blocks in a single 118276479Sdim // statement. 119276479Sdim if (Style.Language == FormatStyle::LK_JavaScript && 120276479Sdim Previous.is(tok::l_brace) && State.Stack.size() > 1 && 121276479Sdim State.Stack[State.Stack.size() - 2].JSFunctionInlined && 122276479Sdim State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks) 123276479Sdim return false; 124276479Sdim 125259701Sdim return !State.Stack.back().NoLineBreak; 126259701Sdim} 127259701Sdim 128259701Sdimbool ContinuationIndenter::mustBreak(const LineState &State) { 129259701Sdim const FormatToken &Current = *State.NextToken; 130259701Sdim const FormatToken &Previous = *Current.Previous; 131259701Sdim if (Current.MustBreakBefore || Current.Type == TT_InlineASMColon) 132259701Sdim return true; 133259701Sdim if (State.Stack.back().BreakBeforeClosingBrace && 134259701Sdim Current.closesBlockTypeList(Style)) 135259701Sdim return true; 136259701Sdim if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection) 137259701Sdim return true; 138259701Sdim if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || 139259701Sdim (Style.BreakBeforeTernaryOperators && 140259701Sdim (Current.is(tok::question) || (Current.Type == TT_ConditionalExpr && 141259701Sdim Previous.isNot(tok::question)))) || 142259701Sdim (!Style.BreakBeforeTernaryOperators && 143259701Sdim (Previous.is(tok::question) || Previous.Type == TT_ConditionalExpr))) && 144259701Sdim State.Stack.back().BreakBeforeParameter && !Current.isTrailingComment() && 145259701Sdim !Current.isOneOf(tok::r_paren, tok::r_brace)) 146259701Sdim return true; 147259701Sdim if (Style.AlwaysBreakBeforeMultilineStrings && 148259701Sdim State.Column > State.Stack.back().Indent && // Breaking saves columns. 149259701Sdim !Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) && 150276479Sdim Previous.Type != TT_InlineASMColon && 151276479Sdim Previous.Type != TT_ConditionalExpr && nextIsMultilineString(State)) 152259701Sdim return true; 153259701Sdim if (((Previous.Type == TT_DictLiteral && Previous.is(tok::l_brace)) || 154259701Sdim Previous.Type == TT_ArrayInitializerLSquare) && 155276479Sdim Style.ColumnLimit > 0 && 156259701Sdim getLengthToMatchingParen(Previous) + State.Column > getColumnLimit(State)) 157259701Sdim return true; 158276479Sdim if (Current.Type == TT_CtorInitializerColon && 159276479Sdim ((Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All) || 160276479Sdim Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0)) 161276479Sdim return true; 162259701Sdim 163276479Sdim if (State.Column < getNewLineColumn(State)) 164276479Sdim return false; 165259701Sdim if (!Style.BreakBeforeBinaryOperators) { 166259701Sdim // If we need to break somewhere inside the LHS of a binary expression, we 167259701Sdim // should also break after the operator. Otherwise, the formatting would 168259701Sdim // hide the operator precedence, e.g. in: 169259701Sdim // if (aaaaaaaaaaaaaa == 170259701Sdim // bbbbbbbbbbbbbb && c) {.. 171259701Sdim // For comparisons, we only apply this rule, if the LHS is a binary 172259701Sdim // expression itself as otherwise, the line breaks seem superfluous. 173259701Sdim // We need special cases for ">>" which we have split into two ">" while 174259701Sdim // lexing in order to make template parsing easier. 175259701Sdim // 176259701Sdim // FIXME: We'll need something similar for styles that break before binary 177259701Sdim // operators. 178259701Sdim bool IsComparison = (Previous.getPrecedence() == prec::Relational || 179259701Sdim Previous.getPrecedence() == prec::Equality) && 180259701Sdim Previous.Previous && 181259701Sdim Previous.Previous->Type != TT_BinaryOperator; // For >>. 182259701Sdim bool LHSIsBinaryExpr = 183259701Sdim Previous.Previous && Previous.Previous->EndsBinaryExpression; 184259701Sdim if (Previous.Type == TT_BinaryOperator && 185259701Sdim (!IsComparison || LHSIsBinaryExpr) && 186259701Sdim Current.Type != TT_BinaryOperator && // For >>. 187276479Sdim !Current.isTrailingComment() && !Previous.is(tok::lessless) && 188259701Sdim Previous.getPrecedence() != prec::Assignment && 189259701Sdim State.Stack.back().BreakBeforeParameter) 190259701Sdim return true; 191259701Sdim } 192259701Sdim 193259701Sdim // Same as above, but for the first "<<" operator. 194276479Sdim if (Current.is(tok::lessless) && Current.Type != TT_OverloadedOperator && 195276479Sdim State.Stack.back().BreakBeforeParameter && 196259701Sdim State.Stack.back().FirstLessLess == 0) 197259701Sdim return true; 198259701Sdim 199276479Sdim if (Current.Type == TT_SelectorName && 200276479Sdim State.Stack.back().ObjCSelectorNameFound && 201259701Sdim State.Stack.back().BreakBeforeParameter) 202259701Sdim return true; 203276479Sdim if (Previous.ClosesTemplateDeclaration && Current.NestingLevel == 0 && 204276479Sdim !Current.isTrailingComment()) 205259701Sdim return true; 206259701Sdim 207276479Sdim // If the return type spans multiple lines, wrap before the function name. 208276479Sdim if ((Current.Type == TT_FunctionDeclarationName || 209276479Sdim Current.is(tok::kw_operator)) && 210276479Sdim State.Stack.back().BreakBeforeParameter) 211259701Sdim return true; 212276479Sdim 213259701Sdim if (startsSegmentOfBuilderTypeCall(Current) && 214259701Sdim (State.Stack.back().CallContinuation != 0 || 215259701Sdim (State.Stack.back().BreakBeforeParameter && 216259701Sdim State.Stack.back().ContainsUnwrappedBuilder))) 217259701Sdim return true; 218276479Sdim 219276479Sdim // The following could be precomputed as they do not depend on the state. 220276479Sdim // However, as they should take effect only if the UnwrappedLine does not fit 221276479Sdim // into the ColumnLimit, they are checked here in the ContinuationIndenter. 222276479Sdim if (Style.ColumnLimit != 0 && Previous.BlockKind == BK_Block && 223276479Sdim Previous.is(tok::l_brace) && !Current.isOneOf(tok::r_brace, tok::comment)) 224276479Sdim return true; 225276479Sdim 226259701Sdim return false; 227259701Sdim} 228259701Sdim 229259701Sdimunsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, 230259701Sdim bool DryRun, 231259701Sdim unsigned ExtraSpaces) { 232259701Sdim const FormatToken &Current = *State.NextToken; 233259701Sdim 234276479Sdim assert(!State.Stack.empty()); 235276479Sdim if ((Current.Type == TT_ImplicitStringLiteral && 236276479Sdim (Current.Previous->Tok.getIdentifierInfo() == nullptr || 237259701Sdim Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() == 238259701Sdim tok::pp_not_keyword))) { 239259701Sdim // FIXME: Is this correct? 240259701Sdim int WhitespaceLength = SourceMgr.getSpellingColumnNumber( 241259701Sdim State.NextToken->WhitespaceRange.getEnd()) - 242259701Sdim SourceMgr.getSpellingColumnNumber( 243259701Sdim State.NextToken->WhitespaceRange.getBegin()); 244276479Sdim State.Column += WhitespaceLength; 245276479Sdim moveStateToNextToken(State, DryRun, /*Newline=*/false); 246259701Sdim return 0; 247259701Sdim } 248259701Sdim 249259701Sdim unsigned Penalty = 0; 250259701Sdim if (Newline) 251259701Sdim Penalty = addTokenOnNewLine(State, DryRun); 252259701Sdim else 253259701Sdim addTokenOnCurrentLine(State, DryRun, ExtraSpaces); 254259701Sdim 255259701Sdim return moveStateToNextToken(State, DryRun, Newline) + Penalty; 256259701Sdim} 257259701Sdim 258259701Sdimvoid ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, 259259701Sdim unsigned ExtraSpaces) { 260259701Sdim FormatToken &Current = *State.NextToken; 261259701Sdim const FormatToken &Previous = *State.NextToken->Previous; 262259701Sdim if (Current.is(tok::equal) && 263276479Sdim (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) && 264259701Sdim State.Stack.back().VariablePos == 0) { 265259701Sdim State.Stack.back().VariablePos = State.Column; 266259701Sdim // Move over * and & if they are bound to the variable name. 267259701Sdim const FormatToken *Tok = &Previous; 268259701Sdim while (Tok && State.Stack.back().VariablePos >= Tok->ColumnWidth) { 269259701Sdim State.Stack.back().VariablePos -= Tok->ColumnWidth; 270259701Sdim if (Tok->SpacesRequiredBefore != 0) 271259701Sdim break; 272259701Sdim Tok = Tok->Previous; 273259701Sdim } 274259701Sdim if (Previous.PartOfMultiVariableDeclStmt) 275259701Sdim State.Stack.back().LastSpace = State.Stack.back().VariablePos; 276259701Sdim } 277259701Sdim 278259701Sdim unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces; 279259701Sdim 280259701Sdim if (!DryRun) 281259701Sdim Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, /*IndentLevel=*/0, 282259701Sdim Spaces, State.Column + Spaces); 283259701Sdim 284276479Sdim if (Current.Type == TT_SelectorName && 285276479Sdim !State.Stack.back().ObjCSelectorNameFound) { 286276479Sdim if (Current.LongestObjCSelectorName == 0) 287276479Sdim State.Stack.back().AlignColons = false; 288276479Sdim else if (State.Stack.back().Indent + Current.LongestObjCSelectorName > 289276479Sdim State.Column + Spaces + Current.ColumnWidth) 290259701Sdim State.Stack.back().ColonPos = 291259701Sdim State.Stack.back().Indent + Current.LongestObjCSelectorName; 292259701Sdim else 293259701Sdim State.Stack.back().ColonPos = State.Column + Spaces + Current.ColumnWidth; 294259701Sdim } 295259701Sdim 296259701Sdim if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr && 297276479Sdim (Current.Type != TT_LineComment || Previous.BlockKind == BK_BracedInit)) 298259701Sdim State.Stack.back().Indent = State.Column + Spaces; 299259701Sdim if (State.Stack.back().AvoidBinPacking && startsNextParameter(Current, Style)) 300259701Sdim State.Stack.back().NoLineBreak = true; 301259701Sdim if (startsSegmentOfBuilderTypeCall(Current)) 302259701Sdim State.Stack.back().ContainsUnwrappedBuilder = true; 303259701Sdim 304259701Sdim State.Column += Spaces; 305276479Sdim if (Current.isNot(tok::comment) && Previous.is(tok::l_paren) && 306276479Sdim Previous.Previous && Previous.Previous->isOneOf(tok::kw_if, tok::kw_for)) 307259701Sdim // Treat the condition inside an if as if it was a second function 308259701Sdim // parameter, i.e. let nested calls have a continuation indent. 309259701Sdim State.Stack.back().LastSpace = State.Column; 310276479Sdim else if (!Current.isOneOf(tok::comment, tok::caret) && 311276479Sdim (Previous.is(tok::comma) || 312276479Sdim (Previous.is(tok::colon) && Previous.Type == TT_ObjCMethodExpr))) 313276479Sdim State.Stack.back().LastSpace = State.Column; 314259701Sdim else if ((Previous.Type == TT_BinaryOperator || 315259701Sdim Previous.Type == TT_ConditionalExpr || 316259701Sdim Previous.Type == TT_CtorInitializerColon) && 317276479Sdim ((Previous.getPrecedence() != prec::Assignment && 318276479Sdim (Previous.isNot(tok::lessless) || Previous.OperatorIndex != 0 || 319276479Sdim !Previous.LastOperator)) || 320259701Sdim Current.StartsBinaryExpression)) 321259701Sdim // Always indent relative to the RHS of the expression unless this is a 322259701Sdim // simple assignment without binary expression on the RHS. Also indent 323259701Sdim // relative to unary operators and the colons of constructor initializers. 324259701Sdim State.Stack.back().LastSpace = State.Column; 325259701Sdim else if (Previous.Type == TT_InheritanceColon) { 326259701Sdim State.Stack.back().Indent = State.Column; 327259701Sdim State.Stack.back().LastSpace = State.Column; 328259701Sdim } else if (Previous.opensScope()) { 329259701Sdim // If a function has a trailing call, indent all parameters from the 330259701Sdim // opening parenthesis. This avoids confusing indents like: 331259701Sdim // OuterFunction(InnerFunctionCall( // break 332259701Sdim // ParameterToInnerFunction)) // break 333259701Sdim // .SecondInnerFunctionCall(); 334259701Sdim bool HasTrailingCall = false; 335259701Sdim if (Previous.MatchingParen) { 336259701Sdim const FormatToken *Next = Previous.MatchingParen->getNextNonComment(); 337259701Sdim HasTrailingCall = Next && Next->isMemberAccess(); 338259701Sdim } 339259701Sdim if (HasTrailingCall && 340259701Sdim State.Stack[State.Stack.size() - 2].CallContinuation == 0) 341259701Sdim State.Stack.back().LastSpace = State.Column; 342259701Sdim } 343259701Sdim} 344259701Sdim 345259701Sdimunsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, 346259701Sdim bool DryRun) { 347259701Sdim FormatToken &Current = *State.NextToken; 348259701Sdim const FormatToken &Previous = *State.NextToken->Previous; 349276479Sdim 350259701Sdim // Extra penalty that needs to be added because of the way certain line 351259701Sdim // breaks are chosen. 352259701Sdim unsigned Penalty = 0; 353259701Sdim 354276479Sdim const FormatToken *PreviousNonComment = Current.getPreviousNonComment(); 355276479Sdim const FormatToken *NextNonComment = Previous.getNextNonComment(); 356276479Sdim if (!NextNonComment) 357276479Sdim NextNonComment = &Current; 358276479Sdim // The first line break on any NestingLevel causes an extra penalty in order 359259701Sdim // prefer similar line breaks. 360259701Sdim if (!State.Stack.back().ContainsLineBreak) 361259701Sdim Penalty += 15; 362259701Sdim State.Stack.back().ContainsLineBreak = true; 363259701Sdim 364259701Sdim Penalty += State.NextToken->SplitPenalty; 365259701Sdim 366259701Sdim // Breaking before the first "<<" is generally not desirable if the LHS is 367276479Sdim // short. Also always add the penalty if the LHS is split over mutliple lines 368276479Sdim // to avoid unnecessary line breaks that just work around this penalty. 369276479Sdim if (NextNonComment->is(tok::lessless) && 370276479Sdim State.Stack.back().FirstLessLess == 0 && 371276479Sdim (State.Column <= Style.ColumnLimit / 3 || 372276479Sdim State.Stack.back().BreakBeforeParameter)) 373259701Sdim Penalty += Style.PenaltyBreakFirstLessLess; 374259701Sdim 375276479Sdim State.Column = getNewLineColumn(State); 376276479Sdim if (NextNonComment->isMemberAccess()) { 377276479Sdim if (State.Stack.back().CallContinuation == 0) 378259701Sdim State.Stack.back().CallContinuation = State.Column; 379276479Sdim } else if (NextNonComment->Type == TT_SelectorName) { 380276479Sdim if (!State.Stack.back().ObjCSelectorNameFound) { 381276479Sdim if (NextNonComment->LongestObjCSelectorName == 0) { 382276479Sdim State.Stack.back().AlignColons = false; 383276479Sdim } else { 384276479Sdim State.Stack.back().ColonPos = 385276479Sdim State.Stack.back().Indent + NextNonComment->LongestObjCSelectorName; 386276479Sdim } 387276479Sdim } else if (State.Stack.back().AlignColons && 388276479Sdim State.Stack.back().ColonPos <= NextNonComment->ColumnWidth) { 389276479Sdim State.Stack.back().ColonPos = State.Column + NextNonComment->ColumnWidth; 390259701Sdim } 391276479Sdim } else if (PreviousNonComment && PreviousNonComment->is(tok::colon) && 392276479Sdim (PreviousNonComment->Type == TT_ObjCMethodExpr || 393276479Sdim PreviousNonComment->Type == TT_DictLiteral)) { 394276479Sdim // FIXME: This is hacky, find a better way. The problem is that in an ObjC 395276479Sdim // method expression, the block should be aligned to the line starting it, 396276479Sdim // e.g.: 397276479Sdim // [aaaaaaaaaaaaaaa aaaaaaaaa: \\ break for some reason 398276479Sdim // ^(int *i) { 399276479Sdim // // ... 400276479Sdim // }]; 401276479Sdim // Thus, we set LastSpace of the next higher NestingLevel, to which we move 402276479Sdim // when we consume all of the "}"'s FakeRParens at the "{". 403276479Sdim if (State.Stack.size() > 1) 404276479Sdim State.Stack[State.Stack.size() - 2].LastSpace = 405276479Sdim std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) + 406276479Sdim Style.ContinuationIndentWidth; 407259701Sdim } 408259701Sdim 409259701Sdim if ((Previous.isOneOf(tok::comma, tok::semi) && 410259701Sdim !State.Stack.back().AvoidBinPacking) || 411259701Sdim Previous.Type == TT_BinaryOperator) 412259701Sdim State.Stack.back().BreakBeforeParameter = false; 413276479Sdim if (Previous.Type == TT_TemplateCloser && Current.NestingLevel == 0) 414259701Sdim State.Stack.back().BreakBeforeParameter = false; 415276479Sdim if (NextNonComment->is(tok::question) || 416259701Sdim (PreviousNonComment && PreviousNonComment->is(tok::question))) 417259701Sdim State.Stack.back().BreakBeforeParameter = true; 418259701Sdim 419259701Sdim if (!DryRun) { 420276479Sdim unsigned Newlines = std::max( 421276479Sdim 1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1)); 422259701Sdim Whitespaces.replaceWhitespace(Current, Newlines, 423259701Sdim State.Stack.back().IndentLevel, State.Column, 424259701Sdim State.Column, State.Line->InPPDirective); 425259701Sdim } 426259701Sdim 427259701Sdim if (!Current.isTrailingComment()) 428259701Sdim State.Stack.back().LastSpace = State.Column; 429276479Sdim State.StartOfLineLevel = Current.NestingLevel; 430276479Sdim State.LowestLevelOnLine = Current.NestingLevel; 431259701Sdim 432259701Sdim // Any break on this level means that the parent level has been broken 433259701Sdim // and we need to avoid bin packing there. 434276479Sdim bool JavaScriptFormat = Style.Language == FormatStyle::LK_JavaScript && 435276479Sdim Current.is(tok::r_brace) && 436276479Sdim State.Stack.size() > 1 && 437276479Sdim State.Stack[State.Stack.size() - 2].JSFunctionInlined; 438276479Sdim if (!JavaScriptFormat) { 439276479Sdim for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) { 440276479Sdim State.Stack[i].BreakBeforeParameter = true; 441276479Sdim } 442259701Sdim } 443276479Sdim 444259701Sdim if (PreviousNonComment && 445259701Sdim !PreviousNonComment->isOneOf(tok::comma, tok::semi) && 446259701Sdim PreviousNonComment->Type != TT_TemplateCloser && 447259701Sdim PreviousNonComment->Type != TT_BinaryOperator && 448276479Sdim Current.Type != TT_BinaryOperator && !PreviousNonComment->opensScope()) 449259701Sdim State.Stack.back().BreakBeforeParameter = true; 450259701Sdim 451259701Sdim // If we break after { or the [ of an array initializer, we should also break 452259701Sdim // before the corresponding } or ]. 453276479Sdim if (PreviousNonComment && 454276479Sdim (PreviousNonComment->is(tok::l_brace) || 455276479Sdim PreviousNonComment->Type == TT_ArrayInitializerLSquare)) 456259701Sdim State.Stack.back().BreakBeforeClosingBrace = true; 457259701Sdim 458259701Sdim if (State.Stack.back().AvoidBinPacking) { 459259701Sdim // If we are breaking after '(', '{', '<', this is not bin packing 460276479Sdim // unless AllowAllParametersOfDeclarationOnNextLine is false or this is a 461276479Sdim // dict/object literal. 462259701Sdim if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) || 463259701Sdim Previous.Type == TT_BinaryOperator) || 464259701Sdim (!Style.AllowAllParametersOfDeclarationOnNextLine && 465276479Sdim State.Line->MustBeDeclaration) || 466276479Sdim Previous.Type == TT_DictLiteral) 467259701Sdim State.Stack.back().BreakBeforeParameter = true; 468259701Sdim } 469259701Sdim 470259701Sdim return Penalty; 471259701Sdim} 472259701Sdim 473276479Sdimunsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { 474276479Sdim if (!State.NextToken || !State.NextToken->Previous) 475276479Sdim return 0; 476276479Sdim FormatToken &Current = *State.NextToken; 477276479Sdim const FormatToken &Previous = *State.NextToken->Previous; 478276479Sdim // If we are continuing an expression, we want to use the continuation indent. 479276479Sdim unsigned ContinuationIndent = 480276479Sdim std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) + 481276479Sdim Style.ContinuationIndentWidth; 482276479Sdim const FormatToken *PreviousNonComment = Current.getPreviousNonComment(); 483276479Sdim const FormatToken *NextNonComment = Previous.getNextNonComment(); 484276479Sdim if (!NextNonComment) 485276479Sdim NextNonComment = &Current; 486276479Sdim if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block) 487276479Sdim return Current.NestingLevel == 0 ? State.FirstIndent 488276479Sdim : State.Stack.back().Indent; 489276479Sdim if (Current.isOneOf(tok::r_brace, tok::r_square)) { 490276479Sdim if (State.Stack.size() > 1 && 491276479Sdim State.Stack[State.Stack.size() - 2].JSFunctionInlined) 492276479Sdim return State.FirstIndent; 493276479Sdim if (Current.closesBlockTypeList(Style) || 494276479Sdim (Current.MatchingParen && 495276479Sdim Current.MatchingParen->BlockKind == BK_BracedInit)) 496276479Sdim return State.Stack[State.Stack.size() - 2].LastSpace; 497276479Sdim else 498276479Sdim return State.FirstIndent; 499276479Sdim } 500276479Sdim if (Current.is(tok::identifier) && Current.Next && 501276479Sdim Current.Next->Type == TT_DictLiteral) 502276479Sdim return State.Stack.back().Indent; 503276479Sdim if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0) 504276479Sdim return State.StartOfStringLiteral; 505276479Sdim if (NextNonComment->is(tok::lessless) && 506276479Sdim State.Stack.back().FirstLessLess != 0) 507276479Sdim return State.Stack.back().FirstLessLess; 508276479Sdim if (NextNonComment->isMemberAccess()) { 509276479Sdim if (State.Stack.back().CallContinuation == 0) { 510276479Sdim return ContinuationIndent; 511276479Sdim } else { 512276479Sdim return State.Stack.back().CallContinuation; 513276479Sdim } 514276479Sdim } 515276479Sdim if (State.Stack.back().QuestionColumn != 0 && 516276479Sdim ((NextNonComment->is(tok::colon) && 517276479Sdim NextNonComment->Type == TT_ConditionalExpr) || 518276479Sdim Previous.Type == TT_ConditionalExpr)) 519276479Sdim return State.Stack.back().QuestionColumn; 520276479Sdim if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0) 521276479Sdim return State.Stack.back().VariablePos; 522276479Sdim if ((PreviousNonComment && (PreviousNonComment->ClosesTemplateDeclaration || 523276479Sdim PreviousNonComment->Type == TT_AttributeParen)) || 524276479Sdim (!Style.IndentWrappedFunctionNames && 525276479Sdim (NextNonComment->is(tok::kw_operator) || 526276479Sdim NextNonComment->Type == TT_FunctionDeclarationName))) 527276479Sdim return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent); 528276479Sdim if (NextNonComment->Type == TT_SelectorName) { 529276479Sdim if (!State.Stack.back().ObjCSelectorNameFound) { 530276479Sdim if (NextNonComment->LongestObjCSelectorName == 0) { 531276479Sdim return State.Stack.back().Indent; 532276479Sdim } else { 533276479Sdim return State.Stack.back().Indent + 534276479Sdim NextNonComment->LongestObjCSelectorName - 535276479Sdim NextNonComment->ColumnWidth; 536276479Sdim } 537276479Sdim } else if (!State.Stack.back().AlignColons) { 538276479Sdim return State.Stack.back().Indent; 539276479Sdim } else if (State.Stack.back().ColonPos > NextNonComment->ColumnWidth) { 540276479Sdim return State.Stack.back().ColonPos - NextNonComment->ColumnWidth; 541276479Sdim } else { 542276479Sdim return State.Stack.back().Indent; 543276479Sdim } 544276479Sdim } 545276479Sdim if (NextNonComment->Type == TT_ArraySubscriptLSquare) { 546276479Sdim if (State.Stack.back().StartOfArraySubscripts != 0) 547276479Sdim return State.Stack.back().StartOfArraySubscripts; 548276479Sdim else 549276479Sdim return ContinuationIndent; 550276479Sdim } 551276479Sdim if (NextNonComment->Type == TT_StartOfName || 552276479Sdim Previous.isOneOf(tok::coloncolon, tok::equal)) { 553276479Sdim return ContinuationIndent; 554276479Sdim } 555276479Sdim if (PreviousNonComment && PreviousNonComment->is(tok::colon) && 556276479Sdim (PreviousNonComment->Type == TT_ObjCMethodExpr || 557276479Sdim PreviousNonComment->Type == TT_DictLiteral)) 558276479Sdim return ContinuationIndent; 559276479Sdim if (NextNonComment->Type == TT_CtorInitializerColon) 560276479Sdim return State.FirstIndent + Style.ConstructorInitializerIndentWidth; 561276479Sdim if (NextNonComment->Type == TT_CtorInitializerComma) 562276479Sdim return State.Stack.back().Indent; 563276479Sdim if (State.Stack.back().Indent == State.FirstIndent && PreviousNonComment && 564276479Sdim PreviousNonComment->isNot(tok::r_brace)) 565276479Sdim // Ensure that we fall back to the continuation indent width instead of 566276479Sdim // just flushing continuations left. 567276479Sdim return State.Stack.back().Indent + Style.ContinuationIndentWidth; 568276479Sdim return State.Stack.back().Indent; 569276479Sdim} 570276479Sdim 571259701Sdimunsigned ContinuationIndenter::moveStateToNextToken(LineState &State, 572259701Sdim bool DryRun, bool Newline) { 573276479Sdim assert(State.Stack.size()); 574259701Sdim const FormatToken &Current = *State.NextToken; 575259701Sdim 576259701Sdim if (Current.Type == TT_InheritanceColon) 577259701Sdim State.Stack.back().AvoidBinPacking = true; 578276479Sdim if (Current.is(tok::lessless) && Current.Type != TT_OverloadedOperator) { 579276479Sdim if (State.Stack.back().FirstLessLess == 0) 580276479Sdim State.Stack.back().FirstLessLess = State.Column; 581276479Sdim else 582276479Sdim State.Stack.back().LastOperatorWrapped = Newline; 583276479Sdim } 584276479Sdim if ((Current.Type == TT_BinaryOperator && Current.isNot(tok::lessless)) || 585276479Sdim Current.Type == TT_ConditionalExpr) 586276479Sdim State.Stack.back().LastOperatorWrapped = Newline; 587259701Sdim if (Current.Type == TT_ArraySubscriptLSquare && 588259701Sdim State.Stack.back().StartOfArraySubscripts == 0) 589259701Sdim State.Stack.back().StartOfArraySubscripts = State.Column; 590259701Sdim if ((Current.is(tok::question) && Style.BreakBeforeTernaryOperators) || 591259701Sdim (Current.getPreviousNonComment() && Current.isNot(tok::colon) && 592259701Sdim Current.getPreviousNonComment()->is(tok::question) && 593259701Sdim !Style.BreakBeforeTernaryOperators)) 594259701Sdim State.Stack.back().QuestionColumn = State.Column; 595259701Sdim if (!Current.opensScope() && !Current.closesScope()) 596259701Sdim State.LowestLevelOnLine = 597276479Sdim std::min(State.LowestLevelOnLine, Current.NestingLevel); 598259701Sdim if (Current.isMemberAccess()) 599259701Sdim State.Stack.back().StartOfFunctionCall = 600276479Sdim Current.LastOperator ? 0 : State.Column + Current.ColumnWidth; 601276479Sdim if (Current.Type == TT_SelectorName) 602276479Sdim State.Stack.back().ObjCSelectorNameFound = true; 603259701Sdim if (Current.Type == TT_CtorInitializerColon) { 604259701Sdim // Indent 2 from the column, so: 605259701Sdim // SomeClass::SomeClass() 606259701Sdim // : First(...), ... 607259701Sdim // Next(...) 608259701Sdim // ^ line up here. 609259701Sdim State.Stack.back().Indent = 610259701Sdim State.Column + (Style.BreakConstructorInitializersBeforeComma ? 0 : 2); 611259701Sdim if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine) 612259701Sdim State.Stack.back().AvoidBinPacking = true; 613259701Sdim State.Stack.back().BreakBeforeParameter = false; 614259701Sdim } 615259701Sdim 616259701Sdim // In ObjC method declaration we align on the ":" of parameters, but we need 617259701Sdim // to ensure that we indent parameters on subsequent lines by at least our 618259701Sdim // continuation indent width. 619259701Sdim if (Current.Type == TT_ObjCMethodSpecifier) 620259701Sdim State.Stack.back().Indent += Style.ContinuationIndentWidth; 621259701Sdim 622259701Sdim // Insert scopes created by fake parenthesis. 623259701Sdim const FormatToken *Previous = Current.getPreviousNonComment(); 624276479Sdim 625276479Sdim // Add special behavior to support a format commonly used for JavaScript 626276479Sdim // closures: 627276479Sdim // SomeFunction(function() { 628276479Sdim // foo(); 629276479Sdim // bar(); 630276479Sdim // }, a, b, c); 631276479Sdim if (Style.Language == FormatStyle::LK_JavaScript) { 632276479Sdim if (Current.isNot(tok::comment) && Previous && Previous->is(tok::l_brace) && 633276479Sdim State.Stack.size() > 1) { 634276479Sdim if (State.Stack[State.Stack.size() - 2].JSFunctionInlined && Newline) { 635276479Sdim for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) { 636276479Sdim State.Stack[i].NoLineBreak = true; 637276479Sdim } 638276479Sdim } 639276479Sdim State.Stack[State.Stack.size() - 2].JSFunctionInlined = false; 640276479Sdim } 641276479Sdim if (Current.TokenText == "function") 642276479Sdim State.Stack.back().JSFunctionInlined = !Newline; 643276479Sdim } 644276479Sdim 645276479Sdim moveStatePastFakeLParens(State, Newline); 646276479Sdim moveStatePastScopeOpener(State, Newline); 647276479Sdim moveStatePastScopeCloser(State); 648276479Sdim moveStatePastFakeRParens(State); 649276479Sdim 650276479Sdim if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) { 651276479Sdim State.StartOfStringLiteral = State.Column; 652276479Sdim } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) && 653276479Sdim !Current.isStringLiteral()) { 654276479Sdim State.StartOfStringLiteral = 0; 655276479Sdim } 656276479Sdim 657276479Sdim State.Column += Current.ColumnWidth; 658276479Sdim State.NextToken = State.NextToken->Next; 659276479Sdim unsigned Penalty = breakProtrudingToken(Current, State, DryRun); 660276479Sdim if (State.Column > getColumnLimit(State)) { 661276479Sdim unsigned ExcessCharacters = State.Column - getColumnLimit(State); 662276479Sdim Penalty += Style.PenaltyExcessCharacter * ExcessCharacters; 663276479Sdim } 664276479Sdim 665276479Sdim if (Current.Role) 666276479Sdim Current.Role->formatFromToken(State, this, DryRun); 667276479Sdim // If the previous has a special role, let it consume tokens as appropriate. 668276479Sdim // It is necessary to start at the previous token for the only implemented 669276479Sdim // role (comma separated list). That way, the decision whether or not to break 670276479Sdim // after the "{" is already done and both options are tried and evaluated. 671276479Sdim // FIXME: This is ugly, find a better way. 672276479Sdim if (Previous && Previous->Role) 673276479Sdim Penalty += Previous->Role->formatAfterToken(State, this, DryRun); 674276479Sdim 675276479Sdim return Penalty; 676276479Sdim} 677276479Sdim 678276479Sdimvoid ContinuationIndenter::moveStatePastFakeLParens(LineState &State, 679276479Sdim bool Newline) { 680276479Sdim const FormatToken &Current = *State.NextToken; 681276479Sdim const FormatToken *Previous = Current.getPreviousNonComment(); 682276479Sdim 683259701Sdim // Don't add extra indentation for the first fake parenthesis after 684276479Sdim // 'return', assignments or opening <({[. The indentation for these cases 685259701Sdim // is special cased. 686259701Sdim bool SkipFirstExtraIndent = 687259701Sdim (Previous && (Previous->opensScope() || Previous->is(tok::kw_return) || 688259701Sdim Previous->getPrecedence() == prec::Assignment || 689259701Sdim Previous->Type == TT_ObjCMethodExpr)); 690259701Sdim for (SmallVectorImpl<prec::Level>::const_reverse_iterator 691259701Sdim I = Current.FakeLParens.rbegin(), 692259701Sdim E = Current.FakeLParens.rend(); 693259701Sdim I != E; ++I) { 694259701Sdim ParenState NewParenState = State.Stack.back(); 695259701Sdim NewParenState.ContainsLineBreak = false; 696259701Sdim 697259701Sdim // Indent from 'LastSpace' unless this the fake parentheses encapsulating a 698259701Sdim // builder type call after 'return'. If such a call is line-wrapped, we 699259701Sdim // commonly just want to indent from the start of the line. 700259701Sdim if (!Previous || Previous->isNot(tok::kw_return) || *I > 0) 701259701Sdim NewParenState.Indent = 702259701Sdim std::max(std::max(State.Column, NewParenState.Indent), 703259701Sdim State.Stack.back().LastSpace); 704259701Sdim 705276479Sdim // Don't allow the RHS of an operator to be split over multiple lines unless 706276479Sdim // there is a line-break right after the operator. 707276479Sdim // Exclude relational operators, as there, it is always more desirable to 708276479Sdim // have the LHS 'left' of the RHS. 709276479Sdim if (Previous && Previous->getPrecedence() > prec::Assignment && 710276479Sdim (Previous->Type == TT_BinaryOperator || 711276479Sdim Previous->Type == TT_ConditionalExpr) && 712276479Sdim Previous->getPrecedence() != prec::Relational) { 713276479Sdim bool BreakBeforeOperator = Previous->is(tok::lessless) || 714276479Sdim (Previous->Type == TT_BinaryOperator && 715276479Sdim Style.BreakBeforeBinaryOperators) || 716276479Sdim (Previous->Type == TT_ConditionalExpr && 717276479Sdim Style.BreakBeforeTernaryOperators); 718276479Sdim if ((!Newline && !BreakBeforeOperator) || 719276479Sdim (!State.Stack.back().LastOperatorWrapped && BreakBeforeOperator)) 720276479Sdim NewParenState.NoLineBreak = true; 721276479Sdim } 722276479Sdim 723259701Sdim // Do not indent relative to the fake parentheses inserted for "." or "->". 724259701Sdim // This is a special case to make the following to statements consistent: 725259701Sdim // OuterFunction(InnerFunctionCall( // break 726259701Sdim // ParameterToInnerFunction)); 727259701Sdim // OuterFunction(SomeObject.InnerFunctionCall( // break 728259701Sdim // ParameterToInnerFunction)); 729259701Sdim if (*I > prec::Unknown) 730259701Sdim NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column); 731276479Sdim NewParenState.StartOfFunctionCall = State.Column; 732259701Sdim 733259701Sdim // Always indent conditional expressions. Never indent expression where 734259701Sdim // the 'operator' is ',', ';' or an assignment (i.e. *I <= 735259701Sdim // prec::Assignment) as those have different indentation rules. Indent 736259701Sdim // other expression, unless the indentation needs to be skipped. 737259701Sdim if (*I == prec::Conditional || 738259701Sdim (!SkipFirstExtraIndent && *I > prec::Assignment && 739259701Sdim !Style.BreakBeforeBinaryOperators)) 740259701Sdim NewParenState.Indent += Style.ContinuationIndentWidth; 741259701Sdim if ((Previous && !Previous->opensScope()) || *I > prec::Comma) 742259701Sdim NewParenState.BreakBeforeParameter = false; 743259701Sdim State.Stack.push_back(NewParenState); 744259701Sdim SkipFirstExtraIndent = false; 745259701Sdim } 746276479Sdim} 747259701Sdim 748276479Sdim// Remove the fake r_parens after 'Tok'. 749276479Sdimstatic void consumeRParens(LineState& State, const FormatToken &Tok) { 750276479Sdim for (unsigned i = 0, e = Tok.FakeRParens; i != e; ++i) { 751276479Sdim unsigned VariablePos = State.Stack.back().VariablePos; 752276479Sdim assert(State.Stack.size() > 1); 753276479Sdim if (State.Stack.size() == 1) { 754276479Sdim // Do not pop the last element. 755276479Sdim break; 756259701Sdim } 757276479Sdim State.Stack.pop_back(); 758276479Sdim State.Stack.back().VariablePos = VariablePos; 759276479Sdim } 760276479Sdim} 761259701Sdim 762276479Sdim// Returns whether 'Tok' opens or closes a scope requiring special handling 763276479Sdim// of the subsequent fake r_parens. 764276479Sdim// 765276479Sdim// For example, if this is an l_brace starting a nested block, we pretend (wrt. 766276479Sdim// to indentation) that we already consumed the corresponding r_brace. Thus, we 767276479Sdim// remove all ParenStates caused by fake parentheses that end at the r_brace. 768276479Sdim// The net effect of this is that we don't indent relative to the l_brace, if 769276479Sdim// the nested block is the last parameter of a function. This formats: 770276479Sdim// 771276479Sdim// SomeFunction(a, [] { 772276479Sdim// f(); // break 773276479Sdim// }); 774276479Sdim// 775276479Sdim// instead of: 776276479Sdim// SomeFunction(a, [] { 777276479Sdim// f(); // break 778276479Sdim// }); 779276479Sdimstatic bool fakeRParenSpecialCase(const LineState &State) { 780276479Sdim const FormatToken &Tok = *State.NextToken; 781276479Sdim if (!Tok.MatchingParen) 782276479Sdim return false; 783276479Sdim const FormatToken *Left = &Tok; 784276479Sdim if (Tok.isOneOf(tok::r_brace, tok::r_square)) 785276479Sdim Left = Tok.MatchingParen; 786276479Sdim return !State.Stack.back().HasMultipleNestedBlocks && 787276479Sdim Left->isOneOf(tok::l_brace, tok::l_square) && 788276479Sdim (Left->BlockKind == BK_Block || 789276479Sdim Left->Type == TT_ArrayInitializerLSquare || 790276479Sdim Left->Type == TT_DictLiteral); 791276479Sdim} 792276479Sdim 793276479Sdimvoid ContinuationIndenter::moveStatePastFakeRParens(LineState &State) { 794276479Sdim // Don't remove FakeRParens attached to r_braces that surround nested blocks 795276479Sdim // as they will have been removed early (see above). 796276479Sdim if (fakeRParenSpecialCase(State)) 797276479Sdim return; 798276479Sdim 799276479Sdim consumeRParens(State, *State.NextToken); 800276479Sdim} 801276479Sdim 802276479Sdimvoid ContinuationIndenter::moveStatePastScopeOpener(LineState &State, 803276479Sdim bool Newline) { 804276479Sdim const FormatToken &Current = *State.NextToken; 805276479Sdim if (!Current.opensScope()) 806276479Sdim return; 807276479Sdim 808276479Sdim if (Current.MatchingParen && Current.BlockKind == BK_Block) { 809276479Sdim moveStateToNewBlock(State); 810276479Sdim return; 811259701Sdim } 812259701Sdim 813276479Sdim unsigned NewIndent; 814276479Sdim unsigned NewIndentLevel = State.Stack.back().IndentLevel; 815276479Sdim bool AvoidBinPacking; 816276479Sdim bool BreakBeforeParameter = false; 817276479Sdim if (Current.is(tok::l_brace) || Current.Type == TT_ArrayInitializerLSquare) { 818276479Sdim if (fakeRParenSpecialCase(State)) 819276479Sdim consumeRParens(State, *Current.MatchingParen); 820276479Sdim 821276479Sdim NewIndent = State.Stack.back().LastSpace; 822276479Sdim if (Current.opensBlockTypeList(Style)) { 823276479Sdim NewIndent += Style.IndentWidth; 824276479Sdim NewIndent = std::min(State.Column + 2, NewIndent); 825276479Sdim ++NewIndentLevel; 826276479Sdim } else { 827276479Sdim NewIndent += Style.ContinuationIndentWidth; 828276479Sdim NewIndent = std::min(State.Column + 1, NewIndent); 829276479Sdim } 830276479Sdim const FormatToken *NextNoComment = Current.getNextNonComment(); 831276479Sdim AvoidBinPacking = Current.Type == TT_ArrayInitializerLSquare || 832276479Sdim Current.Type == TT_DictLiteral || 833276479Sdim Style.Language == FormatStyle::LK_Proto || 834276479Sdim !Style.BinPackParameters || 835276479Sdim (NextNoComment && 836276479Sdim NextNoComment->Type == TT_DesignatedInitializerPeriod); 837276479Sdim } else { 838276479Sdim NewIndent = Style.ContinuationIndentWidth + 839276479Sdim std::max(State.Stack.back().LastSpace, 840276479Sdim State.Stack.back().StartOfFunctionCall); 841276479Sdim AvoidBinPacking = !Style.BinPackParameters || 842276479Sdim (Style.ExperimentalAutoDetectBinPacking && 843276479Sdim (Current.PackingKind == PPK_OnePerLine || 844276479Sdim (!BinPackInconclusiveFunctions && 845276479Sdim Current.PackingKind == PPK_Inconclusive))); 846276479Sdim // If this '[' opens an ObjC call, determine whether all parameters fit 847276479Sdim // into one line and put one per line if they don't. 848276479Sdim if (Current.Type == TT_ObjCMethodExpr && Style.ColumnLimit != 0 && 849276479Sdim getLengthToMatchingParen(Current) + State.Column > 850276479Sdim getColumnLimit(State)) 851276479Sdim BreakBeforeParameter = true; 852276479Sdim } 853276479Sdim bool NoLineBreak = State.Stack.back().NoLineBreak || 854276479Sdim (Current.Type == TT_TemplateOpener && 855276479Sdim State.Stack.back().ContainsUnwrappedBuilder); 856276479Sdim State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, 857276479Sdim State.Stack.back().LastSpace, 858276479Sdim AvoidBinPacking, NoLineBreak)); 859276479Sdim State.Stack.back().BreakBeforeParameter = BreakBeforeParameter; 860276479Sdim State.Stack.back().HasMultipleNestedBlocks = Current.BlockParameterCount > 1; 861276479Sdim} 862276479Sdim 863276479Sdimvoid ContinuationIndenter::moveStatePastScopeCloser(LineState &State) { 864276479Sdim const FormatToken &Current = *State.NextToken; 865276479Sdim if (!Current.closesScope()) 866276479Sdim return; 867276479Sdim 868259701Sdim // If we encounter a closing ), ], } or >, we can remove a level from our 869259701Sdim // stacks. 870259701Sdim if (State.Stack.size() > 1 && 871259701Sdim (Current.isOneOf(tok::r_paren, tok::r_square) || 872259701Sdim (Current.is(tok::r_brace) && State.NextToken != State.Line->First) || 873276479Sdim State.NextToken->Type == TT_TemplateCloser)) 874259701Sdim State.Stack.pop_back(); 875276479Sdim 876259701Sdim if (Current.is(tok::r_square)) { 877259701Sdim // If this ends the array subscript expr, reset the corresponding value. 878259701Sdim const FormatToken *NextNonComment = Current.getNextNonComment(); 879259701Sdim if (NextNonComment && NextNonComment->isNot(tok::l_square)) 880259701Sdim State.Stack.back().StartOfArraySubscripts = 0; 881259701Sdim } 882276479Sdim} 883259701Sdim 884276479Sdimvoid ContinuationIndenter::moveStateToNewBlock(LineState &State) { 885276479Sdim // If we have already found more than one lambda introducers on this level, we 886276479Sdim // opt out of this because similarity between the lambdas is more important. 887276479Sdim if (fakeRParenSpecialCase(State)) 888276479Sdim consumeRParens(State, *State.NextToken->MatchingParen); 889259701Sdim 890276479Sdim // For some reason, ObjC blocks are indented like continuations. 891276479Sdim unsigned NewIndent = State.Stack.back().LastSpace + 892276479Sdim (State.NextToken->Type == TT_ObjCBlockLBrace 893276479Sdim ? Style.ContinuationIndentWidth 894276479Sdim : Style.IndentWidth); 895276479Sdim State.Stack.push_back(ParenState( 896276479Sdim NewIndent, /*NewIndentLevel=*/State.Stack.back().IndentLevel + 1, 897276479Sdim State.Stack.back().LastSpace, /*AvoidBinPacking=*/true, 898276479Sdim State.Stack.back().NoLineBreak)); 899276479Sdim State.Stack.back().BreakBeforeParameter = true; 900259701Sdim} 901259701Sdim 902259701Sdimunsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current, 903259701Sdim LineState &State) { 904259701Sdim // Break before further function parameters on all levels. 905259701Sdim for (unsigned i = 0, e = State.Stack.size(); i != e; ++i) 906259701Sdim State.Stack[i].BreakBeforeParameter = true; 907259701Sdim 908259701Sdim unsigned ColumnsUsed = State.Column; 909259701Sdim // We can only affect layout of the first and the last line, so the penalty 910259701Sdim // for all other lines is constant, and we ignore it. 911259701Sdim State.Column = Current.LastLineColumnWidth; 912259701Sdim 913259701Sdim if (ColumnsUsed > getColumnLimit(State)) 914259701Sdim return Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit(State)); 915259701Sdim return 0; 916259701Sdim} 917259701Sdim 918276479Sdimstatic bool getRawStringLiteralPrefixPostfix(StringRef Text, StringRef &Prefix, 919259701Sdim StringRef &Postfix) { 920259701Sdim if (Text.startswith(Prefix = "R\"") || Text.startswith(Prefix = "uR\"") || 921259701Sdim Text.startswith(Prefix = "UR\"") || Text.startswith(Prefix = "u8R\"") || 922259701Sdim Text.startswith(Prefix = "LR\"")) { 923259701Sdim size_t ParenPos = Text.find('('); 924259701Sdim if (ParenPos != StringRef::npos) { 925259701Sdim StringRef Delimiter = 926259701Sdim Text.substr(Prefix.size(), ParenPos - Prefix.size()); 927259701Sdim Prefix = Text.substr(0, ParenPos + 1); 928259701Sdim Postfix = Text.substr(Text.size() - 2 - Delimiter.size()); 929259701Sdim return Postfix.front() == ')' && Postfix.back() == '"' && 930259701Sdim Postfix.substr(1).startswith(Delimiter); 931259701Sdim } 932259701Sdim } 933259701Sdim return false; 934259701Sdim} 935259701Sdim 936259701Sdimunsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current, 937259701Sdim LineState &State, 938259701Sdim bool DryRun) { 939259701Sdim // Don't break multi-line tokens other than block comments. Instead, just 940259701Sdim // update the state. 941259701Sdim if (Current.Type != TT_BlockComment && Current.IsMultiline) 942259701Sdim return addMultilineToken(Current, State); 943259701Sdim 944259701Sdim // Don't break implicit string literals. 945259701Sdim if (Current.Type == TT_ImplicitStringLiteral) 946259701Sdim return 0; 947259701Sdim 948276479Sdim if (!Current.isStringLiteral() && !Current.is(tok::comment)) 949259701Sdim return 0; 950259701Sdim 951276479Sdim std::unique_ptr<BreakableToken> Token; 952259701Sdim unsigned StartColumn = State.Column - Current.ColumnWidth; 953259701Sdim unsigned ColumnLimit = getColumnLimit(State); 954259701Sdim 955276479Sdim if (Current.isStringLiteral()) { 956259701Sdim // Don't break string literals inside preprocessor directives (except for 957259701Sdim // #define directives, as their contents are stored in separate lines and 958259701Sdim // are not affected by this check). 959259701Sdim // This way we avoid breaking code with line directives and unknown 960259701Sdim // preprocessor directives that contain long string literals. 961259701Sdim if (State.Line->Type == LT_PreprocessorDirective) 962259701Sdim return 0; 963259701Sdim // Exempts unterminated string literals from line breaking. The user will 964259701Sdim // likely want to terminate the string before any line breaking is done. 965259701Sdim if (Current.IsUnterminatedLiteral) 966259701Sdim return 0; 967259701Sdim 968259701Sdim StringRef Text = Current.TokenText; 969259701Sdim StringRef Prefix; 970259701Sdim StringRef Postfix; 971276479Sdim bool IsNSStringLiteral = false; 972259701Sdim // FIXME: Handle whitespace between '_T', '(', '"..."', and ')'. 973259701Sdim // FIXME: Store Prefix and Suffix (or PrefixLength and SuffixLength to 974259701Sdim // reduce the overhead) for each FormatToken, which is a string, so that we 975259701Sdim // don't run multiple checks here on the hot path. 976276479Sdim if (Text.startswith("\"") && Current.Previous && 977276479Sdim Current.Previous->is(tok::at)) { 978276479Sdim IsNSStringLiteral = true; 979276479Sdim Prefix = "@\""; 980276479Sdim } 981259701Sdim if ((Text.endswith(Postfix = "\"") && 982276479Sdim (IsNSStringLiteral || Text.startswith(Prefix = "\"") || 983276479Sdim Text.startswith(Prefix = "u\"") || Text.startswith(Prefix = "U\"") || 984276479Sdim Text.startswith(Prefix = "u8\"") || 985259701Sdim Text.startswith(Prefix = "L\""))) || 986259701Sdim (Text.startswith(Prefix = "_T(\"") && Text.endswith(Postfix = "\")")) || 987259701Sdim getRawStringLiteralPrefixPostfix(Text, Prefix, Postfix)) { 988259701Sdim Token.reset(new BreakableStringLiteral( 989259701Sdim Current, State.Line->Level, StartColumn, Prefix, Postfix, 990259701Sdim State.Line->InPPDirective, Encoding, Style)); 991259701Sdim } else { 992259701Sdim return 0; 993259701Sdim } 994259701Sdim } else if (Current.Type == TT_BlockComment && Current.isTrailingComment()) { 995276479Sdim if (CommentPragmasRegex.match(Current.TokenText.substr(2))) 996276479Sdim return 0; 997259701Sdim Token.reset(new BreakableBlockComment( 998259701Sdim Current, State.Line->Level, StartColumn, Current.OriginalColumn, 999259701Sdim !Current.Previous, State.Line->InPPDirective, Encoding, Style)); 1000259701Sdim } else if (Current.Type == TT_LineComment && 1001276479Sdim (Current.Previous == nullptr || 1002259701Sdim Current.Previous->Type != TT_ImplicitStringLiteral)) { 1003276479Sdim if (CommentPragmasRegex.match(Current.TokenText.substr(2))) 1004276479Sdim return 0; 1005259701Sdim Token.reset(new BreakableLineComment(Current, State.Line->Level, 1006259701Sdim StartColumn, /*InPPDirective=*/false, 1007259701Sdim Encoding, Style)); 1008259701Sdim // We don't insert backslashes when breaking line comments. 1009259701Sdim ColumnLimit = Style.ColumnLimit; 1010259701Sdim } else { 1011259701Sdim return 0; 1012259701Sdim } 1013259701Sdim if (Current.UnbreakableTailLength >= ColumnLimit) 1014259701Sdim return 0; 1015259701Sdim 1016259701Sdim unsigned RemainingSpace = ColumnLimit - Current.UnbreakableTailLength; 1017259701Sdim bool BreakInserted = false; 1018259701Sdim unsigned Penalty = 0; 1019259701Sdim unsigned RemainingTokenColumns = 0; 1020259701Sdim for (unsigned LineIndex = 0, EndIndex = Token->getLineCount(); 1021259701Sdim LineIndex != EndIndex; ++LineIndex) { 1022259701Sdim if (!DryRun) 1023259701Sdim Token->replaceWhitespaceBefore(LineIndex, Whitespaces); 1024259701Sdim unsigned TailOffset = 0; 1025259701Sdim RemainingTokenColumns = 1026259701Sdim Token->getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos); 1027259701Sdim while (RemainingTokenColumns > RemainingSpace) { 1028259701Sdim BreakableToken::Split Split = 1029259701Sdim Token->getSplit(LineIndex, TailOffset, ColumnLimit); 1030259701Sdim if (Split.first == StringRef::npos) { 1031259701Sdim // The last line's penalty is handled in addNextStateToQueue(). 1032259701Sdim if (LineIndex < EndIndex - 1) 1033259701Sdim Penalty += Style.PenaltyExcessCharacter * 1034259701Sdim (RemainingTokenColumns - RemainingSpace); 1035259701Sdim break; 1036259701Sdim } 1037259701Sdim assert(Split.first != 0); 1038259701Sdim unsigned NewRemainingTokenColumns = Token->getLineLengthAfterSplit( 1039259701Sdim LineIndex, TailOffset + Split.first + Split.second, StringRef::npos); 1040259701Sdim 1041259701Sdim // We can remove extra whitespace instead of breaking the line. 1042259701Sdim if (RemainingTokenColumns + 1 - Split.second <= RemainingSpace) { 1043259701Sdim RemainingTokenColumns = 0; 1044259701Sdim if (!DryRun) 1045259701Sdim Token->replaceWhitespace(LineIndex, TailOffset, Split, Whitespaces); 1046259701Sdim break; 1047259701Sdim } 1048259701Sdim 1049276479Sdim // When breaking before a tab character, it may be moved by a few columns, 1050276479Sdim // but will still be expanded to the next tab stop, so we don't save any 1051276479Sdim // columns. 1052276479Sdim if (NewRemainingTokenColumns == RemainingTokenColumns) 1053276479Sdim break; 1054276479Sdim 1055259701Sdim assert(NewRemainingTokenColumns < RemainingTokenColumns); 1056259701Sdim if (!DryRun) 1057259701Sdim Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces); 1058259701Sdim Penalty += Current.SplitPenalty; 1059259701Sdim unsigned ColumnsUsed = 1060259701Sdim Token->getLineLengthAfterSplit(LineIndex, TailOffset, Split.first); 1061259701Sdim if (ColumnsUsed > ColumnLimit) { 1062259701Sdim Penalty += Style.PenaltyExcessCharacter * (ColumnsUsed - ColumnLimit); 1063259701Sdim } 1064259701Sdim TailOffset += Split.first + Split.second; 1065259701Sdim RemainingTokenColumns = NewRemainingTokenColumns; 1066259701Sdim BreakInserted = true; 1067259701Sdim } 1068259701Sdim } 1069259701Sdim 1070259701Sdim State.Column = RemainingTokenColumns; 1071259701Sdim 1072259701Sdim if (BreakInserted) { 1073259701Sdim // If we break the token inside a parameter list, we need to break before 1074259701Sdim // the next parameter on all levels, so that the next parameter is clearly 1075259701Sdim // visible. Line comments already introduce a break. 1076259701Sdim if (Current.Type != TT_LineComment) { 1077259701Sdim for (unsigned i = 0, e = State.Stack.size(); i != e; ++i) 1078259701Sdim State.Stack[i].BreakBeforeParameter = true; 1079259701Sdim } 1080259701Sdim 1081276479Sdim Penalty += Current.isStringLiteral() ? Style.PenaltyBreakString 1082276479Sdim : Style.PenaltyBreakComment; 1083259701Sdim 1084259701Sdim State.Stack.back().LastSpace = StartColumn; 1085259701Sdim } 1086259701Sdim return Penalty; 1087259701Sdim} 1088259701Sdim 1089259701Sdimunsigned ContinuationIndenter::getColumnLimit(const LineState &State) const { 1090259701Sdim // In preprocessor directives reserve two chars for trailing " \" 1091259701Sdim return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0); 1092259701Sdim} 1093259701Sdim 1094276479Sdimbool ContinuationIndenter::nextIsMultilineString(const LineState &State) { 1095259701Sdim const FormatToken &Current = *State.NextToken; 1096276479Sdim if (!Current.isStringLiteral() || Current.Type == TT_ImplicitStringLiteral) 1097259701Sdim return false; 1098259701Sdim // We never consider raw string literals "multiline" for the purpose of 1099276479Sdim // AlwaysBreakBeforeMultilineStrings implementation as they are special-cased 1100276479Sdim // (see TokenAnnotator::mustBreakBefore(). 1101259701Sdim if (Current.TokenText.startswith("R\"")) 1102259701Sdim return false; 1103259701Sdim if (Current.IsMultiline) 1104259701Sdim return true; 1105259701Sdim if (Current.getNextNonComment() && 1106276479Sdim Current.getNextNonComment()->isStringLiteral()) 1107259701Sdim return true; // Implicit concatenation. 1108259701Sdim if (State.Column + Current.ColumnWidth + Current.UnbreakableTailLength > 1109259701Sdim Style.ColumnLimit) 1110259701Sdim return true; // String will be split. 1111259701Sdim return false; 1112259701Sdim} 1113259701Sdim 1114259701Sdim} // namespace format 1115259701Sdim} // namespace clang 1116