Format.cpp revision 251662
1249261Sdim//===--- Format.cpp - Format C++ code -------------------------------------===// 2249261Sdim// 3249261Sdim// The LLVM Compiler Infrastructure 4249261Sdim// 5249261Sdim// This file is distributed under the University of Illinois Open Source 6249261Sdim// License. See LICENSE.TXT for details. 7249261Sdim// 8249261Sdim//===----------------------------------------------------------------------===// 9249261Sdim/// 10249261Sdim/// \file 11249261Sdim/// \brief This file implements functions declared in Format.h. This will be 12249261Sdim/// split into separate files as we go. 13249261Sdim/// 14249261Sdim//===----------------------------------------------------------------------===// 15249261Sdim 16249261Sdim#define DEBUG_TYPE "format-formatter" 17249261Sdim 18251662Sdim#include "BreakableToken.h" 19249261Sdim#include "TokenAnnotator.h" 20249261Sdim#include "UnwrappedLineParser.h" 21251662Sdim#include "WhitespaceManager.h" 22249261Sdim#include "clang/Basic/Diagnostic.h" 23249261Sdim#include "clang/Basic/OperatorPrecedence.h" 24249261Sdim#include "clang/Basic/SourceManager.h" 25249261Sdim#include "clang/Format/Format.h" 26249261Sdim#include "clang/Frontend/TextDiagnosticPrinter.h" 27249261Sdim#include "clang/Lex/Lexer.h" 28249261Sdim#include "llvm/ADT/STLExtras.h" 29249261Sdim#include "llvm/Support/Allocator.h" 30249261Sdim#include "llvm/Support/Debug.h" 31249261Sdim#include <queue> 32249261Sdim#include <string> 33249261Sdim 34249261Sdimnamespace clang { 35249261Sdimnamespace format { 36249261Sdim 37249261SdimFormatStyle getLLVMStyle() { 38249261Sdim FormatStyle LLVMStyle; 39251662Sdim LLVMStyle.AccessModifierOffset = -2; 40251662Sdim LLVMStyle.AlignEscapedNewlinesLeft = false; 41251662Sdim LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; 42251662Sdim LLVMStyle.AllowShortIfStatementsOnASingleLine = false; 43251662Sdim LLVMStyle.BinPackParameters = true; 44249261Sdim LLVMStyle.ColumnLimit = 80; 45251662Sdim LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; 46249261Sdim LLVMStyle.DerivePointerBinding = false; 47249261Sdim LLVMStyle.IndentCaseLabels = false; 48251662Sdim LLVMStyle.MaxEmptyLinesToKeep = 1; 49249261Sdim LLVMStyle.ObjCSpaceBeforeProtocolList = true; 50249261Sdim LLVMStyle.PenaltyExcessCharacter = 1000000; 51251662Sdim LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 75; 52251662Sdim LLVMStyle.PointerBindsToType = false; 53251662Sdim LLVMStyle.SpacesBeforeTrailingComments = 1; 54251662Sdim LLVMStyle.Standard = FormatStyle::LS_Cpp03; 55249261Sdim return LLVMStyle; 56249261Sdim} 57249261Sdim 58249261SdimFormatStyle getGoogleStyle() { 59249261Sdim FormatStyle GoogleStyle; 60251662Sdim GoogleStyle.AccessModifierOffset = -1; 61251662Sdim GoogleStyle.AlignEscapedNewlinesLeft = true; 62251662Sdim GoogleStyle.AllowAllParametersOfDeclarationOnNextLine = true; 63251662Sdim GoogleStyle.AllowShortIfStatementsOnASingleLine = true; 64251662Sdim GoogleStyle.BinPackParameters = true; 65249261Sdim GoogleStyle.ColumnLimit = 80; 66251662Sdim GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true; 67249261Sdim GoogleStyle.DerivePointerBinding = true; 68249261Sdim GoogleStyle.IndentCaseLabels = true; 69251662Sdim GoogleStyle.MaxEmptyLinesToKeep = 1; 70249261Sdim GoogleStyle.ObjCSpaceBeforeProtocolList = false; 71249261Sdim GoogleStyle.PenaltyExcessCharacter = 1000000; 72251662Sdim GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; 73251662Sdim GoogleStyle.PointerBindsToType = true; 74251662Sdim GoogleStyle.SpacesBeforeTrailingComments = 2; 75251662Sdim GoogleStyle.Standard = FormatStyle::LS_Auto; 76249261Sdim return GoogleStyle; 77249261Sdim} 78249261Sdim 79249261SdimFormatStyle getChromiumStyle() { 80249261Sdim FormatStyle ChromiumStyle = getGoogleStyle(); 81249261Sdim ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 82251662Sdim ChromiumStyle.AllowShortIfStatementsOnASingleLine = false; 83249261Sdim ChromiumStyle.BinPackParameters = false; 84249261Sdim ChromiumStyle.Standard = FormatStyle::LS_Cpp03; 85249261Sdim ChromiumStyle.DerivePointerBinding = false; 86249261Sdim return ChromiumStyle; 87249261Sdim} 88249261Sdim 89251662SdimFormatStyle getMozillaStyle() { 90251662Sdim FormatStyle MozillaStyle = getLLVMStyle(); 91251662Sdim MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 92251662Sdim MozillaStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true; 93251662Sdim MozillaStyle.DerivePointerBinding = true; 94251662Sdim MozillaStyle.IndentCaseLabels = true; 95251662Sdim MozillaStyle.ObjCSpaceBeforeProtocolList = false; 96251662Sdim MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 97251662Sdim MozillaStyle.PointerBindsToType = true; 98251662Sdim return MozillaStyle; 99249261Sdim} 100249261Sdim 101249261Sdim// Returns the length of everything up to the first possible line break after 102249261Sdim// the ), ], } or > matching \c Tok. 103249261Sdimstatic unsigned getLengthToMatchingParen(const AnnotatedToken &Tok) { 104249261Sdim if (Tok.MatchingParen == NULL) 105249261Sdim return 0; 106249261Sdim AnnotatedToken *End = Tok.MatchingParen; 107249261Sdim while (!End->Children.empty() && !End->Children[0].CanBreakBefore) { 108249261Sdim End = &End->Children[0]; 109249261Sdim } 110249261Sdim return End->TotalLength - Tok.TotalLength + 1; 111249261Sdim} 112249261Sdim 113249261Sdimclass UnwrappedLineFormatter { 114249261Sdimpublic: 115249261Sdim UnwrappedLineFormatter(const FormatStyle &Style, SourceManager &SourceMgr, 116249261Sdim const AnnotatedLine &Line, unsigned FirstIndent, 117249261Sdim const AnnotatedToken &RootToken, 118251662Sdim WhitespaceManager &Whitespaces) 119249261Sdim : Style(Style), SourceMgr(SourceMgr), Line(Line), 120249261Sdim FirstIndent(FirstIndent), RootToken(RootToken), 121249261Sdim Whitespaces(Whitespaces), Count(0) {} 122249261Sdim 123249261Sdim /// \brief Formats an \c UnwrappedLine. 124249261Sdim /// 125249261Sdim /// \returns The column after the last token in the last line of the 126249261Sdim /// \c UnwrappedLine. 127249261Sdim unsigned format(const AnnotatedLine *NextLine) { 128249261Sdim // Initialize state dependent on indent. 129249261Sdim LineState State; 130249261Sdim State.Column = FirstIndent; 131249261Sdim State.NextToken = &RootToken; 132249261Sdim State.Stack.push_back( 133249261Sdim ParenState(FirstIndent, FirstIndent, !Style.BinPackParameters, 134251662Sdim /*NoLineBreak=*/ false)); 135249261Sdim State.LineContainsContinuedForLoopSection = false; 136249261Sdim State.ParenLevel = 0; 137249261Sdim State.StartOfStringLiteral = 0; 138249261Sdim State.StartOfLineLevel = State.ParenLevel; 139249261Sdim 140249261Sdim // The first token has already been indented and thus consumed. 141249261Sdim moveStateToNextToken(State, /*DryRun=*/ false); 142249261Sdim 143249261Sdim // If everything fits on a single line, just put it there. 144249261Sdim unsigned ColumnLimit = Style.ColumnLimit; 145249261Sdim if (NextLine && NextLine->InPPDirective && 146249261Sdim !NextLine->First.FormatTok.HasUnescapedNewline) 147249261Sdim ColumnLimit = getColumnLimit(); 148249261Sdim if (Line.Last->TotalLength <= ColumnLimit - FirstIndent) { 149249261Sdim while (State.NextToken != NULL) { 150249261Sdim addTokenToState(false, false, State); 151249261Sdim } 152249261Sdim return State.Column; 153249261Sdim } 154249261Sdim 155249261Sdim // If the ObjC method declaration does not fit on a line, we should format 156249261Sdim // it with one arg per line. 157249261Sdim if (Line.Type == LT_ObjCMethodDecl) 158249261Sdim State.Stack.back().BreakBeforeParameter = true; 159249261Sdim 160249261Sdim // Find best solution in solution space. 161249261Sdim return analyzeSolutionSpace(State); 162249261Sdim } 163249261Sdim 164249261Sdimprivate: 165249261Sdim void DebugTokenState(const AnnotatedToken &AnnotatedTok) { 166249261Sdim const Token &Tok = AnnotatedTok.FormatTok.Tok; 167249261Sdim llvm::errs() << StringRef(SourceMgr.getCharacterData(Tok.getLocation()), 168249261Sdim Tok.getLength()); 169249261Sdim llvm::errs(); 170249261Sdim } 171249261Sdim 172249261Sdim struct ParenState { 173249261Sdim ParenState(unsigned Indent, unsigned LastSpace, bool AvoidBinPacking, 174251662Sdim bool NoLineBreak) 175249261Sdim : Indent(Indent), LastSpace(LastSpace), FirstLessLess(0), 176249261Sdim BreakBeforeClosingBrace(false), QuestionColumn(0), 177249261Sdim AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false), 178251662Sdim NoLineBreak(NoLineBreak), ColonPos(0), StartOfFunctionCall(0), 179251662Sdim NestedNameSpecifierContinuation(0), CallContinuation(0), 180251662Sdim VariablePos(0) {} 181249261Sdim 182249261Sdim /// \brief The position to which a specific parenthesis level needs to be 183249261Sdim /// indented. 184249261Sdim unsigned Indent; 185249261Sdim 186249261Sdim /// \brief The position of the last space on each level. 187249261Sdim /// 188249261Sdim /// Used e.g. to break like: 189249261Sdim /// functionCall(Parameter, otherCall( 190249261Sdim /// OtherParameter)); 191249261Sdim unsigned LastSpace; 192249261Sdim 193249261Sdim /// \brief The position the first "<<" operator encountered on each level. 194249261Sdim /// 195249261Sdim /// Used to align "<<" operators. 0 if no such operator has been encountered 196249261Sdim /// on a level. 197249261Sdim unsigned FirstLessLess; 198249261Sdim 199249261Sdim /// \brief Whether a newline needs to be inserted before the block's closing 200249261Sdim /// brace. 201249261Sdim /// 202249261Sdim /// We only want to insert a newline before the closing brace if there also 203249261Sdim /// was a newline after the beginning left brace. 204249261Sdim bool BreakBeforeClosingBrace; 205249261Sdim 206249261Sdim /// \brief The column of a \c ? in a conditional expression; 207249261Sdim unsigned QuestionColumn; 208249261Sdim 209249261Sdim /// \brief Avoid bin packing, i.e. multiple parameters/elements on multiple 210249261Sdim /// lines, in this context. 211249261Sdim bool AvoidBinPacking; 212249261Sdim 213249261Sdim /// \brief Break after the next comma (or all the commas in this context if 214249261Sdim /// \c AvoidBinPacking is \c true). 215249261Sdim bool BreakBeforeParameter; 216249261Sdim 217251662Sdim /// \brief Line breaking in this context would break a formatting rule. 218251662Sdim bool NoLineBreak; 219249261Sdim 220249261Sdim /// \brief The position of the colon in an ObjC method declaration/call. 221249261Sdim unsigned ColonPos; 222249261Sdim 223249261Sdim /// \brief The start of the most recent function in a builder-type call. 224249261Sdim unsigned StartOfFunctionCall; 225249261Sdim 226249261Sdim /// \brief If a nested name specifier was broken over multiple lines, this 227249261Sdim /// contains the start column of the second line. Otherwise 0. 228249261Sdim unsigned NestedNameSpecifierContinuation; 229249261Sdim 230249261Sdim /// \brief If a call expression was broken over multiple lines, this 231249261Sdim /// contains the start column of the second line. Otherwise 0. 232249261Sdim unsigned CallContinuation; 233249261Sdim 234249261Sdim /// \brief The column of the first variable name in a variable declaration. 235249261Sdim /// 236249261Sdim /// Used to align further variables if necessary. 237249261Sdim unsigned VariablePos; 238249261Sdim 239249261Sdim bool operator<(const ParenState &Other) const { 240249261Sdim if (Indent != Other.Indent) 241249261Sdim return Indent < Other.Indent; 242249261Sdim if (LastSpace != Other.LastSpace) 243249261Sdim return LastSpace < Other.LastSpace; 244249261Sdim if (FirstLessLess != Other.FirstLessLess) 245249261Sdim return FirstLessLess < Other.FirstLessLess; 246249261Sdim if (BreakBeforeClosingBrace != Other.BreakBeforeClosingBrace) 247249261Sdim return BreakBeforeClosingBrace; 248249261Sdim if (QuestionColumn != Other.QuestionColumn) 249249261Sdim return QuestionColumn < Other.QuestionColumn; 250249261Sdim if (AvoidBinPacking != Other.AvoidBinPacking) 251249261Sdim return AvoidBinPacking; 252249261Sdim if (BreakBeforeParameter != Other.BreakBeforeParameter) 253249261Sdim return BreakBeforeParameter; 254251662Sdim if (NoLineBreak != Other.NoLineBreak) 255251662Sdim return NoLineBreak; 256249261Sdim if (ColonPos != Other.ColonPos) 257249261Sdim return ColonPos < Other.ColonPos; 258249261Sdim if (StartOfFunctionCall != Other.StartOfFunctionCall) 259249261Sdim return StartOfFunctionCall < Other.StartOfFunctionCall; 260249261Sdim if (NestedNameSpecifierContinuation != 261251662Sdim Other.NestedNameSpecifierContinuation) 262249261Sdim return NestedNameSpecifierContinuation < 263249261Sdim Other.NestedNameSpecifierContinuation; 264249261Sdim if (CallContinuation != Other.CallContinuation) 265249261Sdim return CallContinuation < Other.CallContinuation; 266249261Sdim if (VariablePos != Other.VariablePos) 267249261Sdim return VariablePos < Other.VariablePos; 268249261Sdim return false; 269249261Sdim } 270249261Sdim }; 271249261Sdim 272249261Sdim /// \brief The current state when indenting a unwrapped line. 273249261Sdim /// 274249261Sdim /// As the indenting tries different combinations this is copied by value. 275249261Sdim struct LineState { 276249261Sdim /// \brief The number of used columns in the current line. 277249261Sdim unsigned Column; 278249261Sdim 279249261Sdim /// \brief The token that needs to be next formatted. 280249261Sdim const AnnotatedToken *NextToken; 281249261Sdim 282249261Sdim /// \brief \c true if this line contains a continued for-loop section. 283249261Sdim bool LineContainsContinuedForLoopSection; 284249261Sdim 285249261Sdim /// \brief The level of nesting inside (), [], <> and {}. 286249261Sdim unsigned ParenLevel; 287249261Sdim 288249261Sdim /// \brief The \c ParenLevel at the start of this line. 289249261Sdim unsigned StartOfLineLevel; 290249261Sdim 291249261Sdim /// \brief The start column of the string literal, if we're in a string 292249261Sdim /// literal sequence, 0 otherwise. 293249261Sdim unsigned StartOfStringLiteral; 294249261Sdim 295249261Sdim /// \brief A stack keeping track of properties applying to parenthesis 296249261Sdim /// levels. 297249261Sdim std::vector<ParenState> Stack; 298249261Sdim 299249261Sdim /// \brief Comparison operator to be able to used \c LineState in \c map. 300249261Sdim bool operator<(const LineState &Other) const { 301249261Sdim if (NextToken != Other.NextToken) 302249261Sdim return NextToken < Other.NextToken; 303249261Sdim if (Column != Other.Column) 304249261Sdim return Column < Other.Column; 305249261Sdim if (LineContainsContinuedForLoopSection != 306251662Sdim Other.LineContainsContinuedForLoopSection) 307249261Sdim return LineContainsContinuedForLoopSection; 308249261Sdim if (ParenLevel != Other.ParenLevel) 309249261Sdim return ParenLevel < Other.ParenLevel; 310249261Sdim if (StartOfLineLevel != Other.StartOfLineLevel) 311249261Sdim return StartOfLineLevel < Other.StartOfLineLevel; 312249261Sdim if (StartOfStringLiteral != Other.StartOfStringLiteral) 313249261Sdim return StartOfStringLiteral < Other.StartOfStringLiteral; 314249261Sdim return Stack < Other.Stack; 315249261Sdim } 316249261Sdim }; 317249261Sdim 318249261Sdim /// \brief Appends the next token to \p State and updates information 319249261Sdim /// necessary for indentation. 320249261Sdim /// 321249261Sdim /// Puts the token on the current line if \p Newline is \c true and adds a 322249261Sdim /// line break and necessary indentation otherwise. 323249261Sdim /// 324249261Sdim /// If \p DryRun is \c false, also creates and stores the required 325249261Sdim /// \c Replacement. 326249261Sdim unsigned addTokenToState(bool Newline, bool DryRun, LineState &State) { 327249261Sdim const AnnotatedToken &Current = *State.NextToken; 328249261Sdim const AnnotatedToken &Previous = *State.NextToken->Parent; 329249261Sdim 330249261Sdim if (State.Stack.size() == 0 || Current.Type == TT_ImplicitStringLiteral) { 331249261Sdim State.Column += State.NextToken->FormatTok.WhiteSpaceLength + 332249261Sdim State.NextToken->FormatTok.TokenLength; 333249261Sdim if (State.NextToken->Children.empty()) 334249261Sdim State.NextToken = NULL; 335249261Sdim else 336249261Sdim State.NextToken = &State.NextToken->Children[0]; 337249261Sdim return 0; 338249261Sdim } 339249261Sdim 340249261Sdim // If we are continuing an expression, we want to indent an extra 4 spaces. 341249261Sdim unsigned ContinuationIndent = 342249261Sdim std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) + 4; 343249261Sdim if (Newline) { 344249261Sdim unsigned WhitespaceStartColumn = State.Column; 345249261Sdim if (Current.is(tok::r_brace)) { 346249261Sdim State.Column = Line.Level * 2; 347249261Sdim } else if (Current.is(tok::string_literal) && 348249261Sdim State.StartOfStringLiteral != 0) { 349249261Sdim State.Column = State.StartOfStringLiteral; 350249261Sdim State.Stack.back().BreakBeforeParameter = true; 351249261Sdim } else if (Current.is(tok::lessless) && 352249261Sdim State.Stack.back().FirstLessLess != 0) { 353249261Sdim State.Column = State.Stack.back().FirstLessLess; 354249261Sdim } else if (Previous.is(tok::coloncolon)) { 355249261Sdim if (State.Stack.back().NestedNameSpecifierContinuation == 0) { 356249261Sdim State.Column = ContinuationIndent; 357249261Sdim State.Stack.back().NestedNameSpecifierContinuation = State.Column; 358249261Sdim } else { 359249261Sdim State.Column = State.Stack.back().NestedNameSpecifierContinuation; 360249261Sdim } 361249261Sdim } else if (Current.isOneOf(tok::period, tok::arrow)) { 362249261Sdim if (State.Stack.back().CallContinuation == 0) { 363249261Sdim State.Column = ContinuationIndent; 364249261Sdim State.Stack.back().CallContinuation = State.Column; 365249261Sdim } else { 366249261Sdim State.Column = State.Stack.back().CallContinuation; 367249261Sdim } 368249261Sdim } else if (Current.Type == TT_ConditionalExpr) { 369249261Sdim State.Column = State.Stack.back().QuestionColumn; 370249261Sdim } else if (Previous.is(tok::comma) && 371249261Sdim State.Stack.back().VariablePos != 0) { 372249261Sdim State.Column = State.Stack.back().VariablePos; 373249261Sdim } else if (Previous.ClosesTemplateDeclaration || 374251662Sdim (Current.Type == TT_StartOfName && State.ParenLevel == 0 && 375251662Sdim Line.StartsDefinition)) { 376249261Sdim State.Column = State.Stack.back().Indent; 377249261Sdim } else if (Current.Type == TT_ObjCSelectorName) { 378249261Sdim if (State.Stack.back().ColonPos > Current.FormatTok.TokenLength) { 379249261Sdim State.Column = 380249261Sdim State.Stack.back().ColonPos - Current.FormatTok.TokenLength; 381249261Sdim } else { 382249261Sdim State.Column = State.Stack.back().Indent; 383249261Sdim State.Stack.back().ColonPos = 384249261Sdim State.Column + Current.FormatTok.TokenLength; 385249261Sdim } 386251662Sdim } else if (Current.Type == TT_StartOfName || Previous.is(tok::equal) || 387249261Sdim Previous.Type == TT_ObjCMethodExpr) { 388249261Sdim State.Column = ContinuationIndent; 389249261Sdim } else { 390249261Sdim State.Column = State.Stack.back().Indent; 391249261Sdim // Ensure that we fall back to indenting 4 spaces instead of just 392249261Sdim // flushing continuations left. 393249261Sdim if (State.Column == FirstIndent) 394249261Sdim State.Column += 4; 395249261Sdim } 396249261Sdim 397249261Sdim if (Current.is(tok::question)) 398249261Sdim State.Stack.back().BreakBeforeParameter = true; 399249261Sdim if (Previous.isOneOf(tok::comma, tok::semi) && 400249261Sdim !State.Stack.back().AvoidBinPacking) 401249261Sdim State.Stack.back().BreakBeforeParameter = false; 402249261Sdim 403249261Sdim if (!DryRun) { 404249261Sdim unsigned NewLines = 1; 405249261Sdim if (Current.Type == TT_LineComment) 406249261Sdim NewLines = 407249261Sdim std::max(NewLines, std::min(Current.FormatTok.NewlinesBefore, 408249261Sdim Style.MaxEmptyLinesToKeep + 1)); 409249261Sdim if (!Line.InPPDirective) 410249261Sdim Whitespaces.replaceWhitespace(Current, NewLines, State.Column, 411249261Sdim WhitespaceStartColumn); 412249261Sdim else 413249261Sdim Whitespaces.replacePPWhitespace(Current, NewLines, State.Column, 414249261Sdim WhitespaceStartColumn); 415249261Sdim } 416249261Sdim 417249261Sdim State.Stack.back().LastSpace = State.Column; 418249261Sdim State.StartOfLineLevel = State.ParenLevel; 419249261Sdim 420249261Sdim // Any break on this level means that the parent level has been broken 421249261Sdim // and we need to avoid bin packing there. 422249261Sdim for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) { 423249261Sdim State.Stack[i].BreakBeforeParameter = true; 424249261Sdim } 425251662Sdim const AnnotatedToken *TokenBefore = Current.getPreviousNoneComment(); 426251662Sdim if (TokenBefore && !TokenBefore->isOneOf(tok::comma, tok::semi) && 427251662Sdim !TokenBefore->opensScope()) 428249261Sdim State.Stack.back().BreakBeforeParameter = true; 429249261Sdim 430249261Sdim // If we break after {, we should also break before the corresponding }. 431249261Sdim if (Previous.is(tok::l_brace)) 432249261Sdim State.Stack.back().BreakBeforeClosingBrace = true; 433249261Sdim 434249261Sdim if (State.Stack.back().AvoidBinPacking) { 435249261Sdim // If we are breaking after '(', '{', '<', this is not bin packing 436249261Sdim // unless AllowAllParametersOfDeclarationOnNextLine is false. 437249261Sdim if ((Previous.isNot(tok::l_paren) && Previous.isNot(tok::l_brace)) || 438249261Sdim (!Style.AllowAllParametersOfDeclarationOnNextLine && 439249261Sdim Line.MustBeDeclaration)) 440249261Sdim State.Stack.back().BreakBeforeParameter = true; 441249261Sdim } 442249261Sdim } else { 443249261Sdim if (Current.is(tok::equal) && 444249261Sdim (RootToken.is(tok::kw_for) || State.ParenLevel == 0) && 445249261Sdim State.Stack.back().VariablePos == 0) { 446249261Sdim State.Stack.back().VariablePos = State.Column; 447249261Sdim // Move over * and & if they are bound to the variable name. 448249261Sdim const AnnotatedToken *Tok = &Previous; 449249261Sdim while (Tok && 450249261Sdim State.Stack.back().VariablePos >= Tok->FormatTok.TokenLength) { 451249261Sdim State.Stack.back().VariablePos -= Tok->FormatTok.TokenLength; 452249261Sdim if (Tok->SpacesRequiredBefore != 0) 453249261Sdim break; 454249261Sdim Tok = Tok->Parent; 455249261Sdim } 456249261Sdim if (Previous.PartOfMultiVariableDeclStmt) 457249261Sdim State.Stack.back().LastSpace = State.Stack.back().VariablePos; 458249261Sdim } 459249261Sdim 460249261Sdim unsigned Spaces = State.NextToken->SpacesRequiredBefore; 461249261Sdim 462249261Sdim if (!DryRun) 463249261Sdim Whitespaces.replaceWhitespace(Current, 0, Spaces, State.Column); 464249261Sdim 465249261Sdim if (Current.Type == TT_ObjCSelectorName && 466249261Sdim State.Stack.back().ColonPos == 0) { 467249261Sdim if (State.Stack.back().Indent + Current.LongestObjCSelectorName > 468251662Sdim State.Column + Spaces + Current.FormatTok.TokenLength) 469249261Sdim State.Stack.back().ColonPos = 470249261Sdim State.Stack.back().Indent + Current.LongestObjCSelectorName; 471249261Sdim else 472249261Sdim State.Stack.back().ColonPos = 473249261Sdim State.Column + Spaces + Current.FormatTok.TokenLength; 474249261Sdim } 475249261Sdim 476251662Sdim if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr && 477251662Sdim Current.Type != TT_LineComment) 478249261Sdim State.Stack.back().Indent = State.Column + Spaces; 479251662Sdim if (Previous.is(tok::comma) && !Current.isTrailingComment() && 480251662Sdim State.Stack.back().AvoidBinPacking) 481251662Sdim State.Stack.back().NoLineBreak = true; 482249261Sdim 483249261Sdim State.Column += Spaces; 484249261Sdim if (Current.is(tok::l_paren) && Previous.isOneOf(tok::kw_if, tok::kw_for)) 485249261Sdim // Treat the condition inside an if as if it was a second function 486249261Sdim // parameter, i.e. let nested calls have an indent of 4. 487249261Sdim State.Stack.back().LastSpace = State.Column + 1; // 1 is length of "(". 488249261Sdim else if (Previous.is(tok::comma)) 489249261Sdim State.Stack.back().LastSpace = State.Column; 490249261Sdim else if ((Previous.Type == TT_BinaryOperator || 491249261Sdim Previous.Type == TT_ConditionalExpr || 492249261Sdim Previous.Type == TT_CtorInitializerColon) && 493249261Sdim getPrecedence(Previous) != prec::Assignment) 494249261Sdim State.Stack.back().LastSpace = State.Column; 495249261Sdim else if (Previous.Type == TT_InheritanceColon) 496249261Sdim State.Stack.back().Indent = State.Column; 497251662Sdim else if (Previous.opensScope() && Previous.ParameterCount > 1) 498249261Sdim // If this function has multiple parameters, indent nested calls from 499249261Sdim // the start of the first parameter. 500249261Sdim State.Stack.back().LastSpace = State.Column; 501249261Sdim } 502249261Sdim 503249261Sdim return moveStateToNextToken(State, DryRun); 504249261Sdim } 505249261Sdim 506249261Sdim /// \brief Mark the next token as consumed in \p State and modify its stacks 507249261Sdim /// accordingly. 508249261Sdim unsigned moveStateToNextToken(LineState &State, bool DryRun) { 509249261Sdim const AnnotatedToken &Current = *State.NextToken; 510249261Sdim assert(State.Stack.size()); 511249261Sdim 512249261Sdim if (Current.Type == TT_InheritanceColon) 513249261Sdim State.Stack.back().AvoidBinPacking = true; 514249261Sdim if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0) 515249261Sdim State.Stack.back().FirstLessLess = State.Column; 516249261Sdim if (Current.is(tok::question)) 517249261Sdim State.Stack.back().QuestionColumn = State.Column; 518249261Sdim if (Current.isOneOf(tok::period, tok::arrow) && 519249261Sdim Line.Type == LT_BuilderTypeCall && State.ParenLevel == 0) 520249261Sdim State.Stack.back().StartOfFunctionCall = 521249261Sdim Current.LastInChainOfCalls ? 0 : State.Column; 522249261Sdim if (Current.Type == TT_CtorInitializerColon) { 523251662Sdim State.Stack.back().Indent = State.Column + 2; 524249261Sdim if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine) 525249261Sdim State.Stack.back().AvoidBinPacking = true; 526249261Sdim State.Stack.back().BreakBeforeParameter = false; 527249261Sdim } 528249261Sdim 529251662Sdim // If return returns a binary expression, align after it. 530251662Sdim if (Current.is(tok::kw_return) && !Current.FakeLParens.empty()) 531251662Sdim State.Stack.back().LastSpace = State.Column + 7; 532251662Sdim 533249261Sdim // In ObjC method declaration we align on the ":" of parameters, but we need 534249261Sdim // to ensure that we indent parameters on subsequent lines by at least 4. 535249261Sdim if (Current.Type == TT_ObjCMethodSpecifier) 536249261Sdim State.Stack.back().Indent += 4; 537249261Sdim 538249261Sdim // Insert scopes created by fake parenthesis. 539251662Sdim const AnnotatedToken *Previous = Current.getPreviousNoneComment(); 540251662Sdim // Don't add extra indentation for the first fake parenthesis after 541251662Sdim // 'return', assignements or opening <({[. The indentation for these cases 542251662Sdim // is special cased. 543251662Sdim bool SkipFirstExtraIndent = 544251662Sdim Current.is(tok::kw_return) || 545251662Sdim (Previous && (Previous->opensScope() || 546251662Sdim getPrecedence(*Previous) == prec::Assignment)); 547251662Sdim for (SmallVector<prec::Level, 4>::const_reverse_iterator 548251662Sdim I = Current.FakeLParens.rbegin(), 549251662Sdim E = Current.FakeLParens.rend(); 550251662Sdim I != E; ++I) { 551249261Sdim ParenState NewParenState = State.Stack.back(); 552251662Sdim NewParenState.Indent = 553251662Sdim std::max(std::max(State.Column, NewParenState.Indent), 554251662Sdim State.Stack.back().LastSpace); 555251662Sdim 556251662Sdim // Always indent conditional expressions. Never indent expression where 557251662Sdim // the 'operator' is ',', ';' or an assignment (i.e. *I <= 558251662Sdim // prec::Assignment) as those have different indentation rules. Indent 559251662Sdim // other expression, unless the indentation needs to be skipped. 560251662Sdim if (*I == prec::Conditional || 561251662Sdim (!SkipFirstExtraIndent && *I > prec::Assignment)) 562251662Sdim NewParenState.Indent += 4; 563251662Sdim if (Previous && !Previous->opensScope()) 564251662Sdim NewParenState.BreakBeforeParameter = false; 565249261Sdim State.Stack.push_back(NewParenState); 566251662Sdim SkipFirstExtraIndent = false; 567249261Sdim } 568249261Sdim 569249261Sdim // If we encounter an opening (, [, { or <, we add a level to our stacks to 570249261Sdim // prepare for the following tokens. 571251662Sdim if (Current.opensScope()) { 572249261Sdim unsigned NewIndent; 573249261Sdim bool AvoidBinPacking; 574249261Sdim if (Current.is(tok::l_brace)) { 575249261Sdim NewIndent = 2 + State.Stack.back().LastSpace; 576249261Sdim AvoidBinPacking = false; 577249261Sdim } else { 578249261Sdim NewIndent = 4 + std::max(State.Stack.back().LastSpace, 579249261Sdim State.Stack.back().StartOfFunctionCall); 580251662Sdim AvoidBinPacking = !Style.BinPackParameters; 581249261Sdim } 582249261Sdim State.Stack.push_back( 583249261Sdim ParenState(NewIndent, State.Stack.back().LastSpace, AvoidBinPacking, 584251662Sdim State.Stack.back().NoLineBreak)); 585251662Sdim 586251662Sdim if (Current.NoMoreTokensOnLevel && Current.FakeLParens.empty()) { 587251662Sdim // This parenthesis was the last token possibly making use of Indent and 588251662Sdim // LastSpace of the next higher ParenLevel. Thus, erase them to acieve 589251662Sdim // better memoization results. 590251662Sdim State.Stack[State.Stack.size() - 2].Indent = 0; 591251662Sdim State.Stack[State.Stack.size() - 2].LastSpace = 0; 592251662Sdim } 593251662Sdim 594249261Sdim ++State.ParenLevel; 595249261Sdim } 596249261Sdim 597249261Sdim // If this '[' opens an ObjC call, determine whether all parameters fit into 598249261Sdim // one line and put one per line if they don't. 599249261Sdim if (Current.is(tok::l_square) && Current.Type == TT_ObjCMethodExpr && 600249261Sdim Current.MatchingParen != NULL) { 601249261Sdim if (getLengthToMatchingParen(Current) + State.Column > getColumnLimit()) 602249261Sdim State.Stack.back().BreakBeforeParameter = true; 603249261Sdim } 604249261Sdim 605249261Sdim // If we encounter a closing ), ], } or >, we can remove a level from our 606249261Sdim // stacks. 607249261Sdim if (Current.isOneOf(tok::r_paren, tok::r_square) || 608249261Sdim (Current.is(tok::r_brace) && State.NextToken != &RootToken) || 609249261Sdim State.NextToken->Type == TT_TemplateCloser) { 610249261Sdim State.Stack.pop_back(); 611249261Sdim --State.ParenLevel; 612249261Sdim } 613249261Sdim 614249261Sdim // Remove scopes created by fake parenthesis. 615249261Sdim for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) { 616249261Sdim unsigned VariablePos = State.Stack.back().VariablePos; 617249261Sdim State.Stack.pop_back(); 618249261Sdim State.Stack.back().VariablePos = VariablePos; 619249261Sdim } 620249261Sdim 621249261Sdim if (Current.is(tok::string_literal)) { 622249261Sdim State.StartOfStringLiteral = State.Column; 623249261Sdim } else if (Current.isNot(tok::comment)) { 624249261Sdim State.StartOfStringLiteral = 0; 625249261Sdim } 626249261Sdim 627249261Sdim State.Column += Current.FormatTok.TokenLength; 628249261Sdim 629249261Sdim if (State.NextToken->Children.empty()) 630249261Sdim State.NextToken = NULL; 631249261Sdim else 632249261Sdim State.NextToken = &State.NextToken->Children[0]; 633249261Sdim 634249261Sdim return breakProtrudingToken(Current, State, DryRun); 635249261Sdim } 636249261Sdim 637249261Sdim /// \brief If the current token sticks out over the end of the line, break 638249261Sdim /// it if possible. 639249261Sdim unsigned breakProtrudingToken(const AnnotatedToken &Current, LineState &State, 640249261Sdim bool DryRun) { 641251662Sdim llvm::OwningPtr<BreakableToken> Token; 642251662Sdim unsigned StartColumn = State.Column - Current.FormatTok.TokenLength; 643251662Sdim if (Current.is(tok::string_literal)) { 644251662Sdim // Only break up default narrow strings. 645251662Sdim const char *LiteralData = SourceMgr.getCharacterData( 646251662Sdim Current.FormatTok.getStartOfNonWhitespace()); 647251662Sdim if (!LiteralData || *LiteralData != '"') 648251662Sdim return 0; 649251662Sdim 650251662Sdim Token.reset(new BreakableStringLiteral(SourceMgr, Current.FormatTok, 651251662Sdim StartColumn)); 652251662Sdim } else if (Current.Type == TT_BlockComment) { 653251662Sdim BreakableBlockComment *BBC = 654251662Sdim new BreakableBlockComment(SourceMgr, Current, StartColumn); 655251662Sdim if (!DryRun) 656251662Sdim BBC->alignLines(Whitespaces); 657251662Sdim Token.reset(BBC); 658251662Sdim } else if (Current.Type == TT_LineComment && 659251662Sdim (Current.Parent == NULL || 660251662Sdim Current.Parent->Type != TT_ImplicitStringLiteral)) { 661251662Sdim Token.reset(new BreakableLineComment(SourceMgr, Current, StartColumn)); 662251662Sdim } else { 663249261Sdim return 0; 664251662Sdim } 665249261Sdim 666251662Sdim bool BreakInserted = false; 667249261Sdim unsigned Penalty = 0; 668251662Sdim for (unsigned LineIndex = 0; LineIndex < Token->getLineCount(); 669251662Sdim ++LineIndex) { 670251662Sdim unsigned TailOffset = 0; 671251662Sdim unsigned RemainingLength = 672251662Sdim Token->getLineLengthAfterSplit(LineIndex, TailOffset); 673251662Sdim while (RemainingLength > getColumnLimit()) { 674251662Sdim BreakableToken::Split Split = 675251662Sdim Token->getSplit(LineIndex, TailOffset, getColumnLimit()); 676251662Sdim if (Split.first == StringRef::npos) 677251662Sdim break; 678251662Sdim assert(Split.first != 0); 679251662Sdim unsigned NewRemainingLength = Token->getLineLengthAfterSplit( 680251662Sdim LineIndex, TailOffset + Split.first + Split.second); 681251662Sdim if (NewRemainingLength >= RemainingLength) 682251662Sdim break; 683251662Sdim if (!DryRun) { 684251662Sdim Token->insertBreak(LineIndex, TailOffset, Split, Line.InPPDirective, 685251662Sdim Whitespaces); 686251662Sdim } 687251662Sdim TailOffset += Split.first + Split.second; 688251662Sdim RemainingLength = NewRemainingLength; 689251662Sdim Penalty += Style.PenaltyExcessCharacter; 690251662Sdim BreakInserted = true; 691251662Sdim } 692251662Sdim State.Column = RemainingLength; 693249261Sdim if (!DryRun) { 694251662Sdim Token->trimLine(LineIndex, TailOffset, Line.InPPDirective, Whitespaces); 695249261Sdim } 696251662Sdim } 697251662Sdim 698251662Sdim if (BreakInserted) { 699249261Sdim for (unsigned i = 0, e = State.Stack.size(); i != e; ++i) 700249261Sdim State.Stack[i].BreakBeforeParameter = true; 701251662Sdim State.Stack.back().LastSpace = StartColumn; 702249261Sdim } 703249261Sdim return Penalty; 704249261Sdim } 705249261Sdim 706249261Sdim unsigned getColumnLimit() { 707251662Sdim // In preprocessor directives reserve two chars for trailing " \" 708251662Sdim return Style.ColumnLimit - (Line.InPPDirective ? 2 : 0); 709249261Sdim } 710249261Sdim 711249261Sdim /// \brief An edge in the solution space from \c Previous->State to \c State, 712249261Sdim /// inserting a newline dependent on the \c NewLine. 713249261Sdim struct StateNode { 714249261Sdim StateNode(const LineState &State, bool NewLine, StateNode *Previous) 715249261Sdim : State(State), NewLine(NewLine), Previous(Previous) {} 716249261Sdim LineState State; 717249261Sdim bool NewLine; 718249261Sdim StateNode *Previous; 719249261Sdim }; 720249261Sdim 721249261Sdim /// \brief A pair of <penalty, count> that is used to prioritize the BFS on. 722249261Sdim /// 723249261Sdim /// In case of equal penalties, we want to prefer states that were inserted 724249261Sdim /// first. During state generation we make sure that we insert states first 725249261Sdim /// that break the line as late as possible. 726249261Sdim typedef std::pair<unsigned, unsigned> OrderedPenalty; 727249261Sdim 728249261Sdim /// \brief An item in the prioritized BFS search queue. The \c StateNode's 729249261Sdim /// \c State has the given \c OrderedPenalty. 730249261Sdim typedef std::pair<OrderedPenalty, StateNode *> QueueItem; 731249261Sdim 732249261Sdim /// \brief The BFS queue type. 733249261Sdim typedef std::priority_queue<QueueItem, std::vector<QueueItem>, 734249261Sdim std::greater<QueueItem> > QueueType; 735249261Sdim 736249261Sdim /// \brief Analyze the entire solution space starting from \p InitialState. 737249261Sdim /// 738249261Sdim /// This implements a variant of Dijkstra's algorithm on the graph that spans 739249261Sdim /// the solution space (\c LineStates are the nodes). The algorithm tries to 740249261Sdim /// find the shortest path (the one with lowest penalty) from \p InitialState 741249261Sdim /// to a state where all tokens are placed. 742249261Sdim unsigned analyzeSolutionSpace(LineState &InitialState) { 743249261Sdim std::set<LineState> Seen; 744249261Sdim 745249261Sdim // Insert start element into queue. 746249261Sdim StateNode *Node = 747249261Sdim new (Allocator.Allocate()) StateNode(InitialState, false, NULL); 748249261Sdim Queue.push(QueueItem(OrderedPenalty(0, Count), Node)); 749249261Sdim ++Count; 750249261Sdim 751249261Sdim // While not empty, take first element and follow edges. 752249261Sdim while (!Queue.empty()) { 753249261Sdim unsigned Penalty = Queue.top().first.first; 754249261Sdim StateNode *Node = Queue.top().second; 755249261Sdim if (Node->State.NextToken == NULL) { 756249261Sdim DEBUG(llvm::errs() << "\n---\nPenalty for line: " << Penalty << "\n"); 757249261Sdim break; 758249261Sdim } 759249261Sdim Queue.pop(); 760249261Sdim 761249261Sdim if (!Seen.insert(Node->State).second) 762249261Sdim // State already examined with lower penalty. 763249261Sdim continue; 764249261Sdim 765249261Sdim addNextStateToQueue(Penalty, Node, /*NewLine=*/ false); 766249261Sdim addNextStateToQueue(Penalty, Node, /*NewLine=*/ true); 767249261Sdim } 768249261Sdim 769249261Sdim if (Queue.empty()) 770249261Sdim // We were unable to find a solution, do nothing. 771249261Sdim // FIXME: Add diagnostic? 772249261Sdim return 0; 773249261Sdim 774249261Sdim // Reconstruct the solution. 775249261Sdim reconstructPath(InitialState, Queue.top().second); 776249261Sdim DEBUG(llvm::errs() << "---\n"); 777249261Sdim 778249261Sdim // Return the column after the last token of the solution. 779249261Sdim return Queue.top().second->State.Column; 780249261Sdim } 781249261Sdim 782249261Sdim void reconstructPath(LineState &State, StateNode *Current) { 783249261Sdim // FIXME: This recursive implementation limits the possible number 784249261Sdim // of tokens per line if compiled into a binary with small stack space. 785249261Sdim // To become more independent of stack frame limitations we would need 786249261Sdim // to also change the TokenAnnotator. 787249261Sdim if (Current->Previous == NULL) 788249261Sdim return; 789249261Sdim reconstructPath(State, Current->Previous); 790249261Sdim DEBUG({ 791249261Sdim if (Current->NewLine) { 792249261Sdim llvm::errs() 793249261Sdim << "Penalty for splitting before " 794249261Sdim << Current->Previous->State.NextToken->FormatTok.Tok.getName() 795249261Sdim << ": " << Current->Previous->State.NextToken->SplitPenalty << "\n"; 796249261Sdim } 797249261Sdim }); 798249261Sdim addTokenToState(Current->NewLine, false, State); 799249261Sdim } 800249261Sdim 801249261Sdim /// \brief Add the following state to the analysis queue \c Queue. 802249261Sdim /// 803249261Sdim /// Assume the current state is \p PreviousNode and has been reached with a 804249261Sdim /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true. 805249261Sdim void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode, 806249261Sdim bool NewLine) { 807249261Sdim if (NewLine && !canBreak(PreviousNode->State)) 808249261Sdim return; 809249261Sdim if (!NewLine && mustBreak(PreviousNode->State)) 810249261Sdim return; 811249261Sdim if (NewLine) 812249261Sdim Penalty += PreviousNode->State.NextToken->SplitPenalty; 813249261Sdim 814249261Sdim StateNode *Node = new (Allocator.Allocate()) 815249261Sdim StateNode(PreviousNode->State, NewLine, PreviousNode); 816249261Sdim Penalty += addTokenToState(NewLine, true, Node->State); 817249261Sdim if (Node->State.Column > getColumnLimit()) { 818249261Sdim unsigned ExcessCharacters = Node->State.Column - getColumnLimit(); 819249261Sdim Penalty += Style.PenaltyExcessCharacter * ExcessCharacters; 820249261Sdim } 821249261Sdim 822249261Sdim Queue.push(QueueItem(OrderedPenalty(Penalty, Count), Node)); 823249261Sdim ++Count; 824249261Sdim } 825249261Sdim 826249261Sdim /// \brief Returns \c true, if a line break after \p State is allowed. 827249261Sdim bool canBreak(const LineState &State) { 828249261Sdim if (!State.NextToken->CanBreakBefore && 829249261Sdim !(State.NextToken->is(tok::r_brace) && 830249261Sdim State.Stack.back().BreakBeforeClosingBrace)) 831249261Sdim return false; 832251662Sdim return !State.Stack.back().NoLineBreak; 833249261Sdim } 834249261Sdim 835249261Sdim /// \brief Returns \c true, if a line break after \p State is mandatory. 836249261Sdim bool mustBreak(const LineState &State) { 837249261Sdim if (State.NextToken->MustBreakBefore) 838249261Sdim return true; 839249261Sdim if (State.NextToken->is(tok::r_brace) && 840249261Sdim State.Stack.back().BreakBeforeClosingBrace) 841249261Sdim return true; 842249261Sdim if (State.NextToken->Parent->is(tok::semi) && 843249261Sdim State.LineContainsContinuedForLoopSection) 844249261Sdim return true; 845249261Sdim if ((State.NextToken->Parent->isOneOf(tok::comma, tok::semi) || 846249261Sdim State.NextToken->is(tok::question) || 847249261Sdim State.NextToken->Type == TT_ConditionalExpr) && 848249261Sdim State.Stack.back().BreakBeforeParameter && 849251662Sdim !State.NextToken->isTrailingComment() && 850249261Sdim State.NextToken->isNot(tok::r_paren) && 851249261Sdim State.NextToken->isNot(tok::r_brace)) 852249261Sdim return true; 853249261Sdim // FIXME: Comparing LongestObjCSelectorName to 0 is a hacky way of finding 854249261Sdim // out whether it is the first parameter. Clean this up. 855249261Sdim if (State.NextToken->Type == TT_ObjCSelectorName && 856249261Sdim State.NextToken->LongestObjCSelectorName == 0 && 857249261Sdim State.Stack.back().BreakBeforeParameter) 858249261Sdim return true; 859249261Sdim if ((State.NextToken->Type == TT_CtorInitializerColon || 860249261Sdim (State.NextToken->Parent->ClosesTemplateDeclaration && 861249261Sdim State.ParenLevel == 0))) 862249261Sdim return true; 863249261Sdim if (State.NextToken->Type == TT_InlineASMColon) 864249261Sdim return true; 865249261Sdim // This prevents breaks like: 866249261Sdim // ... 867249261Sdim // SomeParameter, OtherParameter).DoSomething( 868249261Sdim // ... 869249261Sdim // As they hide "DoSomething" and generally bad for readability. 870249261Sdim if (State.NextToken->isOneOf(tok::period, tok::arrow) && 871249261Sdim getRemainingLength(State) + State.Column > getColumnLimit() && 872249261Sdim State.ParenLevel < State.StartOfLineLevel) 873249261Sdim return true; 874249261Sdim return false; 875249261Sdim } 876249261Sdim 877249261Sdim // Returns the total number of columns required for the remaining tokens. 878249261Sdim unsigned getRemainingLength(const LineState &State) { 879249261Sdim if (State.NextToken && State.NextToken->Parent) 880249261Sdim return Line.Last->TotalLength - State.NextToken->Parent->TotalLength; 881249261Sdim return 0; 882249261Sdim } 883249261Sdim 884249261Sdim FormatStyle Style; 885249261Sdim SourceManager &SourceMgr; 886249261Sdim const AnnotatedLine &Line; 887249261Sdim const unsigned FirstIndent; 888249261Sdim const AnnotatedToken &RootToken; 889249261Sdim WhitespaceManager &Whitespaces; 890249261Sdim 891249261Sdim llvm::SpecificBumpPtrAllocator<StateNode> Allocator; 892249261Sdim QueueType Queue; 893249261Sdim // Increasing count of \c StateNode items we have created. This is used 894249261Sdim // to create a deterministic order independent of the container. 895249261Sdim unsigned Count; 896249261Sdim}; 897249261Sdim 898249261Sdimclass LexerBasedFormatTokenSource : public FormatTokenSource { 899249261Sdimpublic: 900249261Sdim LexerBasedFormatTokenSource(Lexer &Lex, SourceManager &SourceMgr) 901249261Sdim : GreaterStashed(false), Lex(Lex), SourceMgr(SourceMgr), 902249261Sdim IdentTable(Lex.getLangOpts()) { 903249261Sdim Lex.SetKeepWhitespaceMode(true); 904249261Sdim } 905249261Sdim 906249261Sdim virtual FormatToken getNextToken() { 907249261Sdim if (GreaterStashed) { 908249261Sdim FormatTok.NewlinesBefore = 0; 909249261Sdim FormatTok.WhiteSpaceStart = 910249261Sdim FormatTok.Tok.getLocation().getLocWithOffset(1); 911249261Sdim FormatTok.WhiteSpaceLength = 0; 912249261Sdim GreaterStashed = false; 913249261Sdim return FormatTok; 914249261Sdim } 915249261Sdim 916249261Sdim FormatTok = FormatToken(); 917249261Sdim Lex.LexFromRawLexer(FormatTok.Tok); 918249261Sdim StringRef Text = rawTokenText(FormatTok.Tok); 919249261Sdim FormatTok.WhiteSpaceStart = FormatTok.Tok.getLocation(); 920249261Sdim if (SourceMgr.getFileOffset(FormatTok.WhiteSpaceStart) == 0) 921249261Sdim FormatTok.IsFirst = true; 922249261Sdim 923249261Sdim // Consume and record whitespace until we find a significant token. 924249261Sdim while (FormatTok.Tok.is(tok::unknown)) { 925249261Sdim unsigned Newlines = Text.count('\n'); 926249261Sdim if (Newlines > 0) 927249261Sdim FormatTok.LastNewlineOffset = 928249261Sdim FormatTok.WhiteSpaceLength + Text.rfind('\n') + 1; 929249261Sdim unsigned EscapedNewlines = Text.count("\\\n"); 930249261Sdim FormatTok.NewlinesBefore += Newlines; 931249261Sdim FormatTok.HasUnescapedNewline |= EscapedNewlines != Newlines; 932249261Sdim FormatTok.WhiteSpaceLength += FormatTok.Tok.getLength(); 933249261Sdim 934249261Sdim if (FormatTok.Tok.is(tok::eof)) 935249261Sdim return FormatTok; 936249261Sdim Lex.LexFromRawLexer(FormatTok.Tok); 937249261Sdim Text = rawTokenText(FormatTok.Tok); 938249261Sdim } 939249261Sdim 940249261Sdim // Now FormatTok is the next non-whitespace token. 941249261Sdim FormatTok.TokenLength = Text.size(); 942249261Sdim 943251662Sdim if (FormatTok.Tok.is(tok::comment)) { 944251662Sdim FormatTok.TrailingWhiteSpaceLength = Text.size() - Text.rtrim().size(); 945251662Sdim FormatTok.TokenLength -= FormatTok.TrailingWhiteSpaceLength; 946251662Sdim } 947251662Sdim 948249261Sdim // In case the token starts with escaped newlines, we want to 949249261Sdim // take them into account as whitespace - this pattern is quite frequent 950249261Sdim // in macro definitions. 951249261Sdim // FIXME: What do we want to do with other escaped spaces, and escaped 952249261Sdim // spaces or newlines in the middle of tokens? 953249261Sdim // FIXME: Add a more explicit test. 954249261Sdim unsigned i = 0; 955249261Sdim while (i + 1 < Text.size() && Text[i] == '\\' && Text[i + 1] == '\n') { 956249261Sdim // FIXME: ++FormatTok.NewlinesBefore is missing... 957249261Sdim FormatTok.WhiteSpaceLength += 2; 958249261Sdim FormatTok.TokenLength -= 2; 959249261Sdim i += 2; 960249261Sdim } 961249261Sdim 962249261Sdim if (FormatTok.Tok.is(tok::raw_identifier)) { 963249261Sdim IdentifierInfo &Info = IdentTable.get(Text); 964249261Sdim FormatTok.Tok.setIdentifierInfo(&Info); 965249261Sdim FormatTok.Tok.setKind(Info.getTokenID()); 966249261Sdim } 967249261Sdim 968249261Sdim if (FormatTok.Tok.is(tok::greatergreater)) { 969249261Sdim FormatTok.Tok.setKind(tok::greater); 970249261Sdim FormatTok.TokenLength = 1; 971249261Sdim GreaterStashed = true; 972249261Sdim } 973249261Sdim 974249261Sdim return FormatTok; 975249261Sdim } 976249261Sdim 977249261Sdim IdentifierTable &getIdentTable() { return IdentTable; } 978249261Sdim 979249261Sdimprivate: 980249261Sdim FormatToken FormatTok; 981249261Sdim bool GreaterStashed; 982249261Sdim Lexer &Lex; 983249261Sdim SourceManager &SourceMgr; 984249261Sdim IdentifierTable IdentTable; 985249261Sdim 986249261Sdim /// Returns the text of \c FormatTok. 987249261Sdim StringRef rawTokenText(Token &Tok) { 988249261Sdim return StringRef(SourceMgr.getCharacterData(Tok.getLocation()), 989249261Sdim Tok.getLength()); 990249261Sdim } 991249261Sdim}; 992249261Sdim 993249261Sdimclass Formatter : public UnwrappedLineConsumer { 994249261Sdimpublic: 995249261Sdim Formatter(DiagnosticsEngine &Diag, const FormatStyle &Style, Lexer &Lex, 996249261Sdim SourceManager &SourceMgr, 997249261Sdim const std::vector<CharSourceRange> &Ranges) 998249261Sdim : Diag(Diag), Style(Style), Lex(Lex), SourceMgr(SourceMgr), 999249261Sdim Whitespaces(SourceMgr, Style), Ranges(Ranges) {} 1000249261Sdim 1001249261Sdim virtual ~Formatter() {} 1002249261Sdim 1003249261Sdim tooling::Replacements format() { 1004249261Sdim LexerBasedFormatTokenSource Tokens(Lex, SourceMgr); 1005249261Sdim UnwrappedLineParser Parser(Diag, Style, Tokens, *this); 1006251662Sdim bool StructuralError = Parser.parse(); 1007249261Sdim unsigned PreviousEndOfLineColumn = 0; 1008249261Sdim TokenAnnotator Annotator(Style, SourceMgr, Lex, 1009249261Sdim Tokens.getIdentTable().get("in")); 1010249261Sdim for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1011249261Sdim Annotator.annotate(AnnotatedLines[i]); 1012249261Sdim } 1013249261Sdim deriveLocalStyle(); 1014249261Sdim for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1015249261Sdim Annotator.calculateFormattingInformation(AnnotatedLines[i]); 1016251662Sdim } 1017249261Sdim 1018251662Sdim // Adapt level to the next line if this is a comment. 1019251662Sdim // FIXME: Can/should this be done in the UnwrappedLineParser? 1020251662Sdim const AnnotatedLine *NextNoneCommentLine = NULL; 1021251662Sdim for (unsigned i = AnnotatedLines.size() - 1; i > 0; --i) { 1022251662Sdim if (NextNoneCommentLine && AnnotatedLines[i].First.is(tok::comment) && 1023251662Sdim AnnotatedLines[i].First.Children.empty()) 1024251662Sdim AnnotatedLines[i].Level = NextNoneCommentLine->Level; 1025251662Sdim else 1026251662Sdim NextNoneCommentLine = 1027251662Sdim AnnotatedLines[i].First.isNot(tok::r_brace) ? &AnnotatedLines[i] 1028251662Sdim : NULL; 1029249261Sdim } 1030251662Sdim 1031249261Sdim std::vector<int> IndentForLevel; 1032249261Sdim bool PreviousLineWasTouched = false; 1033249261Sdim const AnnotatedToken *PreviousLineLastToken = 0; 1034249261Sdim for (std::vector<AnnotatedLine>::iterator I = AnnotatedLines.begin(), 1035249261Sdim E = AnnotatedLines.end(); 1036249261Sdim I != E; ++I) { 1037249261Sdim const AnnotatedLine &TheLine = *I; 1038249261Sdim const FormatToken &FirstTok = TheLine.First.FormatTok; 1039249261Sdim int Offset = getIndentOffset(TheLine.First); 1040249261Sdim while (IndentForLevel.size() <= TheLine.Level) 1041249261Sdim IndentForLevel.push_back(-1); 1042249261Sdim IndentForLevel.resize(TheLine.Level + 1); 1043249261Sdim bool WasMoved = PreviousLineWasTouched && FirstTok.NewlinesBefore == 0; 1044249261Sdim if (TheLine.First.is(tok::eof)) { 1045249261Sdim if (PreviousLineWasTouched) { 1046249261Sdim unsigned NewLines = std::min(FirstTok.NewlinesBefore, 1u); 1047249261Sdim Whitespaces.replaceWhitespace(TheLine.First, NewLines, /*Indent*/ 0, 1048249261Sdim /*WhitespaceStartColumn*/ 0); 1049249261Sdim } 1050249261Sdim } else if (TheLine.Type != LT_Invalid && 1051249261Sdim (WasMoved || touchesLine(TheLine))) { 1052249261Sdim unsigned LevelIndent = getIndent(IndentForLevel, TheLine.Level); 1053249261Sdim unsigned Indent = LevelIndent; 1054249261Sdim if (static_cast<int>(Indent) + Offset >= 0) 1055249261Sdim Indent += Offset; 1056251662Sdim if (FirstTok.WhiteSpaceStart.isValid() && 1057251662Sdim // Insert a break even if there is a structural error in case where 1058251662Sdim // we break apart a line consisting of multiple unwrapped lines. 1059251662Sdim (FirstTok.NewlinesBefore == 0 || !StructuralError)) { 1060251662Sdim formatFirstToken(TheLine.First, PreviousLineLastToken, Indent, 1061251662Sdim TheLine.InPPDirective, PreviousEndOfLineColumn); 1062251662Sdim } else { 1063249261Sdim Indent = LevelIndent = 1064249261Sdim SourceMgr.getSpellingColumnNumber(FirstTok.Tok.getLocation()) - 1; 1065249261Sdim } 1066249261Sdim tryFitMultipleLinesInOne(Indent, I, E); 1067249261Sdim UnwrappedLineFormatter Formatter(Style, SourceMgr, TheLine, Indent, 1068251662Sdim TheLine.First, Whitespaces); 1069249261Sdim PreviousEndOfLineColumn = 1070249261Sdim Formatter.format(I + 1 != E ? &*(I + 1) : NULL); 1071249261Sdim IndentForLevel[TheLine.Level] = LevelIndent; 1072249261Sdim PreviousLineWasTouched = true; 1073249261Sdim } else { 1074249261Sdim if (FirstTok.NewlinesBefore > 0 || FirstTok.IsFirst) { 1075249261Sdim unsigned Indent = 1076249261Sdim SourceMgr.getSpellingColumnNumber(FirstTok.Tok.getLocation()) - 1; 1077249261Sdim unsigned LevelIndent = Indent; 1078249261Sdim if (static_cast<int>(LevelIndent) - Offset >= 0) 1079249261Sdim LevelIndent -= Offset; 1080249261Sdim if (TheLine.First.isNot(tok::comment)) 1081249261Sdim IndentForLevel[TheLine.Level] = LevelIndent; 1082249261Sdim 1083249261Sdim // Remove trailing whitespace of the previous line if it was touched. 1084249261Sdim if (PreviousLineWasTouched || touchesEmptyLineBefore(TheLine)) 1085249261Sdim formatFirstToken(TheLine.First, PreviousLineLastToken, Indent, 1086249261Sdim TheLine.InPPDirective, PreviousEndOfLineColumn); 1087249261Sdim } 1088249261Sdim // If we did not reformat this unwrapped line, the column at the end of 1089249261Sdim // the last token is unchanged - thus, we can calculate the end of the 1090249261Sdim // last token. 1091249261Sdim SourceLocation LastLoc = TheLine.Last->FormatTok.Tok.getLocation(); 1092249261Sdim PreviousEndOfLineColumn = 1093249261Sdim SourceMgr.getSpellingColumnNumber(LastLoc) + 1094249261Sdim Lex.MeasureTokenLength(LastLoc, SourceMgr, Lex.getLangOpts()) - 1; 1095249261Sdim PreviousLineWasTouched = false; 1096249261Sdim if (TheLine.Last->is(tok::comment)) 1097249261Sdim Whitespaces.addUntouchableComment(SourceMgr.getSpellingColumnNumber( 1098249261Sdim TheLine.Last->FormatTok.Tok.getLocation()) - 1); 1099251662Sdim else 1100251662Sdim Whitespaces.alignComments(); 1101249261Sdim } 1102249261Sdim PreviousLineLastToken = I->Last; 1103249261Sdim } 1104249261Sdim return Whitespaces.generateReplacements(); 1105249261Sdim } 1106249261Sdim 1107249261Sdimprivate: 1108249261Sdim void deriveLocalStyle() { 1109249261Sdim unsigned CountBoundToVariable = 0; 1110249261Sdim unsigned CountBoundToType = 0; 1111249261Sdim bool HasCpp03IncompatibleFormat = false; 1112249261Sdim for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1113249261Sdim if (AnnotatedLines[i].First.Children.empty()) 1114249261Sdim continue; 1115249261Sdim AnnotatedToken *Tok = &AnnotatedLines[i].First.Children[0]; 1116249261Sdim while (!Tok->Children.empty()) { 1117249261Sdim if (Tok->Type == TT_PointerOrReference) { 1118249261Sdim bool SpacesBefore = Tok->FormatTok.WhiteSpaceLength > 0; 1119249261Sdim bool SpacesAfter = Tok->Children[0].FormatTok.WhiteSpaceLength > 0; 1120249261Sdim if (SpacesBefore && !SpacesAfter) 1121249261Sdim ++CountBoundToVariable; 1122249261Sdim else if (!SpacesBefore && SpacesAfter) 1123249261Sdim ++CountBoundToType; 1124249261Sdim } 1125249261Sdim 1126249261Sdim if (Tok->Type == TT_TemplateCloser && 1127249261Sdim Tok->Parent->Type == TT_TemplateCloser && 1128249261Sdim Tok->FormatTok.WhiteSpaceLength == 0) 1129249261Sdim HasCpp03IncompatibleFormat = true; 1130249261Sdim Tok = &Tok->Children[0]; 1131249261Sdim } 1132249261Sdim } 1133249261Sdim if (Style.DerivePointerBinding) { 1134249261Sdim if (CountBoundToType > CountBoundToVariable) 1135249261Sdim Style.PointerBindsToType = true; 1136249261Sdim else if (CountBoundToType < CountBoundToVariable) 1137249261Sdim Style.PointerBindsToType = false; 1138249261Sdim } 1139249261Sdim if (Style.Standard == FormatStyle::LS_Auto) { 1140249261Sdim Style.Standard = HasCpp03IncompatibleFormat ? FormatStyle::LS_Cpp11 1141249261Sdim : FormatStyle::LS_Cpp03; 1142249261Sdim } 1143249261Sdim } 1144249261Sdim 1145249261Sdim /// \brief Get the indent of \p Level from \p IndentForLevel. 1146249261Sdim /// 1147249261Sdim /// \p IndentForLevel must contain the indent for the level \c l 1148249261Sdim /// at \p IndentForLevel[l], or a value < 0 if the indent for 1149249261Sdim /// that level is unknown. 1150249261Sdim unsigned getIndent(const std::vector<int> IndentForLevel, unsigned Level) { 1151249261Sdim if (IndentForLevel[Level] != -1) 1152249261Sdim return IndentForLevel[Level]; 1153249261Sdim if (Level == 0) 1154249261Sdim return 0; 1155249261Sdim return getIndent(IndentForLevel, Level - 1) + 2; 1156249261Sdim } 1157249261Sdim 1158249261Sdim /// \brief Get the offset of the line relatively to the level. 1159249261Sdim /// 1160249261Sdim /// For example, 'public:' labels in classes are offset by 1 or 2 1161249261Sdim /// characters to the left from their level. 1162249261Sdim int getIndentOffset(const AnnotatedToken &RootToken) { 1163249261Sdim if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier()) 1164249261Sdim return Style.AccessModifierOffset; 1165249261Sdim return 0; 1166249261Sdim } 1167249261Sdim 1168249261Sdim /// \brief Tries to merge lines into one. 1169249261Sdim /// 1170249261Sdim /// This will change \c Line and \c AnnotatedLine to contain the merged line, 1171249261Sdim /// if possible; note that \c I will be incremented when lines are merged. 1172249261Sdim /// 1173249261Sdim /// Returns whether the resulting \c Line can fit in a single line. 1174249261Sdim void tryFitMultipleLinesInOne(unsigned Indent, 1175249261Sdim std::vector<AnnotatedLine>::iterator &I, 1176249261Sdim std::vector<AnnotatedLine>::iterator E) { 1177249261Sdim // We can never merge stuff if there are trailing line comments. 1178249261Sdim if (I->Last->Type == TT_LineComment) 1179249261Sdim return; 1180249261Sdim 1181249261Sdim unsigned Limit = Style.ColumnLimit - Indent; 1182249261Sdim // If we already exceed the column limit, we set 'Limit' to 0. The different 1183249261Sdim // tryMerge..() functions can then decide whether to still do merging. 1184249261Sdim Limit = I->Last->TotalLength > Limit ? 0 : Limit - I->Last->TotalLength; 1185249261Sdim 1186249261Sdim if (I + 1 == E || (I + 1)->Type == LT_Invalid) 1187249261Sdim return; 1188249261Sdim 1189249261Sdim if (I->Last->is(tok::l_brace)) { 1190249261Sdim tryMergeSimpleBlock(I, E, Limit); 1191249261Sdim } else if (I->First.is(tok::kw_if)) { 1192249261Sdim tryMergeSimpleIf(I, E, Limit); 1193249261Sdim } else if (I->InPPDirective && (I->First.FormatTok.HasUnescapedNewline || 1194249261Sdim I->First.FormatTok.IsFirst)) { 1195249261Sdim tryMergeSimplePPDirective(I, E, Limit); 1196249261Sdim } 1197249261Sdim return; 1198249261Sdim } 1199249261Sdim 1200249261Sdim void tryMergeSimplePPDirective(std::vector<AnnotatedLine>::iterator &I, 1201249261Sdim std::vector<AnnotatedLine>::iterator E, 1202249261Sdim unsigned Limit) { 1203249261Sdim if (Limit == 0) 1204249261Sdim return; 1205249261Sdim AnnotatedLine &Line = *I; 1206249261Sdim if (!(I + 1)->InPPDirective || (I + 1)->First.FormatTok.HasUnescapedNewline) 1207249261Sdim return; 1208249261Sdim if (I + 2 != E && (I + 2)->InPPDirective && 1209249261Sdim !(I + 2)->First.FormatTok.HasUnescapedNewline) 1210249261Sdim return; 1211249261Sdim if (1 + (I + 1)->Last->TotalLength > Limit) 1212249261Sdim return; 1213249261Sdim join(Line, *(++I)); 1214249261Sdim } 1215249261Sdim 1216249261Sdim void tryMergeSimpleIf(std::vector<AnnotatedLine>::iterator &I, 1217249261Sdim std::vector<AnnotatedLine>::iterator E, 1218249261Sdim unsigned Limit) { 1219249261Sdim if (Limit == 0) 1220249261Sdim return; 1221249261Sdim if (!Style.AllowShortIfStatementsOnASingleLine) 1222249261Sdim return; 1223249261Sdim if ((I + 1)->InPPDirective != I->InPPDirective || 1224249261Sdim ((I + 1)->InPPDirective && 1225249261Sdim (I + 1)->First.FormatTok.HasUnescapedNewline)) 1226249261Sdim return; 1227249261Sdim AnnotatedLine &Line = *I; 1228249261Sdim if (Line.Last->isNot(tok::r_paren)) 1229249261Sdim return; 1230249261Sdim if (1 + (I + 1)->Last->TotalLength > Limit) 1231249261Sdim return; 1232249261Sdim if ((I + 1)->First.is(tok::kw_if) || (I + 1)->First.Type == TT_LineComment) 1233249261Sdim return; 1234249261Sdim // Only inline simple if's (no nested if or else). 1235249261Sdim if (I + 2 != E && (I + 2)->First.is(tok::kw_else)) 1236249261Sdim return; 1237249261Sdim join(Line, *(++I)); 1238249261Sdim } 1239249261Sdim 1240249261Sdim void tryMergeSimpleBlock(std::vector<AnnotatedLine>::iterator &I, 1241249261Sdim std::vector<AnnotatedLine>::iterator E, 1242249261Sdim unsigned Limit) { 1243249261Sdim // First, check that the current line allows merging. This is the case if 1244249261Sdim // we're not in a control flow statement and the last token is an opening 1245249261Sdim // brace. 1246249261Sdim AnnotatedLine &Line = *I; 1247249261Sdim if (Line.First.isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace, 1248249261Sdim tok::kw_else, tok::kw_try, tok::kw_catch, 1249249261Sdim tok::kw_for, 1250249261Sdim // This gets rid of all ObjC @ keywords and methods. 1251249261Sdim tok::at, tok::minus, tok::plus)) 1252249261Sdim return; 1253249261Sdim 1254249261Sdim AnnotatedToken *Tok = &(I + 1)->First; 1255249261Sdim if (Tok->Children.empty() && Tok->is(tok::r_brace) && 1256249261Sdim !Tok->MustBreakBefore) { 1257249261Sdim // We merge empty blocks even if the line exceeds the column limit. 1258249261Sdim Tok->SpacesRequiredBefore = 0; 1259249261Sdim Tok->CanBreakBefore = true; 1260249261Sdim join(Line, *(I + 1)); 1261249261Sdim I += 1; 1262249261Sdim } else if (Limit != 0) { 1263249261Sdim // Check that we still have three lines and they fit into the limit. 1264249261Sdim if (I + 2 == E || (I + 2)->Type == LT_Invalid || 1265249261Sdim !nextTwoLinesFitInto(I, Limit)) 1266249261Sdim return; 1267249261Sdim 1268249261Sdim // Second, check that the next line does not contain any braces - if it 1269249261Sdim // does, readability declines when putting it into a single line. 1270249261Sdim if ((I + 1)->Last->Type == TT_LineComment || Tok->MustBreakBefore) 1271249261Sdim return; 1272249261Sdim do { 1273249261Sdim if (Tok->isOneOf(tok::l_brace, tok::r_brace)) 1274249261Sdim return; 1275249261Sdim Tok = Tok->Children.empty() ? NULL : &Tok->Children.back(); 1276249261Sdim } while (Tok != NULL); 1277249261Sdim 1278249261Sdim // Last, check that the third line contains a single closing brace. 1279249261Sdim Tok = &(I + 2)->First; 1280249261Sdim if (!Tok->Children.empty() || Tok->isNot(tok::r_brace) || 1281249261Sdim Tok->MustBreakBefore) 1282249261Sdim return; 1283249261Sdim 1284249261Sdim join(Line, *(I + 1)); 1285249261Sdim join(Line, *(I + 2)); 1286249261Sdim I += 2; 1287249261Sdim } 1288249261Sdim } 1289249261Sdim 1290249261Sdim bool nextTwoLinesFitInto(std::vector<AnnotatedLine>::iterator I, 1291249261Sdim unsigned Limit) { 1292249261Sdim return 1 + (I + 1)->Last->TotalLength + 1 + (I + 2)->Last->TotalLength <= 1293249261Sdim Limit; 1294249261Sdim } 1295249261Sdim 1296249261Sdim void join(AnnotatedLine &A, const AnnotatedLine &B) { 1297249261Sdim unsigned LengthA = A.Last->TotalLength + B.First.SpacesRequiredBefore; 1298249261Sdim A.Last->Children.push_back(B.First); 1299249261Sdim while (!A.Last->Children.empty()) { 1300249261Sdim A.Last->Children[0].Parent = A.Last; 1301249261Sdim A.Last->Children[0].TotalLength += LengthA; 1302249261Sdim A.Last = &A.Last->Children[0]; 1303249261Sdim } 1304249261Sdim } 1305249261Sdim 1306249261Sdim bool touchesRanges(const CharSourceRange &Range) { 1307249261Sdim for (unsigned i = 0, e = Ranges.size(); i != e; ++i) { 1308249261Sdim if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), 1309249261Sdim Ranges[i].getBegin()) && 1310249261Sdim !SourceMgr.isBeforeInTranslationUnit(Ranges[i].getEnd(), 1311249261Sdim Range.getBegin())) 1312249261Sdim return true; 1313249261Sdim } 1314249261Sdim return false; 1315249261Sdim } 1316249261Sdim 1317249261Sdim bool touchesLine(const AnnotatedLine &TheLine) { 1318249261Sdim const FormatToken *First = &TheLine.First.FormatTok; 1319249261Sdim const FormatToken *Last = &TheLine.Last->FormatTok; 1320249261Sdim CharSourceRange LineRange = CharSourceRange::getTokenRange( 1321249261Sdim First->WhiteSpaceStart.getLocWithOffset(First->LastNewlineOffset), 1322249261Sdim Last->Tok.getLocation()); 1323249261Sdim return touchesRanges(LineRange); 1324249261Sdim } 1325249261Sdim 1326249261Sdim bool touchesEmptyLineBefore(const AnnotatedLine &TheLine) { 1327249261Sdim const FormatToken *First = &TheLine.First.FormatTok; 1328249261Sdim CharSourceRange LineRange = CharSourceRange::getCharRange( 1329249261Sdim First->WhiteSpaceStart, 1330249261Sdim First->WhiteSpaceStart.getLocWithOffset(First->LastNewlineOffset)); 1331249261Sdim return touchesRanges(LineRange); 1332249261Sdim } 1333249261Sdim 1334249261Sdim virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) { 1335249261Sdim AnnotatedLines.push_back(AnnotatedLine(TheLine)); 1336249261Sdim } 1337249261Sdim 1338249261Sdim /// \brief Add a new line and the required indent before the first Token 1339249261Sdim /// of the \c UnwrappedLine if there was no structural parsing error. 1340249261Sdim /// Returns the indent level of the \c UnwrappedLine. 1341249261Sdim void formatFirstToken(const AnnotatedToken &RootToken, 1342249261Sdim const AnnotatedToken *PreviousToken, unsigned Indent, 1343249261Sdim bool InPPDirective, unsigned PreviousEndOfLineColumn) { 1344249261Sdim const FormatToken &Tok = RootToken.FormatTok; 1345249261Sdim 1346249261Sdim unsigned Newlines = 1347249261Sdim std::min(Tok.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1); 1348249261Sdim if (Newlines == 0 && !Tok.IsFirst) 1349249261Sdim Newlines = 1; 1350249261Sdim 1351249261Sdim if (!InPPDirective || Tok.HasUnescapedNewline) { 1352249261Sdim // Insert extra new line before access specifiers. 1353249261Sdim if (PreviousToken && PreviousToken->isOneOf(tok::semi, tok::r_brace) && 1354249261Sdim RootToken.isAccessSpecifier() && Tok.NewlinesBefore == 1) 1355249261Sdim ++Newlines; 1356249261Sdim 1357249261Sdim Whitespaces.replaceWhitespace(RootToken, Newlines, Indent, 0); 1358249261Sdim } else { 1359249261Sdim Whitespaces.replacePPWhitespace(RootToken, Newlines, Indent, 1360249261Sdim PreviousEndOfLineColumn); 1361249261Sdim } 1362249261Sdim } 1363249261Sdim 1364249261Sdim DiagnosticsEngine &Diag; 1365249261Sdim FormatStyle Style; 1366249261Sdim Lexer &Lex; 1367249261Sdim SourceManager &SourceMgr; 1368249261Sdim WhitespaceManager Whitespaces; 1369249261Sdim std::vector<CharSourceRange> Ranges; 1370249261Sdim std::vector<AnnotatedLine> AnnotatedLines; 1371249261Sdim}; 1372249261Sdim 1373251662Sdimtooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex, 1374251662Sdim SourceManager &SourceMgr, 1375251662Sdim std::vector<CharSourceRange> Ranges, 1376251662Sdim DiagnosticConsumer *DiagClient) { 1377249261Sdim IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 1378249261Sdim OwningPtr<DiagnosticConsumer> DiagPrinter; 1379249261Sdim if (DiagClient == 0) { 1380249261Sdim DiagPrinter.reset(new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts)); 1381249261Sdim DiagPrinter->BeginSourceFile(Lex.getLangOpts(), Lex.getPP()); 1382249261Sdim DiagClient = DiagPrinter.get(); 1383249261Sdim } 1384249261Sdim DiagnosticsEngine Diagnostics( 1385249261Sdim IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, 1386249261Sdim DiagClient, false); 1387249261Sdim Diagnostics.setSourceManager(&SourceMgr); 1388249261Sdim Formatter formatter(Diagnostics, Style, Lex, SourceMgr, Ranges); 1389249261Sdim return formatter.format(); 1390249261Sdim} 1391249261Sdim 1392249261SdimLangOptions getFormattingLangOpts() { 1393249261Sdim LangOptions LangOpts; 1394249261Sdim LangOpts.CPlusPlus = 1; 1395249261Sdim LangOpts.CPlusPlus11 = 1; 1396249261Sdim LangOpts.LineComment = 1; 1397249261Sdim LangOpts.Bool = 1; 1398249261Sdim LangOpts.ObjC1 = 1; 1399249261Sdim LangOpts.ObjC2 = 1; 1400249261Sdim return LangOpts; 1401249261Sdim} 1402249261Sdim 1403249261Sdim} // namespace format 1404249261Sdim} // namespace clang 1405