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#define DEBUG_TYPE "format-formatter" 16259701Sdim 17259701Sdim#include "BreakableToken.h" 18259701Sdim#include "ContinuationIndenter.h" 19259701Sdim#include "WhitespaceManager.h" 20259701Sdim#include "clang/Basic/OperatorPrecedence.h" 21259701Sdim#include "clang/Basic/SourceManager.h" 22259701Sdim#include "clang/Format/Format.h" 23259701Sdim#include "llvm/Support/Debug.h" 24259701Sdim#include <string> 25259701Sdim 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) { 32259701Sdim if (Tok.MatchingParen == NULL) 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), 66259701Sdim BinPackInconclusiveFunctions(BinPackInconclusiveFunctions) {} 67259701Sdim 68259701SdimLineState ContinuationIndenter::getInitialState(unsigned FirstIndent, 69259701Sdim const AnnotatedLine *Line, 70259701Sdim bool DryRun) { 71259701Sdim LineState State; 72259701Sdim State.FirstIndent = FirstIndent; 73259701Sdim State.Column = FirstIndent; 74259701Sdim State.Line = Line; 75259701Sdim State.NextToken = Line->First; 76259701Sdim State.Stack.push_back(ParenState(FirstIndent, Line->Level, FirstIndent, 77259701Sdim /*AvoidBinPacking=*/false, 78259701Sdim /*NoLineBreak=*/false)); 79259701Sdim State.LineContainsContinuedForLoopSection = false; 80259701Sdim State.ParenLevel = 0; 81259701Sdim State.StartOfStringLiteral = 0; 82259701Sdim State.StartOfLineLevel = State.ParenLevel; 83259701Sdim State.LowestLevelOnLine = State.ParenLevel; 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) && 101259701Sdim Previous.Type != TT_DictLiteral && 102259701Sdim Previous.BlockKind == BK_BracedInit && 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. 110259701Sdim if (Previous.opensScope() && State.LowestLevelOnLine < State.StartOfLineLevel) 111259701Sdim return false; 112259701Sdim if (Current.isMemberAccess() && State.Stack.back().ContainsUnwrappedBuilder) 113259701Sdim return false; 114259701Sdim return !State.Stack.back().NoLineBreak; 115259701Sdim} 116259701Sdim 117259701Sdimbool ContinuationIndenter::mustBreak(const LineState &State) { 118259701Sdim const FormatToken &Current = *State.NextToken; 119259701Sdim const FormatToken &Previous = *Current.Previous; 120259701Sdim if (Current.MustBreakBefore || Current.Type == TT_InlineASMColon) 121259701Sdim return true; 122259701Sdim if (State.Stack.back().BreakBeforeClosingBrace && 123259701Sdim Current.closesBlockTypeList(Style)) 124259701Sdim return true; 125259701Sdim if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection) 126259701Sdim return true; 127259701Sdim if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || 128259701Sdim (Style.BreakBeforeTernaryOperators && 129259701Sdim (Current.is(tok::question) || (Current.Type == TT_ConditionalExpr && 130259701Sdim Previous.isNot(tok::question)))) || 131259701Sdim (!Style.BreakBeforeTernaryOperators && 132259701Sdim (Previous.is(tok::question) || Previous.Type == TT_ConditionalExpr))) && 133259701Sdim State.Stack.back().BreakBeforeParameter && !Current.isTrailingComment() && 134259701Sdim !Current.isOneOf(tok::r_paren, tok::r_brace)) 135259701Sdim return true; 136259701Sdim if (Style.AlwaysBreakBeforeMultilineStrings && 137259701Sdim State.Column > State.Stack.back().Indent && // Breaking saves columns. 138259701Sdim !Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) && 139259701Sdim Previous.Type != TT_InlineASMColon && NextIsMultilineString(State)) 140259701Sdim return true; 141259701Sdim if (((Previous.Type == TT_DictLiteral && Previous.is(tok::l_brace)) || 142259701Sdim Previous.Type == TT_ArrayInitializerLSquare) && 143259701Sdim getLengthToMatchingParen(Previous) + State.Column > getColumnLimit(State)) 144259701Sdim return true; 145259701Sdim 146259701Sdim if (!Style.BreakBeforeBinaryOperators) { 147259701Sdim // If we need to break somewhere inside the LHS of a binary expression, we 148259701Sdim // should also break after the operator. Otherwise, the formatting would 149259701Sdim // hide the operator precedence, e.g. in: 150259701Sdim // if (aaaaaaaaaaaaaa == 151259701Sdim // bbbbbbbbbbbbbb && c) {.. 152259701Sdim // For comparisons, we only apply this rule, if the LHS is a binary 153259701Sdim // expression itself as otherwise, the line breaks seem superfluous. 154259701Sdim // We need special cases for ">>" which we have split into two ">" while 155259701Sdim // lexing in order to make template parsing easier. 156259701Sdim // 157259701Sdim // FIXME: We'll need something similar for styles that break before binary 158259701Sdim // operators. 159259701Sdim bool IsComparison = (Previous.getPrecedence() == prec::Relational || 160259701Sdim Previous.getPrecedence() == prec::Equality) && 161259701Sdim Previous.Previous && 162259701Sdim Previous.Previous->Type != TT_BinaryOperator; // For >>. 163259701Sdim bool LHSIsBinaryExpr = 164259701Sdim Previous.Previous && Previous.Previous->EndsBinaryExpression; 165259701Sdim if (Previous.Type == TT_BinaryOperator && 166259701Sdim (!IsComparison || LHSIsBinaryExpr) && 167259701Sdim Current.Type != TT_BinaryOperator && // For >>. 168259701Sdim !Current.isTrailingComment() && 169259701Sdim !Previous.isOneOf(tok::lessless, tok::question) && 170259701Sdim Previous.getPrecedence() != prec::Assignment && 171259701Sdim State.Stack.back().BreakBeforeParameter) 172259701Sdim return true; 173259701Sdim } 174259701Sdim 175259701Sdim // Same as above, but for the first "<<" operator. 176259701Sdim if (Current.is(tok::lessless) && State.Stack.back().BreakBeforeParameter && 177259701Sdim State.Stack.back().FirstLessLess == 0) 178259701Sdim return true; 179259701Sdim 180259701Sdim // FIXME: Comparing LongestObjCSelectorName to 0 is a hacky way of finding 181259701Sdim // out whether it is the first parameter. Clean this up. 182259701Sdim if (Current.Type == TT_ObjCSelectorName && 183259701Sdim Current.LongestObjCSelectorName == 0 && 184259701Sdim State.Stack.back().BreakBeforeParameter) 185259701Sdim return true; 186259701Sdim if ((Current.Type == TT_CtorInitializerColon || 187259701Sdim (Previous.ClosesTemplateDeclaration && State.ParenLevel == 0 && 188259701Sdim !Current.isTrailingComment()))) 189259701Sdim return true; 190259701Sdim 191259701Sdim if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) && 192259701Sdim State.Line->MightBeFunctionDecl && 193259701Sdim State.Stack.back().BreakBeforeParameter && State.ParenLevel == 0) 194259701Sdim return true; 195259701Sdim if (startsSegmentOfBuilderTypeCall(Current) && 196259701Sdim (State.Stack.back().CallContinuation != 0 || 197259701Sdim (State.Stack.back().BreakBeforeParameter && 198259701Sdim State.Stack.back().ContainsUnwrappedBuilder))) 199259701Sdim return true; 200259701Sdim return false; 201259701Sdim} 202259701Sdim 203259701Sdimunsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, 204259701Sdim bool DryRun, 205259701Sdim unsigned ExtraSpaces) { 206259701Sdim const FormatToken &Current = *State.NextToken; 207259701Sdim 208259701Sdim if (State.Stack.size() == 0 || 209259701Sdim (Current.Type == TT_ImplicitStringLiteral && 210259701Sdim (Current.Previous->Tok.getIdentifierInfo() == NULL || 211259701Sdim Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() == 212259701Sdim tok::pp_not_keyword))) { 213259701Sdim // FIXME: Is this correct? 214259701Sdim int WhitespaceLength = SourceMgr.getSpellingColumnNumber( 215259701Sdim State.NextToken->WhitespaceRange.getEnd()) - 216259701Sdim SourceMgr.getSpellingColumnNumber( 217259701Sdim State.NextToken->WhitespaceRange.getBegin()); 218259701Sdim State.Column += WhitespaceLength + State.NextToken->ColumnWidth; 219259701Sdim State.NextToken = State.NextToken->Next; 220259701Sdim return 0; 221259701Sdim } 222259701Sdim 223259701Sdim unsigned Penalty = 0; 224259701Sdim if (Newline) 225259701Sdim Penalty = addTokenOnNewLine(State, DryRun); 226259701Sdim else 227259701Sdim addTokenOnCurrentLine(State, DryRun, ExtraSpaces); 228259701Sdim 229259701Sdim return moveStateToNextToken(State, DryRun, Newline) + Penalty; 230259701Sdim} 231259701Sdim 232259701Sdimvoid ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, 233259701Sdim unsigned ExtraSpaces) { 234259701Sdim FormatToken &Current = *State.NextToken; 235259701Sdim const FormatToken &Previous = *State.NextToken->Previous; 236259701Sdim if (Current.is(tok::equal) && 237259701Sdim (State.Line->First->is(tok::kw_for) || State.ParenLevel == 0) && 238259701Sdim State.Stack.back().VariablePos == 0) { 239259701Sdim State.Stack.back().VariablePos = State.Column; 240259701Sdim // Move over * and & if they are bound to the variable name. 241259701Sdim const FormatToken *Tok = &Previous; 242259701Sdim while (Tok && State.Stack.back().VariablePos >= Tok->ColumnWidth) { 243259701Sdim State.Stack.back().VariablePos -= Tok->ColumnWidth; 244259701Sdim if (Tok->SpacesRequiredBefore != 0) 245259701Sdim break; 246259701Sdim Tok = Tok->Previous; 247259701Sdim } 248259701Sdim if (Previous.PartOfMultiVariableDeclStmt) 249259701Sdim State.Stack.back().LastSpace = State.Stack.back().VariablePos; 250259701Sdim } 251259701Sdim 252259701Sdim unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces; 253259701Sdim 254259701Sdim if (!DryRun) 255259701Sdim Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, /*IndentLevel=*/0, 256259701Sdim Spaces, State.Column + Spaces); 257259701Sdim 258259701Sdim if (Current.Type == TT_ObjCSelectorName && State.Stack.back().ColonPos == 0) { 259259701Sdim if (State.Stack.back().Indent + Current.LongestObjCSelectorName > 260259701Sdim State.Column + Spaces + Current.ColumnWidth) 261259701Sdim State.Stack.back().ColonPos = 262259701Sdim State.Stack.back().Indent + Current.LongestObjCSelectorName; 263259701Sdim else 264259701Sdim State.Stack.back().ColonPos = State.Column + Spaces + Current.ColumnWidth; 265259701Sdim } 266259701Sdim 267259701Sdim if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr && 268259701Sdim Current.Type != TT_LineComment) 269259701Sdim State.Stack.back().Indent = State.Column + Spaces; 270259701Sdim if (State.Stack.back().AvoidBinPacking && startsNextParameter(Current, Style)) 271259701Sdim State.Stack.back().NoLineBreak = true; 272259701Sdim if (startsSegmentOfBuilderTypeCall(Current)) 273259701Sdim State.Stack.back().ContainsUnwrappedBuilder = true; 274259701Sdim 275259701Sdim State.Column += Spaces; 276259701Sdim if (Current.is(tok::l_paren) && Previous.isOneOf(tok::kw_if, tok::kw_for)) 277259701Sdim // Treat the condition inside an if as if it was a second function 278259701Sdim // parameter, i.e. let nested calls have a continuation indent. 279259701Sdim State.Stack.back().LastSpace = State.Column + 1; // 1 is length of "(". 280259701Sdim else if (Previous.is(tok::comma) || Previous.Type == TT_ObjCMethodExpr) 281259701Sdim State.Stack.back().LastSpace = State.Column; 282259701Sdim else if ((Previous.Type == TT_BinaryOperator || 283259701Sdim Previous.Type == TT_ConditionalExpr || 284259701Sdim Previous.Type == TT_UnaryOperator || 285259701Sdim Previous.Type == TT_CtorInitializerColon) && 286259701Sdim (Previous.getPrecedence() != prec::Assignment || 287259701Sdim Current.StartsBinaryExpression)) 288259701Sdim // Always indent relative to the RHS of the expression unless this is a 289259701Sdim // simple assignment without binary expression on the RHS. Also indent 290259701Sdim // relative to unary operators and the colons of constructor initializers. 291259701Sdim State.Stack.back().LastSpace = State.Column; 292259701Sdim else if (Previous.Type == TT_InheritanceColon) { 293259701Sdim State.Stack.back().Indent = State.Column; 294259701Sdim State.Stack.back().LastSpace = State.Column; 295259701Sdim } else if (Previous.opensScope()) { 296259701Sdim // If a function has a trailing call, indent all parameters from the 297259701Sdim // opening parenthesis. This avoids confusing indents like: 298259701Sdim // OuterFunction(InnerFunctionCall( // break 299259701Sdim // ParameterToInnerFunction)) // break 300259701Sdim // .SecondInnerFunctionCall(); 301259701Sdim bool HasTrailingCall = false; 302259701Sdim if (Previous.MatchingParen) { 303259701Sdim const FormatToken *Next = Previous.MatchingParen->getNextNonComment(); 304259701Sdim HasTrailingCall = Next && Next->isMemberAccess(); 305259701Sdim } 306259701Sdim if (HasTrailingCall && 307259701Sdim State.Stack[State.Stack.size() - 2].CallContinuation == 0) 308259701Sdim State.Stack.back().LastSpace = State.Column; 309259701Sdim } 310259701Sdim} 311259701Sdim 312259701Sdimunsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, 313259701Sdim bool DryRun) { 314259701Sdim FormatToken &Current = *State.NextToken; 315259701Sdim const FormatToken &Previous = *State.NextToken->Previous; 316259701Sdim // If we are continuing an expression, we want to use the continuation indent. 317259701Sdim unsigned ContinuationIndent = 318259701Sdim std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) + 319259701Sdim Style.ContinuationIndentWidth; 320259701Sdim // Extra penalty that needs to be added because of the way certain line 321259701Sdim // breaks are chosen. 322259701Sdim unsigned Penalty = 0; 323259701Sdim 324259701Sdim const FormatToken *PreviousNonComment = 325259701Sdim State.NextToken->getPreviousNonComment(); 326259701Sdim // The first line break on any ParenLevel causes an extra penalty in order 327259701Sdim // prefer similar line breaks. 328259701Sdim if (!State.Stack.back().ContainsLineBreak) 329259701Sdim Penalty += 15; 330259701Sdim State.Stack.back().ContainsLineBreak = true; 331259701Sdim 332259701Sdim Penalty += State.NextToken->SplitPenalty; 333259701Sdim 334259701Sdim // Breaking before the first "<<" is generally not desirable if the LHS is 335259701Sdim // short. 336259701Sdim if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0 && 337259701Sdim State.Column <= Style.ColumnLimit / 2) 338259701Sdim Penalty += Style.PenaltyBreakFirstLessLess; 339259701Sdim 340259701Sdim if (Current.is(tok::l_brace) && Current.BlockKind == BK_Block) { 341259701Sdim State.Column = State.FirstIndent; 342259701Sdim } else if (Current.isOneOf(tok::r_brace, tok::r_square)) { 343259701Sdim if (Current.closesBlockTypeList(Style) || 344259701Sdim (Current.MatchingParen && 345259701Sdim Current.MatchingParen->BlockKind == BK_BracedInit)) 346259701Sdim State.Column = State.Stack[State.Stack.size() - 2].LastSpace; 347259701Sdim else 348259701Sdim State.Column = State.FirstIndent; 349259701Sdim } else if (Current.is(tok::string_literal) && 350259701Sdim State.StartOfStringLiteral != 0) { 351259701Sdim State.Column = State.StartOfStringLiteral; 352259701Sdim State.Stack.back().BreakBeforeParameter = true; 353259701Sdim } else if (Current.is(tok::lessless) && 354259701Sdim State.Stack.back().FirstLessLess != 0) { 355259701Sdim State.Column = State.Stack.back().FirstLessLess; 356259701Sdim } else if (Current.isMemberAccess()) { 357259701Sdim if (State.Stack.back().CallContinuation == 0) { 358259701Sdim State.Column = ContinuationIndent; 359259701Sdim State.Stack.back().CallContinuation = State.Column; 360259701Sdim } else { 361259701Sdim State.Column = State.Stack.back().CallContinuation; 362259701Sdim } 363259701Sdim } else if (State.Stack.back().QuestionColumn != 0 && 364259701Sdim (Current.Type == TT_ConditionalExpr || 365259701Sdim Previous.Type == TT_ConditionalExpr)) { 366259701Sdim State.Column = State.Stack.back().QuestionColumn; 367259701Sdim } else if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0) { 368259701Sdim State.Column = State.Stack.back().VariablePos; 369259701Sdim } else if ((PreviousNonComment && 370259701Sdim PreviousNonComment->ClosesTemplateDeclaration) || 371259701Sdim ((Current.Type == TT_StartOfName || 372259701Sdim Current.is(tok::kw_operator)) && 373259701Sdim State.ParenLevel == 0 && 374259701Sdim (!Style.IndentFunctionDeclarationAfterType || 375259701Sdim State.Line->StartsDefinition))) { 376259701Sdim State.Column = State.Stack.back().Indent; 377259701Sdim } else if (Current.Type == TT_ObjCSelectorName) { 378259701Sdim if (State.Stack.back().ColonPos == 0) { 379259701Sdim State.Stack.back().ColonPos = 380259701Sdim State.Stack.back().Indent + Current.LongestObjCSelectorName; 381259701Sdim State.Column = State.Stack.back().ColonPos - Current.ColumnWidth; 382259701Sdim } else if (State.Stack.back().ColonPos > Current.ColumnWidth) { 383259701Sdim State.Column = State.Stack.back().ColonPos - Current.ColumnWidth; 384259701Sdim } else { 385259701Sdim State.Column = State.Stack.back().Indent; 386259701Sdim State.Stack.back().ColonPos = State.Column + Current.ColumnWidth; 387259701Sdim } 388259701Sdim } else if (Current.Type == TT_ArraySubscriptLSquare) { 389259701Sdim if (State.Stack.back().StartOfArraySubscripts != 0) 390259701Sdim State.Column = State.Stack.back().StartOfArraySubscripts; 391259701Sdim else 392259701Sdim State.Column = ContinuationIndent; 393259701Sdim } else if (Current.Type == TT_StartOfName || 394259701Sdim Previous.isOneOf(tok::coloncolon, tok::equal) || 395259701Sdim Previous.Type == TT_ObjCMethodExpr) { 396259701Sdim State.Column = ContinuationIndent; 397259701Sdim } else if (Current.Type == TT_CtorInitializerColon) { 398259701Sdim State.Column = State.FirstIndent + Style.ConstructorInitializerIndentWidth; 399259701Sdim } else if (Current.Type == TT_CtorInitializerComma) { 400259701Sdim State.Column = State.Stack.back().Indent; 401259701Sdim } else { 402259701Sdim State.Column = State.Stack.back().Indent; 403259701Sdim // Ensure that we fall back to the continuation indent width instead of just 404259701Sdim // flushing continuations left. 405259701Sdim if (State.Column == State.FirstIndent && 406259701Sdim PreviousNonComment->isNot(tok::r_brace)) 407259701Sdim State.Column += Style.ContinuationIndentWidth; 408259701Sdim } 409259701Sdim 410259701Sdim if ((Previous.isOneOf(tok::comma, tok::semi) && 411259701Sdim !State.Stack.back().AvoidBinPacking) || 412259701Sdim Previous.Type == TT_BinaryOperator) 413259701Sdim State.Stack.back().BreakBeforeParameter = false; 414259701Sdim if (Previous.Type == TT_TemplateCloser && State.ParenLevel == 0) 415259701Sdim State.Stack.back().BreakBeforeParameter = false; 416259701Sdim if (Current.is(tok::question) || 417259701Sdim (PreviousNonComment && PreviousNonComment->is(tok::question))) 418259701Sdim State.Stack.back().BreakBeforeParameter = true; 419259701Sdim 420259701Sdim if (!DryRun) { 421259701Sdim unsigned Newlines = 1; 422259701Sdim if (Current.is(tok::comment)) 423259701Sdim Newlines = std::max(Newlines, std::min(Current.NewlinesBefore, 424259701Sdim Style.MaxEmptyLinesToKeep + 1)); 425259701Sdim Whitespaces.replaceWhitespace(Current, Newlines, 426259701Sdim State.Stack.back().IndentLevel, State.Column, 427259701Sdim State.Column, State.Line->InPPDirective); 428259701Sdim } 429259701Sdim 430259701Sdim if (!Current.isTrailingComment()) 431259701Sdim State.Stack.back().LastSpace = State.Column; 432259701Sdim if (Current.isMemberAccess()) 433259701Sdim State.Stack.back().LastSpace += Current.ColumnWidth; 434259701Sdim State.StartOfLineLevel = State.ParenLevel; 435259701Sdim State.LowestLevelOnLine = State.ParenLevel; 436259701Sdim 437259701Sdim // Any break on this level means that the parent level has been broken 438259701Sdim // and we need to avoid bin packing there. 439259701Sdim for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) { 440259701Sdim State.Stack[i].BreakBeforeParameter = true; 441259701Sdim } 442259701Sdim if (PreviousNonComment && 443259701Sdim !PreviousNonComment->isOneOf(tok::comma, tok::semi) && 444259701Sdim PreviousNonComment->Type != TT_TemplateCloser && 445259701Sdim PreviousNonComment->Type != TT_BinaryOperator && 446259701Sdim Current.Type != TT_BinaryOperator && 447259701Sdim !PreviousNonComment->opensScope()) 448259701Sdim State.Stack.back().BreakBeforeParameter = true; 449259701Sdim 450259701Sdim // If we break after { or the [ of an array initializer, we should also break 451259701Sdim // before the corresponding } or ]. 452259701Sdim if (Previous.is(tok::l_brace) || Previous.Type == TT_ArrayInitializerLSquare) 453259701Sdim State.Stack.back().BreakBeforeClosingBrace = true; 454259701Sdim 455259701Sdim if (State.Stack.back().AvoidBinPacking) { 456259701Sdim // If we are breaking after '(', '{', '<', this is not bin packing 457259701Sdim // unless AllowAllParametersOfDeclarationOnNextLine is false. 458259701Sdim if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) || 459259701Sdim Previous.Type == TT_BinaryOperator) || 460259701Sdim (!Style.AllowAllParametersOfDeclarationOnNextLine && 461259701Sdim State.Line->MustBeDeclaration)) 462259701Sdim State.Stack.back().BreakBeforeParameter = true; 463259701Sdim } 464259701Sdim 465259701Sdim return Penalty; 466259701Sdim} 467259701Sdim 468259701Sdimunsigned ContinuationIndenter::moveStateToNextToken(LineState &State, 469259701Sdim bool DryRun, bool Newline) { 470259701Sdim const FormatToken &Current = *State.NextToken; 471259701Sdim assert(State.Stack.size()); 472259701Sdim 473259701Sdim if (Current.Type == TT_InheritanceColon) 474259701Sdim State.Stack.back().AvoidBinPacking = true; 475259701Sdim if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0) 476259701Sdim State.Stack.back().FirstLessLess = State.Column; 477259701Sdim if (Current.Type == TT_ArraySubscriptLSquare && 478259701Sdim State.Stack.back().StartOfArraySubscripts == 0) 479259701Sdim State.Stack.back().StartOfArraySubscripts = State.Column; 480259701Sdim if ((Current.is(tok::question) && Style.BreakBeforeTernaryOperators) || 481259701Sdim (Current.getPreviousNonComment() && Current.isNot(tok::colon) && 482259701Sdim Current.getPreviousNonComment()->is(tok::question) && 483259701Sdim !Style.BreakBeforeTernaryOperators)) 484259701Sdim State.Stack.back().QuestionColumn = State.Column; 485259701Sdim if (!Current.opensScope() && !Current.closesScope()) 486259701Sdim State.LowestLevelOnLine = 487259701Sdim std::min(State.LowestLevelOnLine, State.ParenLevel); 488259701Sdim if (Current.isMemberAccess()) 489259701Sdim State.Stack.back().StartOfFunctionCall = 490259701Sdim Current.LastInChainOfCalls ? 0 : State.Column + Current.ColumnWidth; 491259701Sdim if (Current.Type == TT_CtorInitializerColon) { 492259701Sdim // Indent 2 from the column, so: 493259701Sdim // SomeClass::SomeClass() 494259701Sdim // : First(...), ... 495259701Sdim // Next(...) 496259701Sdim // ^ line up here. 497259701Sdim State.Stack.back().Indent = 498259701Sdim State.Column + (Style.BreakConstructorInitializersBeforeComma ? 0 : 2); 499259701Sdim if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine) 500259701Sdim State.Stack.back().AvoidBinPacking = true; 501259701Sdim State.Stack.back().BreakBeforeParameter = false; 502259701Sdim } 503259701Sdim 504259701Sdim // In ObjC method declaration we align on the ":" of parameters, but we need 505259701Sdim // to ensure that we indent parameters on subsequent lines by at least our 506259701Sdim // continuation indent width. 507259701Sdim if (Current.Type == TT_ObjCMethodSpecifier) 508259701Sdim State.Stack.back().Indent += Style.ContinuationIndentWidth; 509259701Sdim 510259701Sdim // Insert scopes created by fake parenthesis. 511259701Sdim const FormatToken *Previous = Current.getPreviousNonComment(); 512259701Sdim // Don't add extra indentation for the first fake parenthesis after 513259701Sdim // 'return', assignements or opening <({[. The indentation for these cases 514259701Sdim // is special cased. 515259701Sdim bool SkipFirstExtraIndent = 516259701Sdim (Previous && (Previous->opensScope() || Previous->is(tok::kw_return) || 517259701Sdim Previous->getPrecedence() == prec::Assignment || 518259701Sdim Previous->Type == TT_ObjCMethodExpr)); 519259701Sdim for (SmallVectorImpl<prec::Level>::const_reverse_iterator 520259701Sdim I = Current.FakeLParens.rbegin(), 521259701Sdim E = Current.FakeLParens.rend(); 522259701Sdim I != E; ++I) { 523259701Sdim ParenState NewParenState = State.Stack.back(); 524259701Sdim NewParenState.ContainsLineBreak = false; 525259701Sdim 526259701Sdim // Indent from 'LastSpace' unless this the fake parentheses encapsulating a 527259701Sdim // builder type call after 'return'. If such a call is line-wrapped, we 528259701Sdim // commonly just want to indent from the start of the line. 529259701Sdim if (!Previous || Previous->isNot(tok::kw_return) || *I > 0) 530259701Sdim NewParenState.Indent = 531259701Sdim std::max(std::max(State.Column, NewParenState.Indent), 532259701Sdim State.Stack.back().LastSpace); 533259701Sdim 534259701Sdim // Do not indent relative to the fake parentheses inserted for "." or "->". 535259701Sdim // This is a special case to make the following to statements consistent: 536259701Sdim // OuterFunction(InnerFunctionCall( // break 537259701Sdim // ParameterToInnerFunction)); 538259701Sdim // OuterFunction(SomeObject.InnerFunctionCall( // break 539259701Sdim // ParameterToInnerFunction)); 540259701Sdim if (*I > prec::Unknown) 541259701Sdim NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column); 542259701Sdim 543259701Sdim // Always indent conditional expressions. Never indent expression where 544259701Sdim // the 'operator' is ',', ';' or an assignment (i.e. *I <= 545259701Sdim // prec::Assignment) as those have different indentation rules. Indent 546259701Sdim // other expression, unless the indentation needs to be skipped. 547259701Sdim if (*I == prec::Conditional || 548259701Sdim (!SkipFirstExtraIndent && *I > prec::Assignment && 549259701Sdim !Style.BreakBeforeBinaryOperators)) 550259701Sdim NewParenState.Indent += Style.ContinuationIndentWidth; 551259701Sdim if ((Previous && !Previous->opensScope()) || *I > prec::Comma) 552259701Sdim NewParenState.BreakBeforeParameter = false; 553259701Sdim State.Stack.push_back(NewParenState); 554259701Sdim SkipFirstExtraIndent = false; 555259701Sdim } 556259701Sdim 557259701Sdim // If we encounter an opening (, [, { or <, we add a level to our stacks to 558259701Sdim // prepare for the following tokens. 559259701Sdim if (Current.opensScope()) { 560259701Sdim unsigned NewIndent; 561259701Sdim unsigned NewIndentLevel = State.Stack.back().IndentLevel; 562259701Sdim bool AvoidBinPacking; 563259701Sdim bool BreakBeforeParameter = false; 564259701Sdim if (Current.is(tok::l_brace) || 565259701Sdim Current.Type == TT_ArrayInitializerLSquare) { 566259701Sdim if (Current.MatchingParen && Current.BlockKind == BK_Block) { 567259701Sdim // If this is an l_brace starting a nested block, we pretend (wrt. to 568259701Sdim // indentation) that we already consumed the corresponding r_brace. 569259701Sdim // Thus, we remove all ParenStates caused bake fake parentheses that end 570259701Sdim // at the r_brace. The net effect of this is that we don't indent 571259701Sdim // relative to the l_brace, if the nested block is the last parameter of 572259701Sdim // a function. For example, this formats: 573259701Sdim // 574259701Sdim // SomeFunction(a, [] { 575259701Sdim // f(); // break 576259701Sdim // }); 577259701Sdim // 578259701Sdim // instead of: 579259701Sdim // SomeFunction(a, [] { 580259701Sdim // f(); // break 581259701Sdim // }); 582259701Sdim for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i) 583259701Sdim State.Stack.pop_back(); 584259701Sdim NewIndent = State.Stack.back().LastSpace + Style.IndentWidth; 585259701Sdim ++NewIndentLevel; 586259701Sdim BreakBeforeParameter = true; 587259701Sdim } else { 588259701Sdim NewIndent = State.Stack.back().LastSpace; 589259701Sdim if (Current.opensBlockTypeList(Style)) { 590259701Sdim NewIndent += Style.IndentWidth; 591259701Sdim ++NewIndentLevel; 592259701Sdim } else { 593259701Sdim NewIndent += Style.ContinuationIndentWidth; 594259701Sdim } 595259701Sdim } 596259701Sdim const FormatToken *NextNoComment = Current.getNextNonComment(); 597259701Sdim AvoidBinPacking = Current.BlockKind == BK_Block || 598259701Sdim Current.Type == TT_ArrayInitializerLSquare || 599259701Sdim Current.Type == TT_DictLiteral || 600259701Sdim (NextNoComment && 601259701Sdim NextNoComment->Type == TT_DesignatedInitializerPeriod); 602259701Sdim } else { 603259701Sdim NewIndent = Style.ContinuationIndentWidth + 604259701Sdim std::max(State.Stack.back().LastSpace, 605259701Sdim State.Stack.back().StartOfFunctionCall); 606259701Sdim AvoidBinPacking = !Style.BinPackParameters || 607259701Sdim (Style.ExperimentalAutoDetectBinPacking && 608259701Sdim (Current.PackingKind == PPK_OnePerLine || 609259701Sdim (!BinPackInconclusiveFunctions && 610259701Sdim Current.PackingKind == PPK_Inconclusive))); 611259701Sdim // If this '[' opens an ObjC call, determine whether all parameters fit 612259701Sdim // into one line and put one per line if they don't. 613259701Sdim if (Current.Type == TT_ObjCMethodExpr && 614259701Sdim getLengthToMatchingParen(Current) + State.Column > 615259701Sdim getColumnLimit(State)) 616259701Sdim BreakBeforeParameter = true; 617259701Sdim } 618259701Sdim 619259701Sdim bool NoLineBreak = State.Stack.back().NoLineBreak || 620259701Sdim (Current.Type == TT_TemplateOpener && 621259701Sdim State.Stack.back().ContainsUnwrappedBuilder); 622259701Sdim State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, 623259701Sdim State.Stack.back().LastSpace, 624259701Sdim AvoidBinPacking, NoLineBreak)); 625259701Sdim State.Stack.back().BreakBeforeParameter = BreakBeforeParameter; 626259701Sdim ++State.ParenLevel; 627259701Sdim } 628259701Sdim 629259701Sdim // If we encounter a closing ), ], } or >, we can remove a level from our 630259701Sdim // stacks. 631259701Sdim if (State.Stack.size() > 1 && 632259701Sdim (Current.isOneOf(tok::r_paren, tok::r_square) || 633259701Sdim (Current.is(tok::r_brace) && State.NextToken != State.Line->First) || 634259701Sdim State.NextToken->Type == TT_TemplateCloser)) { 635259701Sdim State.Stack.pop_back(); 636259701Sdim --State.ParenLevel; 637259701Sdim } 638259701Sdim if (Current.is(tok::r_square)) { 639259701Sdim // If this ends the array subscript expr, reset the corresponding value. 640259701Sdim const FormatToken *NextNonComment = Current.getNextNonComment(); 641259701Sdim if (NextNonComment && NextNonComment->isNot(tok::l_square)) 642259701Sdim State.Stack.back().StartOfArraySubscripts = 0; 643259701Sdim } 644259701Sdim 645259701Sdim // Remove scopes created by fake parenthesis. 646259701Sdim if (Current.isNot(tok::r_brace) || 647259701Sdim (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) { 648259701Sdim // Don't remove FakeRParens attached to r_braces that surround nested blocks 649259701Sdim // as they will have been removed early (see above). 650259701Sdim for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) { 651259701Sdim unsigned VariablePos = State.Stack.back().VariablePos; 652259701Sdim State.Stack.pop_back(); 653259701Sdim State.Stack.back().VariablePos = VariablePos; 654259701Sdim } 655259701Sdim } 656259701Sdim 657259701Sdim if (Current.is(tok::string_literal) && State.StartOfStringLiteral == 0) { 658259701Sdim State.StartOfStringLiteral = State.Column; 659259701Sdim } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash, 660259701Sdim tok::string_literal)) { 661259701Sdim State.StartOfStringLiteral = 0; 662259701Sdim } 663259701Sdim 664259701Sdim State.Column += Current.ColumnWidth; 665259701Sdim State.NextToken = State.NextToken->Next; 666259701Sdim unsigned Penalty = breakProtrudingToken(Current, State, DryRun); 667259701Sdim if (State.Column > getColumnLimit(State)) { 668259701Sdim unsigned ExcessCharacters = State.Column - getColumnLimit(State); 669259701Sdim Penalty += Style.PenaltyExcessCharacter * ExcessCharacters; 670259701Sdim } 671259701Sdim 672259701Sdim // If the previous has a special role, let it consume tokens as appropriate. 673259701Sdim // It is necessary to start at the previous token for the only implemented 674259701Sdim // role (comma separated list). That way, the decision whether or not to break 675259701Sdim // after the "{" is already done and both options are tried and evaluated. 676259701Sdim // FIXME: This is ugly, find a better way. 677259701Sdim if (Previous && Previous->Role) 678259701Sdim Penalty += Previous->Role->format(State, this, DryRun); 679259701Sdim 680259701Sdim return Penalty; 681259701Sdim} 682259701Sdim 683259701Sdimunsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current, 684259701Sdim LineState &State) { 685259701Sdim // Break before further function parameters on all levels. 686259701Sdim for (unsigned i = 0, e = State.Stack.size(); i != e; ++i) 687259701Sdim State.Stack[i].BreakBeforeParameter = true; 688259701Sdim 689259701Sdim unsigned ColumnsUsed = State.Column; 690259701Sdim // We can only affect layout of the first and the last line, so the penalty 691259701Sdim // for all other lines is constant, and we ignore it. 692259701Sdim State.Column = Current.LastLineColumnWidth; 693259701Sdim 694259701Sdim if (ColumnsUsed > getColumnLimit(State)) 695259701Sdim return Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit(State)); 696259701Sdim return 0; 697259701Sdim} 698259701Sdim 699259701Sdimstatic bool getRawStringLiteralPrefixPostfix(StringRef Text, 700259701Sdim StringRef &Prefix, 701259701Sdim StringRef &Postfix) { 702259701Sdim if (Text.startswith(Prefix = "R\"") || Text.startswith(Prefix = "uR\"") || 703259701Sdim Text.startswith(Prefix = "UR\"") || Text.startswith(Prefix = "u8R\"") || 704259701Sdim Text.startswith(Prefix = "LR\"")) { 705259701Sdim size_t ParenPos = Text.find('('); 706259701Sdim if (ParenPos != StringRef::npos) { 707259701Sdim StringRef Delimiter = 708259701Sdim Text.substr(Prefix.size(), ParenPos - Prefix.size()); 709259701Sdim Prefix = Text.substr(0, ParenPos + 1); 710259701Sdim Postfix = Text.substr(Text.size() - 2 - Delimiter.size()); 711259701Sdim return Postfix.front() == ')' && Postfix.back() == '"' && 712259701Sdim Postfix.substr(1).startswith(Delimiter); 713259701Sdim } 714259701Sdim } 715259701Sdim return false; 716259701Sdim} 717259701Sdim 718259701Sdimunsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current, 719259701Sdim LineState &State, 720259701Sdim bool DryRun) { 721259701Sdim // Don't break multi-line tokens other than block comments. Instead, just 722259701Sdim // update the state. 723259701Sdim if (Current.Type != TT_BlockComment && Current.IsMultiline) 724259701Sdim return addMultilineToken(Current, State); 725259701Sdim 726259701Sdim // Don't break implicit string literals. 727259701Sdim if (Current.Type == TT_ImplicitStringLiteral) 728259701Sdim return 0; 729259701Sdim 730259701Sdim if (!Current.isOneOf(tok::string_literal, tok::wide_string_literal, 731259701Sdim tok::utf8_string_literal, tok::utf16_string_literal, 732259701Sdim tok::utf32_string_literal, tok::comment)) 733259701Sdim return 0; 734259701Sdim 735259701Sdim llvm::OwningPtr<BreakableToken> Token; 736259701Sdim unsigned StartColumn = State.Column - Current.ColumnWidth; 737259701Sdim unsigned ColumnLimit = getColumnLimit(State); 738259701Sdim 739259701Sdim if (Current.isOneOf(tok::string_literal, tok::wide_string_literal, 740259701Sdim tok::utf8_string_literal, tok::utf16_string_literal, 741259701Sdim tok::utf32_string_literal) && 742259701Sdim Current.Type != TT_ImplicitStringLiteral) { 743259701Sdim // Don't break string literals inside preprocessor directives (except for 744259701Sdim // #define directives, as their contents are stored in separate lines and 745259701Sdim // are not affected by this check). 746259701Sdim // This way we avoid breaking code with line directives and unknown 747259701Sdim // preprocessor directives that contain long string literals. 748259701Sdim if (State.Line->Type == LT_PreprocessorDirective) 749259701Sdim return 0; 750259701Sdim // Exempts unterminated string literals from line breaking. The user will 751259701Sdim // likely want to terminate the string before any line breaking is done. 752259701Sdim if (Current.IsUnterminatedLiteral) 753259701Sdim return 0; 754259701Sdim 755259701Sdim StringRef Text = Current.TokenText; 756259701Sdim StringRef Prefix; 757259701Sdim StringRef Postfix; 758259701Sdim // FIXME: Handle whitespace between '_T', '(', '"..."', and ')'. 759259701Sdim // FIXME: Store Prefix and Suffix (or PrefixLength and SuffixLength to 760259701Sdim // reduce the overhead) for each FormatToken, which is a string, so that we 761259701Sdim // don't run multiple checks here on the hot path. 762259701Sdim if ((Text.endswith(Postfix = "\"") && 763259701Sdim (Text.startswith(Prefix = "\"") || Text.startswith(Prefix = "u\"") || 764259701Sdim Text.startswith(Prefix = "U\"") || Text.startswith(Prefix = "u8\"") || 765259701Sdim Text.startswith(Prefix = "L\""))) || 766259701Sdim (Text.startswith(Prefix = "_T(\"") && Text.endswith(Postfix = "\")")) || 767259701Sdim getRawStringLiteralPrefixPostfix(Text, Prefix, Postfix)) { 768259701Sdim Token.reset(new BreakableStringLiteral( 769259701Sdim Current, State.Line->Level, StartColumn, Prefix, Postfix, 770259701Sdim State.Line->InPPDirective, Encoding, Style)); 771259701Sdim } else { 772259701Sdim return 0; 773259701Sdim } 774259701Sdim } else if (Current.Type == TT_BlockComment && Current.isTrailingComment()) { 775259701Sdim Token.reset(new BreakableBlockComment( 776259701Sdim Current, State.Line->Level, StartColumn, Current.OriginalColumn, 777259701Sdim !Current.Previous, State.Line->InPPDirective, Encoding, Style)); 778259701Sdim } else if (Current.Type == TT_LineComment && 779259701Sdim (Current.Previous == NULL || 780259701Sdim Current.Previous->Type != TT_ImplicitStringLiteral)) { 781259701Sdim Token.reset(new BreakableLineComment(Current, State.Line->Level, 782259701Sdim StartColumn, /*InPPDirective=*/false, 783259701Sdim Encoding, Style)); 784259701Sdim // We don't insert backslashes when breaking line comments. 785259701Sdim ColumnLimit = Style.ColumnLimit; 786259701Sdim } else { 787259701Sdim return 0; 788259701Sdim } 789259701Sdim if (Current.UnbreakableTailLength >= ColumnLimit) 790259701Sdim return 0; 791259701Sdim 792259701Sdim unsigned RemainingSpace = ColumnLimit - Current.UnbreakableTailLength; 793259701Sdim bool BreakInserted = false; 794259701Sdim unsigned Penalty = 0; 795259701Sdim unsigned RemainingTokenColumns = 0; 796259701Sdim for (unsigned LineIndex = 0, EndIndex = Token->getLineCount(); 797259701Sdim LineIndex != EndIndex; ++LineIndex) { 798259701Sdim if (!DryRun) 799259701Sdim Token->replaceWhitespaceBefore(LineIndex, Whitespaces); 800259701Sdim unsigned TailOffset = 0; 801259701Sdim RemainingTokenColumns = 802259701Sdim Token->getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos); 803259701Sdim while (RemainingTokenColumns > RemainingSpace) { 804259701Sdim BreakableToken::Split Split = 805259701Sdim Token->getSplit(LineIndex, TailOffset, ColumnLimit); 806259701Sdim if (Split.first == StringRef::npos) { 807259701Sdim // The last line's penalty is handled in addNextStateToQueue(). 808259701Sdim if (LineIndex < EndIndex - 1) 809259701Sdim Penalty += Style.PenaltyExcessCharacter * 810259701Sdim (RemainingTokenColumns - RemainingSpace); 811259701Sdim break; 812259701Sdim } 813259701Sdim assert(Split.first != 0); 814259701Sdim unsigned NewRemainingTokenColumns = Token->getLineLengthAfterSplit( 815259701Sdim LineIndex, TailOffset + Split.first + Split.second, StringRef::npos); 816259701Sdim 817259701Sdim // We can remove extra whitespace instead of breaking the line. 818259701Sdim if (RemainingTokenColumns + 1 - Split.second <= RemainingSpace) { 819259701Sdim RemainingTokenColumns = 0; 820259701Sdim if (!DryRun) 821259701Sdim Token->replaceWhitespace(LineIndex, TailOffset, Split, Whitespaces); 822259701Sdim break; 823259701Sdim } 824259701Sdim 825259701Sdim assert(NewRemainingTokenColumns < RemainingTokenColumns); 826259701Sdim if (!DryRun) 827259701Sdim Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces); 828259701Sdim Penalty += Current.SplitPenalty; 829259701Sdim unsigned ColumnsUsed = 830259701Sdim Token->getLineLengthAfterSplit(LineIndex, TailOffset, Split.first); 831259701Sdim if (ColumnsUsed > ColumnLimit) { 832259701Sdim Penalty += Style.PenaltyExcessCharacter * (ColumnsUsed - ColumnLimit); 833259701Sdim } 834259701Sdim TailOffset += Split.first + Split.second; 835259701Sdim RemainingTokenColumns = NewRemainingTokenColumns; 836259701Sdim BreakInserted = true; 837259701Sdim } 838259701Sdim } 839259701Sdim 840259701Sdim State.Column = RemainingTokenColumns; 841259701Sdim 842259701Sdim if (BreakInserted) { 843259701Sdim // If we break the token inside a parameter list, we need to break before 844259701Sdim // the next parameter on all levels, so that the next parameter is clearly 845259701Sdim // visible. Line comments already introduce a break. 846259701Sdim if (Current.Type != TT_LineComment) { 847259701Sdim for (unsigned i = 0, e = State.Stack.size(); i != e; ++i) 848259701Sdim State.Stack[i].BreakBeforeParameter = true; 849259701Sdim } 850259701Sdim 851259701Sdim Penalty += Current.is(tok::string_literal) ? Style.PenaltyBreakString 852259701Sdim : Style.PenaltyBreakComment; 853259701Sdim 854259701Sdim State.Stack.back().LastSpace = StartColumn; 855259701Sdim } 856259701Sdim return Penalty; 857259701Sdim} 858259701Sdim 859259701Sdimunsigned ContinuationIndenter::getColumnLimit(const LineState &State) const { 860259701Sdim // In preprocessor directives reserve two chars for trailing " \" 861259701Sdim return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0); 862259701Sdim} 863259701Sdim 864259701Sdimbool ContinuationIndenter::NextIsMultilineString(const LineState &State) { 865259701Sdim const FormatToken &Current = *State.NextToken; 866259701Sdim if (!Current.is(tok::string_literal)) 867259701Sdim return false; 868259701Sdim // We never consider raw string literals "multiline" for the purpose of 869259701Sdim // AlwaysBreakBeforeMultilineStrings implementation. 870259701Sdim if (Current.TokenText.startswith("R\"")) 871259701Sdim return false; 872259701Sdim if (Current.IsMultiline) 873259701Sdim return true; 874259701Sdim if (Current.getNextNonComment() && 875259701Sdim Current.getNextNonComment()->is(tok::string_literal)) 876259701Sdim return true; // Implicit concatenation. 877259701Sdim if (State.Column + Current.ColumnWidth + Current.UnbreakableTailLength > 878259701Sdim Style.ColumnLimit) 879259701Sdim return true; // String will be split. 880259701Sdim return false; 881259701Sdim} 882259701Sdim 883259701Sdim} // namespace format 884259701Sdim} // namespace clang 885