1 //===--- TokenAnnotator.cpp - Format C++ code -----------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief This file implements a token annotator, i.e. creates
12 /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
14 //===----------------------------------------------------------------------===//
16 #include "TokenAnnotator.h"
17 #include "clang/Basic/SourceManager.h"
18 #include "llvm/Support/Debug.h"
25 /// \brief A parser that gathers additional information about tokens.
27 /// The \c TokenAnnotator tries to match parenthesis and square brakets and
28 /// store a parenthesis levels. It also tries to resolve matching "<" and ">"
29 /// into template parameter lists.
30 class AnnotatingParser {
32 AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,
33 IdentifierInfo &Ident_in)
34 : Style(Style), Line(Line), CurrentToken(Line.First),
35 KeywordVirtualFound(false), AutoFound(false), Ident_in(Ident_in) {
36 Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
41 if (CurrentToken == NULL)
43 ScopedContextCreator ContextCreator(*this, tok::less, 10);
44 FormatToken *Left = CurrentToken->Previous;
45 Contexts.back().IsExpression = false;
46 while (CurrentToken != NULL) {
47 if (CurrentToken->is(tok::greater)) {
48 Left->MatchingParen = CurrentToken;
49 CurrentToken->MatchingParen = Left;
50 CurrentToken->Type = TT_TemplateCloser;
54 if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace,
55 tok::question, tok::colon))
57 // If a && or || is found and interpreted as a binary operator, this set
58 // of angles is likely part of something like "a < b && c > d". If the
59 // angles are inside an expression, the ||/&& might also be a binary
60 // operator that was misinterpreted because we are parsing template
62 // FIXME: This is getting out of hand, write a decent parser.
63 if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
64 (CurrentToken->Previous->Type == TT_BinaryOperator ||
65 Contexts[Contexts.size() - 2].IsExpression) &&
66 Line.First->isNot(tok::kw_template))
68 updateParameterCount(Left, CurrentToken);
75 bool parseParens(bool LookForDecls = false) {
76 if (CurrentToken == NULL)
78 ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);
80 // FIXME: This is a bit of a hack. Do better.
81 Contexts.back().ColonIsForRangeExpr =
82 Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
84 bool StartsObjCMethodExpr = false;
85 FormatToken *Left = CurrentToken->Previous;
86 if (CurrentToken->is(tok::caret)) {
88 Left->Type = TT_ObjCBlockLParen;
89 } else if (FormatToken *MaybeSel = Left->Previous) {
90 // @selector( starts a selector.
91 if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous &&
92 MaybeSel->Previous->is(tok::at)) {
93 StartsObjCMethodExpr = true;
97 if (Left->Previous && Left->Previous->isOneOf(tok::kw_static_assert,
98 tok::kw_if, tok::kw_while)) {
99 // static_assert, if and while usually contain expressions.
100 Contexts.back().IsExpression = true;
101 } else if (Left->Previous && Left->Previous->is(tok::r_square) &&
102 Left->Previous->MatchingParen &&
103 Left->Previous->MatchingParen->Type == TT_LambdaLSquare) {
104 // This is a parameter list of a lambda expression.
105 Contexts.back().IsExpression = false;
108 if (StartsObjCMethodExpr) {
109 Contexts.back().ColonIsObjCMethodExpr = true;
110 Left->Type = TT_ObjCMethodExpr;
113 bool MightBeFunctionType = CurrentToken->is(tok::star);
114 bool HasMultipleLines = false;
115 bool HasMultipleParametersOnALine = false;
116 while (CurrentToken != NULL) {
117 // LookForDecls is set when "if (" has been seen. Check for
118 // 'identifier' '*' 'identifier' followed by not '=' -- this
119 // '*' has to be a binary operator but determineStarAmpUsage() will
120 // categorize it as an unary operator, so set the right type here.
121 if (LookForDecls && CurrentToken->Next) {
122 FormatToken *Prev = CurrentToken->getPreviousNonComment();
124 FormatToken *PrevPrev = Prev->getPreviousNonComment();
125 FormatToken *Next = CurrentToken->Next;
126 if (PrevPrev && PrevPrev->is(tok::identifier) &&
127 Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
128 CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
129 Prev->Type = TT_BinaryOperator;
130 LookForDecls = false;
135 if (CurrentToken->Previous->Type == TT_PointerOrReference &&
136 CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
138 MightBeFunctionType = true;
139 if (CurrentToken->is(tok::r_paren)) {
140 if (MightBeFunctionType && CurrentToken->Next &&
141 (CurrentToken->Next->is(tok::l_paren) ||
142 (CurrentToken->Next->is(tok::l_square) &&
143 !Contexts.back().IsExpression)))
144 Left->Type = TT_FunctionTypeLParen;
145 Left->MatchingParen = CurrentToken;
146 CurrentToken->MatchingParen = Left;
148 if (StartsObjCMethodExpr) {
149 CurrentToken->Type = TT_ObjCMethodExpr;
150 if (Contexts.back().FirstObjCSelectorName != NULL) {
151 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
152 Contexts.back().LongestObjCSelectorName;
156 if (!HasMultipleLines)
157 Left->PackingKind = PPK_Inconclusive;
158 else if (HasMultipleParametersOnALine)
159 Left->PackingKind = PPK_BinPacked;
161 Left->PackingKind = PPK_OnePerLine;
166 if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
168 updateParameterCount(Left, CurrentToken);
169 if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
170 !CurrentToken->Next->HasUnescapedNewline &&
171 !CurrentToken->Next->isTrailingComment())
172 HasMultipleParametersOnALine = true;
175 if (CurrentToken && CurrentToken->HasUnescapedNewline)
176 HasMultipleLines = true;
185 // A '[' could be an index subscript (after an identifier 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 FormatToken *Left = CurrentToken->Previous;
189 FormatToken *Parent = Left->getPreviousNonComment();
190 bool StartsObjCMethodExpr =
191 Contexts.back().CanBeExpression && Left->Type != TT_LambdaLSquare &&
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->Tok.getKind(), true, true) > prec::Unknown);
197 ScopedContextCreator ContextCreator(*this, tok::l_square, 10);
198 Contexts.back().IsExpression = true;
199 bool ColonFound = false;
201 if (StartsObjCMethodExpr) {
202 Contexts.back().ColonIsObjCMethodExpr = true;
203 Left->Type = TT_ObjCMethodExpr;
204 } else if (Parent && Parent->is(tok::at)) {
205 Left->Type = TT_ArrayInitializerLSquare;
206 } else if (Left->Type == TT_Unknown) {
207 Left->Type = TT_ArraySubscriptLSquare;
210 while (CurrentToken != NULL) {
211 if (CurrentToken->is(tok::r_square)) {
212 if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
213 Left->Type == TT_ObjCMethodExpr) {
214 // An ObjC method call is rarely followed by an open parenthesis.
215 // FIXME: Do we incorrectly label ":" with this?
216 StartsObjCMethodExpr = false;
217 Left->Type = TT_Unknown;
219 if (StartsObjCMethodExpr) {
220 CurrentToken->Type = TT_ObjCMethodExpr;
221 // determineStarAmpUsage() thinks that '*' '[' is allocating an
222 // array of pointers, but if '[' starts a selector then '*' is a
224 if (Parent != NULL && Parent->Type == TT_PointerOrReference)
225 Parent->Type = TT_BinaryOperator;
227 Left->MatchingParen = CurrentToken;
228 CurrentToken->MatchingParen = Left;
229 if (Contexts.back().FirstObjCSelectorName != NULL)
230 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
231 Contexts.back().LongestObjCSelectorName;
235 if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
237 if (CurrentToken->is(tok::colon))
239 if (CurrentToken->is(tok::comma) &&
240 (Left->Type == TT_ArraySubscriptLSquare ||
241 (Left->Type == TT_ObjCMethodExpr && !ColonFound)))
242 Left->Type = TT_ArrayInitializerLSquare;
243 updateParameterCount(Left, CurrentToken);
251 if (CurrentToken != NULL) {
252 FormatToken *Left = CurrentToken->Previous;
253 ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
254 Contexts.back().ColonIsDictLiteral = true;
256 while (CurrentToken != NULL) {
257 if (CurrentToken->is(tok::r_brace)) {
258 Left->MatchingParen = CurrentToken;
259 CurrentToken->MatchingParen = Left;
263 if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
265 updateParameterCount(Left, CurrentToken);
266 if (CurrentToken->is(tok::colon))
267 Left->Type = TT_DictLiteral;
272 // No closing "}" found, this probably starts a definition.
273 Line.StartsDefinition = true;
277 void updateParameterCount(FormatToken *Left, FormatToken *Current) {
278 if (Current->is(tok::comma)) {
279 ++Left->ParameterCount;
281 Left->Role.reset(new CommaSeparatedList(Style));
282 Left->Role->CommaFound(Current);
283 } else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) {
284 Left->ParameterCount = 1;
288 bool parseConditional() {
289 while (CurrentToken != NULL) {
290 if (CurrentToken->is(tok::colon)) {
291 CurrentToken->Type = TT_ConditionalExpr;
301 bool parseTemplateDeclaration() {
302 if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
303 CurrentToken->Type = TT_TemplateOpener;
307 if (CurrentToken != NULL)
308 CurrentToken->Previous->ClosesTemplateDeclaration = true;
314 bool consumeToken() {
315 FormatToken *Tok = CurrentToken;
317 switch (Tok->Tok.getKind()) {
320 if (Tok->Previous == NULL && Line.MustBeDeclaration)
321 Tok->Type = TT_ObjCMethodSpecifier;
324 if (Tok->Previous == NULL)
326 // Colons from ?: are handled in parseConditional().
327 if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1) {
328 Tok->Type = TT_CtorInitializerColon;
329 } else if (Contexts.back().ColonIsDictLiteral) {
330 Tok->Type = TT_DictLiteral;
331 } else if (Contexts.back().ColonIsObjCMethodExpr ||
332 Line.First->Type == TT_ObjCMethodSpecifier) {
333 Tok->Type = TT_ObjCMethodExpr;
334 Tok->Previous->Type = TT_ObjCSelectorName;
335 if (Tok->Previous->ColumnWidth >
336 Contexts.back().LongestObjCSelectorName) {
337 Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth;
339 if (Contexts.back().FirstObjCSelectorName == NULL)
340 Contexts.back().FirstObjCSelectorName = Tok->Previous;
341 } else if (Contexts.back().ColonIsForRangeExpr) {
342 Tok->Type = TT_RangeBasedForLoopColon;
343 } else if (CurrentToken != NULL &&
344 CurrentToken->is(tok::numeric_constant)) {
345 Tok->Type = TT_BitFieldColon;
346 } else if (Contexts.size() == 1 && Line.First->isNot(tok::kw_enum)) {
347 Tok->Type = TT_InheritanceColon;
348 } else if (Contexts.back().ContextKind == tok::l_paren) {
349 Tok->Type = TT_InlineASMColon;
354 if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) {
356 if (!parseParens(/*LookForDecls=*/true))
361 Contexts.back().ColonIsForRangeExpr = true;
369 if (Line.MustBeDeclaration && Contexts.size() == 1 &&
370 !Contexts.back().IsExpression)
371 Line.MightBeFunctionDecl = true;
382 if (Tok->Previous && !Tok->Previous->Tok.isLiteral() && parseAngle())
383 Tok->Type = TT_TemplateOpener;
385 Tok->Type = TT_BinaryOperator;
394 // Lines can start with '}'.
395 if (Tok->Previous != NULL)
399 Tok->Type = TT_BinaryOperator;
401 case tok::kw_operator:
402 while (CurrentToken &&
403 !CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) {
404 if (CurrentToken->isOneOf(tok::star, tok::amp))
405 CurrentToken->Type = TT_PointerOrReference;
407 if (CurrentToken && CurrentToken->Previous->Type == TT_BinaryOperator)
408 CurrentToken->Previous->Type = TT_OverloadedOperator;
411 CurrentToken->Type = TT_OverloadedOperatorLParen;
412 if (CurrentToken->Previous->Type == TT_BinaryOperator)
413 CurrentToken->Previous->Type = TT_OverloadedOperator;
419 case tok::kw_template:
420 parseTemplateDeclaration();
422 case tok::identifier:
423 if (Line.First->is(tok::kw_for) &&
424 Tok->Tok.getIdentifierInfo() == &Ident_in)
425 Tok->Type = TT_ObjCForIn;
428 if (Contexts.back().FirstStartOfName)
429 Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
430 if (Contexts.back().InCtorInitializer)
431 Tok->Type = TT_CtorInitializerComma;
439 void parseIncludeDirective() {
441 if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
443 while (CurrentToken != NULL) {
444 if (CurrentToken->isNot(tok::comment) || CurrentToken->Next)
445 CurrentToken->Type = TT_ImplicitStringLiteral;
449 while (CurrentToken != NULL) {
450 if (CurrentToken->is(tok::string_literal))
451 // Mark these string literals as "implicit" literals, too, so that
452 // they are not split or line-wrapped.
453 CurrentToken->Type = TT_ImplicitStringLiteral;
459 void parseWarningOrError() {
461 // We still want to format the whitespace left of the first token of the
464 while (CurrentToken != NULL) {
465 CurrentToken->Type = TT_ImplicitStringLiteral;
470 void parsePreprocessorDirective() {
472 if (CurrentToken == NULL)
474 if (CurrentToken->Tok.is(tok::numeric_constant)) {
475 CurrentToken->SpacesRequiredBefore = 1;
478 // Hashes in the middle of a line can lead to any strange token
480 if (CurrentToken->Tok.getIdentifierInfo() == NULL)
482 switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {
483 case tok::pp_include:
485 parseIncludeDirective();
488 case tok::pp_warning:
489 parseWarningOrError();
498 while (CurrentToken != NULL)
503 LineType parseLine() {
504 if (CurrentToken->is(tok::hash)) {
505 parsePreprocessorDirective();
506 return LT_PreprocessorDirective;
508 while (CurrentToken != NULL) {
509 if (CurrentToken->is(tok::kw_virtual))
510 KeywordVirtualFound = true;
514 if (KeywordVirtualFound)
515 return LT_VirtualFunctionDecl;
517 if (Line.First->Type == TT_ObjCMethodSpecifier) {
518 if (Contexts.back().FirstObjCSelectorName != NULL)
519 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
520 Contexts.back().LongestObjCSelectorName;
521 return LT_ObjCMethodDecl;
529 if (CurrentToken != NULL) {
530 determineTokenType(*CurrentToken);
531 CurrentToken->BindingStrength = Contexts.back().BindingStrength;
534 if (CurrentToken != NULL)
535 CurrentToken = CurrentToken->Next;
537 if (CurrentToken != NULL) {
538 // Reset token type in case we have already looked at it and then
539 // recovered from an error (e.g. failure to find the matching >).
540 if (CurrentToken->Type != TT_LambdaLSquare &&
541 CurrentToken->Type != TT_ImplicitStringLiteral)
542 CurrentToken->Type = TT_Unknown;
543 if (CurrentToken->Role)
544 CurrentToken->Role.reset(NULL);
545 CurrentToken->FakeLParens.clear();
546 CurrentToken->FakeRParens = 0;
550 /// \brief A struct to hold information valid in a specific context, e.g.
551 /// a pair of parenthesis.
553 Context(tok::TokenKind ContextKind, unsigned BindingStrength,
555 : ContextKind(ContextKind), BindingStrength(BindingStrength),
556 LongestObjCSelectorName(0), ColonIsForRangeExpr(false),
557 ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false),
558 FirstObjCSelectorName(NULL), FirstStartOfName(NULL),
559 IsExpression(IsExpression), CanBeExpression(true),
560 InCtorInitializer(false) {}
562 tok::TokenKind ContextKind;
563 unsigned BindingStrength;
564 unsigned LongestObjCSelectorName;
565 bool ColonIsForRangeExpr;
566 bool ColonIsDictLiteral;
567 bool ColonIsObjCMethodExpr;
568 FormatToken *FirstObjCSelectorName;
569 FormatToken *FirstStartOfName;
571 bool CanBeExpression;
572 bool InCtorInitializer;
575 /// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime
576 /// of each instance.
577 struct ScopedContextCreator {
580 ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind,
583 P.Contexts.push_back(Context(ContextKind,
584 P.Contexts.back().BindingStrength + Increase,
585 P.Contexts.back().IsExpression));
588 ~ScopedContextCreator() { P.Contexts.pop_back(); }
591 void determineTokenType(FormatToken &Current) {
592 if (Current.getPrecedence() == prec::Assignment &&
593 !Line.First->isOneOf(tok::kw_template, tok::kw_using) &&
594 (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
595 Contexts.back().IsExpression = true;
596 for (FormatToken *Previous = Current.Previous;
597 Previous && !Previous->isOneOf(tok::comma, tok::semi);
598 Previous = Previous->Previous) {
599 if (Previous->is(tok::r_square))
600 Previous = Previous->MatchingParen;
601 if (Previous->Type == TT_BinaryOperator &&
602 Previous->isOneOf(tok::star, tok::amp)) {
603 Previous->Type = TT_PointerOrReference;
606 } else if (Current.isOneOf(tok::kw_return, tok::kw_throw) ||
607 (Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
608 !Line.InPPDirective &&
609 (!Current.Previous ||
610 !Current.Previous->isOneOf(tok::kw_for, tok::kw_catch)))) {
611 Contexts.back().IsExpression = true;
612 } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
613 for (FormatToken *Previous = Current.Previous;
614 Previous && Previous->isOneOf(tok::star, tok::amp);
615 Previous = Previous->Previous)
616 Previous->Type = TT_PointerOrReference;
617 } else if (Current.Previous &&
618 Current.Previous->Type == TT_CtorInitializerColon) {
619 Contexts.back().IsExpression = true;
620 Contexts.back().InCtorInitializer = true;
621 } else if (Current.is(tok::kw_new)) {
622 Contexts.back().CanBeExpression = false;
623 } else if (Current.is(tok::semi) || Current.is(tok::exclaim)) {
624 // This should be the condition or increment in a for-loop.
625 Contexts.back().IsExpression = true;
628 if (Current.Type == TT_Unknown) {
629 // Line.MightBeFunctionDecl can only be true after the parentheses of a
630 // function declaration have been found. In this case, 'Current' is a
631 // trailing token of this declaration and thus cannot be a name.
632 if (isStartOfName(Current) && !Line.MightBeFunctionDecl) {
633 Contexts.back().FirstStartOfName = &Current;
634 Current.Type = TT_StartOfName;
635 } else if (Current.is(tok::kw_auto)) {
637 } else if (Current.is(tok::arrow) && AutoFound &&
638 Line.MustBeDeclaration) {
639 Current.Type = TT_TrailingReturnArrow;
640 } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
642 determineStarAmpUsage(Current, Contexts.back().CanBeExpression &&
643 Contexts.back().IsExpression);
644 } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
645 Current.Type = determinePlusMinusCaretUsage(Current);
646 } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {
647 Current.Type = determineIncrementUsage(Current);
648 } else if (Current.is(tok::exclaim)) {
649 Current.Type = TT_UnaryOperator;
650 } else if (Current.isBinaryOperator() &&
651 (!Current.Previous ||
652 Current.Previous->isNot(tok::l_square))) {
653 Current.Type = TT_BinaryOperator;
654 } else if (Current.is(tok::comment)) {
655 if (Current.TokenText.startswith("//"))
656 Current.Type = TT_LineComment;
658 Current.Type = TT_BlockComment;
659 } else if (Current.is(tok::r_paren)) {
660 FormatToken *LeftOfParens = NULL;
661 if (Current.MatchingParen)
662 LeftOfParens = Current.MatchingParen->getPreviousNonComment();
664 bool ParensAreEmpty = Current.Previous == Current.MatchingParen;
665 bool ParensAreType = !Current.Previous ||
666 Current.Previous->Type == TT_PointerOrReference ||
667 Current.Previous->Type == TT_TemplateCloser ||
668 isSimpleTypeSpecifier(*Current.Previous);
669 bool ParensCouldEndDecl =
671 Current.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
672 bool IsSizeOfOrAlignOf =
674 LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
675 if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
676 (Contexts.back().IsExpression ||
677 (Current.Next && Current.Next->isBinaryOperator())))
679 if (Current.Next && Current.Next->isNot(tok::string_literal) &&
680 (Current.Next->Tok.isLiteral() ||
681 Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
683 // If there is an identifier after the (), it is likely a cast, unless
684 // there is also an identifier before the ().
685 if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL ||
686 LeftOfParens->is(tok::kw_return)) &&
687 LeftOfParens->Type != TT_OverloadedOperator &&
688 LeftOfParens->Type != TT_TemplateCloser && Current.Next &&
689 Current.Next->is(tok::identifier))
691 if (IsCast && !ParensAreEmpty)
692 Current.Type = TT_CastRParen;
693 } else if (Current.is(tok::at) && Current.Next) {
694 switch (Current.Next->Tok.getObjCKeywordID()) {
695 case tok::objc_interface:
696 case tok::objc_implementation:
697 case tok::objc_protocol:
698 Current.Type = TT_ObjCDecl;
700 case tok::objc_property:
701 Current.Type = TT_ObjCProperty;
706 } else if (Current.is(tok::period)) {
707 FormatToken *PreviousNoComment = Current.getPreviousNonComment();
708 if (PreviousNoComment &&
709 PreviousNoComment->isOneOf(tok::comma, tok::l_brace))
710 Current.Type = TT_DesignatedInitializerPeriod;
715 /// \brief Take a guess at whether \p Tok starts a name of a function or
716 /// variable declaration.
718 /// This is a heuristic based on whether \p Tok is an identifier following
719 /// something that is likely a type.
720 bool isStartOfName(const FormatToken &Tok) {
721 if (Tok.isNot(tok::identifier) || Tok.Previous == NULL)
724 // Skip "const" as it does not have an influence on whether this is a name.
725 FormatToken *PreviousNotConst = Tok.Previous;
726 while (PreviousNotConst != NULL && PreviousNotConst->is(tok::kw_const))
727 PreviousNotConst = PreviousNotConst->Previous;
729 if (PreviousNotConst == NULL)
732 bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&
733 PreviousNotConst->Previous &&
734 PreviousNotConst->Previous->is(tok::hash);
736 if (PreviousNotConst->Type == TT_TemplateCloser)
737 return PreviousNotConst && PreviousNotConst->MatchingParen &&
738 PreviousNotConst->MatchingParen->Previous &&
739 PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
741 return (!IsPPKeyword && PreviousNotConst->is(tok::identifier)) ||
742 PreviousNotConst->Type == TT_PointerOrReference ||
743 isSimpleTypeSpecifier(*PreviousNotConst);
746 /// \brief Return the type of the given token assuming it is * or &.
747 TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression) {
748 const FormatToken *PrevToken = Tok.getPreviousNonComment();
749 if (PrevToken == NULL)
750 return TT_UnaryOperator;
752 const FormatToken *NextToken = Tok.getNextNonComment();
753 if (NextToken == NULL)
756 if (PrevToken->is(tok::coloncolon) ||
757 (PrevToken->is(tok::l_paren) && !IsExpression))
758 return TT_PointerOrReference;
760 if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace,
761 tok::comma, tok::semi, tok::kw_return, tok::colon,
762 tok::equal, tok::kw_delete, tok::kw_sizeof) ||
763 PrevToken->Type == TT_BinaryOperator ||
764 PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen)
765 return TT_UnaryOperator;
767 if (NextToken->is(tok::l_square))
768 return TT_PointerOrReference;
770 if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
771 PrevToken->MatchingParen->Previous &&
772 PrevToken->MatchingParen->Previous->is(tok::kw_typeof))
773 return TT_PointerOrReference;
775 if (PrevToken->Tok.isLiteral() ||
776 PrevToken->isOneOf(tok::r_paren, tok::r_square) ||
777 NextToken->Tok.isLiteral() || NextToken->isUnaryOperator())
778 return TT_BinaryOperator;
780 // It is very unlikely that we are going to find a pointer or reference type
781 // definition on the RHS of an assignment.
783 return TT_BinaryOperator;
785 return TT_PointerOrReference;
788 TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
789 const FormatToken *PrevToken = Tok.getPreviousNonComment();
790 if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
791 return TT_UnaryOperator;
793 // Use heuristics to recognize unary operators.
794 if (PrevToken->isOneOf(tok::equal, tok::l_paren, tok::comma, tok::l_square,
795 tok::question, tok::colon, tok::kw_return,
796 tok::kw_case, tok::at, tok::l_brace))
797 return TT_UnaryOperator;
799 // There can't be two consecutive binary operators.
800 if (PrevToken->Type == TT_BinaryOperator)
801 return TT_UnaryOperator;
803 // Fall back to marking the token as binary operator.
804 return TT_BinaryOperator;
807 /// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
808 TokenType determineIncrementUsage(const FormatToken &Tok) {
809 const FormatToken *PrevToken = Tok.getPreviousNonComment();
810 if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
811 return TT_UnaryOperator;
812 if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))
813 return TT_TrailingUnaryOperator;
815 return TT_UnaryOperator;
818 // FIXME: This is copy&pasted from Sema. Put it in a common place and remove
820 /// \brief Determine whether the token kind starts a simple-type-specifier.
821 bool isSimpleTypeSpecifier(const FormatToken &Tok) const {
822 switch (Tok.Tok.getKind()) {
825 case tok::kw___int64:
826 case tok::kw___int128:
828 case tok::kw_unsigned:
835 case tok::kw_wchar_t:
837 case tok::kw___underlying_type:
838 case tok::annot_typename:
839 case tok::kw_char16_t:
840 case tok::kw_char32_t:
842 case tok::kw_decltype:
849 SmallVector<Context, 8> Contexts;
851 const FormatStyle &Style;
853 FormatToken *CurrentToken;
854 bool KeywordVirtualFound;
856 IdentifierInfo &Ident_in;
859 static int PrecedenceUnaryOperator = prec::PointerToMember + 1;
860 static int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
862 /// \brief Parses binary expressions by inserting fake parenthesis based on
863 /// operator precedence.
864 class ExpressionParser {
866 ExpressionParser(AnnotatedLine &Line) : Current(Line.First) {
867 // Skip leading "}", e.g. in "} else if (...) {".
868 if (Current->is(tok::r_brace))
872 /// \brief Parse expressions with the given operatore precedence.
873 void parse(int Precedence = 0) {
874 // Skip 'return' and ObjC selector colons as they are not part of a binary
877 (Current->is(tok::kw_return) ||
878 (Current->is(tok::colon) && Current->Type == TT_ObjCMethodExpr)))
881 if (Current == NULL || Precedence > PrecedenceArrowAndPeriod)
884 // Conditional expressions need to be parsed separately for proper nesting.
885 if (Precedence == prec::Conditional) {
886 parseConditionalExpr();
890 // Parse unary operators, which all have a higher precedence than binary
892 if (Precedence == PrecedenceUnaryOperator) {
893 parseUnaryOperator();
897 FormatToken *Start = Current;
898 FormatToken *LatestOperator = NULL;
901 // Consume operators with higher precedence.
902 parse(Precedence + 1);
904 int CurrentPrecedence = getCurrentPrecedence();
906 if (Current && Current->Type == TT_ObjCSelectorName &&
907 Precedence == CurrentPrecedence)
910 // At the end of the line or when an operator with higher precedence is
911 // found, insert fake parenthesis and return.
912 if (Current == NULL || Current->closesScope() ||
913 (CurrentPrecedence != -1 && CurrentPrecedence < Precedence)) {
914 if (LatestOperator) {
915 if (Precedence == PrecedenceArrowAndPeriod) {
916 LatestOperator->LastInChainOfCalls = true;
917 // Call expressions don't have a binary operator precedence.
918 addFakeParenthesis(Start, prec::Unknown);
920 addFakeParenthesis(Start, prec::Level(Precedence));
926 // Consume scopes: (), [], <> and {}
927 if (Current->opensScope()) {
928 while (Current && !Current->closesScope()) {
935 if (CurrentPrecedence == Precedence)
936 LatestOperator = Current;
944 /// \brief Gets the precedence (+1) of the given token for binary operators
945 /// and other tokens that we treat like binary operators.
946 int getCurrentPrecedence() {
948 if (Current->Type == TT_ConditionalExpr)
949 return prec::Conditional;
950 else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon ||
951 Current->Type == TT_ObjCSelectorName)
953 else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma))
954 return Current->getPrecedence();
955 else if (Current->isOneOf(tok::period, tok::arrow))
956 return PrecedenceArrowAndPeriod;
961 void addFakeParenthesis(FormatToken *Start, prec::Level Precedence) {
962 Start->FakeLParens.push_back(Precedence);
963 if (Precedence > prec::Unknown)
964 Start->StartsBinaryExpression = true;
966 ++Current->Previous->FakeRParens;
967 if (Precedence > prec::Unknown)
968 Current->Previous->EndsBinaryExpression = true;
972 /// \brief Parse unary operator expressions and surround them with fake
973 /// parentheses if appropriate.
974 void parseUnaryOperator() {
975 if (Current == NULL || Current->Type != TT_UnaryOperator) {
976 parse(PrecedenceArrowAndPeriod);
980 FormatToken *Start = Current;
982 parseUnaryOperator();
984 // The actual precedence doesn't matter.
985 addFakeParenthesis(Start, prec::Unknown);
988 void parseConditionalExpr() {
989 FormatToken *Start = Current;
990 parse(prec::LogicalOr);
991 if (!Current || !Current->is(tok::question))
994 parse(prec::LogicalOr);
995 if (!Current || Current->Type != TT_ConditionalExpr)
998 parseConditionalExpr();
999 addFakeParenthesis(Start, prec::Conditional);
1004 Current = Current->Next;
1005 while (Current && Current->isTrailingComment())
1006 Current = Current->Next;
1009 FormatToken *Current;
1012 } // end anonymous namespace
1015 TokenAnnotator::setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) {
1016 const AnnotatedLine *NextNonCommentLine = NULL;
1017 for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(),
1020 if (NextNonCommentLine && (*I)->First->is(tok::comment) &&
1021 (*I)->First->Next == NULL)
1022 (*I)->Level = NextNonCommentLine->Level;
1024 NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : NULL;
1026 setCommentLineLevels((*I)->Children);
1030 void TokenAnnotator::annotate(AnnotatedLine &Line) {
1031 for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
1032 E = Line.Children.end();
1036 AnnotatingParser Parser(Style, Line, Ident_in);
1037 Line.Type = Parser.parseLine();
1038 if (Line.Type == LT_Invalid)
1041 ExpressionParser ExprParser(Line);
1044 if (Line.First->Type == TT_ObjCMethodSpecifier)
1045 Line.Type = LT_ObjCMethodDecl;
1046 else if (Line.First->Type == TT_ObjCDecl)
1047 Line.Type = LT_ObjCDecl;
1048 else if (Line.First->Type == TT_ObjCProperty)
1049 Line.Type = LT_ObjCProperty;
1051 Line.First->SpacesRequiredBefore = 1;
1052 Line.First->CanBreakBefore = Line.First->MustBreakBefore;
1055 void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
1056 Line.First->TotalLength =
1057 Line.First->IsMultiline ? Style.ColumnLimit : Line.First->ColumnWidth;
1058 if (!Line.First->Next)
1060 FormatToken *Current = Line.First->Next;
1061 bool InFunctionDecl = Line.MightBeFunctionDecl;
1062 while (Current != NULL) {
1063 if (Current->Type == TT_LineComment)
1064 Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;
1065 else if (Current->SpacesRequiredBefore == 0 &&
1066 spaceRequiredBefore(Line, *Current))
1067 Current->SpacesRequiredBefore = 1;
1069 Current->MustBreakBefore =
1070 Current->MustBreakBefore || mustBreakBefore(Line, *Current);
1072 Current->CanBreakBefore =
1073 Current->MustBreakBefore || canBreakBefore(Line, *Current);
1074 if (Current->MustBreakBefore || !Current->Children.empty() ||
1075 Current->IsMultiline)
1076 Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit;
1078 Current->TotalLength = Current->Previous->TotalLength +
1079 Current->ColumnWidth +
1080 Current->SpacesRequiredBefore;
1082 if (Current->Type == TT_CtorInitializerColon)
1083 InFunctionDecl = false;
1085 // FIXME: Only calculate this if CanBreakBefore is true once static
1086 // initializers etc. are sorted out.
1087 // FIXME: Move magic numbers to a better place.
1088 Current->SplitPenalty = 20 * Current->BindingStrength +
1089 splitPenalty(Line, *Current, InFunctionDecl);
1091 Current = Current->Next;
1094 calculateUnbreakableTailLengths(Line);
1095 for (Current = Line.First; Current != NULL; Current = Current->Next) {
1097 Current->Role->precomputeFormattingInfos(Current);
1100 DEBUG({ printDebugInfo(Line); });
1102 for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
1103 E = Line.Children.end();
1105 calculateFormattingInformation(**I);
1109 void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
1110 unsigned UnbreakableTailLength = 0;
1111 FormatToken *Current = Line.Last;
1112 while (Current != NULL) {
1113 Current->UnbreakableTailLength = UnbreakableTailLength;
1114 if (Current->CanBreakBefore ||
1115 Current->isOneOf(tok::comment, tok::string_literal)) {
1116 UnbreakableTailLength = 0;
1118 UnbreakableTailLength +=
1119 Current->ColumnWidth + Current->SpacesRequiredBefore;
1121 Current = Current->Previous;
1125 unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
1126 const FormatToken &Tok,
1127 bool InFunctionDecl) {
1128 const FormatToken &Left = *Tok.Previous;
1129 const FormatToken &Right = Tok;
1131 if (Left.is(tok::semi))
1133 if (Left.is(tok::comma))
1135 if (Right.is(tok::l_square))
1138 if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator)) {
1139 if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
1141 if (Left.Type == TT_StartOfName)
1143 if (InFunctionDecl && Right.BindingStrength == 1)
1144 // FIXME: Clean up hack of using BindingStrength to find top-level names.
1145 return Style.PenaltyReturnTypeOnItsOwnLine;
1148 if (Left.is(tok::equal) && Right.is(tok::l_brace))
1150 if (Left.Type == TT_CastRParen)
1152 if (Left.is(tok::coloncolon))
1154 if (Left.isOneOf(tok::kw_class, tok::kw_struct))
1157 if (Left.Type == TT_RangeBasedForLoopColon ||
1158 Left.Type == TT_InheritanceColon)
1161 if (Right.isMemberAccess()) {
1162 if (Left.isOneOf(tok::r_paren, tok::r_square) && Left.MatchingParen &&
1163 Left.MatchingParen->ParameterCount > 0)
1164 return 20; // Should be smaller than breaking at a nested comma.
1168 // Breaking before a trailing 'const' or not-function-like annotation is bad.
1169 if (Left.is(tok::r_paren) && Line.Type != LT_ObjCProperty &&
1170 (Right.is(tok::kw_const) || (Right.is(tok::identifier) && Right.Next &&
1171 Right.Next->isNot(tok::l_paren))))
1174 // In for-loops, prefer breaking at ',' and ';'.
1175 if (Line.First->is(tok::kw_for) && Left.is(tok::equal))
1178 // In Objective-C method expressions, prefer breaking before "param:" over
1179 // breaking after it.
1180 if (Right.Type == TT_ObjCSelectorName)
1182 if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
1185 if (Left.is(tok::l_paren) && InFunctionDecl)
1187 if (Left.opensScope())
1188 return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter
1191 if (Right.is(tok::lessless)) {
1192 if (Left.is(tok::string_literal)) {
1193 StringRef Content = Left.TokenText;
1194 if (Content.startswith("\""))
1195 Content = Content.drop_front(1);
1196 if (Content.endswith("\""))
1197 Content = Content.drop_back(1);
1198 Content = Content.trim();
1199 if (Content.size() > 1 &&
1200 (Content.back() == ':' || Content.back() == '='))
1203 return 1; // Breaking at a << is really cheap.
1205 if (Left.Type == TT_ConditionalExpr)
1206 return prec::Conditional;
1207 prec::Level Level = Left.getPrecedence();
1209 if (Level != prec::Unknown)
1215 bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
1216 const FormatToken &Left,
1217 const FormatToken &Right) {
1218 if (Right.is(tok::hashhash))
1219 return Left.is(tok::hash);
1220 if (Left.isOneOf(tok::hashhash, tok::hash))
1221 return Right.is(tok::hash);
1222 if (Left.is(tok::l_paren) && Right.is(tok::r_paren))
1223 return Style.SpaceInEmptyParentheses;
1224 if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
1225 return (Right.Type == TT_CastRParen ||
1226 (Left.MatchingParen && Left.MatchingParen->Type == TT_CastRParen))
1227 ? Style.SpacesInCStyleCastParentheses
1228 : Style.SpacesInParentheses;
1229 if (Style.SpacesInAngles &&
1230 ((Left.Type == TT_TemplateOpener) != (Right.Type == TT_TemplateCloser)))
1232 if (Right.isOneOf(tok::semi, tok::comma))
1234 if (Right.is(tok::less) &&
1235 (Left.is(tok::kw_template) ||
1236 (Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
1238 if (Left.is(tok::arrow) || Right.is(tok::arrow))
1240 if (Left.isOneOf(tok::exclaim, tok::tilde))
1242 if (Left.is(tok::at) &&
1243 Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant,
1244 tok::numeric_constant, tok::l_paren, tok::l_brace,
1245 tok::kw_true, tok::kw_false))
1247 if (Left.is(tok::coloncolon))
1249 if (Right.is(tok::coloncolon))
1250 return (Left.is(tok::less) && Style.Standard == FormatStyle::LS_Cpp03) ||
1251 !Left.isOneOf(tok::identifier, tok::greater, tok::l_paren,
1252 tok::r_paren, tok::less);
1253 if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less))
1255 if (Right.is(tok::ellipsis))
1256 return Left.Tok.isLiteral();
1257 if (Left.is(tok::l_square) && Right.is(tok::amp))
1259 if (Right.Type == TT_PointerOrReference)
1260 return Left.Tok.isLiteral() ||
1261 ((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) &&
1262 !Style.PointerBindsToType);
1263 if (Right.Type == TT_FunctionTypeLParen && Left.isNot(tok::l_paren) &&
1264 (Left.Type != TT_PointerOrReference || Style.PointerBindsToType))
1266 if (Left.Type == TT_PointerOrReference)
1267 return Right.Tok.isLiteral() || Right.Type == TT_BlockComment ||
1268 ((Right.Type != TT_PointerOrReference) &&
1269 Right.isNot(tok::l_paren) && Style.PointerBindsToType &&
1271 !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
1272 if (Right.is(tok::star) && Left.is(tok::l_paren))
1274 if (Left.is(tok::l_square))
1275 return Left.Type == TT_ArrayInitializerLSquare &&
1276 Right.isNot(tok::r_square);
1277 if (Right.is(tok::r_square))
1278 return Right.MatchingParen &&
1279 Right.MatchingParen->Type == TT_ArrayInitializerLSquare;
1280 if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr &&
1281 Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant))
1283 if (Left.is(tok::colon))
1284 return Left.Type != TT_ObjCMethodExpr;
1285 if (Right.is(tok::colon))
1286 return Right.Type != TT_ObjCMethodExpr && !Left.is(tok::question);
1287 if (Right.is(tok::l_paren)) {
1288 if (Left.is(tok::r_paren) && Left.MatchingParen &&
1289 Left.MatchingParen->Previous &&
1290 Left.MatchingParen->Previous->is(tok::kw___attribute))
1292 return Line.Type == LT_ObjCDecl ||
1293 Left.isOneOf(tok::kw_return, tok::kw_new, tok::kw_delete,
1295 (Style.SpaceAfterControlStatementKeyword &&
1296 Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,
1299 if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
1301 if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
1302 return !Left.Children.empty(); // No spaces in "{}".
1303 if (Left.is(tok::l_brace) || Right.is(tok::r_brace))
1304 return !Style.Cpp11BracedListStyle;
1305 if (Right.Type == TT_UnaryOperator)
1306 return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
1307 (Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr);
1308 if (Left.isOneOf(tok::identifier, tok::greater, tok::r_square) &&
1309 Right.is(tok::l_brace) && Right.getNextNonComment() &&
1310 Right.BlockKind != BK_Block)
1312 if (Left.is(tok::period) || Right.is(tok::period))
1314 if (Left.Type == TT_BlockComment && Left.TokenText.endswith("=*/"))
1316 if (Right.is(tok::hash) && Left.is(tok::identifier) && Left.TokenText == "L")
1321 bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
1322 const FormatToken &Tok) {
1323 if (Tok.Tok.getIdentifierInfo() && Tok.Previous->Tok.getIdentifierInfo())
1324 return true; // Never ever merge two identifiers.
1325 if (Tok.Previous->Type == TT_ImplicitStringLiteral)
1326 return Tok.WhitespaceRange.getBegin() != Tok.WhitespaceRange.getEnd();
1327 if (Line.Type == LT_ObjCMethodDecl) {
1328 if (Tok.Previous->Type == TT_ObjCMethodSpecifier)
1330 if (Tok.Previous->is(tok::r_paren) && Tok.is(tok::identifier))
1331 // Don't space between ')' and <id>
1334 if (Line.Type == LT_ObjCProperty &&
1335 (Tok.is(tok::equal) || Tok.Previous->is(tok::equal)))
1338 if (Tok.Type == TT_TrailingReturnArrow ||
1339 Tok.Previous->Type == TT_TrailingReturnArrow)
1341 if (Tok.Previous->is(tok::comma))
1343 if (Tok.is(tok::comma))
1345 if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
1347 if (Tok.Previous->Tok.is(tok::kw_operator))
1348 return Tok.is(tok::coloncolon);
1349 if (Tok.Type == TT_OverloadedOperatorLParen)
1351 if (Tok.is(tok::colon))
1352 return !Line.First->isOneOf(tok::kw_case, tok::kw_default) &&
1353 Tok.getNextNonComment() != NULL && Tok.Type != TT_ObjCMethodExpr &&
1354 !Tok.Previous->is(tok::question);
1355 if (Tok.Previous->Type == TT_UnaryOperator ||
1356 Tok.Previous->Type == TT_CastRParen)
1358 if (Tok.Previous->is(tok::greater) && Tok.is(tok::greater)) {
1359 return Tok.Type == TT_TemplateCloser &&
1360 Tok.Previous->Type == TT_TemplateCloser &&
1361 (Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
1363 if (Tok.isOneOf(tok::arrowstar, tok::periodstar) ||
1364 Tok.Previous->isOneOf(tok::arrowstar, tok::periodstar))
1366 if (!Style.SpaceBeforeAssignmentOperators &&
1367 Tok.getPrecedence() == prec::Assignment)
1369 if ((Tok.Type == TT_BinaryOperator && !Tok.Previous->is(tok::l_paren)) ||
1370 Tok.Previous->Type == TT_BinaryOperator)
1372 if (Tok.Previous->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
1374 if (Tok.is(tok::less) && Tok.Previous->isNot(tok::l_paren) &&
1375 Line.First->is(tok::hash))
1377 if (Tok.Type == TT_TrailingUnaryOperator)
1379 return spaceRequiredBetween(Line, *Tok.Previous, Tok);
1382 bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
1383 const FormatToken &Right) {
1384 if (Right.is(tok::comment)) {
1385 return Right.NewlinesBefore > 0;
1386 } else if (Right.Previous->isTrailingComment() ||
1387 (Right.is(tok::string_literal) &&
1388 Right.Previous->is(tok::string_literal))) {
1390 } else if (Right.Previous->IsUnterminatedLiteral) {
1392 } else if (Right.is(tok::lessless) && Right.Next &&
1393 Right.Previous->is(tok::string_literal) &&
1394 Right.Next->is(tok::string_literal)) {
1396 } else if (Right.Previous->ClosesTemplateDeclaration &&
1397 Right.Previous->MatchingParen &&
1398 Right.Previous->MatchingParen->BindingStrength == 1 &&
1399 Style.AlwaysBreakTemplateDeclarations) {
1400 // FIXME: Fix horrible hack of using BindingStrength to find top-level <>.
1402 } else if (Right.Type == TT_CtorInitializerComma &&
1403 Style.BreakConstructorInitializersBeforeComma &&
1404 !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) {
1406 } else if (Right.Previous->BlockKind == BK_Block &&
1407 Right.Previous->isNot(tok::r_brace) && Right.isNot(tok::r_brace)) {
1409 } else if (Right.is(tok::l_brace) && (Right.BlockKind == BK_Block)) {
1410 return Style.BreakBeforeBraces == FormatStyle::BS_Allman;
1415 bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
1416 const FormatToken &Right) {
1417 const FormatToken &Left = *Right.Previous;
1418 if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator))
1420 if (Right.isTrailingComment())
1421 // We rely on MustBreakBefore being set correctly here as we should not
1422 // change the "binding" behavior of a comment.
1424 if (Left.is(tok::question) && Right.is(tok::colon))
1426 if (Right.Type == TT_ConditionalExpr || Right.is(tok::question))
1427 return Style.BreakBeforeTernaryOperators;
1428 if (Left.Type == TT_ConditionalExpr || Left.is(tok::question))
1429 return !Style.BreakBeforeTernaryOperators;
1430 if (Right.is(tok::colon) &&
1431 (Right.Type == TT_DictLiteral || Right.Type == TT_ObjCMethodExpr))
1433 if (Left.is(tok::colon) &&
1434 (Left.Type == TT_DictLiteral || Left.Type == TT_ObjCMethodExpr))
1436 if (Right.Type == TT_ObjCSelectorName)
1438 if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
1440 if (Left.ClosesTemplateDeclaration)
1442 if (Right.Type == TT_RangeBasedForLoopColon ||
1443 Right.Type == TT_OverloadedOperatorLParen ||
1444 Right.Type == TT_OverloadedOperator)
1446 if (Left.Type == TT_RangeBasedForLoopColon)
1448 if (Right.Type == TT_RangeBasedForLoopColon)
1450 if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser ||
1451 Left.Type == TT_UnaryOperator || Left.is(tok::kw_operator))
1453 if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl)
1455 if (Left.Previous) {
1456 if (Left.is(tok::l_paren) && Right.is(tok::l_paren) &&
1457 Left.Previous->is(tok::kw___attribute))
1459 if (Left.is(tok::l_paren) && (Left.Previous->Type == TT_BinaryOperator ||
1460 Left.Previous->Type == TT_CastRParen))
1463 if (Right.Type == TT_ImplicitStringLiteral)
1466 if (Right.is(tok::r_paren) || Right.Type == TT_TemplateCloser)
1469 // We only break before r_brace if there was a corresponding break before
1470 // the l_brace, which is tracked by BreakBeforeClosingBrace.
1471 if (Right.is(tok::r_brace))
1472 return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block;
1474 // Allow breaking after a trailing 'const', e.g. after a method declaration,
1475 // unless it is follow by ';', '{' or '='.
1476 if (Left.is(tok::kw_const) && Left.Previous != NULL &&
1477 Left.Previous->is(tok::r_paren))
1478 return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal);
1480 if (Right.is(tok::kw___attribute))
1483 if (Left.is(tok::identifier) && Right.is(tok::string_literal))
1486 if (Left.Type == TT_CtorInitializerComma &&
1487 Style.BreakConstructorInitializersBeforeComma)
1489 if (Right.Type == TT_CtorInitializerComma &&
1490 Style.BreakConstructorInitializersBeforeComma)
1492 if (Right.isBinaryOperator() && Style.BreakBeforeBinaryOperators)
1494 if (Left.is(tok::greater) && Right.is(tok::greater) &&
1495 Left.Type != TT_TemplateCloser)
1497 if (Left.Type == TT_ArrayInitializerLSquare)
1499 return (Left.isBinaryOperator() && Left.isNot(tok::lessless) &&
1500 !Style.BreakBeforeBinaryOperators) ||
1501 Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
1502 tok::kw_class, tok::kw_struct) ||
1503 Right.isOneOf(tok::lessless, tok::arrow, tok::period, tok::colon,
1504 tok::l_square, tok::at) ||
1505 (Left.is(tok::r_paren) &&
1506 Right.isOneOf(tok::identifier, tok::kw_const, tok::kw___attribute)) ||
1507 (Left.is(tok::l_paren) && !Right.is(tok::r_paren));
1510 void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
1511 llvm::errs() << "AnnotatedTokens:\n";
1512 const FormatToken *Tok = Line.First;
1514 llvm::errs() << " M=" << Tok->MustBreakBefore
1515 << " C=" << Tok->CanBreakBefore << " T=" << Tok->Type
1516 << " S=" << Tok->SpacesRequiredBefore
1517 << " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName()
1518 << " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind
1520 for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
1521 llvm::errs() << Tok->FakeLParens[i] << "/";
1522 llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n";
1523 if (Tok->Next == NULL)
1524 assert(Tok == Line.Last);
1527 llvm::errs() << "----\n";
1530 } // namespace format
1531 } // namespace clang