TokenAnnotator.cpp revision 263509
1184610Salfred//===--- TokenAnnotator.cpp - Format C++ code -----------------------------===// 2184610Salfred// 3184610Salfred// The LLVM Compiler Infrastructure 4184610Salfred// 5184610Salfred// This file is distributed under the University of Illinois Open Source 6189002Sed// License. See LICENSE.TXT for details. 7184610Salfred// 8184610Salfred//===----------------------------------------------------------------------===// 9184610Salfred/// 10184610Salfred/// \file 11184610Salfred/// \brief This file implements a token annotator, i.e. creates 12184610Salfred/// \c AnnotatedTokens out of \c FormatTokens with required extra information. 13184610Salfred/// 14184610Salfred//===----------------------------------------------------------------------===// 15184610Salfred 16184610Salfred#include "TokenAnnotator.h" 17184610Salfred#include "clang/Basic/SourceManager.h" 18184610Salfred#include "llvm/Support/Debug.h" 19184610Salfred 20184610Salfrednamespace clang { 21184610Salfrednamespace format { 22184610Salfred 23184610Salfrednamespace { 24184610Salfred 25184610Salfred/// \brief A parser that gathers additional information about tokens. 26184610Salfred/// 27184610Salfred/// The \c TokenAnnotator tries to match parenthesis and square brakets and 28184610Salfred/// store a parenthesis levels. It also tries to resolve matching "<" and ">" 29184610Salfred/// into template parameter lists. 30184610Salfredclass AnnotatingParser { 31184610Salfredpublic: 32184610Salfred AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line, 33184610Salfred IdentifierInfo &Ident_in) 34184610Salfred : Style(Style), Line(Line), CurrentToken(Line.First), 35184610Salfred KeywordVirtualFound(false), AutoFound(false), Ident_in(Ident_in) { 36184610Salfred Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false)); 37184610Salfred } 38184610Salfred 39184610Salfredprivate: 40184610Salfred bool parseAngle() { 41184610Salfred if (CurrentToken == NULL) 42184610Salfred return false; 43184610Salfred ScopedContextCreator ContextCreator(*this, tok::less, 10); 44184610Salfred FormatToken *Left = CurrentToken->Previous; 45184610Salfred Contexts.back().IsExpression = false; 46184610Salfred while (CurrentToken != NULL) { 47184610Salfred if (CurrentToken->is(tok::greater)) { 48184610Salfred Left->MatchingParen = CurrentToken; 49184610Salfred CurrentToken->MatchingParen = Left; 50184610Salfred CurrentToken->Type = TT_TemplateCloser; 51184610Salfred next(); 52184610Salfred return true; 53184610Salfred } 54184610Salfred if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace, 55184610Salfred tok::question, tok::colon)) 56184610Salfred return false; 57184610Salfred // If a && or || is found and interpreted as a binary operator, this set 58184610Salfred // of angles is likely part of something like "a < b && c > d". If the 59184610Salfred // angles are inside an expression, the ||/&& might also be a binary 60184610Salfred // operator that was misinterpreted because we are parsing template 61184610Salfred // parameters. 62184610Salfred // FIXME: This is getting out of hand, write a decent parser. 63184610Salfred if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) && 64184610Salfred (CurrentToken->Previous->Type == TT_BinaryOperator || 65184610Salfred Contexts[Contexts.size() - 2].IsExpression) && 66184610Salfred Line.First->isNot(tok::kw_template)) 67184610Salfred return false; 68184610Salfred updateParameterCount(Left, CurrentToken); 69184610Salfred if (!consumeToken()) 70184610Salfred return false; 71184610Salfred } 72184610Salfred return false; 73184610Salfred } 74184610Salfred 75184610Salfred bool parseParens(bool LookForDecls = false) { 76184610Salfred if (CurrentToken == NULL) 77184610Salfred return false; 78184610Salfred ScopedContextCreator ContextCreator(*this, tok::l_paren, 1); 79184610Salfred 80184610Salfred // FIXME: This is a bit of a hack. Do better. 81184610Salfred Contexts.back().ColonIsForRangeExpr = 82184610Salfred Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr; 83184610Salfred 84184610Salfred bool StartsObjCMethodExpr = false; 85184610Salfred FormatToken *Left = CurrentToken->Previous; 86184610Salfred if (CurrentToken->is(tok::caret)) { 87184610Salfred // ^( starts a block. 88184610Salfred Left->Type = TT_ObjCBlockLParen; 89184610Salfred } else if (FormatToken *MaybeSel = Left->Previous) { 90184610Salfred // @selector( starts a selector. 91184610Salfred if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous && 92184610Salfred MaybeSel->Previous->is(tok::at)) { 93184610Salfred StartsObjCMethodExpr = true; 94184610Salfred } 95184610Salfred } 96189002Sed 97184610Salfred if (Left->Previous && Left->Previous->isOneOf(tok::kw_static_assert, 98184610Salfred tok::kw_if, tok::kw_while)) { 99184610Salfred // static_assert, if and while usually contain expressions. 100184610Salfred Contexts.back().IsExpression = true; 101184610Salfred } else if (Left->Previous && Left->Previous->is(tok::r_square) && 102184610Salfred Left->Previous->MatchingParen && 103184610Salfred Left->Previous->MatchingParen->Type == TT_LambdaLSquare) { 104184610Salfred // This is a parameter list of a lambda expression. 105194677Sthompsa Contexts.back().IsExpression = false; 106194677Sthompsa } 107194677Sthompsa 108194677Sthompsa if (StartsObjCMethodExpr) { 109194677Sthompsa Contexts.back().ColonIsObjCMethodExpr = true; 110194677Sthompsa Left->Type = TT_ObjCMethodExpr; 111194677Sthompsa } 112194677Sthompsa 113194677Sthompsa bool MightBeFunctionType = CurrentToken->is(tok::star); 114194677Sthompsa bool HasMultipleLines = false; 115194677Sthompsa bool HasMultipleParametersOnALine = false; 116194677Sthompsa while (CurrentToken != NULL) { 117194677Sthompsa // LookForDecls is set when "if (" has been seen. Check for 118194677Sthompsa // 'identifier' '*' 'identifier' followed by not '=' -- this 119194677Sthompsa // '*' has to be a binary operator but determineStarAmpUsage() will 120194677Sthompsa // categorize it as an unary operator, so set the right type here. 121194677Sthompsa if (LookForDecls && CurrentToken->Next) { 122194677Sthompsa FormatToken *Prev = CurrentToken->getPreviousNonComment(); 123194677Sthompsa if (Prev) { 124194677Sthompsa FormatToken *PrevPrev = Prev->getPreviousNonComment(); 125194677Sthompsa FormatToken *Next = CurrentToken->Next; 126194677Sthompsa if (PrevPrev && PrevPrev->is(tok::identifier) && 127196826Strasz Prev->isOneOf(tok::star, tok::amp, tok::ampamp) && 128188746Sthompsa CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) { 129184610Salfred Prev->Type = TT_BinaryOperator; 130184610Salfred LookForDecls = false; 131184610Salfred } 132184610Salfred } 133184610Salfred } 134184610Salfred 135184610Salfred if (CurrentToken->Previous->Type == TT_PointerOrReference && 136184610Salfred CurrentToken->Previous->Previous->isOneOf(tok::l_paren, 137184610Salfred tok::coloncolon)) 138184610Salfred MightBeFunctionType = true; 139194677Sthompsa if (CurrentToken->is(tok::r_paren)) { 140194677Sthompsa if (MightBeFunctionType && CurrentToken->Next && 141184610Salfred (CurrentToken->Next->is(tok::l_paren) || 142184610Salfred (CurrentToken->Next->is(tok::l_square) && 143184610Salfred !Contexts.back().IsExpression))) 144184610Salfred Left->Type = TT_FunctionTypeLParen; 145184610Salfred Left->MatchingParen = CurrentToken; 146184610Salfred CurrentToken->MatchingParen = Left; 147184610Salfred 148184610Salfred if (StartsObjCMethodExpr) { 149184610Salfred CurrentToken->Type = TT_ObjCMethodExpr; 150184610Salfred if (Contexts.back().FirstObjCSelectorName != NULL) { 151184610Salfred Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 152184610Salfred Contexts.back().LongestObjCSelectorName; 153184610Salfred } 154184610Salfred } 155184610Salfred 156184610Salfred if (!HasMultipleLines) 157184610Salfred Left->PackingKind = PPK_Inconclusive; 158184610Salfred else if (HasMultipleParametersOnALine) 159184610Salfred Left->PackingKind = PPK_BinPacked; 160184610Salfred else 161184610Salfred Left->PackingKind = PPK_OnePerLine; 162184610Salfred 163184610Salfred next(); 164184610Salfred return true; 165184610Salfred } 166184610Salfred if (CurrentToken->isOneOf(tok::r_square, tok::r_brace)) 167184610Salfred return false; 168184610Salfred updateParameterCount(Left, CurrentToken); 169184610Salfred if (CurrentToken->is(tok::comma) && CurrentToken->Next && 170184610Salfred !CurrentToken->Next->HasUnescapedNewline && 171184610Salfred !CurrentToken->Next->isTrailingComment()) 172184610Salfred HasMultipleParametersOnALine = true; 173184610Salfred if (!consumeToken()) 174184610Salfred return false; 175192502Sthompsa if (CurrentToken && CurrentToken->HasUnescapedNewline) 176192502Sthompsa HasMultipleLines = true; 177184610Salfred } 178184610Salfred return false; 179184610Salfred } 180184610Salfred 181184610Salfred bool parseSquare() { 182184610Salfred if (!CurrentToken) 183184610Salfred return false; 184184610Salfred 185184610Salfred // A '[' could be an index subscript (after an identifier or after 186184610Salfred // ')' or ']'), it could be the start of an Objective-C method 187184610Salfred // expression, or it could the the start of an Objective-C array literal. 188184610Salfred FormatToken *Left = CurrentToken->Previous; 189184610Salfred FormatToken *Parent = Left->getPreviousNonComment(); 190184610Salfred bool StartsObjCMethodExpr = 191184610Salfred Contexts.back().CanBeExpression && Left->Type != TT_LambdaLSquare && 192184610Salfred (!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren, 193184610Salfred tok::kw_return, tok::kw_throw) || 194184610Salfred Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn || 195184610Salfred Parent->Type == TT_CastRParen || 196184610Salfred getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown); 197184610Salfred ScopedContextCreator ContextCreator(*this, tok::l_square, 10); 198184610Salfred Contexts.back().IsExpression = true; 199184610Salfred bool ColonFound = false; 200184610Salfred 201184610Salfred if (StartsObjCMethodExpr) { 202184610Salfred Contexts.back().ColonIsObjCMethodExpr = true; 203184610Salfred Left->Type = TT_ObjCMethodExpr; 204184610Salfred } else if (Parent && Parent->is(tok::at)) { 205184610Salfred Left->Type = TT_ArrayInitializerLSquare; 206184610Salfred } else if (Left->Type == TT_Unknown) { 207184610Salfred Left->Type = TT_ArraySubscriptLSquare; 208184610Salfred } 209184610Salfred 210184610Salfred while (CurrentToken != NULL) { 211184610Salfred if (CurrentToken->is(tok::r_square)) { 212184610Salfred if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) && 213184610Salfred Left->Type == TT_ObjCMethodExpr) { 214184610Salfred // An ObjC method call is rarely followed by an open parenthesis. 215184610Salfred // FIXME: Do we incorrectly label ":" with this? 216184610Salfred StartsObjCMethodExpr = false; 217184610Salfred Left->Type = TT_Unknown; 218184610Salfred } 219184610Salfred if (StartsObjCMethodExpr) { 220184610Salfred CurrentToken->Type = TT_ObjCMethodExpr; 221184610Salfred // determineStarAmpUsage() thinks that '*' '[' is allocating an 222184610Salfred // array of pointers, but if '[' starts a selector then '*' is a 223184610Salfred // binary operator. 224184610Salfred if (Parent != NULL && Parent->Type == TT_PointerOrReference) 225184610Salfred Parent->Type = TT_BinaryOperator; 226184610Salfred } 227184610Salfred Left->MatchingParen = CurrentToken; 228184610Salfred CurrentToken->MatchingParen = Left; 229184610Salfred if (Contexts.back().FirstObjCSelectorName != NULL) 230184610Salfred Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 231184610Salfred Contexts.back().LongestObjCSelectorName; 232184610Salfred next(); 233184610Salfred return true; 234184610Salfred } 235184610Salfred if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace)) 236184610Salfred return false; 237184610Salfred if (CurrentToken->is(tok::colon)) 238184610Salfred ColonFound = true; 239184610Salfred if (CurrentToken->is(tok::comma) && 240184610Salfred (Left->Type == TT_ArraySubscriptLSquare || 241184610Salfred (Left->Type == TT_ObjCMethodExpr && !ColonFound))) 242184610Salfred Left->Type = TT_ArrayInitializerLSquare; 243184610Salfred updateParameterCount(Left, CurrentToken); 244184610Salfred if (!consumeToken()) 245184610Salfred return false; 246184610Salfred } 247184610Salfred return false; 248184610Salfred } 249184610Salfred 250184610Salfred bool parseBrace() { 251184610Salfred if (CurrentToken != NULL) { 252184610Salfred FormatToken *Left = CurrentToken->Previous; 253184610Salfred ScopedContextCreator ContextCreator(*this, tok::l_brace, 1); 254184610Salfred Contexts.back().ColonIsDictLiteral = true; 255184610Salfred 256184610Salfred while (CurrentToken != NULL) { 257184610Salfred if (CurrentToken->is(tok::r_brace)) { 258184610Salfred Left->MatchingParen = CurrentToken; 259184610Salfred CurrentToken->MatchingParen = Left; 260184610Salfred next(); 261184610Salfred return true; 262184610Salfred } 263184610Salfred if (CurrentToken->isOneOf(tok::r_paren, tok::r_square)) 264184610Salfred return false; 265184610Salfred updateParameterCount(Left, CurrentToken); 266184610Salfred if (CurrentToken->is(tok::colon)) 267184610Salfred Left->Type = TT_DictLiteral; 268184610Salfred if (!consumeToken()) 269184610Salfred return false; 270184610Salfred } 271184610Salfred } 272184610Salfred // No closing "}" found, this probably starts a definition. 273184610Salfred Line.StartsDefinition = true; 274184610Salfred return true; 275184610Salfred } 276184610Salfred 277184610Salfred void updateParameterCount(FormatToken *Left, FormatToken *Current) { 278184610Salfred if (Current->is(tok::comma)) { 279184610Salfred ++Left->ParameterCount; 280184610Salfred if (!Left->Role) 281184610Salfred Left->Role.reset(new CommaSeparatedList(Style)); 282184610Salfred Left->Role->CommaFound(Current); 283184610Salfred } else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) { 284184610Salfred Left->ParameterCount = 1; 285184610Salfred } 286184610Salfred } 287184610Salfred 288184610Salfred bool parseConditional() { 289184610Salfred while (CurrentToken != NULL) { 290184610Salfred if (CurrentToken->is(tok::colon)) { 291184610Salfred CurrentToken->Type = TT_ConditionalExpr; 292184610Salfred next(); 293184610Salfred return true; 294184610Salfred } 295184610Salfred if (!consumeToken()) 296184610Salfred return false; 297184610Salfred } 298184610Salfred return false; 299184610Salfred } 300184610Salfred 301184610Salfred bool parseTemplateDeclaration() { 302184610Salfred if (CurrentToken != NULL && CurrentToken->is(tok::less)) { 303184610Salfred CurrentToken->Type = TT_TemplateOpener; 304184610Salfred next(); 305184610Salfred if (!parseAngle()) 306184610Salfred return false; 307184610Salfred if (CurrentToken != NULL) 308184610Salfred CurrentToken->Previous->ClosesTemplateDeclaration = true; 309184610Salfred return true; 310184610Salfred } 311184610Salfred return false; 312184610Salfred } 313184610Salfred 314184610Salfred bool consumeToken() { 315184610Salfred FormatToken *Tok = CurrentToken; 316184610Salfred next(); 317184610Salfred switch (Tok->Tok.getKind()) { 318184610Salfred case tok::plus: 319184610Salfred case tok::minus: 320184610Salfred if (Tok->Previous == NULL && Line.MustBeDeclaration) 321184610Salfred Tok->Type = TT_ObjCMethodSpecifier; 322184610Salfred break; 323184610Salfred case tok::colon: 324184610Salfred if (Tok->Previous == NULL) 325192052Sthompsa return false; 326184610Salfred // Colons from ?: are handled in parseConditional(). 327184610Salfred if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1) { 328184610Salfred Tok->Type = TT_CtorInitializerColon; 329184610Salfred } else if (Contexts.back().ColonIsDictLiteral) { 330184610Salfred Tok->Type = TT_DictLiteral; 331184610Salfred } else if (Contexts.back().ColonIsObjCMethodExpr || 332184610Salfred Line.First->Type == TT_ObjCMethodSpecifier) { 333184610Salfred Tok->Type = TT_ObjCMethodExpr; 334184610Salfred Tok->Previous->Type = TT_ObjCSelectorName; 335184610Salfred if (Tok->Previous->ColumnWidth > 336184610Salfred Contexts.back().LongestObjCSelectorName) { 337184610Salfred Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth; 338184610Salfred } 339184610Salfred if (Contexts.back().FirstObjCSelectorName == NULL) 340184610Salfred Contexts.back().FirstObjCSelectorName = Tok->Previous; 341184610Salfred } else if (Contexts.back().ColonIsForRangeExpr) { 342184610Salfred Tok->Type = TT_RangeBasedForLoopColon; 343184610Salfred } else if (CurrentToken != NULL && 344184610Salfred CurrentToken->is(tok::numeric_constant)) { 345184610Salfred Tok->Type = TT_BitFieldColon; 346184610Salfred } else if (Contexts.size() == 1 && Line.First->isNot(tok::kw_enum)) { 347184610Salfred Tok->Type = TT_InheritanceColon; 348184610Salfred } else if (Contexts.back().ContextKind == tok::l_paren) { 349184610Salfred Tok->Type = TT_InlineASMColon; 350184610Salfred } 351184610Salfred break; 352184610Salfred case tok::kw_if: 353184610Salfred case tok::kw_while: 354184610Salfred if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) { 355184610Salfred next(); 356184610Salfred if (!parseParens(/*LookForDecls=*/true)) 357184610Salfred return false; 358184610Salfred } 359184610Salfred break; 360184610Salfred case tok::kw_for: 361184610Salfred Contexts.back().ColonIsForRangeExpr = true; 362184610Salfred next(); 363184610Salfred if (!parseParens()) 364184610Salfred return false; 365184610Salfred break; 366184610Salfred case tok::l_paren: 367184610Salfred if (!parseParens()) 368184610Salfred return false; 369184610Salfred if (Line.MustBeDeclaration && Contexts.size() == 1 && 370184610Salfred !Contexts.back().IsExpression) 371184610Salfred Line.MightBeFunctionDecl = true; 372184610Salfred break; 373184610Salfred case tok::l_square: 374184610Salfred if (!parseSquare()) 375184610Salfred return false; 376184610Salfred break; 377184610Salfred case tok::l_brace: 378184610Salfred if (!parseBrace()) 379184610Salfred return false; 380184610Salfred break; 381184610Salfred case tok::less: 382184610Salfred if (Tok->Previous && !Tok->Previous->Tok.isLiteral() && parseAngle()) 383184610Salfred Tok->Type = TT_TemplateOpener; 384184610Salfred else { 385184610Salfred Tok->Type = TT_BinaryOperator; 386184610Salfred CurrentToken = Tok; 387184610Salfred next(); 388184610Salfred } 389192052Sthompsa break; 390184610Salfred case tok::r_paren: 391184610Salfred case tok::r_square: 392184610Salfred return false; 393184610Salfred case tok::r_brace: 394184610Salfred // Lines can start with '}'. 395184610Salfred if (Tok->Previous != NULL) 396184610Salfred return false; 397184610Salfred break; 398184610Salfred case tok::greater: 399184610Salfred Tok->Type = TT_BinaryOperator; 400184610Salfred break; 401184610Salfred case tok::kw_operator: 402184610Salfred while (CurrentToken && 403184610Salfred !CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) { 404184610Salfred if (CurrentToken->isOneOf(tok::star, tok::amp)) 405184610Salfred CurrentToken->Type = TT_PointerOrReference; 406184610Salfred consumeToken(); 407184610Salfred if (CurrentToken && CurrentToken->Previous->Type == TT_BinaryOperator) 408184610Salfred CurrentToken->Previous->Type = TT_OverloadedOperator; 409184610Salfred } 410184610Salfred if (CurrentToken) { 411184610Salfred CurrentToken->Type = TT_OverloadedOperatorLParen; 412193171Sdeischen if (CurrentToken->Previous->Type == TT_BinaryOperator) 413193171Sdeischen CurrentToken->Previous->Type = TT_OverloadedOperator; 414193171Sdeischen } 415193171Sdeischen break; 416196495Salfred case tok::question: 417196495Salfred parseConditional(); 418196495Salfred break; 419196495Salfred case tok::kw_template: 420192052Sthompsa parseTemplateDeclaration(); 421192052Sthompsa break; 422192052Sthompsa case tok::identifier: 423192052Sthompsa if (Line.First->is(tok::kw_for) && 424184610Salfred Tok->Tok.getIdentifierInfo() == &Ident_in) 425184610Salfred Tok->Type = TT_ObjCForIn; 426184610Salfred break; 427184610Salfred case tok::comma: 428186730Salfred if (Contexts.back().FirstStartOfName) 429186730Salfred Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true; 430186730Salfred if (Contexts.back().InCtorInitializer) 431186730Salfred Tok->Type = TT_CtorInitializerComma; 432184610Salfred break; 433184610Salfred default: 434184610Salfred break; 435184610Salfred } 436184610Salfred return true; 437184610Salfred } 438184610Salfred 439184610Salfred void parseIncludeDirective() { 440184610Salfred next(); 441184610Salfred if (CurrentToken != NULL && CurrentToken->is(tok::less)) { 442184610Salfred next(); 443184610Salfred while (CurrentToken != NULL) { 444184610Salfred if (CurrentToken->isNot(tok::comment) || CurrentToken->Next) 445184610Salfred CurrentToken->Type = TT_ImplicitStringLiteral; 446184610Salfred next(); 447184610Salfred } 448184610Salfred } else { 449184610Salfred while (CurrentToken != NULL) { 450184610Salfred if (CurrentToken->is(tok::string_literal)) 451184610Salfred // Mark these string literals as "implicit" literals, too, so that 452184610Salfred // they are not split or line-wrapped. 453184610Salfred CurrentToken->Type = TT_ImplicitStringLiteral; 454184610Salfred next(); 455184610Salfred } 456192052Sthompsa } 457192052Sthompsa } 458192052Sthompsa 459192052Sthompsa void parseWarningOrError() { 460184610Salfred next(); 461184610Salfred // We still want to format the whitespace left of the first token of the 462184610Salfred // warning or error. 463184610Salfred next(); 464184610Salfred while (CurrentToken != NULL) { 465184610Salfred CurrentToken->Type = TT_ImplicitStringLiteral; 466184610Salfred next(); 467184610Salfred } 468184610Salfred } 469184610Salfred 470184610Salfred void parsePreprocessorDirective() { 471184610Salfred next(); 472184610Salfred if (CurrentToken == NULL) 473184610Salfred return; 474184610Salfred if (CurrentToken->Tok.is(tok::numeric_constant)) { 475184610Salfred CurrentToken->SpacesRequiredBefore = 1; 476184610Salfred return; 477184610Salfred } 478184610Salfred // Hashes in the middle of a line can lead to any strange token 479184610Salfred // sequence. 480184610Salfred if (CurrentToken->Tok.getIdentifierInfo() == NULL) 481184610Salfred return; 482184610Salfred switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) { 483184610Salfred case tok::pp_include: 484184610Salfred case tok::pp_import: 485184610Salfred parseIncludeDirective(); 486184610Salfred break; 487184610Salfred case tok::pp_error: 488184610Salfred case tok::pp_warning: 489184610Salfred parseWarningOrError(); 490184610Salfred break; 491190189Sthompsa case tok::pp_if: 492184610Salfred case tok::pp_elif: 493184610Salfred parseLine(); 494184610Salfred break; 495184610Salfred default: 496184610Salfred break; 497184610Salfred } 498184610Salfred while (CurrentToken != NULL) 499184610Salfred next(); 500184610Salfred } 501184610Salfred 502184610Salfredpublic: 503184610Salfred LineType parseLine() { 504184610Salfred if (CurrentToken->is(tok::hash)) { 505184610Salfred parsePreprocessorDirective(); 506184610Salfred return LT_PreprocessorDirective; 507184610Salfred } 508184610Salfred while (CurrentToken != NULL) { 509184610Salfred if (CurrentToken->is(tok::kw_virtual)) 510184610Salfred KeywordVirtualFound = true; 511184610Salfred if (!consumeToken()) 512184610Salfred return LT_Invalid; 513184610Salfred } 514184610Salfred if (KeywordVirtualFound) 515184610Salfred return LT_VirtualFunctionDecl; 516184610Salfred 517184610Salfred if (Line.First->Type == TT_ObjCMethodSpecifier) { 518184610Salfred if (Contexts.back().FirstObjCSelectorName != NULL) 519184610Salfred Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 520184610Salfred Contexts.back().LongestObjCSelectorName; 521184610Salfred return LT_ObjCMethodDecl; 522184610Salfred } 523184610Salfred 524184610Salfred return LT_Other; 525184610Salfred } 526184610Salfred 527184610Salfredprivate: 528184610Salfred void next() { 529184610Salfred if (CurrentToken != NULL) { 530184610Salfred determineTokenType(*CurrentToken); 531184610Salfred CurrentToken->BindingStrength = Contexts.back().BindingStrength; 532184610Salfred } 533184610Salfred 534184610Salfred if (CurrentToken != NULL) 535184610Salfred CurrentToken = CurrentToken->Next; 536184610Salfred 537184610Salfred if (CurrentToken != NULL) { 538184610Salfred // Reset token type in case we have already looked at it and then 539184610Salfred // recovered from an error (e.g. failure to find the matching >). 540184610Salfred if (CurrentToken->Type != TT_LambdaLSquare && 541184610Salfred CurrentToken->Type != TT_ImplicitStringLiteral) 542184610Salfred CurrentToken->Type = TT_Unknown; 543184610Salfred if (CurrentToken->Role) 544184610Salfred CurrentToken->Role.reset(NULL); 545184610Salfred CurrentToken->FakeLParens.clear(); 546184610Salfred CurrentToken->FakeRParens = 0; 547184610Salfred } 548184610Salfred } 549184610Salfred 550184610Salfred /// \brief A struct to hold information valid in a specific context, e.g. 551184610Salfred /// a pair of parenthesis. 552184610Salfred struct Context { 553184610Salfred Context(tok::TokenKind ContextKind, unsigned BindingStrength, 554184610Salfred bool IsExpression) 555184610Salfred : ContextKind(ContextKind), BindingStrength(BindingStrength), 556184610Salfred LongestObjCSelectorName(0), ColonIsForRangeExpr(false), 557184610Salfred ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false), 558184610Salfred FirstObjCSelectorName(NULL), FirstStartOfName(NULL), 559184610Salfred IsExpression(IsExpression), CanBeExpression(true), 560184610Salfred InCtorInitializer(false) {} 561184610Salfred 562184610Salfred tok::TokenKind ContextKind; 563184610Salfred unsigned BindingStrength; 564184610Salfred unsigned LongestObjCSelectorName; 565184610Salfred bool ColonIsForRangeExpr; 566184610Salfred bool ColonIsDictLiteral; 567184610Salfred bool ColonIsObjCMethodExpr; 568184610Salfred FormatToken *FirstObjCSelectorName; 569184610Salfred FormatToken *FirstStartOfName; 570184610Salfred bool IsExpression; 571184610Salfred bool CanBeExpression; 572184610Salfred bool InCtorInitializer; 573184610Salfred }; 574184610Salfred 575184610Salfred /// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime 576184610Salfred /// of each instance. 577184610Salfred struct ScopedContextCreator { 578184610Salfred AnnotatingParser &P; 579184610Salfred 580184610Salfred ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind, 581184610Salfred unsigned Increase) 582184610Salfred : P(P) { 583184610Salfred P.Contexts.push_back(Context(ContextKind, 584184610Salfred P.Contexts.back().BindingStrength + Increase, 585184610Salfred P.Contexts.back().IsExpression)); 586184610Salfred } 587184610Salfred 588184610Salfred ~ScopedContextCreator() { P.Contexts.pop_back(); } 589184610Salfred }; 590184610Salfred 591184610Salfred void determineTokenType(FormatToken &Current) { 592184610Salfred if (Current.getPrecedence() == prec::Assignment && 593184610Salfred !Line.First->isOneOf(tok::kw_template, tok::kw_using) && 594184610Salfred (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) { 595184610Salfred Contexts.back().IsExpression = true; 596184610Salfred for (FormatToken *Previous = Current.Previous; 597184610Salfred Previous && !Previous->isOneOf(tok::comma, tok::semi); 598184610Salfred Previous = Previous->Previous) { 599184610Salfred if (Previous->is(tok::r_square)) 600184610Salfred Previous = Previous->MatchingParen; 601184610Salfred if (Previous->Type == TT_BinaryOperator && 602184610Salfred Previous->isOneOf(tok::star, tok::amp)) { 603184610Salfred Previous->Type = TT_PointerOrReference; 604184610Salfred } 605184610Salfred } 606184610Salfred } else if (Current.isOneOf(tok::kw_return, tok::kw_throw) || 607184610Salfred (Current.is(tok::l_paren) && !Line.MustBeDeclaration && 608184610Salfred !Line.InPPDirective && 609184610Salfred (!Current.Previous || 610184610Salfred !Current.Previous->isOneOf(tok::kw_for, tok::kw_catch)))) { 611184610Salfred Contexts.back().IsExpression = true; 612184610Salfred } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) { 613184610Salfred for (FormatToken *Previous = Current.Previous; 614184610Salfred Previous && Previous->isOneOf(tok::star, tok::amp); 615184610Salfred Previous = Previous->Previous) 616184610Salfred Previous->Type = TT_PointerOrReference; 617184610Salfred } else if (Current.Previous && 618184610Salfred Current.Previous->Type == TT_CtorInitializerColon) { 619184610Salfred Contexts.back().IsExpression = true; 620184610Salfred Contexts.back().InCtorInitializer = true; 621184610Salfred } else if (Current.is(tok::kw_new)) { 622184610Salfred Contexts.back().CanBeExpression = false; 623184610Salfred } else if (Current.is(tok::semi) || Current.is(tok::exclaim)) { 624184610Salfred // This should be the condition or increment in a for-loop. 625184610Salfred Contexts.back().IsExpression = true; 626184610Salfred } 627184610Salfred 628184610Salfred if (Current.Type == TT_Unknown) { 629184610Salfred // Line.MightBeFunctionDecl can only be true after the parentheses of a 630184610Salfred // function declaration have been found. In this case, 'Current' is a 631184610Salfred // trailing token of this declaration and thus cannot be a name. 632184610Salfred if (isStartOfName(Current) && !Line.MightBeFunctionDecl) { 633192052Sthompsa Contexts.back().FirstStartOfName = &Current; 634192052Sthompsa Current.Type = TT_StartOfName; 635192052Sthompsa } else if (Current.is(tok::kw_auto)) { 636192052Sthompsa AutoFound = true; 637184610Salfred } else if (Current.is(tok::arrow) && AutoFound && 638184610Salfred Line.MustBeDeclaration) { 639184610Salfred Current.Type = TT_TrailingReturnArrow; 640184610Salfred } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) { 641184610Salfred Current.Type = 642184610Salfred determineStarAmpUsage(Current, Contexts.back().CanBeExpression && 643184610Salfred Contexts.back().IsExpression); 644184610Salfred } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) { 645184610Salfred Current.Type = determinePlusMinusCaretUsage(Current); 646192052Sthompsa } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) { 647190263Simp Current.Type = determineIncrementUsage(Current); 648184610Salfred } else if (Current.is(tok::exclaim)) { 649194582Sremko Current.Type = TT_UnaryOperator; 650194584Sremko } else if (Current.isBinaryOperator() && 651194582Sremko (!Current.Previous || 652194582Sremko Current.Previous->isNot(tok::l_square))) { 653187726Sthompsa Current.Type = TT_BinaryOperator; 654192052Sthompsa } else if (Current.is(tok::comment)) { 655187726Sthompsa if (Current.TokenText.startswith("//")) 656187726Sthompsa Current.Type = TT_LineComment; 657184610Salfred else 658184610Salfred Current.Type = TT_BlockComment; 659184610Salfred } else if (Current.is(tok::r_paren)) { 660184610Salfred FormatToken *LeftOfParens = NULL; 661184610Salfred if (Current.MatchingParen) 662184610Salfred LeftOfParens = Current.MatchingParen->getPreviousNonComment(); 663184610Salfred bool IsCast = false; 664184610Salfred bool ParensAreEmpty = Current.Previous == Current.MatchingParen; 665184610Salfred bool ParensAreType = !Current.Previous || 666184610Salfred Current.Previous->Type == TT_PointerOrReference || 667184610Salfred Current.Previous->Type == TT_TemplateCloser || 668184610Salfred isSimpleTypeSpecifier(*Current.Previous); 669184610Salfred bool ParensCouldEndDecl = 670184610Salfred Current.Next && 671184610Salfred Current.Next->isOneOf(tok::equal, tok::semi, tok::l_brace); 672184610Salfred bool IsSizeOfOrAlignOf = 673184610Salfred LeftOfParens && 674184610Salfred LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof); 675184610Salfred if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf && 676184610Salfred (Contexts.back().IsExpression || 677184610Salfred (Current.Next && Current.Next->isBinaryOperator()))) 678184610Salfred IsCast = true; 679184610Salfred if (Current.Next && Current.Next->isNot(tok::string_literal) && 680184610Salfred (Current.Next->Tok.isLiteral() || 681184610Salfred Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof))) 682184610Salfred IsCast = true; 683184610Salfred // If there is an identifier after the (), it is likely a cast, unless 684184610Salfred // there is also an identifier before the (). 685186730Salfred if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL || 686186730Salfred LeftOfParens->is(tok::kw_return)) && 687186730Salfred LeftOfParens->Type != TT_OverloadedOperator && 688186730Salfred LeftOfParens->Type != TT_TemplateCloser && Current.Next && 689184610Salfred Current.Next->is(tok::identifier)) 690184610Salfred IsCast = true; 691184610Salfred if (IsCast && !ParensAreEmpty) 692184610Salfred Current.Type = TT_CastRParen; 693184610Salfred } else if (Current.is(tok::at) && Current.Next) { 694184610Salfred switch (Current.Next->Tok.getObjCKeywordID()) { 695184610Salfred case tok::objc_interface: 696184610Salfred case tok::objc_implementation: 697184610Salfred case tok::objc_protocol: 698184610Salfred Current.Type = TT_ObjCDecl; 699184610Salfred break; 700184610Salfred case tok::objc_property: 701184610Salfred Current.Type = TT_ObjCProperty; 702184610Salfred break; 703184610Salfred default: 704184610Salfred break; 705184610Salfred } 706184610Salfred } else if (Current.is(tok::period)) { 707184610Salfred FormatToken *PreviousNoComment = Current.getPreviousNonComment(); 708184610Salfred if (PreviousNoComment && 709184610Salfred PreviousNoComment->isOneOf(tok::comma, tok::l_brace)) 710184610Salfred Current.Type = TT_DesignatedInitializerPeriod; 711184610Salfred } 712184610Salfred } 713184610Salfred } 714184610Salfred 715184610Salfred /// \brief Take a guess at whether \p Tok starts a name of a function or 716184610Salfred /// variable declaration. 717184610Salfred /// 718184610Salfred /// This is a heuristic based on whether \p Tok is an identifier following 719184610Salfred /// something that is likely a type. 720184610Salfred bool isStartOfName(const FormatToken &Tok) { 721184610Salfred if (Tok.isNot(tok::identifier) || Tok.Previous == NULL) 722184610Salfred return false; 723184610Salfred 724184610Salfred // Skip "const" as it does not have an influence on whether this is a name. 725184610Salfred FormatToken *PreviousNotConst = Tok.Previous; 726184610Salfred while (PreviousNotConst != NULL && PreviousNotConst->is(tok::kw_const)) 727184610Salfred PreviousNotConst = PreviousNotConst->Previous; 728184610Salfred 729184610Salfred if (PreviousNotConst == NULL) 730184610Salfred return false; 731184610Salfred 732184610Salfred bool IsPPKeyword = PreviousNotConst->is(tok::identifier) && 733184610Salfred PreviousNotConst->Previous && 734184610Salfred PreviousNotConst->Previous->is(tok::hash); 735184610Salfred 736184610Salfred if (PreviousNotConst->Type == TT_TemplateCloser) 737184610Salfred return PreviousNotConst && PreviousNotConst->MatchingParen && 738184610Salfred PreviousNotConst->MatchingParen->Previous && 739184610Salfred PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template); 740184610Salfred 741196495Salfred return (!IsPPKeyword && PreviousNotConst->is(tok::identifier)) || 742196495Salfred PreviousNotConst->Type == TT_PointerOrReference || 743196495Salfred isSimpleTypeSpecifier(*PreviousNotConst); 744196495Salfred } 745184610Salfred 746184610Salfred /// \brief Return the type of the given token assuming it is * or &. 747184610Salfred TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression) { 748184610Salfred const FormatToken *PrevToken = Tok.getPreviousNonComment(); 749184610Salfred if (PrevToken == NULL) 750184610Salfred return TT_UnaryOperator; 751184610Salfred 752184610Salfred const FormatToken *NextToken = Tok.getNextNonComment(); 753184610Salfred if (NextToken == NULL) 754184610Salfred return TT_Unknown; 755184610Salfred 756184610Salfred if (PrevToken->is(tok::coloncolon) || 757184610Salfred (PrevToken->is(tok::l_paren) && !IsExpression)) 758184610Salfred return TT_PointerOrReference; 759184610Salfred 760184610Salfred if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace, 761184610Salfred tok::comma, tok::semi, tok::kw_return, tok::colon, 762184610Salfred tok::equal, tok::kw_delete, tok::kw_sizeof) || 763184610Salfred PrevToken->Type == TT_BinaryOperator || 764184610Salfred PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen) 765184610Salfred return TT_UnaryOperator; 766184610Salfred 767184610Salfred if (NextToken->is(tok::l_square)) 768184610Salfred return TT_PointerOrReference; 769184610Salfred 770184610Salfred if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen && 771184610Salfred PrevToken->MatchingParen->Previous && 772184610Salfred PrevToken->MatchingParen->Previous->is(tok::kw_typeof)) 773184610Salfred return TT_PointerOrReference; 774184610Salfred 775184610Salfred if (PrevToken->Tok.isLiteral() || 776184610Salfred PrevToken->isOneOf(tok::r_paren, tok::r_square) || 777184610Salfred NextToken->Tok.isLiteral() || NextToken->isUnaryOperator()) 778184610Salfred return TT_BinaryOperator; 779184610Salfred 780184610Salfred // It is very unlikely that we are going to find a pointer or reference type 781184610Salfred // definition on the RHS of an assignment. 782184610Salfred if (IsExpression) 783184610Salfred return TT_BinaryOperator; 784184610Salfred 785184610Salfred return TT_PointerOrReference; 786184610Salfred } 787184610Salfred 788184610Salfred TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) { 789184610Salfred const FormatToken *PrevToken = Tok.getPreviousNonComment(); 790184610Salfred if (PrevToken == NULL || PrevToken->Type == TT_CastRParen) 791184610Salfred return TT_UnaryOperator; 792184610Salfred 793184610Salfred // Use heuristics to recognize unary operators. 794184610Salfred if (PrevToken->isOneOf(tok::equal, tok::l_paren, tok::comma, tok::l_square, 795184610Salfred tok::question, tok::colon, tok::kw_return, 796184610Salfred tok::kw_case, tok::at, tok::l_brace)) 797184610Salfred return TT_UnaryOperator; 798184610Salfred 799184610Salfred // There can't be two consecutive binary operators. 800184610Salfred if (PrevToken->Type == TT_BinaryOperator) 801184610Salfred return TT_UnaryOperator; 802184610Salfred 803184610Salfred // Fall back to marking the token as binary operator. 804184610Salfred return TT_BinaryOperator; 805184610Salfred } 806184610Salfred 807184610Salfred /// \brief Determine whether ++/-- are pre- or post-increments/-decrements. 808184610Salfred TokenType determineIncrementUsage(const FormatToken &Tok) { 809184610Salfred const FormatToken *PrevToken = Tok.getPreviousNonComment(); 810184610Salfred if (PrevToken == NULL || PrevToken->Type == TT_CastRParen) 811184610Salfred return TT_UnaryOperator; 812184610Salfred if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier)) 813184610Salfred return TT_TrailingUnaryOperator; 814184610Salfred 815184610Salfred return TT_UnaryOperator; 816184610Salfred } 817184610Salfred 818184610Salfred // FIXME: This is copy&pasted from Sema. Put it in a common place and remove 819184610Salfred // duplication. 820184610Salfred /// \brief Determine whether the token kind starts a simple-type-specifier. 821184610Salfred bool isSimpleTypeSpecifier(const FormatToken &Tok) const { 822184610Salfred switch (Tok.Tok.getKind()) { 823184610Salfred case tok::kw_short: 824184610Salfred case tok::kw_long: 825184610Salfred case tok::kw___int64: 826184610Salfred case tok::kw___int128: 827184610Salfred case tok::kw_signed: 828184610Salfred case tok::kw_unsigned: 829184610Salfred case tok::kw_void: 830184610Salfred case tok::kw_char: 831184610Salfred case tok::kw_int: 832184610Salfred case tok::kw_half: 833184610Salfred case tok::kw_float: 834184610Salfred case tok::kw_double: 835184610Salfred case tok::kw_wchar_t: 836184610Salfred case tok::kw_bool: 837184610Salfred case tok::kw___underlying_type: 838184610Salfred case tok::annot_typename: 839184610Salfred case tok::kw_char16_t: 840184610Salfred case tok::kw_char32_t: 841184610Salfred case tok::kw_typeof: 842184610Salfred case tok::kw_decltype: 843184610Salfred return true; 844184610Salfred default: 845184610Salfred return false; 846184610Salfred } 847184610Salfred } 848184610Salfred 849184610Salfred SmallVector<Context, 8> Contexts; 850184610Salfred 851184610Salfred const FormatStyle &Style; 852184610Salfred AnnotatedLine &Line; 853184610Salfred FormatToken *CurrentToken; 854184610Salfred bool KeywordVirtualFound; 855184610Salfred bool AutoFound; 856184610Salfred IdentifierInfo &Ident_in; 857184610Salfred}; 858184610Salfred 859184610Salfredstatic int PrecedenceUnaryOperator = prec::PointerToMember + 1; 860184610Salfredstatic int PrecedenceArrowAndPeriod = prec::PointerToMember + 2; 861184610Salfred 862184610Salfred/// \brief Parses binary expressions by inserting fake parenthesis based on 863184610Salfred/// operator precedence. 864184610Salfredclass ExpressionParser { 865184610Salfredpublic: 866184610Salfred ExpressionParser(AnnotatedLine &Line) : Current(Line.First) { 867184610Salfred // Skip leading "}", e.g. in "} else if (...) {". 868184610Salfred if (Current->is(tok::r_brace)) 869184610Salfred next(); 870184610Salfred } 871184610Salfred 872184610Salfred /// \brief Parse expressions with the given operatore precedence. 873184610Salfred void parse(int Precedence = 0) { 874184610Salfred // Skip 'return' and ObjC selector colons as they are not part of a binary 875184610Salfred // expression. 876184610Salfred while (Current && 877184610Salfred (Current->is(tok::kw_return) || 878184610Salfred (Current->is(tok::colon) && Current->Type == TT_ObjCMethodExpr))) 879184610Salfred next(); 880184610Salfred 881184610Salfred if (Current == NULL || Precedence > PrecedenceArrowAndPeriod) 882184610Salfred return; 883184610Salfred 884184610Salfred // Conditional expressions need to be parsed separately for proper nesting. 885184610Salfred if (Precedence == prec::Conditional) { 886184610Salfred parseConditionalExpr(); 887184610Salfred return; 888184610Salfred } 889189905Sthompsa 890192052Sthompsa // Parse unary operators, which all have a higher precedence than binary 891189905Sthompsa // operators. 892189905Sthompsa if (Precedence == PrecedenceUnaryOperator) { 893184610Salfred parseUnaryOperator(); 894184610Salfred return; 895184610Salfred } 896184610Salfred 897184610Salfred FormatToken *Start = Current; 898184610Salfred FormatToken *LatestOperator = NULL; 899184610Salfred 900184610Salfred while (Current) { 901196495Salfred // Consume operators with higher precedence. 902196495Salfred parse(Precedence + 1); 903196495Salfred 904196495Salfred int CurrentPrecedence = getCurrentPrecedence(); 905184610Salfred 906184610Salfred if (Current && Current->Type == TT_ObjCSelectorName && 907184610Salfred Precedence == CurrentPrecedence) 908184610Salfred Start = Current; 909184610Salfred 910184610Salfred // At the end of the line or when an operator with higher precedence is 911184610Salfred // found, insert fake parenthesis and return. 912184610Salfred if (Current == NULL || Current->closesScope() || 913184610Salfred (CurrentPrecedence != -1 && CurrentPrecedence < Precedence)) { 914184610Salfred if (LatestOperator) { 915184610Salfred if (Precedence == PrecedenceArrowAndPeriod) { 916184610Salfred LatestOperator->LastInChainOfCalls = true; 917184610Salfred // Call expressions don't have a binary operator precedence. 918184610Salfred addFakeParenthesis(Start, prec::Unknown); 919184610Salfred } else { 920184610Salfred addFakeParenthesis(Start, prec::Level(Precedence)); 921184610Salfred } 922184610Salfred } 923184610Salfred return; 924184610Salfred } 925184610Salfred 926184610Salfred // Consume scopes: (), [], <> and {} 927184610Salfred if (Current->opensScope()) { 928184610Salfred while (Current && !Current->closesScope()) { 929184610Salfred next(); 930184610Salfred parse(); 931184610Salfred } 932184610Salfred next(); 933184610Salfred } else { 934184610Salfred // Operator found. 935184610Salfred if (CurrentPrecedence == Precedence) 936184610Salfred LatestOperator = Current; 937184610Salfred 938184610Salfred next(); 939184610Salfred } 940184610Salfred } 941184610Salfred } 942184610Salfred 943184610Salfredprivate: 944184610Salfred /// \brief Gets the precedence (+1) of the given token for binary operators 945184610Salfred /// and other tokens that we treat like binary operators. 946184610Salfred int getCurrentPrecedence() { 947184610Salfred if (Current) { 948184610Salfred if (Current->Type == TT_ConditionalExpr) 949197565Sthompsa return prec::Conditional; 950197565Sthompsa else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon || 951197565Sthompsa Current->Type == TT_ObjCSelectorName) 952197565Sthompsa return 0; 953184610Salfred else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma)) 954184610Salfred return Current->getPrecedence(); 955184610Salfred else if (Current->isOneOf(tok::period, tok::arrow)) 956184610Salfred return PrecedenceArrowAndPeriod; 957184610Salfred } 958184610Salfred return -1; 959184610Salfred } 960184610Salfred 961184610Salfred void addFakeParenthesis(FormatToken *Start, prec::Level Precedence) { 962184610Salfred Start->FakeLParens.push_back(Precedence); 963184610Salfred if (Precedence > prec::Unknown) 964184610Salfred Start->StartsBinaryExpression = true; 965184610Salfred if (Current) { 966184610Salfred ++Current->Previous->FakeRParens; 967184610Salfred if (Precedence > prec::Unknown) 968184610Salfred Current->Previous->EndsBinaryExpression = true; 969184610Salfred } 970184610Salfred } 971184610Salfred 972184610Salfred /// \brief Parse unary operator expressions and surround them with fake 973187163Sthompsa /// parentheses if appropriate. 974187163Sthompsa void parseUnaryOperator() { 975187163Sthompsa if (Current == NULL || Current->Type != TT_UnaryOperator) { 976187163Sthompsa parse(PrecedenceArrowAndPeriod); 977195080Sdelphij return; 978195080Sdelphij } 979195080Sdelphij 980195080Sdelphij FormatToken *Start = Current; 981196495Salfred next(); 982196495Salfred parseUnaryOperator(); 983196495Salfred 984196495Salfred // The actual precedence doesn't matter. 985184610Salfred addFakeParenthesis(Start, prec::Unknown); 986184610Salfred } 987184610Salfred 988184610Salfred void parseConditionalExpr() { 989184610Salfred FormatToken *Start = Current; 990184610Salfred parse(prec::LogicalOr); 991184610Salfred if (!Current || !Current->is(tok::question)) 992184610Salfred return; 993184610Salfred next(); 994184610Salfred parse(prec::LogicalOr); 995184610Salfred if (!Current || Current->Type != TT_ConditionalExpr) 996184610Salfred return; 997184610Salfred next(); 998184610Salfred parseConditionalExpr(); 999184610Salfred addFakeParenthesis(Start, prec::Conditional); 1000184610Salfred } 1001184610Salfred 1002184610Salfred void next() { 1003184610Salfred if (Current) 1004184610Salfred Current = Current->Next; 1005184610Salfred while (Current && Current->isTrailingComment()) 1006184610Salfred Current = Current->Next; 1007184610Salfred } 1008184610Salfred 1009184610Salfred FormatToken *Current; 1010184610Salfred}; 1011184610Salfred 1012184610Salfred} // end anonymous namespace 1013184610Salfred 1014184610Salfredvoid 1015184610SalfredTokenAnnotator::setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) { 1016184610Salfred const AnnotatedLine *NextNonCommentLine = NULL; 1017192984Sthompsa for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(), 1018184610Salfred E = Lines.rend(); 1019192984Sthompsa I != E; ++I) { 1020184610Salfred if (NextNonCommentLine && (*I)->First->is(tok::comment) && 1021184610Salfred (*I)->First->Next == NULL) 1022184610Salfred (*I)->Level = NextNonCommentLine->Level; 1023184610Salfred else 1024184610Salfred NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : NULL; 1025184610Salfred 1026184610Salfred setCommentLineLevels((*I)->Children); 1027184610Salfred } 1028184610Salfred} 1029184610Salfred 1030184610Salfredvoid TokenAnnotator::annotate(AnnotatedLine &Line) { 1031184610Salfred for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(), 1032184610Salfred E = Line.Children.end(); 1033184610Salfred I != E; ++I) { 1034184610Salfred annotate(**I); 1035184610Salfred } 1036184610Salfred AnnotatingParser Parser(Style, Line, Ident_in); 1037184610Salfred Line.Type = Parser.parseLine(); 1038184610Salfred if (Line.Type == LT_Invalid) 1039184610Salfred return; 1040184610Salfred 1041184610Salfred ExpressionParser ExprParser(Line); 1042184610Salfred ExprParser.parse(); 1043184610Salfred 1044184610Salfred if (Line.First->Type == TT_ObjCMethodSpecifier) 1045184610Salfred Line.Type = LT_ObjCMethodDecl; 1046184610Salfred else if (Line.First->Type == TT_ObjCDecl) 1047184610Salfred Line.Type = LT_ObjCDecl; 1048184610Salfred else if (Line.First->Type == TT_ObjCProperty) 1049184610Salfred Line.Type = LT_ObjCProperty; 1050184610Salfred 1051184610Salfred Line.First->SpacesRequiredBefore = 1; 1052193045Sthompsa Line.First->CanBreakBefore = Line.First->MustBreakBefore; 1053193045Sthompsa} 1054193045Sthompsa 1055193045Sthompsavoid TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) { 1056193045Sthompsa Line.First->TotalLength = 1057193045Sthompsa Line.First->IsMultiline ? Style.ColumnLimit : Line.First->ColumnWidth; 1058193045Sthompsa if (!Line.First->Next) 1059193045Sthompsa return; 1060193045Sthompsa FormatToken *Current = Line.First->Next; 1061193045Sthompsa bool InFunctionDecl = Line.MightBeFunctionDecl; 1062193045Sthompsa while (Current != NULL) { 1063193045Sthompsa if (Current->Type == TT_LineComment) 1064193045Sthompsa Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments; 1065193045Sthompsa else if (Current->SpacesRequiredBefore == 0 && 1066193045Sthompsa spaceRequiredBefore(Line, *Current)) 1067193045Sthompsa Current->SpacesRequiredBefore = 1; 1068193045Sthompsa 1069193045Sthompsa Current->MustBreakBefore = 1070193045Sthompsa Current->MustBreakBefore || mustBreakBefore(Line, *Current); 1071193045Sthompsa 1072184610Salfred Current->CanBreakBefore = 1073185948Sthompsa Current->MustBreakBefore || canBreakBefore(Line, *Current); 1074185948Sthompsa if (Current->MustBreakBefore || !Current->Children.empty() || 1075185948Sthompsa Current->IsMultiline) 1076192984Sthompsa Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit; 1077194677Sthompsa else 1078185948Sthompsa Current->TotalLength = Current->Previous->TotalLength + 1079185948Sthompsa Current->ColumnWidth + 1080185948Sthompsa Current->SpacesRequiredBefore; 1081185948Sthompsa 1082192984Sthompsa if (Current->Type == TT_CtorInitializerColon) 1083194677Sthompsa InFunctionDecl = false; 1084185948Sthompsa 1085185948Sthompsa // FIXME: Only calculate this if CanBreakBefore is true once static 1086185948Sthompsa // initializers etc. are sorted out. 1087185948Sthompsa // FIXME: Move magic numbers to a better place. 1088185948Sthompsa Current->SplitPenalty = 20 * Current->BindingStrength + 1089185948Sthompsa splitPenalty(Line, *Current, InFunctionDecl); 1090185948Sthompsa 1091185948Sthompsa Current = Current->Next; 1092185948Sthompsa } 1093185948Sthompsa 1094185948Sthompsa calculateUnbreakableTailLengths(Line); 1095185948Sthompsa for (Current = Line.First; Current != NULL; Current = Current->Next) { 1096185948Sthompsa if (Current->Role) 1097185948Sthompsa Current->Role->precomputeFormattingInfos(Current); 1098185948Sthompsa } 1099185948Sthompsa 1100185948Sthompsa DEBUG({ printDebugInfo(Line); }); 1101185948Sthompsa 1102185948Sthompsa for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(), 1103185948Sthompsa E = Line.Children.end(); 1104185948Sthompsa I != E; ++I) { 1105184610Salfred calculateFormattingInformation(**I); 1106184610Salfred } 1107185948Sthompsa} 1108185948Sthompsa 1109185948Sthompsavoid TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) { 1110185948Sthompsa unsigned UnbreakableTailLength = 0; 1111185948Sthompsa FormatToken *Current = Line.Last; 1112184610Salfred while (Current != NULL) { 1113184610Salfred Current->UnbreakableTailLength = UnbreakableTailLength; 1114194099Sthompsa if (Current->CanBreakBefore || 1115184610Salfred Current->isOneOf(tok::comment, tok::string_literal)) { 1116184610Salfred UnbreakableTailLength = 0; 1117184610Salfred } else { 1118184610Salfred UnbreakableTailLength += 1119184610Salfred Current->ColumnWidth + Current->SpacesRequiredBefore; 1120192984Sthompsa } 1121190734Sthompsa Current = Current->Previous; 1122190734Sthompsa } 1123190734Sthompsa} 1124184610Salfred 1125184610Salfredunsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, 1126184610Salfred const FormatToken &Tok, 1127184610Salfred bool InFunctionDecl) { 1128184610Salfred const FormatToken &Left = *Tok.Previous; 1129184610Salfred const FormatToken &Right = Tok; 1130192984Sthompsa 1131190734Sthompsa if (Left.is(tok::semi)) 1132190734Sthompsa return 0; 1133190734Sthompsa if (Left.is(tok::comma)) 1134184610Salfred return 1; 1135184610Salfred if (Right.is(tok::l_square)) 1136184610Salfred return 150; 1137184610Salfred 1138184610Salfred if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator)) { 1139184610Salfred if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt) 1140192984Sthompsa return 3; 1141190734Sthompsa if (Left.Type == TT_StartOfName) 1142190734Sthompsa return 20; 1143190734Sthompsa if (InFunctionDecl && Right.BindingStrength == 1) 1144184610Salfred // FIXME: Clean up hack of using BindingStrength to find top-level names. 1145184610Salfred return Style.PenaltyReturnTypeOnItsOwnLine; 1146184610Salfred return 200; 1147184610Salfred } 1148184610Salfred if (Left.is(tok::equal) && Right.is(tok::l_brace)) 1149184610Salfred return 150; 1150190734Sthompsa if (Left.Type == TT_CastRParen) 1151190734Sthompsa return 100; 1152190734Sthompsa if (Left.is(tok::coloncolon)) 1153184610Salfred return 500; 1154184610Salfred if (Left.isOneOf(tok::kw_class, tok::kw_struct)) 1155184610Salfred return 5000; 1156184610Salfred 1157184610Salfred if (Left.Type == TT_RangeBasedForLoopColon || 1158184610Salfred Left.Type == TT_InheritanceColon) 1159190734Sthompsa return 2; 1160190734Sthompsa 1161190734Sthompsa if (Right.isMemberAccess()) { 1162190734Sthompsa if (Left.isOneOf(tok::r_paren, tok::r_square) && Left.MatchingParen && 1163184610Salfred Left.MatchingParen->ParameterCount > 0) 1164184610Salfred return 20; // Should be smaller than breaking at a nested comma. 1165184610Salfred return 150; 1166184610Salfred } 1167184610Salfred 1168184610Salfred // Breaking before a trailing 'const' or not-function-like annotation is bad. 1169192984Sthompsa if (Left.is(tok::r_paren) && Line.Type != LT_ObjCProperty && 1170190734Sthompsa (Right.is(tok::kw_const) || (Right.is(tok::identifier) && Right.Next && 1171190734Sthompsa Right.Next->isNot(tok::l_paren)))) 1172184610Salfred return 100; 1173184610Salfred 1174184610Salfred // In for-loops, prefer breaking at ',' and ';'. 1175184610Salfred if (Line.First->is(tok::kw_for) && Left.is(tok::equal)) 1176184610Salfred return 4; 1177184610Salfred 1178190734Sthompsa // In Objective-C method expressions, prefer breaking before "param:" over 1179190734Sthompsa // breaking after it. 1180190734Sthompsa if (Right.Type == TT_ObjCSelectorName) 1181190734Sthompsa return 0; 1182184610Salfred if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr) 1183184610Salfred return 50; 1184184610Salfred 1185184610Salfred if (Left.is(tok::l_paren) && InFunctionDecl) 1186184610Salfred return 100; 1187184610Salfred if (Left.opensScope()) 1188192984Sthompsa return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter 1189190734Sthompsa : 19; 1190190734Sthompsa 1191184610Salfred if (Right.is(tok::lessless)) { 1192184610Salfred if (Left.is(tok::string_literal)) { 1193184610Salfred StringRef Content = Left.TokenText; 1194184610Salfred if (Content.startswith("\"")) 1195184610Salfred Content = Content.drop_front(1); 1196184610Salfred if (Content.endswith("\"")) 1197190734Sthompsa Content = Content.drop_back(1); 1198190734Sthompsa Content = Content.trim(); 1199190734Sthompsa if (Content.size() > 1 && 1200190734Sthompsa (Content.back() == ':' || Content.back() == '=')) 1201184610Salfred return 25; 1202184610Salfred } 1203184610Salfred return 1; // Breaking at a << is really cheap. 1204194099Sthompsa } 1205184610Salfred if (Left.Type == TT_ConditionalExpr) 1206184610Salfred return prec::Conditional; 1207184610Salfred prec::Level Level = Left.getPrecedence(); 1208184610Salfred 1209184610Salfred if (Level != prec::Unknown) 1210192984Sthompsa return Level; 1211184610Salfred 1212190734Sthompsa return 3; 1213190734Sthompsa} 1214190734Sthompsa 1215184610Salfredbool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, 1216184610Salfred const FormatToken &Left, 1217184610Salfred const FormatToken &Right) { 1218184610Salfred if (Right.is(tok::hashhash)) 1219184610Salfred return Left.is(tok::hash); 1220184610Salfred if (Left.isOneOf(tok::hashhash, tok::hash)) 1221192984Sthompsa return Right.is(tok::hash); 1222190734Sthompsa if (Left.is(tok::l_paren) && Right.is(tok::r_paren)) 1223190734Sthompsa return Style.SpaceInEmptyParentheses; 1224190734Sthompsa if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) 1225184610Salfred return (Right.Type == TT_CastRParen || 1226184610Salfred (Left.MatchingParen && Left.MatchingParen->Type == TT_CastRParen)) 1227184610Salfred ? Style.SpacesInCStyleCastParentheses 1228184610Salfred : Style.SpacesInParentheses; 1229184610Salfred if (Style.SpacesInAngles && 1230184610Salfred ((Left.Type == TT_TemplateOpener) != (Right.Type == TT_TemplateCloser))) 1231192984Sthompsa return true; 1232190734Sthompsa if (Right.isOneOf(tok::semi, tok::comma)) 1233190734Sthompsa return false; 1234190734Sthompsa if (Right.is(tok::less) && 1235184610Salfred (Left.is(tok::kw_template) || 1236184610Salfred (Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList))) 1237184610Salfred return true; 1238184610Salfred if (Left.is(tok::arrow) || Right.is(tok::arrow)) 1239184610Salfred return false; 1240184610Salfred if (Left.isOneOf(tok::exclaim, tok::tilde)) 1241192984Sthompsa return false; 1242184610Salfred if (Left.is(tok::at) && 1243190734Sthompsa Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant, 1244190734Sthompsa tok::numeric_constant, tok::l_paren, tok::l_brace, 1245184610Salfred tok::kw_true, tok::kw_false)) 1246184610Salfred return false; 1247184610Salfred if (Left.is(tok::coloncolon)) 1248184610Salfred return false; 1249184610Salfred if (Right.is(tok::coloncolon)) 1250184610Salfred return (Left.is(tok::less) && Style.Standard == FormatStyle::LS_Cpp03) || 1251190734Sthompsa !Left.isOneOf(tok::identifier, tok::greater, tok::l_paren, 1252190734Sthompsa tok::r_paren, tok::less); 1253190734Sthompsa if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) 1254190734Sthompsa return false; 1255184610Salfred if (Right.is(tok::ellipsis)) 1256184610Salfred return Left.Tok.isLiteral(); 1257184610Salfred if (Left.is(tok::l_square) && Right.is(tok::amp)) 1258184610Salfred return false; 1259184610Salfred if (Right.Type == TT_PointerOrReference) 1260184610Salfred return Left.Tok.isLiteral() || 1261192984Sthompsa ((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) && 1262190734Sthompsa !Style.PointerBindsToType); 1263190734Sthompsa if (Right.Type == TT_FunctionTypeLParen && Left.isNot(tok::l_paren) && 1264184610Salfred (Left.Type != TT_PointerOrReference || Style.PointerBindsToType)) 1265184610Salfred return true; 1266184610Salfred if (Left.Type == TT_PointerOrReference) 1267184610Salfred return Right.Tok.isLiteral() || Right.Type == TT_BlockComment || 1268184610Salfred ((Right.Type != TT_PointerOrReference) && 1269184610Salfred Right.isNot(tok::l_paren) && Style.PointerBindsToType && 1270190734Sthompsa Left.Previous && 1271190734Sthompsa !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon)); 1272190734Sthompsa if (Right.is(tok::star) && Left.is(tok::l_paren)) 1273190734Sthompsa return false; 1274184610Salfred if (Left.is(tok::l_square)) 1275184610Salfred return Left.Type == TT_ArrayInitializerLSquare && 1276184610Salfred Right.isNot(tok::r_square); 1277184610Salfred if (Right.is(tok::r_square)) 1278184610Salfred return Right.MatchingParen && 1279184610Salfred Right.MatchingParen->Type == TT_ArrayInitializerLSquare; 1280192984Sthompsa if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr && 1281190734Sthompsa Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant)) 1282190734Sthompsa return false; 1283184610Salfred if (Left.is(tok::colon)) 1284184610Salfred return Left.Type != TT_ObjCMethodExpr; 1285184610Salfred if (Right.is(tok::colon)) 1286184610Salfred return Right.Type != TT_ObjCMethodExpr && !Left.is(tok::question); 1287184610Salfred if (Right.is(tok::l_paren)) { 1288184610Salfred if (Left.is(tok::r_paren) && Left.MatchingParen && 1289190734Sthompsa Left.MatchingParen->Previous && 1290190734Sthompsa Left.MatchingParen->Previous->is(tok::kw___attribute)) 1291190734Sthompsa return true; 1292190734Sthompsa return Line.Type == LT_ObjCDecl || 1293184610Salfred Left.isOneOf(tok::kw_return, tok::kw_new, tok::kw_delete, 1294184610Salfred tok::semi) || 1295184610Salfred (Style.SpaceAfterControlStatementKeyword && 1296184610Salfred Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch, 1297184610Salfred tok::kw_catch)); 1298184610Salfred } 1299192984Sthompsa if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword) 1300190734Sthompsa return false; 1301190734Sthompsa if (Left.is(tok::l_brace) && Right.is(tok::r_brace)) 1302184610Salfred return !Left.Children.empty(); // No spaces in "{}". 1303184610Salfred if (Left.is(tok::l_brace) || Right.is(tok::r_brace)) 1304184610Salfred return !Style.Cpp11BracedListStyle; 1305184610Salfred if (Right.Type == TT_UnaryOperator) 1306184610Salfred return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) && 1307184610Salfred (Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr); 1308184610Salfred if (Left.isOneOf(tok::identifier, tok::greater, tok::r_square) && 1309184610Salfred Right.is(tok::l_brace) && Right.getNextNonComment() && 1310184610Salfred Right.BlockKind != BK_Block) 1311184610Salfred return false; 1312184610Salfred if (Left.is(tok::period) || Right.is(tok::period)) 1313184610Salfred return false; 1314184610Salfred if (Left.Type == TT_BlockComment && Left.TokenText.endswith("=*/")) 1315184610Salfred return false; 1316184610Salfred if (Right.is(tok::hash) && Left.is(tok::identifier) && Left.TokenText == "L") 1317184610Salfred return false; 1318184610Salfred return true; 1319184610Salfred} 1320184610Salfred 1321184610Salfredbool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, 1322184610Salfred const FormatToken &Tok) { 1323184610Salfred if (Tok.Tok.getIdentifierInfo() && Tok.Previous->Tok.getIdentifierInfo()) 1324184610Salfred return true; // Never ever merge two identifiers. 1325184610Salfred if (Tok.Previous->Type == TT_ImplicitStringLiteral) 1326184610Salfred return Tok.WhitespaceRange.getBegin() != Tok.WhitespaceRange.getEnd(); 1327184610Salfred if (Line.Type == LT_ObjCMethodDecl) { 1328184610Salfred if (Tok.Previous->Type == TT_ObjCMethodSpecifier) 1329184610Salfred return true; 1330189275Sthompsa if (Tok.Previous->is(tok::r_paren) && Tok.is(tok::identifier)) 1331188942Sthompsa // Don't space between ')' and <id> 1332184610Salfred return false; 1333184610Salfred } 1334184610Salfred if (Line.Type == LT_ObjCProperty && 1335184610Salfred (Tok.is(tok::equal) || Tok.Previous->is(tok::equal))) 1336184610Salfred return false; 1337184610Salfred 1338192052Sthompsa if (Tok.Type == TT_TrailingReturnArrow || 1339192984Sthompsa Tok.Previous->Type == TT_TrailingReturnArrow) 1340192052Sthompsa return true; 1341192984Sthompsa if (Tok.Previous->is(tok::comma)) 1342192052Sthompsa return true; 1343192052Sthompsa if (Tok.is(tok::comma)) 1344192052Sthompsa return false; 1345192052Sthompsa if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen) 1346192052Sthompsa return true; 1347194228Sthompsa if (Tok.Previous->Tok.is(tok::kw_operator)) 1348192052Sthompsa return Tok.is(tok::coloncolon); 1349192052Sthompsa if (Tok.Type == TT_OverloadedOperatorLParen) 1350192052Sthompsa return false; 1351192052Sthompsa if (Tok.is(tok::colon)) 1352192052Sthompsa return !Line.First->isOneOf(tok::kw_case, tok::kw_default) && 1353192052Sthompsa Tok.getNextNonComment() != NULL && Tok.Type != TT_ObjCMethodExpr && 1354192052Sthompsa !Tok.Previous->is(tok::question); 1355192052Sthompsa if (Tok.Previous->Type == TT_UnaryOperator || 1356192052Sthompsa Tok.Previous->Type == TT_CastRParen) 1357192052Sthompsa return false; 1358192052Sthompsa if (Tok.Previous->is(tok::greater) && Tok.is(tok::greater)) { 1359192052Sthompsa return Tok.Type == TT_TemplateCloser && 1360192052Sthompsa Tok.Previous->Type == TT_TemplateCloser && 1361192052Sthompsa (Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles); 1362192052Sthompsa } 1363192052Sthompsa if (Tok.isOneOf(tok::arrowstar, tok::periodstar) || 1364192052Sthompsa Tok.Previous->isOneOf(tok::arrowstar, tok::periodstar)) 1365192052Sthompsa return false; 1366192052Sthompsa if (!Style.SpaceBeforeAssignmentOperators && 1367192052Sthompsa Tok.getPrecedence() == prec::Assignment) 1368192052Sthompsa return false; 1369192052Sthompsa if ((Tok.Type == TT_BinaryOperator && !Tok.Previous->is(tok::l_paren)) || 1370192052Sthompsa Tok.Previous->Type == TT_BinaryOperator) 1371192052Sthompsa return true; 1372192052Sthompsa if (Tok.Previous->Type == TT_TemplateCloser && Tok.is(tok::l_paren)) 1373192052Sthompsa return false; 1374192052Sthompsa if (Tok.is(tok::less) && Tok.Previous->isNot(tok::l_paren) && 1375192052Sthompsa Line.First->is(tok::hash)) 1376192052Sthompsa return true; 1377192052Sthompsa if (Tok.Type == TT_TrailingUnaryOperator) 1378192052Sthompsa return false; 1379192052Sthompsa return spaceRequiredBetween(Line, *Tok.Previous, Tok); 1380192052Sthompsa} 1381192052Sthompsa 1382192052Sthompsabool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, 1383192052Sthompsa const FormatToken &Right) { 1384192052Sthompsa if (Right.is(tok::comment)) { 1385192052Sthompsa return Right.NewlinesBefore > 0; 1386192052Sthompsa } else if (Right.Previous->isTrailingComment() || 1387192052Sthompsa (Right.is(tok::string_literal) && 1388192052Sthompsa Right.Previous->is(tok::string_literal))) { 1389192052Sthompsa return true; 1390184610Salfred } else if (Right.Previous->IsUnterminatedLiteral) { 1391184610Salfred return true; 1392184610Salfred } else if (Right.is(tok::lessless) && Right.Next && 1393184610Salfred Right.Previous->is(tok::string_literal) && 1394184610Salfred Right.Next->is(tok::string_literal)) { 1395192984Sthompsa return true; 1396184610Salfred } else if (Right.Previous->ClosesTemplateDeclaration && 1397184610Salfred Right.Previous->MatchingParen && 1398184610Salfred Right.Previous->MatchingParen->BindingStrength == 1 && 1399184610Salfred Style.AlwaysBreakTemplateDeclarations) { 1400192052Sthompsa // FIXME: Fix horrible hack of using BindingStrength to find top-level <>. 1401184610Salfred return true; 1402184610Salfred } else if (Right.Type == TT_CtorInitializerComma && 1403184610Salfred Style.BreakConstructorInitializersBeforeComma && 1404184610Salfred !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) { 1405184610Salfred return true; 1406184610Salfred } else if (Right.Previous->BlockKind == BK_Block && 1407184610Salfred Right.Previous->isNot(tok::r_brace) && Right.isNot(tok::r_brace)) { 1408184610Salfred return true; 1409184610Salfred } else if (Right.is(tok::l_brace) && (Right.BlockKind == BK_Block)) { 1410184610Salfred return Style.BreakBeforeBraces == FormatStyle::BS_Allman; 1411184610Salfred } 1412184610Salfred return false; 1413184610Salfred} 1414184610Salfred 1415184610Salfredbool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, 1416184610Salfred const FormatToken &Right) { 1417184610Salfred const FormatToken &Left = *Right.Previous; 1418184610Salfred if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator)) 1419184610Salfred return true; 1420184610Salfred if (Right.isTrailingComment()) 1421184610Salfred // We rely on MustBreakBefore being set correctly here as we should not 1422184610Salfred // change the "binding" behavior of a comment. 1423184610Salfred return false; 1424184610Salfred if (Left.is(tok::question) && Right.is(tok::colon)) 1425184610Salfred return false; 1426184610Salfred if (Right.Type == TT_ConditionalExpr || Right.is(tok::question)) 1427184610Salfred return Style.BreakBeforeTernaryOperators; 1428184610Salfred if (Left.Type == TT_ConditionalExpr || Left.is(tok::question)) 1429184610Salfred return !Style.BreakBeforeTernaryOperators; 1430184610Salfred if (Right.is(tok::colon) && 1431184610Salfred (Right.Type == TT_DictLiteral || Right.Type == TT_ObjCMethodExpr)) 1432184610Salfred return false; 1433184610Salfred if (Left.is(tok::colon) && 1434184610Salfred (Left.Type == TT_DictLiteral || Left.Type == TT_ObjCMethodExpr)) 1435184610Salfred return true; 1436184610Salfred if (Right.Type == TT_ObjCSelectorName) 1437184610Salfred return true; 1438184610Salfred if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty) 1439184610Salfred return true; 1440184610Salfred if (Left.ClosesTemplateDeclaration) 1441192052Sthompsa return true; 1442192052Sthompsa if (Right.Type == TT_RangeBasedForLoopColon || 1443192052Sthompsa Right.Type == TT_OverloadedOperatorLParen || 1444192052Sthompsa Right.Type == TT_OverloadedOperator) 1445184610Salfred return false; 1446184610Salfred if (Left.Type == TT_RangeBasedForLoopColon) 1447184610Salfred return true; 1448192052Sthompsa if (Right.Type == TT_RangeBasedForLoopColon) 1449192052Sthompsa return false; 1450192052Sthompsa if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser || 1451192052Sthompsa Left.Type == TT_UnaryOperator || Left.is(tok::kw_operator)) 1452184610Salfred return false; 1453184610Salfred if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl) 1454184610Salfred return false; 1455184610Salfred if (Left.Previous) { 1456192052Sthompsa if (Left.is(tok::l_paren) && Right.is(tok::l_paren) && 1457192052Sthompsa Left.Previous->is(tok::kw___attribute)) 1458192052Sthompsa return false; 1459184610Salfred if (Left.is(tok::l_paren) && (Left.Previous->Type == TT_BinaryOperator || 1460192052Sthompsa Left.Previous->Type == TT_CastRParen)) 1461192052Sthompsa return false; 1462184610Salfred } 1463184610Salfred if (Right.Type == TT_ImplicitStringLiteral) 1464184610Salfred return false; 1465184610Salfred 1466184610Salfred if (Right.is(tok::r_paren) || Right.Type == TT_TemplateCloser) 1467184610Salfred return false; 1468184610Salfred 1469192984Sthompsa // We only break before r_brace if there was a corresponding break before 1470184610Salfred // the l_brace, which is tracked by BreakBeforeClosingBrace. 1471184610Salfred if (Right.is(tok::r_brace)) 1472192499Sthompsa return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block; 1473184610Salfred 1474184610Salfred // Allow breaking after a trailing 'const', e.g. after a method declaration, 1475184610Salfred // unless it is follow by ';', '{' or '='. 1476184610Salfred if (Left.is(tok::kw_const) && Left.Previous != NULL && 1477184610Salfred Left.Previous->is(tok::r_paren)) 1478184610Salfred return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal); 1479184610Salfred 1480184610Salfred if (Right.is(tok::kw___attribute)) 1481184610Salfred return true; 1482184610Salfred 1483184610Salfred if (Left.is(tok::identifier) && Right.is(tok::string_literal)) 1484184610Salfred return true; 1485184610Salfred 1486184610Salfred if (Left.Type == TT_CtorInitializerComma && 1487184610Salfred Style.BreakConstructorInitializersBeforeComma) 1488192984Sthompsa return false; 1489184610Salfred if (Right.Type == TT_CtorInitializerComma && 1490192984Sthompsa Style.BreakConstructorInitializersBeforeComma) 1491184610Salfred return true; 1492184610Salfred if (Right.isBinaryOperator() && Style.BreakBeforeBinaryOperators) 1493184610Salfred return true; 1494184610Salfred if (Left.is(tok::greater) && Right.is(tok::greater) && 1495184610Salfred Left.Type != TT_TemplateCloser) 1496184610Salfred return false; 1497184610Salfred if (Left.Type == TT_ArrayInitializerLSquare) 1498184610Salfred return true; 1499184610Salfred return (Left.isBinaryOperator() && Left.isNot(tok::lessless) && 1500184610Salfred !Style.BreakBeforeBinaryOperators) || 1501184610Salfred Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace, 1502184610Salfred tok::kw_class, tok::kw_struct) || 1503184610Salfred Right.isOneOf(tok::lessless, tok::arrow, tok::period, tok::colon, 1504184610Salfred tok::l_square, tok::at) || 1505184610Salfred (Left.is(tok::r_paren) && 1506184610Salfred Right.isOneOf(tok::identifier, tok::kw_const, tok::kw___attribute)) || 1507184610Salfred (Left.is(tok::l_paren) && !Right.is(tok::r_paren)); 1508194228Sthompsa} 1509184610Salfred 1510188415Sthompsavoid TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) { 1511188415Sthompsa llvm::errs() << "AnnotatedTokens:\n"; 1512188415Sthompsa const FormatToken *Tok = Line.First; 1513184610Salfred while (Tok) { 1514184610Salfred llvm::errs() << " M=" << Tok->MustBreakBefore 1515194228Sthompsa << " C=" << Tok->CanBreakBefore << " T=" << Tok->Type 1516184610Salfred << " S=" << Tok->SpacesRequiredBefore 1517184610Salfred << " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName() 1518184610Salfred << " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind 1519184610Salfred << " FakeLParens="; 1520184610Salfred for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i) 1521184610Salfred llvm::errs() << Tok->FakeLParens[i] << "/"; 1522184610Salfred llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n"; 1523184610Salfred if (Tok->Next == NULL) 1524184610Salfred assert(Tok == Line.Last); 1525184610Salfred Tok = Tok->Next; 1526184610Salfred } 1527184610Salfred llvm::errs() << "----\n"; 1528184610Salfred} 1529184610Salfred 1530184610Salfred} // namespace format 1531184610Salfred} // namespace clang 1532184610Salfred