1 //===--- Format.cpp - Format C++ code -------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief This file implements functions declared in Format.h. This will be 12 /// split into separate files as we go. 13 /// 14 /// This is EXPERIMENTAL code under heavy development. It is not in a state yet, 15 /// where it can be used to format real code. 16 /// 17 //===----------------------------------------------------------------------===// 18 19 #include "clang/Format/Format.h" 20 #include "UnwrappedLineParser.h" 21 #include "clang/Basic/OperatorPrecedence.h" 22 #include "clang/Basic/SourceManager.h" 23 #include "clang/Lex/Lexer.h" 24 #include <string> 25 26 namespace clang { 27 namespace format { 28 29 enum TokenType { 30 TT_Unknown, 31 TT_TemplateOpener, 32 TT_TemplateCloser, 33 TT_BinaryOperator, 34 TT_UnaryOperator, 35 TT_TrailingUnaryOperator, 36 TT_OverloadedOperator, 37 TT_PointerOrReference, 38 TT_ConditionalExpr, 39 TT_CtorInitializerColon, 40 TT_LineComment, 41 TT_BlockComment, 42 TT_DirectorySeparator, 43 TT_PureVirtualSpecifier, 44 TT_ObjCMethodSpecifier 45 }; 46 47 enum LineType { 48 LT_Invalid, 49 LT_Other, 50 LT_PreprocessorDirective, 51 LT_VirtualFunctionDecl, 52 LT_ObjCMethodDecl 53 }; 54 55 class AnnotatedToken { 56 public: 57 AnnotatedToken(const FormatToken &FormatTok) 58 : FormatTok(FormatTok), Type(TT_Unknown), 59 ClosesTemplateDeclaration(false), Parent(NULL) { 60 } 61 62 bool is(tok::TokenKind Kind) const { 63 return FormatTok.Tok.is(Kind); 64 } 65 bool isNot(tok::TokenKind Kind) const { 66 return FormatTok.Tok.isNot(Kind); 67 } 68 bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const { 69 return FormatTok.Tok.isObjCAtKeyword(Kind); 70 } 71 72 FormatToken FormatTok; 73 74 TokenType Type; 75 76 bool SpaceRequiredBefore; 77 bool CanBreakBefore; 78 bool MustBreakBefore; 79 80 bool ClosesTemplateDeclaration; 81 82 std::vector<AnnotatedToken> Children; 83 AnnotatedToken *Parent; 84 }; 85 86 static prec::Level getPrecedence(const AnnotatedToken &Tok) { 87 return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true); 88 } 89 90 using llvm::MutableArrayRef; 91 92 FormatStyle getLLVMStyle() { 93 FormatStyle LLVMStyle; 94 LLVMStyle.ColumnLimit = 80; 95 LLVMStyle.MaxEmptyLinesToKeep = 1; 96 LLVMStyle.PointerAndReferenceBindToType = false; 97 LLVMStyle.AccessModifierOffset = -2; 98 LLVMStyle.SplitTemplateClosingGreater = true; 99 LLVMStyle.IndentCaseLabels = false; 100 LLVMStyle.SpacesBeforeTrailingComments = 1; 101 return LLVMStyle; 102 } 103 104 FormatStyle getGoogleStyle() { 105 FormatStyle GoogleStyle; 106 GoogleStyle.ColumnLimit = 80; 107 GoogleStyle.MaxEmptyLinesToKeep = 1; 108 GoogleStyle.PointerAndReferenceBindToType = true; 109 GoogleStyle.AccessModifierOffset = -1; 110 GoogleStyle.SplitTemplateClosingGreater = false; 111 GoogleStyle.IndentCaseLabels = true; 112 GoogleStyle.SpacesBeforeTrailingComments = 2; 113 return GoogleStyle; 114 } 115 116 struct OptimizationParameters { 117 unsigned PenaltyIndentLevel; 118 unsigned PenaltyLevelDecrease; 119 }; 120 121 class UnwrappedLineFormatter { 122 public: 123 UnwrappedLineFormatter( 124 const FormatStyle &Style, SourceManager &SourceMgr, 125 const UnwrappedLine &Line, unsigned PreviousEndOfLineColumn, 126 LineType CurrentLineType, const AnnotatedToken &RootToken, 127 tooling::Replacements &Replaces, bool StructuralError) 128 : Style(Style), SourceMgr(SourceMgr), Line(Line), 129 PreviousEndOfLineColumn(PreviousEndOfLineColumn), 130 CurrentLineType(CurrentLineType), RootToken(RootToken), 131 Replaces(Replaces), StructuralError(StructuralError) { 132 Parameters.PenaltyIndentLevel = 15; 133 Parameters.PenaltyLevelDecrease = 30; 134 } 135 136 /// \brief Formats an \c UnwrappedLine. 137 /// 138 /// \returns The column after the last token in the last line of the 139 /// \c UnwrappedLine. 140 unsigned format() { 141 // Format first token and initialize indent. 142 unsigned Indent = formatFirstToken(); 143 144 // Initialize state dependent on indent. 145 IndentState State; 146 State.Column = Indent; 147 State.NextToken = &RootToken; 148 State.Indent.push_back(Indent + 4); 149 State.LastSpace.push_back(Indent); 150 State.FirstLessLess.push_back(0); 151 State.ForLoopVariablePos = 0; 152 State.LineContainsContinuedForLoopSection = false; 153 State.StartOfLineLevel = 1; 154 155 // The first token has already been indented and thus consumed. 156 moveStateToNextToken(State); 157 158 // Check whether the UnwrappedLine can be put onto a single line. If so, 159 // this is bound to be the optimal solution (by definition) and we don't 160 // need to analyze the entire solution space. 161 unsigned Columns = State.Column; 162 bool FitsOnALine = true; 163 const AnnotatedToken *Tok = State.NextToken; 164 while (Tok != NULL) { 165 Columns += (Tok->SpaceRequiredBefore ? 1 : 0) + 166 Tok->FormatTok.TokenLength; 167 // A special case for the colon of a constructor initializer as this only 168 // needs to be put on a new line if the line needs to be split. 169 if (Columns > Style.ColumnLimit - (Line.InPPDirective ? 1 : 0) || 170 (Tok->MustBreakBefore && Tok->Type != TT_CtorInitializerColon)) { 171 FitsOnALine = false; 172 break; 173 } 174 Tok = Tok->Children.empty() ? NULL : &Tok->Children[0]; 175 } 176 177 // Start iterating at 1 as we have correctly formatted of Token #0 above. 178 while (State.NextToken != NULL) { 179 if (FitsOnALine) { 180 addTokenToState(false, false, State); 181 } else { 182 unsigned NoBreak = calcPenalty(State, false, UINT_MAX); 183 unsigned Break = calcPenalty(State, true, NoBreak); 184 addTokenToState(Break < NoBreak, false, State); 185 } 186 } 187 return State.Column; 188 } 189 190 private: 191 /// \brief The current state when indenting a unwrapped line. 192 /// 193 /// As the indenting tries different combinations this is copied by value. 194 struct IndentState { 195 /// \brief The number of used columns in the current line. 196 unsigned Column; 197 198 const AnnotatedToken *NextToken; 199 200 /// \brief The parenthesis level of the first token on the current line. 201 unsigned StartOfLineLevel; 202 203 /// \brief The position to which a specific parenthesis level needs to be 204 /// indented. 205 std::vector<unsigned> Indent; 206 207 /// \brief The position of the last space on each level. 208 /// 209 /// Used e.g. to break like: 210 /// functionCall(Parameter, otherCall( 211 /// OtherParameter)); 212 std::vector<unsigned> LastSpace; 213 214 /// \brief The position the first "<<" operator encountered on each level. 215 /// 216 /// Used to align "<<" operators. 0 if no such operator has been encountered 217 /// on a level. 218 std::vector<unsigned> FirstLessLess; 219 220 /// \brief The column of the first variable in a for-loop declaration. 221 /// 222 /// Used to align the second variable if necessary. 223 unsigned ForLoopVariablePos; 224 225 /// \brief \c true if this line contains a continued for-loop section. 226 bool LineContainsContinuedForLoopSection; 227 228 /// \brief Comparison operator to be able to used \c IndentState in \c map. 229 bool operator<(const IndentState &Other) const { 230 if (Other.NextToken != NextToken) 231 return Other.NextToken > NextToken; 232 if (Other.Column != Column) 233 return Other.Column > Column; 234 if (Other.StartOfLineLevel != StartOfLineLevel) 235 return Other.StartOfLineLevel > StartOfLineLevel; 236 if (Other.Indent.size() != Indent.size()) 237 return Other.Indent.size() > Indent.size(); 238 for (int i = 0, e = Indent.size(); i != e; ++i) { 239 if (Other.Indent[i] != Indent[i]) 240 return Other.Indent[i] > Indent[i]; 241 } 242 if (Other.LastSpace.size() != LastSpace.size()) 243 return Other.LastSpace.size() > LastSpace.size(); 244 for (int i = 0, e = LastSpace.size(); i != e; ++i) { 245 if (Other.LastSpace[i] != LastSpace[i]) 246 return Other.LastSpace[i] > LastSpace[i]; 247 } 248 if (Other.FirstLessLess.size() != FirstLessLess.size()) 249 return Other.FirstLessLess.size() > FirstLessLess.size(); 250 for (int i = 0, e = FirstLessLess.size(); i != e; ++i) { 251 if (Other.FirstLessLess[i] != FirstLessLess[i]) 252 return Other.FirstLessLess[i] > FirstLessLess[i]; 253 } 254 if (Other.ForLoopVariablePos != ForLoopVariablePos) 255 return Other.ForLoopVariablePos < ForLoopVariablePos; 256 if (Other.LineContainsContinuedForLoopSection != 257 LineContainsContinuedForLoopSection) 258 return LineContainsContinuedForLoopSection; 259 return false; 260 } 261 }; 262 263 /// \brief Appends the next token to \p State and updates information 264 /// necessary for indentation. 265 /// 266 /// Puts the token on the current line if \p Newline is \c true and adds a 267 /// line break and necessary indentation otherwise. 268 /// 269 /// If \p DryRun is \c false, also creates and stores the required 270 /// \c Replacement. 271 void addTokenToState(bool Newline, bool DryRun, IndentState &State) { 272 const FormatToken &Current = State.NextToken->FormatTok; 273 const FormatToken &Previous = State.NextToken->Parent->FormatTok; 274 unsigned ParenLevel = State.Indent.size() - 1; 275 276 if (Newline) { 277 unsigned WhitespaceStartColumn = State.Column; 278 if (Previous.Tok.is(tok::l_brace)) { 279 // FIXME: This does not work with nested static initializers. 280 // Implement a better handling for static initializers and similar 281 // constructs. 282 State.Column = Line.Level * 2 + 2; 283 } else if (Current.Tok.is(tok::string_literal) && 284 Previous.Tok.is(tok::string_literal)) { 285 State.Column = State.Column - Previous.TokenLength; 286 } else if (Current.Tok.is(tok::lessless) && 287 State.FirstLessLess[ParenLevel] != 0) { 288 State.Column = State.FirstLessLess[ParenLevel]; 289 } else if (ParenLevel != 0 && 290 (Previous.Tok.is(tok::equal) || Current.Tok.is(tok::arrow) || 291 Current.Tok.is(tok::period))) { 292 // Indent and extra 4 spaces after '=' as it continues an expression. 293 // Don't do that on the top level, as we already indent 4 there. 294 State.Column = State.Indent[ParenLevel] + 4; 295 } else if (RootToken.is(tok::kw_for) && Previous.Tok.is(tok::comma)) { 296 State.Column = State.ForLoopVariablePos; 297 } else if (State.NextToken->Parent->ClosesTemplateDeclaration) { 298 State.Column = State.Indent[ParenLevel] - 4; 299 } else { 300 State.Column = State.Indent[ParenLevel]; 301 } 302 303 State.StartOfLineLevel = ParenLevel + 1; 304 305 if (RootToken.is(tok::kw_for)) 306 State.LineContainsContinuedForLoopSection = 307 Previous.Tok.isNot(tok::semi); 308 309 if (!DryRun) { 310 if (!Line.InPPDirective) 311 replaceWhitespace(Current, 1, State.Column); 312 else 313 replacePPWhitespace(Current, 1, State.Column, WhitespaceStartColumn); 314 } 315 316 State.LastSpace[ParenLevel] = State.Indent[ParenLevel]; 317 if (Current.Tok.is(tok::colon) && CurrentLineType != LT_ObjCMethodDecl && 318 State.NextToken->Type != TT_ConditionalExpr) 319 State.Indent[ParenLevel] += 2; 320 } else { 321 if (Current.Tok.is(tok::equal) && RootToken.is(tok::kw_for)) 322 State.ForLoopVariablePos = State.Column - Previous.TokenLength; 323 324 unsigned Spaces = State.NextToken->SpaceRequiredBefore ? 1 : 0; 325 if (State.NextToken->Type == TT_LineComment) 326 Spaces = Style.SpacesBeforeTrailingComments; 327 328 if (!DryRun) 329 replaceWhitespace(Current, 0, Spaces); 330 331 if (RootToken.isNot(tok::kw_for) && 332 (getPrecedence(Previous) == prec::Assignment || 333 Previous.Tok.is(tok::kw_return))) 334 State.Indent[ParenLevel] = State.Column + Spaces; 335 if (Previous.Tok.is(tok::l_paren) || 336 State.NextToken->Parent->Type == TT_TemplateOpener) 337 State.Indent[ParenLevel] = State.Column; 338 339 // Top-level spaces that are not part of assignments are exempt as that 340 // mostly leads to better results. 341 State.Column += Spaces; 342 if (Spaces > 0 && 343 (ParenLevel != 0 || getPrecedence(Previous) == prec::Assignment)) 344 State.LastSpace[ParenLevel] = State.Column; 345 } 346 moveStateToNextToken(State); 347 } 348 349 /// \brief Mark the next token as consumed in \p State and modify its stacks 350 /// accordingly. 351 void moveStateToNextToken(IndentState &State) { 352 const AnnotatedToken &Current = *State.NextToken; 353 unsigned ParenLevel = State.Indent.size() - 1; 354 355 if (Current.is(tok::lessless) && State.FirstLessLess[ParenLevel] == 0) 356 State.FirstLessLess[ParenLevel] = State.Column; 357 358 State.Column += Current.FormatTok.TokenLength; 359 360 // If we encounter an opening (, [, { or <, we add a level to our stacks to 361 // prepare for the following tokens. 362 if (Current.is(tok::l_paren) || Current.is(tok::l_square) || 363 Current.is(tok::l_brace) || 364 State.NextToken->Type == TT_TemplateOpener) { 365 State.Indent.push_back(4 + State.LastSpace.back()); 366 State.LastSpace.push_back(State.LastSpace.back()); 367 State.FirstLessLess.push_back(0); 368 } 369 370 // If we encounter a closing ), ], } or >, we can remove a level from our 371 // stacks. 372 if (Current.is(tok::r_paren) || Current.is(tok::r_square) || 373 (Current.is(tok::r_brace) && State.NextToken != &RootToken) || 374 State.NextToken->Type == TT_TemplateCloser) { 375 State.Indent.pop_back(); 376 State.LastSpace.pop_back(); 377 State.FirstLessLess.pop_back(); 378 } 379 if (State.NextToken->Children.empty()) 380 State.NextToken = NULL; 381 else 382 State.NextToken = &State.NextToken->Children[0]; 383 } 384 385 /// \brief Calculate the penalty for splitting after the token at \p Index. 386 unsigned splitPenalty(const AnnotatedToken &Tok) { 387 const AnnotatedToken &Left = Tok; 388 const AnnotatedToken &Right = Tok.Children[0]; 389 390 // In for-loops, prefer breaking at ',' and ';'. 391 if (RootToken.is(tok::kw_for) && 392 (Left.isNot(tok::comma) && Left.isNot(tok::semi))) 393 return 20; 394 395 if (Left.is(tok::semi) || Left.is(tok::comma) || 396 Left.ClosesTemplateDeclaration) 397 return 0; 398 if (Left.is(tok::l_paren)) 399 return 20; 400 401 prec::Level Level = getPrecedence(Left); 402 403 // Breaking after an assignment leads to a bad result as the two sides of 404 // the assignment are visually very close together. 405 if (Level == prec::Assignment) 406 return 50; 407 408 if (Level != prec::Unknown) 409 return Level; 410 411 if (Right.is(tok::arrow) || Right.is(tok::period)) 412 return 150; 413 414 return 3; 415 } 416 417 /// \brief Calculate the number of lines needed to format the remaining part 418 /// of the unwrapped line. 419 /// 420 /// Assumes the formatting so far has led to 421 /// the \c IndentState \p State. If \p NewLine is set, a new line will be 422 /// added after the previous token. 423 /// 424 /// \param StopAt is used for optimization. If we can determine that we'll 425 /// definitely need at least \p StopAt additional lines, we already know of a 426 /// better solution. 427 unsigned calcPenalty(IndentState State, bool NewLine, unsigned StopAt) { 428 // We are at the end of the unwrapped line, so we don't need any more lines. 429 if (State.NextToken == NULL) 430 return 0; 431 432 if (!NewLine && State.NextToken->MustBreakBefore) 433 return UINT_MAX; 434 if (NewLine && !State.NextToken->CanBreakBefore) 435 return UINT_MAX; 436 if (!NewLine && State.NextToken->Parent->is(tok::semi) && 437 State.LineContainsContinuedForLoopSection) 438 return UINT_MAX; 439 440 unsigned CurrentPenalty = 0; 441 if (NewLine) { 442 CurrentPenalty += Parameters.PenaltyIndentLevel * State.Indent.size() + 443 splitPenalty(*State.NextToken->Parent); 444 } else { 445 if (State.Indent.size() < State.StartOfLineLevel) 446 CurrentPenalty += Parameters.PenaltyLevelDecrease * 447 (State.StartOfLineLevel - State.Indent.size()); 448 } 449 450 addTokenToState(NewLine, true, State); 451 452 // Exceeding column limit is bad. 453 if (State.Column > Style.ColumnLimit - (Line.InPPDirective ? 1 : 0)) 454 return UINT_MAX; 455 456 if (StopAt <= CurrentPenalty) 457 return UINT_MAX; 458 StopAt -= CurrentPenalty; 459 460 StateMap::iterator I = Memory.find(State); 461 if (I != Memory.end()) { 462 // If this state has already been examined, we can safely return the 463 // previous result if we 464 // - have not hit the optimatization (and thus returned UINT_MAX) OR 465 // - are now computing for a smaller or equal StopAt. 466 unsigned SavedResult = I->second.first; 467 unsigned SavedStopAt = I->second.second; 468 if (SavedResult != UINT_MAX) 469 return SavedResult + CurrentPenalty; 470 else if (StopAt <= SavedStopAt) 471 return UINT_MAX; 472 } 473 474 unsigned NoBreak = calcPenalty(State, false, StopAt); 475 unsigned WithBreak = calcPenalty(State, true, std::min(StopAt, NoBreak)); 476 unsigned Result = std::min(NoBreak, WithBreak); 477 478 // We have to store 'Result' without adding 'CurrentPenalty' as the latter 479 // can depend on 'NewLine'. 480 Memory[State] = std::pair<unsigned, unsigned>(Result, StopAt); 481 482 return Result == UINT_MAX ? UINT_MAX : Result + CurrentPenalty; 483 } 484 485 /// \brief Replaces the whitespace in front of \p Tok. Only call once for 486 /// each \c FormatToken. 487 void replaceWhitespace(const FormatToken &Tok, unsigned NewLines, 488 unsigned Spaces) { 489 Replaces.insert(tooling::Replacement( 490 SourceMgr, Tok.WhiteSpaceStart, Tok.WhiteSpaceLength, 491 std::string(NewLines, '\n') + std::string(Spaces, ' '))); 492 } 493 494 /// \brief Like \c replaceWhitespace, but additionally adds right-aligned 495 /// backslashes to escape newlines inside a preprocessor directive. 496 /// 497 /// This function and \c replaceWhitespace have the same behavior if 498 /// \c Newlines == 0. 499 void replacePPWhitespace(const FormatToken &Tok, unsigned NewLines, 500 unsigned Spaces, unsigned WhitespaceStartColumn) { 501 std::string NewLineText; 502 if (NewLines > 0) { 503 unsigned Offset = std::min<int>(Style.ColumnLimit - 1, 504 WhitespaceStartColumn); 505 for (unsigned i = 0; i < NewLines; ++i) { 506 NewLineText += std::string(Style.ColumnLimit - Offset - 1, ' '); 507 NewLineText += "\\\n"; 508 Offset = 0; 509 } 510 } 511 Replaces.insert(tooling::Replacement(SourceMgr, Tok.WhiteSpaceStart, 512 Tok.WhiteSpaceLength, NewLineText + 513 std::string(Spaces, ' '))); 514 } 515 516 /// \brief Add a new line and the required indent before the first Token 517 /// of the \c UnwrappedLine if there was no structural parsing error. 518 /// Returns the indent level of the \c UnwrappedLine. 519 unsigned formatFirstToken() { 520 const FormatToken &Tok = RootToken.FormatTok; 521 if (!Tok.WhiteSpaceStart.isValid() || StructuralError) 522 return SourceMgr.getSpellingColumnNumber(Tok.Tok.getLocation()) - 1; 523 524 unsigned Newlines = std::min(Tok.NewlinesBefore, 525 Style.MaxEmptyLinesToKeep + 1); 526 if (Newlines == 0 && !Tok.IsFirst) 527 Newlines = 1; 528 unsigned Indent = Line.Level * 2; 529 530 bool IsAccessModifier = false; 531 if (RootToken.is(tok::kw_public) || RootToken.is(tok::kw_protected) || 532 RootToken.is(tok::kw_private)) 533 IsAccessModifier = true; 534 else if (RootToken.is(tok::at) && !RootToken.Children.empty() && 535 (RootToken.Children[0].isObjCAtKeyword(tok::objc_public) || 536 RootToken.Children[0].isObjCAtKeyword(tok::objc_protected) || 537 RootToken.Children[0].isObjCAtKeyword(tok::objc_package) || 538 RootToken.Children[0].isObjCAtKeyword(tok::objc_private))) 539 IsAccessModifier = true; 540 541 if (IsAccessModifier && 542 static_cast<int>(Indent) + Style.AccessModifierOffset >= 0) 543 Indent += Style.AccessModifierOffset; 544 if (!Line.InPPDirective || Tok.HasUnescapedNewline) 545 replaceWhitespace(Tok, Newlines, Indent); 546 else 547 replacePPWhitespace(Tok, Newlines, Indent, PreviousEndOfLineColumn); 548 return Indent; 549 } 550 551 FormatStyle Style; 552 SourceManager &SourceMgr; 553 const UnwrappedLine &Line; 554 const unsigned PreviousEndOfLineColumn; 555 const LineType CurrentLineType; 556 const AnnotatedToken &RootToken; 557 tooling::Replacements &Replaces; 558 bool StructuralError; 559 560 // A map from an indent state to a pair (Result, Used-StopAt). 561 typedef std::map<IndentState, std::pair<unsigned, unsigned> > StateMap; 562 StateMap Memory; 563 564 OptimizationParameters Parameters; 565 }; 566 567 /// \brief Determines extra information about the tokens comprising an 568 /// \c UnwrappedLine. 569 class TokenAnnotator { 570 public: 571 TokenAnnotator(const UnwrappedLine &Line, const FormatStyle &Style, 572 SourceManager &SourceMgr, Lexer &Lex) 573 : Style(Style), SourceMgr(SourceMgr), Lex(Lex), 574 RootToken(Line.RootToken) { 575 } 576 577 /// \brief A parser that gathers additional information about tokens. 578 /// 579 /// The \c TokenAnnotator tries to matches parenthesis and square brakets and 580 /// store a parenthesis levels. It also tries to resolve matching "<" and ">" 581 /// into template parameter lists. 582 class AnnotatingParser { 583 public: 584 AnnotatingParser(AnnotatedToken &RootToken) 585 : CurrentToken(&RootToken), KeywordVirtualFound(false) { 586 } 587 588 bool parseAngle() { 589 while (CurrentToken != NULL) { 590 if (CurrentToken->is(tok::greater)) { 591 CurrentToken->Type = TT_TemplateCloser; 592 next(); 593 return true; 594 } 595 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_square) || 596 CurrentToken->is(tok::r_brace)) 597 return false; 598 if (CurrentToken->is(tok::pipepipe) || CurrentToken->is(tok::ampamp) || 599 CurrentToken->is(tok::question) || CurrentToken->is(tok::colon)) 600 return false; 601 if (!consumeToken()) 602 return false; 603 } 604 return false; 605 } 606 607 bool parseParens() { 608 while (CurrentToken != NULL) { 609 if (CurrentToken->is(tok::r_paren)) { 610 next(); 611 return true; 612 } 613 if (CurrentToken->is(tok::r_square) || CurrentToken->is(tok::r_brace)) 614 return false; 615 if (!consumeToken()) 616 return false; 617 } 618 return false; 619 } 620 621 bool parseSquare() { 622 while (CurrentToken != NULL) { 623 if (CurrentToken->is(tok::r_square)) { 624 next(); 625 return true; 626 } 627 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_brace)) 628 return false; 629 if (!consumeToken()) 630 return false; 631 } 632 return false; 633 } 634 635 bool parseConditional() { 636 while (CurrentToken != NULL) { 637 if (CurrentToken->is(tok::colon)) { 638 CurrentToken->Type = TT_ConditionalExpr; 639 next(); 640 return true; 641 } 642 if (!consumeToken()) 643 return false; 644 } 645 return false; 646 } 647 648 bool parseTemplateDeclaration() { 649 if (CurrentToken != NULL && CurrentToken->is(tok::less)) { 650 CurrentToken->Type = TT_TemplateOpener; 651 next(); 652 if (!parseAngle()) 653 return false; 654 CurrentToken->Parent->ClosesTemplateDeclaration = true; 655 parseLine(); 656 return true; 657 } 658 return false; 659 } 660 661 bool consumeToken() { 662 AnnotatedToken *Tok = CurrentToken; 663 next(); 664 switch (Tok->FormatTok.Tok.getKind()) { 665 case tok::l_paren: 666 if (!parseParens()) 667 return false; 668 if (CurrentToken != NULL && CurrentToken->is(tok::colon)) { 669 CurrentToken->Type = TT_CtorInitializerColon; 670 next(); 671 } 672 break; 673 case tok::l_square: 674 if (!parseSquare()) 675 return false; 676 break; 677 case tok::less: 678 if (parseAngle()) 679 Tok->Type = TT_TemplateOpener; 680 else { 681 Tok->Type = TT_BinaryOperator; 682 CurrentToken = Tok; 683 next(); 684 } 685 break; 686 case tok::r_paren: 687 case tok::r_square: 688 return false; 689 case tok::greater: 690 Tok->Type = TT_BinaryOperator; 691 break; 692 case tok::kw_operator: 693 if (CurrentToken->is(tok::l_paren)) { 694 CurrentToken->Type = TT_OverloadedOperator; 695 next(); 696 if (CurrentToken != NULL && CurrentToken->is(tok::r_paren)) { 697 CurrentToken->Type = TT_OverloadedOperator; 698 next(); 699 } 700 } else { 701 while (CurrentToken != NULL && CurrentToken->isNot(tok::l_paren)) { 702 CurrentToken->Type = TT_OverloadedOperator; 703 next(); 704 } 705 } 706 break; 707 case tok::question: 708 parseConditional(); 709 break; 710 case tok::kw_template: 711 parseTemplateDeclaration(); 712 break; 713 default: 714 break; 715 } 716 return true; 717 } 718 719 void parseIncludeDirective() { 720 while (CurrentToken != NULL) { 721 if (CurrentToken->is(tok::slash)) 722 CurrentToken->Type = TT_DirectorySeparator; 723 else if (CurrentToken->is(tok::less)) 724 CurrentToken->Type = TT_TemplateOpener; 725 else if (CurrentToken->is(tok::greater)) 726 CurrentToken->Type = TT_TemplateCloser; 727 next(); 728 } 729 } 730 731 void parsePreprocessorDirective() { 732 next(); 733 if (CurrentToken == NULL) 734 return; 735 // Hashes in the middle of a line can lead to any strange token 736 // sequence. 737 if (CurrentToken->FormatTok.Tok.getIdentifierInfo() == NULL) 738 return; 739 switch ( 740 CurrentToken->FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) { 741 case tok::pp_include: 742 case tok::pp_import: 743 parseIncludeDirective(); 744 break; 745 default: 746 break; 747 } 748 } 749 750 LineType parseLine() { 751 if (CurrentToken->is(tok::hash)) { 752 parsePreprocessorDirective(); 753 return LT_PreprocessorDirective; 754 } 755 while (CurrentToken != NULL) { 756 if (CurrentToken->is(tok::kw_virtual)) 757 KeywordVirtualFound = true; 758 if (!consumeToken()) 759 return LT_Invalid; 760 } 761 if (KeywordVirtualFound) 762 return LT_VirtualFunctionDecl; 763 return LT_Other; 764 } 765 766 void next() { 767 if (CurrentToken != NULL && !CurrentToken->Children.empty()) 768 CurrentToken = &CurrentToken->Children[0]; 769 else 770 CurrentToken = NULL; 771 } 772 773 private: 774 AnnotatedToken *CurrentToken; 775 bool KeywordVirtualFound; 776 }; 777 778 void createAnnotatedTokens(AnnotatedToken &Current) { 779 if (!Current.FormatTok.Children.empty()) { 780 Current.Children.push_back(AnnotatedToken(Current.FormatTok.Children[0])); 781 Current.Children.back().Parent = &Current; 782 createAnnotatedTokens(Current.Children.back()); 783 } 784 } 785 786 void calculateExtraInformation(AnnotatedToken &Current) { 787 Current.SpaceRequiredBefore = spaceRequiredBefore(Current); 788 789 if (Current.Type == TT_CtorInitializerColon || Current.Parent->Type == 790 TT_LineComment || (Current.is(tok::string_literal) && 791 Current.Parent->is(tok::string_literal))) { 792 Current.MustBreakBefore = true; 793 } else if (Current.is(tok::at) && Current.Parent->Parent->is(tok::at)) { 794 // Don't put two objc's '@' on the same line. This could happen, 795 // as in, @optional @property ... 796 Current.MustBreakBefore = true; 797 } else { 798 Current.MustBreakBefore = false; 799 } 800 801 Current.CanBreakBefore = Current.MustBreakBefore || canBreakBefore(Current); 802 803 if (!Current.Children.empty()) 804 calculateExtraInformation(Current.Children[0]); 805 } 806 807 bool annotate() { 808 createAnnotatedTokens(RootToken); 809 810 AnnotatingParser Parser(RootToken); 811 CurrentLineType = Parser.parseLine(); 812 if (CurrentLineType == LT_Invalid) 813 return false; 814 815 determineTokenTypes(RootToken, /*IsRHS=*/false); 816 817 if (RootToken.Type == TT_ObjCMethodSpecifier) 818 CurrentLineType = LT_ObjCMethodDecl; 819 820 if (!RootToken.Children.empty()) 821 calculateExtraInformation(RootToken.Children[0]); 822 return true; 823 } 824 825 LineType getLineType() { 826 return CurrentLineType; 827 } 828 829 const AnnotatedToken &getRootToken() { 830 return RootToken; 831 } 832 833 private: 834 void determineTokenTypes(AnnotatedToken &Current, bool IsRHS) { 835 if (getPrecedence(Current) == prec::Assignment || 836 Current.is(tok::kw_return) || Current.is(tok::kw_throw)) 837 IsRHS = true; 838 839 if (Current.Type == TT_Unknown) { 840 if (Current.is(tok::star) || Current.is(tok::amp)) { 841 Current.Type = determineStarAmpUsage(Current, IsRHS); 842 } else if (Current.is(tok::minus) || Current.is(tok::plus)) { 843 Current.Type = determinePlusMinusUsage(Current); 844 } else if (Current.is(tok::minusminus) || Current.is(tok::plusplus)) { 845 Current.Type = determineIncrementUsage(Current); 846 } else if (Current.is(tok::exclaim)) { 847 Current.Type = TT_UnaryOperator; 848 } else if (isBinaryOperator(Current)) { 849 Current.Type = TT_BinaryOperator; 850 } else if (Current.is(tok::comment)) { 851 std::string Data(Lexer::getSpelling(Current.FormatTok.Tok, SourceMgr, 852 Lex.getLangOpts())); 853 if (StringRef(Data).startswith("//")) 854 Current.Type = TT_LineComment; 855 else 856 Current.Type = TT_BlockComment; 857 } 858 } 859 860 if (!Current.Children.empty()) 861 determineTokenTypes(Current.Children[0], IsRHS); 862 } 863 864 bool isBinaryOperator(const AnnotatedToken &Tok) { 865 // Comma is a binary operator, but does not behave as such wrt. formatting. 866 return getPrecedence(Tok) > prec::Comma; 867 } 868 869 TokenType determineStarAmpUsage(const AnnotatedToken &Tok, bool IsRHS) { 870 if (Tok.Parent == NULL) 871 return TT_UnaryOperator; 872 if (Tok.Children.size() == 0) 873 return TT_Unknown; 874 const FormatToken &PrevToken = Tok.Parent->FormatTok; 875 const FormatToken &NextToken = Tok.Children[0].FormatTok; 876 877 if (PrevToken.Tok.is(tok::l_paren) || PrevToken.Tok.is(tok::l_square) || 878 PrevToken.Tok.is(tok::comma) || PrevToken.Tok.is(tok::kw_return) || 879 PrevToken.Tok.is(tok::colon) || Tok.Parent->Type == TT_BinaryOperator) 880 return TT_UnaryOperator; 881 882 if (PrevToken.Tok.isLiteral() || NextToken.Tok.isLiteral() || 883 NextToken.Tok.is(tok::plus) || NextToken.Tok.is(tok::minus) || 884 NextToken.Tok.is(tok::plusplus) || NextToken.Tok.is(tok::minusminus) || 885 NextToken.Tok.is(tok::tilde) || NextToken.Tok.is(tok::exclaim) || 886 NextToken.Tok.is(tok::kw_alignof) || NextToken.Tok.is(tok::kw_sizeof)) 887 return TT_BinaryOperator; 888 889 if (NextToken.Tok.is(tok::comma) || NextToken.Tok.is(tok::r_paren) || 890 NextToken.Tok.is(tok::greater)) 891 return TT_PointerOrReference; 892 893 // It is very unlikely that we are going to find a pointer or reference type 894 // definition on the RHS of an assignment. 895 if (IsRHS) 896 return TT_BinaryOperator; 897 898 return TT_PointerOrReference; 899 } 900 901 TokenType determinePlusMinusUsage(const AnnotatedToken &Tok) { 902 // At the start of the line, +/- specific ObjectiveC method declarations. 903 if (Tok.Parent == NULL) 904 return TT_ObjCMethodSpecifier; 905 906 // Use heuristics to recognize unary operators. 907 if (Tok.Parent->is(tok::equal) || Tok.Parent->is(tok::l_paren) || 908 Tok.Parent->is(tok::comma) || Tok.Parent->is(tok::l_square) || 909 Tok.Parent->is(tok::question) || Tok.Parent->is(tok::colon) || 910 Tok.Parent->is(tok::kw_return) || Tok.Parent->is(tok::kw_case)) 911 return TT_UnaryOperator; 912 913 // There can't be to consecutive binary operators. 914 if (Tok.Parent->Type == TT_BinaryOperator) 915 return TT_UnaryOperator; 916 917 // Fall back to marking the token as binary operator. 918 return TT_BinaryOperator; 919 } 920 921 /// \brief Determine whether ++/-- are pre- or post-increments/-decrements. 922 TokenType determineIncrementUsage(const AnnotatedToken &Tok) { 923 if (Tok.Parent != NULL && Tok.Parent->is(tok::identifier)) 924 return TT_TrailingUnaryOperator; 925 926 return TT_UnaryOperator; 927 } 928 929 bool spaceRequiredBetween(const AnnotatedToken &Left, 930 const AnnotatedToken &Right) { 931 if (Right.is(tok::hashhash)) 932 return Left.is(tok::hash); 933 if (Left.is(tok::hashhash) || Left.is(tok::hash)) 934 return Right.is(tok::hash); 935 if (Right.is(tok::r_paren) || Right.is(tok::semi) || Right.is(tok::comma)) 936 return false; 937 if (Left.is(tok::kw_template) && Right.is(tok::less)) 938 return true; 939 if (Left.is(tok::arrow) || Right.is(tok::arrow)) 940 return false; 941 if (Left.is(tok::exclaim) || Left.is(tok::tilde)) 942 return false; 943 if (Left.is(tok::at) && Right.is(tok::identifier)) 944 return false; 945 if (Left.is(tok::less) || Right.is(tok::greater) || Right.is(tok::less)) 946 return false; 947 if (Right.is(tok::amp) || Right.is(tok::star)) 948 return Left.FormatTok.Tok.isLiteral() || 949 (Left.isNot(tok::star) && Left.isNot(tok::amp) && 950 !Style.PointerAndReferenceBindToType); 951 if (Left.is(tok::amp) || Left.is(tok::star)) 952 return Right.FormatTok.Tok.isLiteral() || 953 Style.PointerAndReferenceBindToType; 954 if (Right.is(tok::star) && Left.is(tok::l_paren)) 955 return false; 956 if (Left.is(tok::l_square) || Right.is(tok::l_square) || 957 Right.is(tok::r_square)) 958 return false; 959 if (Left.is(tok::coloncolon) || 960 (Right.is(tok::coloncolon) && 961 (Left.is(tok::identifier) || Left.is(tok::greater)))) 962 return false; 963 if (Left.is(tok::period) || Right.is(tok::period)) 964 return false; 965 if (Left.is(tok::colon) || Right.is(tok::colon)) 966 return true; 967 if (Left.is(tok::l_paren)) 968 return false; 969 if (Right.is(tok::l_paren)) { 970 return Left.is(tok::kw_if) || Left.is(tok::kw_for) || 971 Left.is(tok::kw_while) || Left.is(tok::kw_switch) || 972 (Left.isNot(tok::identifier) && Left.isNot(tok::kw_sizeof) && 973 Left.isNot(tok::kw_typeof) && Left.isNot(tok::kw_alignof)); 974 } 975 if (Left.is(tok::at) && 976 Right.FormatTok.Tok.getObjCKeywordID() != tok::objc_not_keyword) 977 return false; 978 return true; 979 } 980 981 bool spaceRequiredBefore(const AnnotatedToken &Tok) { 982 if (CurrentLineType == LT_ObjCMethodDecl) { 983 if (Tok.is(tok::identifier) && !Tok.Children.empty() && 984 Tok.Children[0].is(tok::colon) && Tok.Parent->is(tok::identifier)) 985 return true; 986 if (Tok.is(tok::colon)) 987 return false; 988 if (Tok.Parent->Type == TT_ObjCMethodSpecifier) 989 return true; 990 if (Tok.Parent->is(tok::r_paren) && Tok.is(tok::identifier)) 991 // Don't space between ')' and <id> 992 return false; 993 if (Tok.Parent->is(tok::colon) && Tok.is(tok::l_paren)) 994 // Don't space between ':' and '(' 995 return false; 996 } 997 998 if (Tok.Type == TT_CtorInitializerColon) 999 return true; 1000 if (Tok.Type == TT_OverloadedOperator) 1001 return Tok.is(tok::identifier) || Tok.is(tok::kw_new) || 1002 Tok.is(tok::kw_delete); 1003 if (Tok.Parent->Type == TT_OverloadedOperator) 1004 return false; 1005 if (Tok.is(tok::colon)) 1006 return RootToken.isNot(tok::kw_case) && (!Tok.Children.empty()); 1007 if (Tok.Parent->Type == TT_UnaryOperator) 1008 return false; 1009 if (Tok.Type == TT_UnaryOperator) 1010 return Tok.Parent->isNot(tok::l_paren) && 1011 Tok.Parent->isNot(tok::l_square); 1012 if (Tok.Parent->is(tok::greater) && Tok.is(tok::greater)) { 1013 return Tok.Type == TT_TemplateCloser && Tok.Parent->Type == 1014 TT_TemplateCloser && Style.SplitTemplateClosingGreater; 1015 } 1016 if (Tok.Type == TT_DirectorySeparator || 1017 Tok.Parent->Type == TT_DirectorySeparator) 1018 return false; 1019 if (Tok.Type == TT_BinaryOperator || Tok.Parent->Type == TT_BinaryOperator) 1020 return true; 1021 if (Tok.Parent->Type == TT_TemplateCloser && Tok.is(tok::l_paren)) 1022 return false; 1023 if (Tok.is(tok::less) && RootToken.is(tok::hash)) 1024 return true; 1025 if (Tok.Type == TT_TrailingUnaryOperator) 1026 return false; 1027 return spaceRequiredBetween(*Tok.Parent, Tok); 1028 } 1029 1030 bool canBreakBefore(const AnnotatedToken &Right) { 1031 const AnnotatedToken &Left = *Right.Parent; 1032 if (CurrentLineType == LT_ObjCMethodDecl) { 1033 if (Right.is(tok::identifier) && !Right.Children.empty() && 1034 Right.Children[0].is(tok::colon) && Left.is(tok::identifier)) 1035 return true; 1036 if (CurrentLineType == LT_ObjCMethodDecl && Right.is(tok::identifier) && 1037 Left.is(tok::l_paren) && Left.Parent->is(tok::colon)) 1038 // Don't break this identifier as ':' or identifier 1039 // before it will break. 1040 return false; 1041 if (Right.is(tok::colon) && Left.is(tok::identifier) && 1042 Left.CanBreakBefore) 1043 // Don't break at ':' if identifier before it can beak. 1044 return false; 1045 } 1046 if (Left.ClosesTemplateDeclaration) 1047 return true; 1048 if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser || 1049 Right.Type == TT_ConditionalExpr) { 1050 return false; 1051 } 1052 if (Left.is(tok::equal) && CurrentLineType == LT_VirtualFunctionDecl) 1053 return false; 1054 1055 if (Right.is(tok::r_paren) || Right.is(tok::l_brace) || 1056 Right.is(tok::comment) || Right.is(tok::greater)) 1057 return false; 1058 return (isBinaryOperator(Left) && Left.isNot(tok::lessless)) || 1059 Left.is(tok::comma) || Right.is(tok::lessless) || 1060 Right.is(tok::arrow) || Right.is(tok::period) || 1061 Right.is(tok::colon) || Left.is(tok::semi) || 1062 Left.is(tok::l_brace) || 1063 (Left.is(tok::l_paren) && !Right.is(tok::r_paren)); 1064 } 1065 1066 FormatStyle Style; 1067 SourceManager &SourceMgr; 1068 Lexer &Lex; 1069 LineType CurrentLineType; 1070 AnnotatedToken RootToken; 1071 }; 1072 1073 class LexerBasedFormatTokenSource : public FormatTokenSource { 1074 public: 1075 LexerBasedFormatTokenSource(Lexer &Lex, SourceManager &SourceMgr) 1076 : GreaterStashed(false), Lex(Lex), SourceMgr(SourceMgr), 1077 IdentTable(Lex.getLangOpts()) { 1078 Lex.SetKeepWhitespaceMode(true); 1079 } 1080 1081 virtual FormatToken getNextToken() { 1082 if (GreaterStashed) { 1083 FormatTok.NewlinesBefore = 0; 1084 FormatTok.WhiteSpaceStart = 1085 FormatTok.Tok.getLocation().getLocWithOffset(1); 1086 FormatTok.WhiteSpaceLength = 0; 1087 GreaterStashed = false; 1088 return FormatTok; 1089 } 1090 1091 FormatTok = FormatToken(); 1092 Lex.LexFromRawLexer(FormatTok.Tok); 1093 StringRef Text = rawTokenText(FormatTok.Tok); 1094 FormatTok.WhiteSpaceStart = FormatTok.Tok.getLocation(); 1095 if (SourceMgr.getFileOffset(FormatTok.WhiteSpaceStart) == 0) 1096 FormatTok.IsFirst = true; 1097 1098 // Consume and record whitespace until we find a significant token. 1099 while (FormatTok.Tok.is(tok::unknown)) { 1100 FormatTok.NewlinesBefore += Text.count('\n'); 1101 FormatTok.HasUnescapedNewline = Text.count("\\\n") != 1102 FormatTok.NewlinesBefore; 1103 FormatTok.WhiteSpaceLength += FormatTok.Tok.getLength(); 1104 1105 if (FormatTok.Tok.is(tok::eof)) 1106 return FormatTok; 1107 Lex.LexFromRawLexer(FormatTok.Tok); 1108 Text = rawTokenText(FormatTok.Tok); 1109 } 1110 1111 // Now FormatTok is the next non-whitespace token. 1112 FormatTok.TokenLength = Text.size(); 1113 1114 // In case the token starts with escaped newlines, we want to 1115 // take them into account as whitespace - this pattern is quite frequent 1116 // in macro definitions. 1117 // FIXME: What do we want to do with other escaped spaces, and escaped 1118 // spaces or newlines in the middle of tokens? 1119 // FIXME: Add a more explicit test. 1120 unsigned i = 0; 1121 while (i + 1 < Text.size() && Text[i] == '\\' && Text[i + 1] == '\n') { 1122 FormatTok.WhiteSpaceLength += 2; 1123 FormatTok.TokenLength -= 2; 1124 i += 2; 1125 } 1126 1127 if (FormatTok.Tok.is(tok::raw_identifier)) { 1128 IdentifierInfo &Info = IdentTable.get(Text); 1129 FormatTok.Tok.setIdentifierInfo(&Info); 1130 FormatTok.Tok.setKind(Info.getTokenID()); 1131 } 1132 1133 if (FormatTok.Tok.is(tok::greatergreater)) { 1134 FormatTok.Tok.setKind(tok::greater); 1135 GreaterStashed = true; 1136 } 1137 1138 return FormatTok; 1139 } 1140 1141 private: 1142 FormatToken FormatTok; 1143 bool GreaterStashed; 1144 Lexer &Lex; 1145 SourceManager &SourceMgr; 1146 IdentifierTable IdentTable; 1147 1148 /// Returns the text of \c FormatTok. 1149 StringRef rawTokenText(Token &Tok) { 1150 return StringRef(SourceMgr.getCharacterData(Tok.getLocation()), 1151 Tok.getLength()); 1152 } 1153 }; 1154 1155 class Formatter : public UnwrappedLineConsumer { 1156 public: 1157 Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr, 1158 const std::vector<CharSourceRange> &Ranges) 1159 : Style(Style), Lex(Lex), SourceMgr(SourceMgr), Ranges(Ranges), 1160 StructuralError(false) { 1161 } 1162 1163 virtual ~Formatter() { 1164 } 1165 1166 tooling::Replacements format() { 1167 LexerBasedFormatTokenSource Tokens(Lex, SourceMgr); 1168 UnwrappedLineParser Parser(Style, Tokens, *this); 1169 StructuralError = Parser.parse(); 1170 unsigned PreviousEndOfLineColumn = 0; 1171 for (std::vector<UnwrappedLine>::iterator I = UnwrappedLines.begin(), 1172 E = UnwrappedLines.end(); 1173 I != E; ++I) 1174 PreviousEndOfLineColumn = formatUnwrappedLine(*I, 1175 PreviousEndOfLineColumn); 1176 return Replaces; 1177 } 1178 1179 private: 1180 virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) { 1181 UnwrappedLines.push_back(TheLine); 1182 } 1183 1184 unsigned formatUnwrappedLine(const UnwrappedLine &TheLine, 1185 unsigned PreviousEndOfLineColumn) { 1186 const FormatToken *First = &TheLine.RootToken; 1187 const FormatToken *Last = First; 1188 while (!Last->Children.empty()) 1189 Last = &Last->Children.back(); 1190 CharSourceRange LineRange = CharSourceRange::getTokenRange( 1191 First->Tok.getLocation(), 1192 Last->Tok.getLocation()); 1193 1194 for (unsigned i = 0, e = Ranges.size(); i != e; ++i) { 1195 if (SourceMgr.isBeforeInTranslationUnit(LineRange.getEnd(), 1196 Ranges[i].getBegin()) || 1197 SourceMgr.isBeforeInTranslationUnit(Ranges[i].getEnd(), 1198 LineRange.getBegin())) 1199 continue; 1200 1201 TokenAnnotator Annotator(TheLine, Style, SourceMgr, Lex); 1202 if (!Annotator.annotate()) 1203 break; 1204 UnwrappedLineFormatter Formatter( 1205 Style, SourceMgr, TheLine, PreviousEndOfLineColumn, 1206 Annotator.getLineType(), Annotator.getRootToken(), Replaces, 1207 StructuralError); 1208 return Formatter.format(); 1209 } 1210 // If we did not reformat this unwrapped line, the column at the end of the 1211 // last token is unchanged - thus, we can calculate the end of the last 1212 // token, and return the result. 1213 return SourceMgr.getSpellingColumnNumber(Last->Tok.getLocation()) + 1214 Lex.MeasureTokenLength(Last->Tok.getLocation(), SourceMgr, 1215 Lex.getLangOpts()) - 1216 1; 1217 } 1218 1219 FormatStyle Style; 1220 Lexer &Lex; 1221 SourceManager &SourceMgr; 1222 tooling::Replacements Replaces; 1223 std::vector<CharSourceRange> Ranges; 1224 std::vector<UnwrappedLine> UnwrappedLines; 1225 bool StructuralError; 1226 }; 1227 1228 tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex, 1229 SourceManager &SourceMgr, 1230 std::vector<CharSourceRange> Ranges) { 1231 Formatter formatter(Style, Lex, SourceMgr, Ranges); 1232 return formatter.format(); 1233 } 1234 1235 } // namespace format 1236 } // namespace clang 1237