1 //===--- TokenAnnotator.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 a token annotator, i.e. creates 12 /// \c AnnotatedTokens out of \c FormatTokens with required extra information. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #include "TokenAnnotator.h" 17 #include "clang/Basic/SourceManager.h" 18 #include "clang/Lex/Lexer.h" 19 #include "llvm/Support/Debug.h" 20 21 namespace clang { 22 namespace format { 23 24 bool AnnotatedToken::isUnaryOperator() const { 25 switch (FormatTok.Tok.getKind()) { 26 case tok::plus: 27 case tok::plusplus: 28 case tok::minus: 29 case tok::minusminus: 30 case tok::exclaim: 31 case tok::tilde: 32 case tok::kw_sizeof: 33 case tok::kw_alignof: 34 return true; 35 default: 36 return false; 37 } 38 } 39 40 bool AnnotatedToken::isBinaryOperator() const { 41 // Comma is a binary operator, but does not behave as such wrt. formatting. 42 return getPrecedence(*this) > prec::Comma; 43 } 44 45 bool AnnotatedToken::isTrailingComment() const { 46 return is(tok::comment) && 47 (Children.empty() || Children[0].FormatTok.NewlinesBefore > 0); 48 } 49 50 AnnotatedToken *AnnotatedToken::getPreviousNoneComment() const { 51 AnnotatedToken *Tok = Parent; 52 while (Tok != NULL && Tok->is(tok::comment)) 53 Tok = Tok->Parent; 54 return Tok; 55 } 56 57 const AnnotatedToken *AnnotatedToken::getNextNoneComment() const { 58 const AnnotatedToken *Tok = Children.empty() ? NULL : &Children[0]; 59 while (Tok != NULL && Tok->is(tok::comment)) 60 Tok = Tok->Children.empty() ? NULL : &Tok->Children[0]; 61 return Tok; 62 } 63 64 bool AnnotatedToken::closesScope() const { 65 return isOneOf(tok::r_paren, tok::r_brace, tok::r_square) || 66 Type == TT_TemplateCloser; 67 } 68 69 bool AnnotatedToken::opensScope() const { 70 return isOneOf(tok::l_paren, tok::l_brace, tok::l_square) || 71 Type == TT_TemplateOpener; 72 } 73 74 /// \brief A parser that gathers additional information about tokens. 75 /// 76 /// The \c TokenAnnotator tries to match parenthesis and square brakets and 77 /// store a parenthesis levels. It also tries to resolve matching "<" and ">" 78 /// into template parameter lists. 79 class AnnotatingParser { 80 public: 81 AnnotatingParser(SourceManager &SourceMgr, Lexer &Lex, AnnotatedLine &Line, 82 IdentifierInfo &Ident_in) 83 : SourceMgr(SourceMgr), Lex(Lex), Line(Line), CurrentToken(&Line.First), 84 KeywordVirtualFound(false), NameFound(false), Ident_in(Ident_in) { 85 Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/ false)); 86 } 87 88 private: 89 bool parseAngle() { 90 if (CurrentToken == NULL) 91 return false; 92 ScopedContextCreator ContextCreator(*this, tok::less, 10); 93 AnnotatedToken *Left = CurrentToken->Parent; 94 Contexts.back().IsExpression = false; 95 while (CurrentToken != NULL) { 96 if (CurrentToken->is(tok::greater)) { 97 Left->MatchingParen = CurrentToken; 98 CurrentToken->MatchingParen = Left; 99 CurrentToken->Type = TT_TemplateCloser; 100 next(); 101 return true; 102 } 103 if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace, 104 tok::pipepipe, tok::ampamp, tok::question, 105 tok::colon)) 106 return false; 107 updateParameterCount(Left, CurrentToken); 108 if (!consumeToken()) 109 return false; 110 } 111 return false; 112 } 113 114 bool parseParens(bool LookForDecls = false) { 115 if (CurrentToken == NULL) 116 return false; 117 ScopedContextCreator ContextCreator(*this, tok::l_paren, 1); 118 119 // FIXME: This is a bit of a hack. Do better. 120 Contexts.back().ColonIsForRangeExpr = 121 Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr; 122 123 bool StartsObjCMethodExpr = false; 124 AnnotatedToken *Left = CurrentToken->Parent; 125 if (CurrentToken->is(tok::caret)) { 126 // ^( starts a block. 127 Left->Type = TT_ObjCBlockLParen; 128 } else if (AnnotatedToken *MaybeSel = Left->Parent) { 129 // @selector( starts a selector. 130 if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Parent && 131 MaybeSel->Parent->is(tok::at)) { 132 StartsObjCMethodExpr = true; 133 } 134 } 135 136 if (StartsObjCMethodExpr) { 137 Contexts.back().ColonIsObjCMethodExpr = true; 138 Left->Type = TT_ObjCMethodExpr; 139 } 140 141 while (CurrentToken != NULL) { 142 // LookForDecls is set when "if (" has been seen. Check for 143 // 'identifier' '*' 'identifier' followed by not '=' -- this 144 // '*' has to be a binary operator but determineStarAmpUsage() will 145 // categorize it as an unary operator, so set the right type here. 146 if (LookForDecls && !CurrentToken->Children.empty()) { 147 AnnotatedToken &Prev = *CurrentToken->Parent; 148 AnnotatedToken &Next = CurrentToken->Children[0]; 149 if (Prev.Parent->is(tok::identifier) && 150 Prev.isOneOf(tok::star, tok::amp, tok::ampamp) && 151 CurrentToken->is(tok::identifier) && Next.isNot(tok::equal)) { 152 Prev.Type = TT_BinaryOperator; 153 LookForDecls = false; 154 } 155 } 156 157 if (CurrentToken->is(tok::r_paren)) { 158 Left->MatchingParen = CurrentToken; 159 CurrentToken->MatchingParen = Left; 160 161 if (StartsObjCMethodExpr) { 162 CurrentToken->Type = TT_ObjCMethodExpr; 163 if (Contexts.back().FirstObjCSelectorName != NULL) { 164 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 165 Contexts.back().LongestObjCSelectorName; 166 } 167 } 168 169 next(); 170 return true; 171 } 172 if (CurrentToken->isOneOf(tok::r_square, tok::r_brace)) 173 return false; 174 updateParameterCount(Left, CurrentToken); 175 if (!consumeToken()) 176 return false; 177 } 178 return false; 179 } 180 181 bool parseSquare() { 182 if (!CurrentToken) 183 return false; 184 185 // A '[' could be an index subscript (after an indentifier or after 186 // ')' or ']'), it could be the start of an Objective-C method 187 // expression, or it could the the start of an Objective-C array literal. 188 AnnotatedToken *Left = CurrentToken->Parent; 189 AnnotatedToken *Parent = Left->getPreviousNoneComment(); 190 bool StartsObjCMethodExpr = 191 Contexts.back().CanBeExpression && 192 (!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren, 193 tok::kw_return, tok::kw_throw) || 194 Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn || 195 Parent->Type == TT_CastRParen || 196 getBinOpPrecedence(Parent->FormatTok.Tok.getKind(), true, true) > 197 prec::Unknown); 198 ScopedContextCreator ContextCreator(*this, tok::l_square, 10); 199 Contexts.back().IsExpression = true; 200 bool StartsObjCArrayLiteral = Parent && Parent->is(tok::at); 201 202 if (StartsObjCMethodExpr) { 203 Contexts.back().ColonIsObjCMethodExpr = true; 204 Left->Type = TT_ObjCMethodExpr; 205 } else if (StartsObjCArrayLiteral) { 206 Left->Type = TT_ObjCArrayLiteral; 207 } 208 209 while (CurrentToken != NULL) { 210 if (CurrentToken->is(tok::r_square)) { 211 if (!CurrentToken->Children.empty() && 212 CurrentToken->Children[0].is(tok::l_paren)) { 213 // An ObjC method call is rarely followed by an open parenthesis. 214 // FIXME: Do we incorrectly label ":" with this? 215 StartsObjCMethodExpr = false; 216 Left->Type = TT_Unknown; 217 } 218 if (StartsObjCMethodExpr) { 219 CurrentToken->Type = TT_ObjCMethodExpr; 220 // determineStarAmpUsage() thinks that '*' '[' is allocating an 221 // array of pointers, but if '[' starts a selector then '*' is a 222 // binary operator. 223 if (Parent != NULL && Parent->Type == TT_PointerOrReference) 224 Parent->Type = TT_BinaryOperator; 225 } else if (StartsObjCArrayLiteral) { 226 CurrentToken->Type = TT_ObjCArrayLiteral; 227 } 228 Left->MatchingParen = CurrentToken; 229 CurrentToken->MatchingParen = Left; 230 if (Contexts.back().FirstObjCSelectorName != NULL) 231 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 232 Contexts.back().LongestObjCSelectorName; 233 next(); 234 return true; 235 } 236 if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace)) 237 return false; 238 updateParameterCount(Left, CurrentToken); 239 if (!consumeToken()) 240 return false; 241 } 242 return false; 243 } 244 245 bool parseBrace() { 246 // Lines are fine to end with '{'. 247 if (CurrentToken == NULL) 248 return true; 249 ScopedContextCreator ContextCreator(*this, tok::l_brace, 1); 250 AnnotatedToken *Left = CurrentToken->Parent; 251 while (CurrentToken != NULL) { 252 if (CurrentToken->is(tok::r_brace)) { 253 Left->MatchingParen = CurrentToken; 254 CurrentToken->MatchingParen = Left; 255 next(); 256 return true; 257 } 258 if (CurrentToken->isOneOf(tok::r_paren, tok::r_square)) 259 return false; 260 updateParameterCount(Left, CurrentToken); 261 if (!consumeToken()) 262 return false; 263 } 264 return true; 265 } 266 267 void updateParameterCount(AnnotatedToken *Left, AnnotatedToken *Current) { 268 if (Current->is(tok::comma)) 269 ++Left->ParameterCount; 270 else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) 271 Left->ParameterCount = 1; 272 } 273 274 bool parseConditional() { 275 while (CurrentToken != NULL) { 276 if (CurrentToken->is(tok::colon)) { 277 CurrentToken->Type = TT_ConditionalExpr; 278 next(); 279 return true; 280 } 281 if (!consumeToken()) 282 return false; 283 } 284 return false; 285 } 286 287 bool parseTemplateDeclaration() { 288 if (CurrentToken != NULL && CurrentToken->is(tok::less)) { 289 CurrentToken->Type = TT_TemplateOpener; 290 next(); 291 if (!parseAngle()) 292 return false; 293 if (CurrentToken != NULL) 294 CurrentToken->Parent->ClosesTemplateDeclaration = true; 295 return true; 296 } 297 return false; 298 } 299 300 bool consumeToken() { 301 AnnotatedToken *Tok = CurrentToken; 302 next(); 303 switch (Tok->FormatTok.Tok.getKind()) { 304 case tok::plus: 305 case tok::minus: 306 if (Tok->Parent == NULL && Line.MustBeDeclaration) 307 Tok->Type = TT_ObjCMethodSpecifier; 308 break; 309 case tok::colon: 310 if (Tok->Parent == NULL) 311 return false; 312 // Colons from ?: are handled in parseConditional(). 313 if (Tok->Parent->is(tok::r_paren) && Contexts.size() == 1) { 314 Tok->Type = TT_CtorInitializerColon; 315 } else if (Contexts.back().ColonIsObjCMethodExpr || 316 Line.First.Type == TT_ObjCMethodSpecifier) { 317 Tok->Type = TT_ObjCMethodExpr; 318 Tok->Parent->Type = TT_ObjCSelectorName; 319 if (Tok->Parent->FormatTok.TokenLength > 320 Contexts.back().LongestObjCSelectorName) 321 Contexts.back().LongestObjCSelectorName = 322 Tok->Parent->FormatTok.TokenLength; 323 if (Contexts.back().FirstObjCSelectorName == NULL) 324 Contexts.back().FirstObjCSelectorName = Tok->Parent; 325 } else if (Contexts.back().ColonIsForRangeExpr) { 326 Tok->Type = TT_RangeBasedForLoopColon; 327 } else if (Contexts.size() == 1) { 328 Tok->Type = TT_InheritanceColon; 329 } else if (Contexts.back().ContextKind == tok::l_paren) { 330 Tok->Type = TT_InlineASMColon; 331 } 332 break; 333 case tok::kw_if: 334 case tok::kw_while: 335 if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) { 336 next(); 337 if (!parseParens(/*LookForDecls=*/ true)) 338 return false; 339 } 340 break; 341 case tok::kw_for: 342 Contexts.back().ColonIsForRangeExpr = true; 343 next(); 344 if (!parseParens()) 345 return false; 346 break; 347 case tok::l_paren: 348 if (!parseParens()) 349 return false; 350 if (Line.MustBeDeclaration && NameFound && !Contexts.back().IsExpression) 351 Line.MightBeFunctionDecl = true; 352 break; 353 case tok::l_square: 354 if (!parseSquare()) 355 return false; 356 break; 357 case tok::l_brace: 358 if (!parseBrace()) 359 return false; 360 break; 361 case tok::less: 362 if (parseAngle()) 363 Tok->Type = TT_TemplateOpener; 364 else { 365 Tok->Type = TT_BinaryOperator; 366 CurrentToken = Tok; 367 next(); 368 } 369 break; 370 case tok::r_paren: 371 case tok::r_square: 372 return false; 373 case tok::r_brace: 374 // Lines can start with '}'. 375 if (Tok->Parent != NULL) 376 return false; 377 break; 378 case tok::greater: 379 Tok->Type = TT_BinaryOperator; 380 break; 381 case tok::kw_operator: 382 while (CurrentToken && CurrentToken->isNot(tok::l_paren)) { 383 if (CurrentToken->isOneOf(tok::star, tok::amp)) 384 CurrentToken->Type = TT_PointerOrReference; 385 consumeToken(); 386 } 387 if (CurrentToken) 388 CurrentToken->Type = TT_OverloadedOperatorLParen; 389 break; 390 case tok::question: 391 parseConditional(); 392 break; 393 case tok::kw_template: 394 parseTemplateDeclaration(); 395 break; 396 case tok::identifier: 397 if (Line.First.is(tok::kw_for) && 398 Tok->FormatTok.Tok.getIdentifierInfo() == &Ident_in) 399 Tok->Type = TT_ObjCForIn; 400 break; 401 case tok::comma: 402 if (Contexts.back().FirstStartOfName) 403 Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true; 404 break; 405 default: 406 break; 407 } 408 return true; 409 } 410 411 void parseIncludeDirective() { 412 next(); 413 if (CurrentToken != NULL && CurrentToken->is(tok::less)) { 414 next(); 415 while (CurrentToken != NULL) { 416 if (CurrentToken->isNot(tok::comment) || 417 !CurrentToken->Children.empty()) 418 CurrentToken->Type = TT_ImplicitStringLiteral; 419 next(); 420 } 421 } else { 422 while (CurrentToken != NULL) { 423 if (CurrentToken->is(tok::string_literal)) 424 // Mark these string literals as "implicit" literals, too, so that 425 // they are not split or line-wrapped. 426 CurrentToken->Type = TT_ImplicitStringLiteral; 427 next(); 428 } 429 } 430 } 431 432 void parseWarningOrError() { 433 next(); 434 // We still want to format the whitespace left of the first token of the 435 // warning or error. 436 next(); 437 while (CurrentToken != NULL) { 438 CurrentToken->Type = TT_ImplicitStringLiteral; 439 next(); 440 } 441 } 442 443 void parsePreprocessorDirective() { 444 next(); 445 if (CurrentToken == NULL) 446 return; 447 // Hashes in the middle of a line can lead to any strange token 448 // sequence. 449 if (CurrentToken->FormatTok.Tok.getIdentifierInfo() == NULL) 450 return; 451 switch (CurrentToken->FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) { 452 case tok::pp_include: 453 case tok::pp_import: 454 parseIncludeDirective(); 455 break; 456 case tok::pp_error: 457 case tok::pp_warning: 458 parseWarningOrError(); 459 break; 460 default: 461 break; 462 } 463 while (CurrentToken != NULL) 464 next(); 465 } 466 467 public: 468 LineType parseLine() { 469 int PeriodsAndArrows = 0; 470 AnnotatedToken *LastPeriodOrArrow = NULL; 471 bool CanBeBuilderTypeStmt = true; 472 if (CurrentToken->is(tok::hash)) { 473 parsePreprocessorDirective(); 474 return LT_PreprocessorDirective; 475 } 476 while (CurrentToken != NULL) { 477 if (CurrentToken->is(tok::kw_virtual)) 478 KeywordVirtualFound = true; 479 if (CurrentToken->isOneOf(tok::period, tok::arrow)) { 480 ++PeriodsAndArrows; 481 LastPeriodOrArrow = CurrentToken; 482 } 483 AnnotatedToken *TheToken = CurrentToken; 484 if (!consumeToken()) 485 return LT_Invalid; 486 if (getPrecedence(*TheToken) > prec::Assignment && 487 TheToken->Type == TT_BinaryOperator) 488 CanBeBuilderTypeStmt = false; 489 } 490 if (KeywordVirtualFound) 491 return LT_VirtualFunctionDecl; 492 493 // Assume a builder-type call if there are 2 or more "." and "->". 494 if (PeriodsAndArrows >= 2 && CanBeBuilderTypeStmt) { 495 LastPeriodOrArrow->LastInChainOfCalls = true; 496 return LT_BuilderTypeCall; 497 } 498 499 if (Line.First.Type == TT_ObjCMethodSpecifier) { 500 if (Contexts.back().FirstObjCSelectorName != NULL) 501 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 502 Contexts.back().LongestObjCSelectorName; 503 return LT_ObjCMethodDecl; 504 } 505 506 return LT_Other; 507 } 508 509 private: 510 void next() { 511 if (CurrentToken != NULL) { 512 determineTokenType(*CurrentToken); 513 CurrentToken->BindingStrength = Contexts.back().BindingStrength; 514 } 515 516 if (CurrentToken != NULL && !CurrentToken->Children.empty()) 517 CurrentToken = &CurrentToken->Children[0]; 518 else 519 CurrentToken = NULL; 520 521 // Reset token type in case we have already looked at it and then recovered 522 // from an error (e.g. failure to find the matching >). 523 if (CurrentToken != NULL) 524 CurrentToken->Type = TT_Unknown; 525 } 526 527 /// \brief A struct to hold information valid in a specific context, e.g. 528 /// a pair of parenthesis. 529 struct Context { 530 Context(tok::TokenKind ContextKind, unsigned BindingStrength, 531 bool IsExpression) 532 : ContextKind(ContextKind), BindingStrength(BindingStrength), 533 LongestObjCSelectorName(0), ColonIsForRangeExpr(false), 534 ColonIsObjCMethodExpr(false), FirstObjCSelectorName(NULL), 535 FirstStartOfName(NULL), IsExpression(IsExpression), 536 CanBeExpression(true) {} 537 538 tok::TokenKind ContextKind; 539 unsigned BindingStrength; 540 unsigned LongestObjCSelectorName; 541 bool ColonIsForRangeExpr; 542 bool ColonIsObjCMethodExpr; 543 AnnotatedToken *FirstObjCSelectorName; 544 AnnotatedToken *FirstStartOfName; 545 bool IsExpression; 546 bool CanBeExpression; 547 }; 548 549 /// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime 550 /// of each instance. 551 struct ScopedContextCreator { 552 AnnotatingParser &P; 553 554 ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind, 555 unsigned Increase) 556 : P(P) { 557 P.Contexts.push_back( 558 Context(ContextKind, P.Contexts.back().BindingStrength + Increase, 559 P.Contexts.back().IsExpression)); 560 } 561 562 ~ScopedContextCreator() { P.Contexts.pop_back(); } 563 }; 564 565 void determineTokenType(AnnotatedToken &Current) { 566 if (getPrecedence(Current) == prec::Assignment && 567 (!Current.Parent || Current.Parent->isNot(tok::kw_operator))) { 568 Contexts.back().IsExpression = true; 569 for (AnnotatedToken *Previous = Current.Parent; 570 Previous && Previous->isNot(tok::comma); 571 Previous = Previous->Parent) { 572 if (Previous->is(tok::r_square)) 573 Previous = Previous->MatchingParen; 574 if (Previous->Type == TT_BinaryOperator && 575 Previous->isOneOf(tok::star, tok::amp)) { 576 Previous->Type = TT_PointerOrReference; 577 } 578 } 579 } else if (Current.isOneOf(tok::kw_return, tok::kw_throw) || 580 (Current.is(tok::l_paren) && !Line.MustBeDeclaration && 581 (!Current.Parent || Current.Parent->isNot(tok::kw_for)))) { 582 Contexts.back().IsExpression = true; 583 } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) { 584 for (AnnotatedToken *Previous = Current.Parent; 585 Previous && Previous->isOneOf(tok::star, tok::amp); 586 Previous = Previous->Parent) 587 Previous->Type = TT_PointerOrReference; 588 } else if (Current.Parent && 589 Current.Parent->Type == TT_CtorInitializerColon) { 590 Contexts.back().IsExpression = true; 591 } else if (Current.is(tok::kw_new)) { 592 Contexts.back().CanBeExpression = false; 593 } 594 595 if (Current.Type == TT_Unknown) { 596 if (Current.Parent && Current.is(tok::identifier) && 597 ((Current.Parent->is(tok::identifier) && 598 Current.Parent->FormatTok.Tok.getIdentifierInfo() 599 ->getPPKeywordID() == tok::pp_not_keyword) || 600 isSimpleTypeSpecifier(*Current.Parent) || 601 Current.Parent->Type == TT_PointerOrReference || 602 Current.Parent->Type == TT_TemplateCloser)) { 603 Contexts.back().FirstStartOfName = &Current; 604 Current.Type = TT_StartOfName; 605 NameFound = true; 606 } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) { 607 Current.Type = 608 determineStarAmpUsage(Current, Contexts.back().IsExpression); 609 } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) { 610 Current.Type = determinePlusMinusCaretUsage(Current); 611 } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) { 612 Current.Type = determineIncrementUsage(Current); 613 } else if (Current.is(tok::exclaim)) { 614 Current.Type = TT_UnaryOperator; 615 } else if (Current.isBinaryOperator()) { 616 Current.Type = TT_BinaryOperator; 617 } else if (Current.is(tok::comment)) { 618 std::string Data(Lexer::getSpelling(Current.FormatTok.Tok, SourceMgr, 619 Lex.getLangOpts())); 620 if (StringRef(Data).startswith("//")) 621 Current.Type = TT_LineComment; 622 else 623 Current.Type = TT_BlockComment; 624 } else if (Current.is(tok::r_paren)) { 625 bool ParensNotExpr = !Current.Parent || 626 Current.Parent->Type == TT_PointerOrReference || 627 Current.Parent->Type == TT_TemplateCloser; 628 bool ParensCouldEndDecl = 629 !Current.Children.empty() && 630 Current.Children[0].isOneOf(tok::equal, tok::semi, tok::l_brace); 631 bool IsSizeOfOrAlignOf = 632 Current.MatchingParen && Current.MatchingParen->Parent && 633 Current.MatchingParen->Parent->isOneOf(tok::kw_sizeof, 634 tok::kw_alignof); 635 if (ParensNotExpr && !ParensCouldEndDecl && !IsSizeOfOrAlignOf && 636 Contexts.back().IsExpression) 637 // FIXME: We need to get smarter and understand more cases of casts. 638 Current.Type = TT_CastRParen; 639 } else if (Current.is(tok::at) && Current.Children.size()) { 640 switch (Current.Children[0].FormatTok.Tok.getObjCKeywordID()) { 641 case tok::objc_interface: 642 case tok::objc_implementation: 643 case tok::objc_protocol: 644 Current.Type = TT_ObjCDecl; 645 break; 646 case tok::objc_property: 647 Current.Type = TT_ObjCProperty; 648 break; 649 default: 650 break; 651 } 652 } 653 } 654 } 655 656 /// \brief Return the type of the given token assuming it is * or &. 657 TokenType 658 determineStarAmpUsage(const AnnotatedToken &Tok, bool IsExpression) { 659 const AnnotatedToken *PrevToken = Tok.getPreviousNoneComment(); 660 if (PrevToken == NULL) 661 return TT_UnaryOperator; 662 663 const AnnotatedToken *NextToken = Tok.getNextNoneComment(); 664 if (NextToken == NULL) 665 return TT_Unknown; 666 667 if (PrevToken->is(tok::l_paren) && !IsExpression) 668 return TT_PointerOrReference; 669 670 if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace, 671 tok::comma, tok::semi, tok::kw_return, tok::colon, 672 tok::equal) || 673 PrevToken->Type == TT_BinaryOperator || 674 PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen) 675 return TT_UnaryOperator; 676 677 if (NextToken->is(tok::l_square)) 678 return TT_PointerOrReference; 679 680 if (PrevToken->FormatTok.Tok.isLiteral() || 681 PrevToken->isOneOf(tok::r_paren, tok::r_square) || 682 NextToken->FormatTok.Tok.isLiteral() || NextToken->isUnaryOperator()) 683 return TT_BinaryOperator; 684 685 // It is very unlikely that we are going to find a pointer or reference type 686 // definition on the RHS of an assignment. 687 if (IsExpression) 688 return TT_BinaryOperator; 689 690 return TT_PointerOrReference; 691 } 692 693 TokenType determinePlusMinusCaretUsage(const AnnotatedToken &Tok) { 694 const AnnotatedToken *PrevToken = Tok.getPreviousNoneComment(); 695 if (PrevToken == NULL) 696 return TT_UnaryOperator; 697 698 // Use heuristics to recognize unary operators. 699 if (PrevToken->isOneOf(tok::equal, tok::l_paren, tok::comma, tok::l_square, 700 tok::question, tok::colon, tok::kw_return, 701 tok::kw_case, tok::at, tok::l_brace)) 702 return TT_UnaryOperator; 703 704 // There can't be two consecutive binary operators. 705 if (PrevToken->Type == TT_BinaryOperator) 706 return TT_UnaryOperator; 707 708 // Fall back to marking the token as binary operator. 709 return TT_BinaryOperator; 710 } 711 712 /// \brief Determine whether ++/-- are pre- or post-increments/-decrements. 713 TokenType determineIncrementUsage(const AnnotatedToken &Tok) { 714 const AnnotatedToken *PrevToken = Tok.getPreviousNoneComment(); 715 if (PrevToken == NULL) 716 return TT_UnaryOperator; 717 if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier)) 718 return TT_TrailingUnaryOperator; 719 720 return TT_UnaryOperator; 721 } 722 723 // FIXME: This is copy&pasted from Sema. Put it in a common place and remove 724 // duplication. 725 /// \brief Determine whether the token kind starts a simple-type-specifier. 726 bool isSimpleTypeSpecifier(const AnnotatedToken &Tok) const { 727 switch (Tok.FormatTok.Tok.getKind()) { 728 case tok::kw_short: 729 case tok::kw_long: 730 case tok::kw___int64: 731 case tok::kw___int128: 732 case tok::kw_signed: 733 case tok::kw_unsigned: 734 case tok::kw_void: 735 case tok::kw_char: 736 case tok::kw_int: 737 case tok::kw_half: 738 case tok::kw_float: 739 case tok::kw_double: 740 case tok::kw_wchar_t: 741 case tok::kw_bool: 742 case tok::kw___underlying_type: 743 return true; 744 case tok::annot_typename: 745 case tok::kw_char16_t: 746 case tok::kw_char32_t: 747 case tok::kw_typeof: 748 case tok::kw_decltype: 749 return Lex.getLangOpts().CPlusPlus; 750 default: 751 break; 752 } 753 return false; 754 } 755 756 SmallVector<Context, 8> Contexts; 757 758 SourceManager &SourceMgr; 759 Lexer &Lex; 760 AnnotatedLine &Line; 761 AnnotatedToken *CurrentToken; 762 bool KeywordVirtualFound; 763 bool NameFound; 764 IdentifierInfo &Ident_in; 765 }; 766 767 /// \brief Parses binary expressions by inserting fake parenthesis based on 768 /// operator precedence. 769 class ExpressionParser { 770 public: 771 ExpressionParser(AnnotatedLine &Line) : Current(&Line.First) {} 772 773 /// \brief Parse expressions with the given operatore precedence. 774 void parse(int Precedence = 0) { 775 if (Precedence > prec::PointerToMember || Current == NULL) 776 return; 777 778 // Eagerly consume trailing comments. 779 while (Current && Current->isTrailingComment()) { 780 next(); 781 } 782 783 AnnotatedToken *Start = Current; 784 bool OperatorFound = false; 785 786 while (Current) { 787 // Consume operators with higher precedence. 788 parse(Precedence + 1); 789 790 int CurrentPrecedence = 0; 791 if (Current) { 792 if (Current->Type == TT_ConditionalExpr) 793 CurrentPrecedence = 1 + (int) prec::Conditional; 794 else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon) 795 CurrentPrecedence = 1; 796 else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma)) 797 CurrentPrecedence = 1 + (int) getPrecedence(*Current); 798 } 799 800 // At the end of the line or when an operator with higher precedence is 801 // found, insert fake parenthesis and return. 802 if (Current == NULL || Current->closesScope() || 803 (CurrentPrecedence != 0 && CurrentPrecedence < Precedence)) { 804 if (OperatorFound) { 805 Start->FakeLParens.push_back(prec::Level(Precedence - 1)); 806 if (Current) 807 ++Current->Parent->FakeRParens; 808 } 809 return; 810 } 811 812 // Consume scopes: (), [], <> and {} 813 if (Current->opensScope()) { 814 while (Current && !Current->closesScope()) { 815 next(); 816 parse(); 817 } 818 next(); 819 } else { 820 // Operator found. 821 if (CurrentPrecedence == Precedence) 822 OperatorFound = true; 823 824 next(); 825 } 826 } 827 } 828 829 private: 830 void next() { 831 if (Current != NULL) 832 Current = Current->Children.empty() ? NULL : &Current->Children[0]; 833 } 834 835 AnnotatedToken *Current; 836 }; 837 838 void TokenAnnotator::annotate(AnnotatedLine &Line) { 839 AnnotatingParser Parser(SourceMgr, Lex, Line, Ident_in); 840 Line.Type = Parser.parseLine(); 841 if (Line.Type == LT_Invalid) 842 return; 843 844 ExpressionParser ExprParser(Line); 845 ExprParser.parse(); 846 847 if (Line.First.Type == TT_ObjCMethodSpecifier) 848 Line.Type = LT_ObjCMethodDecl; 849 else if (Line.First.Type == TT_ObjCDecl) 850 Line.Type = LT_ObjCDecl; 851 else if (Line.First.Type == TT_ObjCProperty) 852 Line.Type = LT_ObjCProperty; 853 854 Line.First.SpacesRequiredBefore = 1; 855 Line.First.MustBreakBefore = Line.First.FormatTok.MustBreakBefore; 856 Line.First.CanBreakBefore = Line.First.MustBreakBefore; 857 858 Line.First.TotalLength = Line.First.FormatTok.TokenLength; 859 } 860 861 void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) { 862 if (Line.First.Children.empty()) 863 return; 864 AnnotatedToken *Current = &Line.First.Children[0]; 865 while (Current != NULL) { 866 if (Current->Type == TT_LineComment) 867 Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments; 868 else 869 Current->SpacesRequiredBefore = 870 spaceRequiredBefore(Line, *Current) ? 1 : 0; 871 872 if (Current->FormatTok.MustBreakBefore) { 873 Current->MustBreakBefore = true; 874 } else if (Current->Type == TT_LineComment) { 875 Current->MustBreakBefore = Current->FormatTok.NewlinesBefore > 0; 876 } else if (Current->Parent->isTrailingComment() || 877 (Current->is(tok::string_literal) && 878 Current->Parent->is(tok::string_literal))) { 879 Current->MustBreakBefore = true; 880 } else if (Current->is(tok::lessless) && !Current->Children.empty() && 881 Current->Parent->is(tok::string_literal) && 882 Current->Children[0].is(tok::string_literal)) { 883 Current->MustBreakBefore = true; 884 } else { 885 Current->MustBreakBefore = false; 886 } 887 Current->CanBreakBefore = 888 Current->MustBreakBefore || canBreakBefore(Line, *Current); 889 if (Current->MustBreakBefore) 890 Current->TotalLength = Current->Parent->TotalLength + Style.ColumnLimit; 891 else 892 Current->TotalLength = 893 Current->Parent->TotalLength + Current->FormatTok.TokenLength + 894 Current->SpacesRequiredBefore; 895 // FIXME: Only calculate this if CanBreakBefore is true once static 896 // initializers etc. are sorted out. 897 // FIXME: Move magic numbers to a better place. 898 Current->SplitPenalty = 899 20 * Current->BindingStrength + splitPenalty(Line, *Current); 900 901 Current = Current->Children.empty() ? NULL : &Current->Children[0]; 902 } 903 904 DEBUG({ 905 printDebugInfo(Line); 906 }); 907 } 908 909 unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, 910 const AnnotatedToken &Tok) { 911 const AnnotatedToken &Left = *Tok.Parent; 912 const AnnotatedToken &Right = Tok; 913 914 if (Right.Type == TT_StartOfName) { 915 if (Line.First.is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt) 916 return 3; 917 else if (Line.MightBeFunctionDecl && Right.BindingStrength == 1) 918 // FIXME: Clean up hack of using BindingStrength to find top-level names. 919 return Style.PenaltyReturnTypeOnItsOwnLine; 920 else 921 return 200; 922 } 923 if (Left.is(tok::equal) && Right.is(tok::l_brace)) 924 return 150; 925 if (Left.is(tok::coloncolon)) 926 return 500; 927 if (Left.isOneOf(tok::kw_class, tok::kw_struct)) 928 return 5000; 929 930 if (Left.Type == TT_RangeBasedForLoopColon || 931 Left.Type == TT_InheritanceColon) 932 return 2; 933 934 if (Right.isOneOf(tok::arrow, tok::period)) { 935 if (Line.Type == LT_BuilderTypeCall) 936 return prec::PointerToMember; 937 if (Left.isOneOf(tok::r_paren, tok::r_square) && Left.MatchingParen && 938 Left.MatchingParen->ParameterCount > 0) 939 return 20; // Should be smaller than breaking at a nested comma. 940 return 150; 941 } 942 943 // In for-loops, prefer breaking at ',' and ';'. 944 if (Line.First.is(tok::kw_for) && Left.is(tok::equal)) 945 return 4; 946 947 if (Left.is(tok::semi)) 948 return 0; 949 if (Left.is(tok::comma)) 950 return 1; 951 952 // In Objective-C method expressions, prefer breaking before "param:" over 953 // breaking after it. 954 if (Right.Type == TT_ObjCSelectorName) 955 return 0; 956 if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr) 957 return 20; 958 959 if (Left.is(tok::l_paren) && Line.MightBeFunctionDecl) 960 return 100; 961 if (Left.opensScope()) 962 return Left.ParameterCount > 1 ? prec::Comma : 20; 963 964 if (Right.is(tok::lessless)) { 965 if (Left.is(tok::string_literal)) { 966 StringRef Content = StringRef(Left.FormatTok.Tok.getLiteralData(), 967 Left.FormatTok.TokenLength); 968 Content = Content.drop_back(1).drop_front(1).trim(); 969 if (Content.size() > 1 && 970 (Content.back() == ':' || Content.back() == '=')) 971 return 100; 972 } 973 return prec::Shift; 974 } 975 if (Left.Type == TT_ConditionalExpr) 976 return prec::Conditional; 977 prec::Level Level = getPrecedence(Left); 978 979 if (Level != prec::Unknown) 980 return Level; 981 982 return 3; 983 } 984 985 bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, 986 const AnnotatedToken &Left, 987 const AnnotatedToken &Right) { 988 if (Right.is(tok::hashhash)) 989 return Left.is(tok::hash); 990 if (Left.isOneOf(tok::hashhash, tok::hash)) 991 return Right.is(tok::hash); 992 if (Right.isOneOf(tok::r_paren, tok::semi, tok::comma)) 993 return false; 994 if (Right.is(tok::less) && 995 (Left.is(tok::kw_template) || 996 (Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList))) 997 return true; 998 if (Left.is(tok::arrow) || Right.is(tok::arrow)) 999 return false; 1000 if (Left.isOneOf(tok::exclaim, tok::tilde)) 1001 return false; 1002 if (Left.is(tok::at) && 1003 Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant, 1004 tok::numeric_constant, tok::l_paren, tok::l_brace, 1005 tok::kw_true, tok::kw_false)) 1006 return false; 1007 if (Left.is(tok::coloncolon)) 1008 return false; 1009 if (Right.is(tok::coloncolon)) 1010 return !Left.isOneOf(tok::identifier, tok::greater, tok::l_paren); 1011 if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) 1012 return false; 1013 if (Right.Type == TT_PointerOrReference) 1014 return Left.FormatTok.Tok.isLiteral() || 1015 ((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) && 1016 !Style.PointerBindsToType); 1017 if (Left.Type == TT_PointerOrReference) 1018 return Right.FormatTok.Tok.isLiteral() || 1019 ((Right.Type != TT_PointerOrReference) && 1020 Right.isNot(tok::l_paren) && Style.PointerBindsToType && 1021 Left.Parent && Left.Parent->isNot(tok::l_paren)); 1022 if (Right.is(tok::star) && Left.is(tok::l_paren)) 1023 return false; 1024 if (Left.is(tok::l_square)) 1025 return Left.Type == TT_ObjCArrayLiteral && Right.isNot(tok::r_square); 1026 if (Right.is(tok::r_square)) 1027 return Right.Type == TT_ObjCArrayLiteral; 1028 if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr) 1029 return false; 1030 if (Left.is(tok::period) || Right.is(tok::period)) 1031 return false; 1032 if (Left.is(tok::colon)) 1033 return Left.Type != TT_ObjCMethodExpr; 1034 if (Right.is(tok::colon)) 1035 return Right.Type != TT_ObjCMethodExpr; 1036 if (Left.is(tok::l_paren)) 1037 return false; 1038 if (Right.is(tok::l_paren)) { 1039 return Line.Type == LT_ObjCDecl || 1040 Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch, 1041 tok::kw_return, tok::kw_catch, tok::kw_new, 1042 tok::kw_delete); 1043 } 1044 if (Left.is(tok::at) && 1045 Right.FormatTok.Tok.getObjCKeywordID() != tok::objc_not_keyword) 1046 return false; 1047 if (Left.is(tok::l_brace) && Right.is(tok::r_brace)) 1048 return false; 1049 return true; 1050 } 1051 1052 bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, 1053 const AnnotatedToken &Tok) { 1054 if (Tok.FormatTok.Tok.getIdentifierInfo() && 1055 Tok.Parent->FormatTok.Tok.getIdentifierInfo()) 1056 return true; // Never ever merge two identifiers. 1057 if (Line.Type == LT_ObjCMethodDecl) { 1058 if (Tok.Parent->Type == TT_ObjCMethodSpecifier) 1059 return true; 1060 if (Tok.Parent->is(tok::r_paren) && Tok.is(tok::identifier)) 1061 // Don't space between ')' and <id> 1062 return false; 1063 } 1064 if (Line.Type == LT_ObjCProperty && 1065 (Tok.is(tok::equal) || Tok.Parent->is(tok::equal))) 1066 return false; 1067 1068 if (Tok.Parent->is(tok::comma)) 1069 return true; 1070 if (Tok.is(tok::comma)) 1071 return false; 1072 if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen) 1073 return true; 1074 if (Tok.Parent->FormatTok.Tok.is(tok::kw_operator)) 1075 return false; 1076 if (Tok.Type == TT_OverloadedOperatorLParen) 1077 return false; 1078 if (Tok.is(tok::colon)) 1079 return !Line.First.isOneOf(tok::kw_case, tok::kw_default) && 1080 Tok.getNextNoneComment() != NULL && Tok.Type != TT_ObjCMethodExpr; 1081 if (Tok.is(tok::l_paren) && !Tok.Children.empty() && 1082 Tok.Children[0].Type == TT_PointerOrReference && 1083 !Tok.Children[0].Children.empty() && 1084 Tok.Children[0].Children[0].isNot(tok::r_paren) && 1085 Tok.Parent->isNot(tok::l_paren) && 1086 (Tok.Parent->Type != TT_PointerOrReference || Style.PointerBindsToType)) 1087 return true; 1088 if (Tok.Parent->Type == TT_UnaryOperator || Tok.Parent->Type == TT_CastRParen) 1089 return false; 1090 if (Tok.Type == TT_UnaryOperator) 1091 return !Tok.Parent->isOneOf(tok::l_paren, tok::l_square, tok::at) && 1092 (Tok.Parent->isNot(tok::colon) || 1093 Tok.Parent->Type != TT_ObjCMethodExpr); 1094 if (Tok.Parent->is(tok::greater) && Tok.is(tok::greater)) { 1095 return Tok.Type == TT_TemplateCloser && 1096 Tok.Parent->Type == TT_TemplateCloser && 1097 Style.Standard != FormatStyle::LS_Cpp11; 1098 } 1099 if (Tok.isOneOf(tok::arrowstar, tok::periodstar) || 1100 Tok.Parent->isOneOf(tok::arrowstar, tok::periodstar)) 1101 return false; 1102 if (Tok.Type == TT_BinaryOperator || Tok.Parent->Type == TT_BinaryOperator) 1103 return true; 1104 if (Tok.Parent->Type == TT_TemplateCloser && Tok.is(tok::l_paren)) 1105 return false; 1106 if (Tok.is(tok::less) && Line.First.is(tok::hash)) 1107 return true; 1108 if (Tok.Type == TT_TrailingUnaryOperator) 1109 return false; 1110 return spaceRequiredBetween(Line, *Tok.Parent, Tok); 1111 } 1112 1113 bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, 1114 const AnnotatedToken &Right) { 1115 const AnnotatedToken &Left = *Right.Parent; 1116 if (Right.Type == TT_StartOfName) 1117 return true; 1118 if (Right.is(tok::colon) && Right.Type == TT_ObjCMethodExpr) 1119 return false; 1120 if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr) 1121 return true; 1122 if (Right.Type == TT_ObjCSelectorName) 1123 return true; 1124 if (Left.ClosesTemplateDeclaration) 1125 return true; 1126 if (Right.Type == TT_ConditionalExpr || Right.is(tok::question)) 1127 return true; 1128 if (Right.Type == TT_RangeBasedForLoopColon || 1129 Right.Type == TT_InheritanceColon || 1130 Right.Type == TT_OverloadedOperatorLParen) 1131 return false; 1132 if (Left.Type == TT_RangeBasedForLoopColon || 1133 Left.Type == TT_InheritanceColon) 1134 return true; 1135 if (Right.Type == TT_RangeBasedForLoopColon) 1136 return false; 1137 if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser || 1138 Left.Type == TT_UnaryOperator || Left.Type == TT_ConditionalExpr || 1139 Left.isOneOf(tok::question, tok::kw_operator)) 1140 return false; 1141 if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl) 1142 return false; 1143 if (Left.is(tok::l_paren) && Right.is(tok::l_paren) && Left.Parent && 1144 Left.Parent->is(tok::kw___attribute)) 1145 return false; 1146 1147 if (Right.Type == TT_LineComment) 1148 // We rely on MustBreakBefore being set correctly here as we should not 1149 // change the "binding" behavior of a comment. 1150 return false; 1151 1152 // Allow breaking after a trailing 'const', e.g. after a method declaration, 1153 // unless it is follow by ';', '{' or '='. 1154 if (Left.is(tok::kw_const) && Left.Parent != NULL && 1155 Left.Parent->is(tok::r_paren)) 1156 return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal); 1157 1158 if (Right.is(tok::kw___attribute)) 1159 return true; 1160 1161 // We only break before r_brace if there was a corresponding break before 1162 // the l_brace, which is tracked by BreakBeforeClosingBrace. 1163 if (Right.isOneOf(tok::r_brace, tok::r_paren, tok::greater)) 1164 return false; 1165 if (Left.is(tok::identifier) && Right.is(tok::string_literal)) 1166 return true; 1167 return (Left.isBinaryOperator() && Left.isNot(tok::lessless)) || 1168 Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace, 1169 tok::kw_class, tok::kw_struct) || 1170 Right.isOneOf(tok::lessless, tok::arrow, tok::period, tok::colon) || 1171 (Left.is(tok::r_paren) && Left.Type != TT_CastRParen && 1172 Right.isOneOf(tok::identifier, tok::kw___attribute)) || 1173 (Left.is(tok::l_paren) && !Right.is(tok::r_paren)) || 1174 (Left.is(tok::l_square) && !Right.is(tok::r_square)); 1175 } 1176 1177 void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) { 1178 llvm::errs() << "AnnotatedTokens:\n"; 1179 const AnnotatedToken *Tok = &Line.First; 1180 while (Tok) { 1181 llvm::errs() << " M=" << Tok->MustBreakBefore 1182 << " C=" << Tok->CanBreakBefore << " T=" << Tok->Type 1183 << " S=" << Tok->SpacesRequiredBefore 1184 << " Name=" << Tok->FormatTok.Tok.getName() << " FakeLParens="; 1185 for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i) 1186 llvm::errs() << Tok->FakeLParens[i] << "/"; 1187 llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n"; 1188 Tok = Tok->Children.empty() ? NULL : &Tok->Children[0]; 1189 } 1190 llvm::errs() << "----\n"; 1191 } 1192 1193 } // namespace format 1194 } // namespace clang 1195