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