1249261Sdim//===--- TokenAnnotator.cpp - Format C++ code -----------------------------===//
2249261Sdim//
3249261Sdim//                     The LLVM Compiler Infrastructure
4249261Sdim//
5249261Sdim// This file is distributed under the University of Illinois Open Source
6249261Sdim// License. See LICENSE.TXT for details.
7249261Sdim//
8249261Sdim//===----------------------------------------------------------------------===//
9249261Sdim///
10249261Sdim/// \file
11249261Sdim/// \brief This file implements a token annotator, i.e. creates
12249261Sdim/// \c AnnotatedTokens out of \c FormatTokens with required extra information.
13249261Sdim///
14249261Sdim//===----------------------------------------------------------------------===//
15249261Sdim
16249261Sdim#include "TokenAnnotator.h"
17249261Sdim#include "clang/Basic/SourceManager.h"
18252723Sdim#include "llvm/Support/Debug.h"
19249261Sdim
20249261Sdimnamespace clang {
21249261Sdimnamespace format {
22249261Sdim
23263509Sdimnamespace {
24249261Sdim
25249261Sdim/// \brief A parser that gathers additional information about tokens.
26249261Sdim///
27249261Sdim/// The \c TokenAnnotator tries to match parenthesis and square brakets and
28249261Sdim/// store a parenthesis levels. It also tries to resolve matching "<" and ">"
29249261Sdim/// into template parameter lists.
30249261Sdimclass AnnotatingParser {
31249261Sdimpublic:
32263509Sdim  AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,
33249261Sdim                   IdentifierInfo &Ident_in)
34263509Sdim      : Style(Style), Line(Line), CurrentToken(Line.First),
35263509Sdim        KeywordVirtualFound(false), AutoFound(false), Ident_in(Ident_in) {
36263509Sdim    Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
37249261Sdim  }
38249261Sdim
39249261Sdimprivate:
40249261Sdim  bool parseAngle() {
41249261Sdim    if (CurrentToken == NULL)
42249261Sdim      return false;
43249261Sdim    ScopedContextCreator ContextCreator(*this, tok::less, 10);
44263509Sdim    FormatToken *Left = CurrentToken->Previous;
45249261Sdim    Contexts.back().IsExpression = false;
46249261Sdim    while (CurrentToken != NULL) {
47249261Sdim      if (CurrentToken->is(tok::greater)) {
48249261Sdim        Left->MatchingParen = CurrentToken;
49249261Sdim        CurrentToken->MatchingParen = Left;
50249261Sdim        CurrentToken->Type = TT_TemplateCloser;
51249261Sdim        next();
52249261Sdim        return true;
53249261Sdim      }
54249261Sdim      if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace,
55263509Sdim                                tok::question, tok::colon))
56249261Sdim        return false;
57263509Sdim      // If a && or || is found and interpreted as a binary operator, this set
58263509Sdim      // of angles is likely part of something like "a < b && c > d". If the
59263509Sdim      // angles are inside an expression, the ||/&& might also be a binary
60263509Sdim      // operator that was misinterpreted because we are parsing template
61263509Sdim      // parameters.
62263509Sdim      // FIXME: This is getting out of hand, write a decent parser.
63263509Sdim      if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
64263509Sdim          (CurrentToken->Previous->Type == TT_BinaryOperator ||
65263509Sdim           Contexts[Contexts.size() - 2].IsExpression) &&
66263509Sdim          Line.First->isNot(tok::kw_template))
67263509Sdim        return false;
68249261Sdim      updateParameterCount(Left, CurrentToken);
69249261Sdim      if (!consumeToken())
70249261Sdim        return false;
71249261Sdim    }
72249261Sdim    return false;
73249261Sdim  }
74249261Sdim
75249261Sdim  bool parseParens(bool LookForDecls = false) {
76249261Sdim    if (CurrentToken == NULL)
77249261Sdim      return false;
78249261Sdim    ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);
79249261Sdim
80249261Sdim    // FIXME: This is a bit of a hack. Do better.
81249261Sdim    Contexts.back().ColonIsForRangeExpr =
82249261Sdim        Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
83249261Sdim
84249261Sdim    bool StartsObjCMethodExpr = false;
85263509Sdim    FormatToken *Left = CurrentToken->Previous;
86249261Sdim    if (CurrentToken->is(tok::caret)) {
87249261Sdim      // ^( starts a block.
88249261Sdim      Left->Type = TT_ObjCBlockLParen;
89263509Sdim    } else if (FormatToken *MaybeSel = Left->Previous) {
90249261Sdim      // @selector( starts a selector.
91263509Sdim      if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous &&
92263509Sdim          MaybeSel->Previous->is(tok::at)) {
93249261Sdim        StartsObjCMethodExpr = true;
94249261Sdim      }
95249261Sdim    }
96249261Sdim
97263509Sdim    if (Left->Previous && Left->Previous->isOneOf(tok::kw_static_assert,
98263509Sdim                                                  tok::kw_if, tok::kw_while)) {
99263509Sdim      // static_assert, if and while usually contain expressions.
100263509Sdim      Contexts.back().IsExpression = true;
101263509Sdim    } else if (Left->Previous && Left->Previous->is(tok::r_square) &&
102263509Sdim               Left->Previous->MatchingParen &&
103263509Sdim               Left->Previous->MatchingParen->Type == TT_LambdaLSquare) {
104263509Sdim      // This is a parameter list of a lambda expression.
105263509Sdim      Contexts.back().IsExpression = false;
106263509Sdim    }
107263509Sdim
108249261Sdim    if (StartsObjCMethodExpr) {
109249261Sdim      Contexts.back().ColonIsObjCMethodExpr = true;
110249261Sdim      Left->Type = TT_ObjCMethodExpr;
111249261Sdim    }
112249261Sdim
113263509Sdim    bool MightBeFunctionType = CurrentToken->is(tok::star);
114263509Sdim    bool HasMultipleLines = false;
115263509Sdim    bool HasMultipleParametersOnALine = false;
116249261Sdim    while (CurrentToken != NULL) {
117249261Sdim      // LookForDecls is set when "if (" has been seen. Check for
118249261Sdim      // 'identifier' '*' 'identifier' followed by not '=' -- this
119249261Sdim      // '*' has to be a binary operator but determineStarAmpUsage() will
120249261Sdim      // categorize it as an unary operator, so set the right type here.
121263509Sdim      if (LookForDecls && CurrentToken->Next) {
122263509Sdim        FormatToken *Prev = CurrentToken->getPreviousNonComment();
123263509Sdim        if (Prev) {
124263509Sdim          FormatToken *PrevPrev = Prev->getPreviousNonComment();
125263509Sdim          FormatToken *Next = CurrentToken->Next;
126263509Sdim          if (PrevPrev && PrevPrev->is(tok::identifier) &&
127263509Sdim              Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
128263509Sdim              CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
129263509Sdim            Prev->Type = TT_BinaryOperator;
130263509Sdim            LookForDecls = false;
131263509Sdim          }
132249261Sdim        }
133249261Sdim      }
134249261Sdim
135263509Sdim      if (CurrentToken->Previous->Type == TT_PointerOrReference &&
136263509Sdim          CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
137263509Sdim                                                    tok::coloncolon))
138263509Sdim        MightBeFunctionType = true;
139249261Sdim      if (CurrentToken->is(tok::r_paren)) {
140263509Sdim        if (MightBeFunctionType && CurrentToken->Next &&
141263509Sdim            (CurrentToken->Next->is(tok::l_paren) ||
142263509Sdim             (CurrentToken->Next->is(tok::l_square) &&
143263509Sdim              !Contexts.back().IsExpression)))
144263509Sdim          Left->Type = TT_FunctionTypeLParen;
145249261Sdim        Left->MatchingParen = CurrentToken;
146249261Sdim        CurrentToken->MatchingParen = Left;
147249261Sdim
148249261Sdim        if (StartsObjCMethodExpr) {
149249261Sdim          CurrentToken->Type = TT_ObjCMethodExpr;
150249261Sdim          if (Contexts.back().FirstObjCSelectorName != NULL) {
151249261Sdim            Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
152249261Sdim                Contexts.back().LongestObjCSelectorName;
153249261Sdim          }
154249261Sdim        }
155249261Sdim
156263509Sdim        if (!HasMultipleLines)
157263509Sdim          Left->PackingKind = PPK_Inconclusive;
158263509Sdim        else if (HasMultipleParametersOnALine)
159263509Sdim          Left->PackingKind = PPK_BinPacked;
160263509Sdim        else
161263509Sdim          Left->PackingKind = PPK_OnePerLine;
162263509Sdim
163249261Sdim        next();
164249261Sdim        return true;
165249261Sdim      }
166249261Sdim      if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
167249261Sdim        return false;
168249261Sdim      updateParameterCount(Left, CurrentToken);
169263509Sdim      if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
170263509Sdim          !CurrentToken->Next->HasUnescapedNewline &&
171263509Sdim          !CurrentToken->Next->isTrailingComment())
172263509Sdim        HasMultipleParametersOnALine = true;
173249261Sdim      if (!consumeToken())
174249261Sdim        return false;
175263509Sdim      if (CurrentToken && CurrentToken->HasUnescapedNewline)
176263509Sdim        HasMultipleLines = true;
177249261Sdim    }
178249261Sdim    return false;
179249261Sdim  }
180249261Sdim
181249261Sdim  bool parseSquare() {
182249261Sdim    if (!CurrentToken)
183249261Sdim      return false;
184249261Sdim
185263509Sdim    // A '[' could be an index subscript (after an identifier or after
186249261Sdim    // ')' or ']'), it could be the start of an Objective-C method
187249261Sdim    // expression, or it could the the start of an Objective-C array literal.
188263509Sdim    FormatToken *Left = CurrentToken->Previous;
189263509Sdim    FormatToken *Parent = Left->getPreviousNonComment();
190249261Sdim    bool StartsObjCMethodExpr =
191263509Sdim        Contexts.back().CanBeExpression && Left->Type != TT_LambdaLSquare &&
192249261Sdim        (!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
193249261Sdim                                    tok::kw_return, tok::kw_throw) ||
194252723Sdim         Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn ||
195249261Sdim         Parent->Type == TT_CastRParen ||
196263509Sdim         getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown);
197249261Sdim    ScopedContextCreator ContextCreator(*this, tok::l_square, 10);
198249261Sdim    Contexts.back().IsExpression = true;
199263509Sdim    bool ColonFound = false;
200249261Sdim
201249261Sdim    if (StartsObjCMethodExpr) {
202249261Sdim      Contexts.back().ColonIsObjCMethodExpr = true;
203249261Sdim      Left->Type = TT_ObjCMethodExpr;
204263509Sdim    } else if (Parent && Parent->is(tok::at)) {
205263509Sdim      Left->Type = TT_ArrayInitializerLSquare;
206263509Sdim    } else if (Left->Type == TT_Unknown) {
207263509Sdim      Left->Type = TT_ArraySubscriptLSquare;
208249261Sdim    }
209249261Sdim
210249261Sdim    while (CurrentToken != NULL) {
211249261Sdim      if (CurrentToken->is(tok::r_square)) {
212263509Sdim        if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
213263509Sdim            Left->Type == TT_ObjCMethodExpr) {
214249261Sdim          // An ObjC method call is rarely followed by an open parenthesis.
215249261Sdim          // FIXME: Do we incorrectly label ":" with this?
216249261Sdim          StartsObjCMethodExpr = false;
217249261Sdim          Left->Type = TT_Unknown;
218249261Sdim        }
219249261Sdim        if (StartsObjCMethodExpr) {
220249261Sdim          CurrentToken->Type = TT_ObjCMethodExpr;
221249261Sdim          // determineStarAmpUsage() thinks that '*' '[' is allocating an
222249261Sdim          // array of pointers, but if '[' starts a selector then '*' is a
223249261Sdim          // binary operator.
224249261Sdim          if (Parent != NULL && Parent->Type == TT_PointerOrReference)
225249261Sdim            Parent->Type = TT_BinaryOperator;
226249261Sdim        }
227249261Sdim        Left->MatchingParen = CurrentToken;
228249261Sdim        CurrentToken->MatchingParen = Left;
229249261Sdim        if (Contexts.back().FirstObjCSelectorName != NULL)
230249261Sdim          Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
231249261Sdim              Contexts.back().LongestObjCSelectorName;
232249261Sdim        next();
233249261Sdim        return true;
234249261Sdim      }
235249261Sdim      if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
236249261Sdim        return false;
237263509Sdim      if (CurrentToken->is(tok::colon))
238263509Sdim        ColonFound = true;
239263509Sdim      if (CurrentToken->is(tok::comma) &&
240263509Sdim          (Left->Type == TT_ArraySubscriptLSquare ||
241263509Sdim           (Left->Type == TT_ObjCMethodExpr && !ColonFound)))
242263509Sdim        Left->Type = TT_ArrayInitializerLSquare;
243249261Sdim      updateParameterCount(Left, CurrentToken);
244249261Sdim      if (!consumeToken())
245249261Sdim        return false;
246249261Sdim    }
247249261Sdim    return false;
248249261Sdim  }
249249261Sdim
250249261Sdim  bool parseBrace() {
251252723Sdim    if (CurrentToken != NULL) {
252263509Sdim      FormatToken *Left = CurrentToken->Previous;
253252723Sdim      ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
254263509Sdim      Contexts.back().ColonIsDictLiteral = true;
255263509Sdim
256252723Sdim      while (CurrentToken != NULL) {
257252723Sdim        if (CurrentToken->is(tok::r_brace)) {
258252723Sdim          Left->MatchingParen = CurrentToken;
259252723Sdim          CurrentToken->MatchingParen = Left;
260252723Sdim          next();
261252723Sdim          return true;
262252723Sdim        }
263252723Sdim        if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
264252723Sdim          return false;
265252723Sdim        updateParameterCount(Left, CurrentToken);
266263509Sdim        if (CurrentToken->is(tok::colon))
267263509Sdim          Left->Type = TT_DictLiteral;
268252723Sdim        if (!consumeToken())
269252723Sdim          return false;
270249261Sdim      }
271249261Sdim    }
272252723Sdim    // No closing "}" found, this probably starts a definition.
273252723Sdim    Line.StartsDefinition = true;
274249261Sdim    return true;
275249261Sdim  }
276249261Sdim
277263509Sdim  void updateParameterCount(FormatToken *Left, FormatToken *Current) {
278263509Sdim    if (Current->is(tok::comma)) {
279249261Sdim      ++Left->ParameterCount;
280263509Sdim      if (!Left->Role)
281263509Sdim        Left->Role.reset(new CommaSeparatedList(Style));
282263509Sdim      Left->Role->CommaFound(Current);
283263509Sdim    } else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) {
284249261Sdim      Left->ParameterCount = 1;
285263509Sdim    }
286249261Sdim  }
287249261Sdim
288249261Sdim  bool parseConditional() {
289249261Sdim    while (CurrentToken != NULL) {
290249261Sdim      if (CurrentToken->is(tok::colon)) {
291249261Sdim        CurrentToken->Type = TT_ConditionalExpr;
292249261Sdim        next();
293249261Sdim        return true;
294249261Sdim      }
295249261Sdim      if (!consumeToken())
296249261Sdim        return false;
297249261Sdim    }
298249261Sdim    return false;
299249261Sdim  }
300249261Sdim
301249261Sdim  bool parseTemplateDeclaration() {
302249261Sdim    if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
303249261Sdim      CurrentToken->Type = TT_TemplateOpener;
304249261Sdim      next();
305249261Sdim      if (!parseAngle())
306249261Sdim        return false;
307249261Sdim      if (CurrentToken != NULL)
308263509Sdim        CurrentToken->Previous->ClosesTemplateDeclaration = true;
309249261Sdim      return true;
310249261Sdim    }
311249261Sdim    return false;
312249261Sdim  }
313249261Sdim
314249261Sdim  bool consumeToken() {
315263509Sdim    FormatToken *Tok = CurrentToken;
316249261Sdim    next();
317263509Sdim    switch (Tok->Tok.getKind()) {
318249261Sdim    case tok::plus:
319249261Sdim    case tok::minus:
320263509Sdim      if (Tok->Previous == NULL && Line.MustBeDeclaration)
321249261Sdim        Tok->Type = TT_ObjCMethodSpecifier;
322249261Sdim      break;
323249261Sdim    case tok::colon:
324263509Sdim      if (Tok->Previous == NULL)
325249261Sdim        return false;
326249261Sdim      // Colons from ?: are handled in parseConditional().
327263509Sdim      if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1) {
328249261Sdim        Tok->Type = TT_CtorInitializerColon;
329263509Sdim      } else if (Contexts.back().ColonIsDictLiteral) {
330263509Sdim        Tok->Type = TT_DictLiteral;
331249261Sdim      } else if (Contexts.back().ColonIsObjCMethodExpr ||
332263509Sdim                 Line.First->Type == TT_ObjCMethodSpecifier) {
333249261Sdim        Tok->Type = TT_ObjCMethodExpr;
334263509Sdim        Tok->Previous->Type = TT_ObjCSelectorName;
335263509Sdim        if (Tok->Previous->ColumnWidth >
336263509Sdim            Contexts.back().LongestObjCSelectorName) {
337263509Sdim          Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth;
338263509Sdim        }
339249261Sdim        if (Contexts.back().FirstObjCSelectorName == NULL)
340263509Sdim          Contexts.back().FirstObjCSelectorName = Tok->Previous;
341249261Sdim      } else if (Contexts.back().ColonIsForRangeExpr) {
342249261Sdim        Tok->Type = TT_RangeBasedForLoopColon;
343263509Sdim      } else if (CurrentToken != NULL &&
344263509Sdim                 CurrentToken->is(tok::numeric_constant)) {
345263509Sdim        Tok->Type = TT_BitFieldColon;
346263509Sdim      } else if (Contexts.size() == 1 && Line.First->isNot(tok::kw_enum)) {
347249261Sdim        Tok->Type = TT_InheritanceColon;
348249261Sdim      } else if (Contexts.back().ContextKind == tok::l_paren) {
349249261Sdim        Tok->Type = TT_InlineASMColon;
350249261Sdim      }
351249261Sdim      break;
352249261Sdim    case tok::kw_if:
353249261Sdim    case tok::kw_while:
354249261Sdim      if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) {
355249261Sdim        next();
356263509Sdim        if (!parseParens(/*LookForDecls=*/true))
357249261Sdim          return false;
358249261Sdim      }
359249261Sdim      break;
360249261Sdim    case tok::kw_for:
361249261Sdim      Contexts.back().ColonIsForRangeExpr = true;
362249261Sdim      next();
363249261Sdim      if (!parseParens())
364249261Sdim        return false;
365249261Sdim      break;
366249261Sdim    case tok::l_paren:
367249261Sdim      if (!parseParens())
368249261Sdim        return false;
369263509Sdim      if (Line.MustBeDeclaration && Contexts.size() == 1 &&
370263509Sdim          !Contexts.back().IsExpression)
371249261Sdim        Line.MightBeFunctionDecl = true;
372249261Sdim      break;
373249261Sdim    case tok::l_square:
374249261Sdim      if (!parseSquare())
375249261Sdim        return false;
376249261Sdim      break;
377249261Sdim    case tok::l_brace:
378249261Sdim      if (!parseBrace())
379249261Sdim        return false;
380249261Sdim      break;
381249261Sdim    case tok::less:
382263509Sdim      if (Tok->Previous && !Tok->Previous->Tok.isLiteral() && parseAngle())
383249261Sdim        Tok->Type = TT_TemplateOpener;
384249261Sdim      else {
385249261Sdim        Tok->Type = TT_BinaryOperator;
386249261Sdim        CurrentToken = Tok;
387249261Sdim        next();
388249261Sdim      }
389249261Sdim      break;
390249261Sdim    case tok::r_paren:
391249261Sdim    case tok::r_square:
392249261Sdim      return false;
393249261Sdim    case tok::r_brace:
394249261Sdim      // Lines can start with '}'.
395263509Sdim      if (Tok->Previous != NULL)
396249261Sdim        return false;
397249261Sdim      break;
398249261Sdim    case tok::greater:
399249261Sdim      Tok->Type = TT_BinaryOperator;
400249261Sdim      break;
401249261Sdim    case tok::kw_operator:
402263509Sdim      while (CurrentToken &&
403263509Sdim             !CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) {
404249261Sdim        if (CurrentToken->isOneOf(tok::star, tok::amp))
405249261Sdim          CurrentToken->Type = TT_PointerOrReference;
406249261Sdim        consumeToken();
407263509Sdim        if (CurrentToken && CurrentToken->Previous->Type == TT_BinaryOperator)
408263509Sdim          CurrentToken->Previous->Type = TT_OverloadedOperator;
409249261Sdim      }
410263509Sdim      if (CurrentToken) {
411249261Sdim        CurrentToken->Type = TT_OverloadedOperatorLParen;
412263509Sdim        if (CurrentToken->Previous->Type == TT_BinaryOperator)
413263509Sdim          CurrentToken->Previous->Type = TT_OverloadedOperator;
414263509Sdim      }
415249261Sdim      break;
416249261Sdim    case tok::question:
417249261Sdim      parseConditional();
418249261Sdim      break;
419249261Sdim    case tok::kw_template:
420249261Sdim      parseTemplateDeclaration();
421249261Sdim      break;
422249261Sdim    case tok::identifier:
423263509Sdim      if (Line.First->is(tok::kw_for) &&
424263509Sdim          Tok->Tok.getIdentifierInfo() == &Ident_in)
425249261Sdim        Tok->Type = TT_ObjCForIn;
426249261Sdim      break;
427249261Sdim    case tok::comma:
428249261Sdim      if (Contexts.back().FirstStartOfName)
429249261Sdim        Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
430263509Sdim      if (Contexts.back().InCtorInitializer)
431263509Sdim        Tok->Type = TT_CtorInitializerComma;
432249261Sdim      break;
433249261Sdim    default:
434249261Sdim      break;
435249261Sdim    }
436249261Sdim    return true;
437249261Sdim  }
438249261Sdim
439249261Sdim  void parseIncludeDirective() {
440249261Sdim    next();
441249261Sdim    if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
442249261Sdim      next();
443249261Sdim      while (CurrentToken != NULL) {
444263509Sdim        if (CurrentToken->isNot(tok::comment) || CurrentToken->Next)
445249261Sdim          CurrentToken->Type = TT_ImplicitStringLiteral;
446249261Sdim        next();
447249261Sdim      }
448249261Sdim    } else {
449249261Sdim      while (CurrentToken != NULL) {
450249261Sdim        if (CurrentToken->is(tok::string_literal))
451249261Sdim          // Mark these string literals as "implicit" literals, too, so that
452249261Sdim          // they are not split or line-wrapped.
453249261Sdim          CurrentToken->Type = TT_ImplicitStringLiteral;
454249261Sdim        next();
455249261Sdim      }
456249261Sdim    }
457249261Sdim  }
458249261Sdim
459249261Sdim  void parseWarningOrError() {
460249261Sdim    next();
461249261Sdim    // We still want to format the whitespace left of the first token of the
462249261Sdim    // warning or error.
463249261Sdim    next();
464249261Sdim    while (CurrentToken != NULL) {
465249261Sdim      CurrentToken->Type = TT_ImplicitStringLiteral;
466249261Sdim      next();
467249261Sdim    }
468249261Sdim  }
469249261Sdim
470249261Sdim  void parsePreprocessorDirective() {
471249261Sdim    next();
472249261Sdim    if (CurrentToken == NULL)
473249261Sdim      return;
474263509Sdim    if (CurrentToken->Tok.is(tok::numeric_constant)) {
475263509Sdim      CurrentToken->SpacesRequiredBefore = 1;
476263509Sdim      return;
477263509Sdim    }
478249261Sdim    // Hashes in the middle of a line can lead to any strange token
479249261Sdim    // sequence.
480263509Sdim    if (CurrentToken->Tok.getIdentifierInfo() == NULL)
481249261Sdim      return;
482263509Sdim    switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {
483249261Sdim    case tok::pp_include:
484249261Sdim    case tok::pp_import:
485249261Sdim      parseIncludeDirective();
486249261Sdim      break;
487249261Sdim    case tok::pp_error:
488249261Sdim    case tok::pp_warning:
489249261Sdim      parseWarningOrError();
490249261Sdim      break;
491252723Sdim    case tok::pp_if:
492252723Sdim    case tok::pp_elif:
493252723Sdim      parseLine();
494252723Sdim      break;
495249261Sdim    default:
496249261Sdim      break;
497249261Sdim    }
498249261Sdim    while (CurrentToken != NULL)
499249261Sdim      next();
500249261Sdim  }
501249261Sdim
502249261Sdimpublic:
503249261Sdim  LineType parseLine() {
504249261Sdim    if (CurrentToken->is(tok::hash)) {
505249261Sdim      parsePreprocessorDirective();
506249261Sdim      return LT_PreprocessorDirective;
507249261Sdim    }
508249261Sdim    while (CurrentToken != NULL) {
509249261Sdim      if (CurrentToken->is(tok::kw_virtual))
510249261Sdim        KeywordVirtualFound = true;
511249261Sdim      if (!consumeToken())
512249261Sdim        return LT_Invalid;
513249261Sdim    }
514249261Sdim    if (KeywordVirtualFound)
515249261Sdim      return LT_VirtualFunctionDecl;
516249261Sdim
517263509Sdim    if (Line.First->Type == TT_ObjCMethodSpecifier) {
518249261Sdim      if (Contexts.back().FirstObjCSelectorName != NULL)
519249261Sdim        Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
520249261Sdim            Contexts.back().LongestObjCSelectorName;
521249261Sdim      return LT_ObjCMethodDecl;
522249261Sdim    }
523249261Sdim
524249261Sdim    return LT_Other;
525249261Sdim  }
526249261Sdim
527249261Sdimprivate:
528249261Sdim  void next() {
529249261Sdim    if (CurrentToken != NULL) {
530249261Sdim      determineTokenType(*CurrentToken);
531249261Sdim      CurrentToken->BindingStrength = Contexts.back().BindingStrength;
532249261Sdim    }
533249261Sdim
534263509Sdim    if (CurrentToken != NULL)
535263509Sdim      CurrentToken = CurrentToken->Next;
536249261Sdim
537263509Sdim    if (CurrentToken != NULL) {
538263509Sdim      // Reset token type in case we have already looked at it and then
539263509Sdim      // recovered from an error (e.g. failure to find the matching >).
540263509Sdim      if (CurrentToken->Type != TT_LambdaLSquare &&
541263509Sdim          CurrentToken->Type != TT_ImplicitStringLiteral)
542263509Sdim        CurrentToken->Type = TT_Unknown;
543263509Sdim      if (CurrentToken->Role)
544263509Sdim        CurrentToken->Role.reset(NULL);
545263509Sdim      CurrentToken->FakeLParens.clear();
546263509Sdim      CurrentToken->FakeRParens = 0;
547263509Sdim    }
548249261Sdim  }
549249261Sdim
550249261Sdim  /// \brief A struct to hold information valid in a specific context, e.g.
551249261Sdim  /// a pair of parenthesis.
552249261Sdim  struct Context {
553249261Sdim    Context(tok::TokenKind ContextKind, unsigned BindingStrength,
554249261Sdim            bool IsExpression)
555249261Sdim        : ContextKind(ContextKind), BindingStrength(BindingStrength),
556249261Sdim          LongestObjCSelectorName(0), ColonIsForRangeExpr(false),
557263509Sdim          ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false),
558263509Sdim          FirstObjCSelectorName(NULL), FirstStartOfName(NULL),
559263509Sdim          IsExpression(IsExpression), CanBeExpression(true),
560263509Sdim          InCtorInitializer(false) {}
561249261Sdim
562249261Sdim    tok::TokenKind ContextKind;
563249261Sdim    unsigned BindingStrength;
564249261Sdim    unsigned LongestObjCSelectorName;
565249261Sdim    bool ColonIsForRangeExpr;
566263509Sdim    bool ColonIsDictLiteral;
567249261Sdim    bool ColonIsObjCMethodExpr;
568263509Sdim    FormatToken *FirstObjCSelectorName;
569263509Sdim    FormatToken *FirstStartOfName;
570249261Sdim    bool IsExpression;
571249261Sdim    bool CanBeExpression;
572263509Sdim    bool InCtorInitializer;
573249261Sdim  };
574249261Sdim
575249261Sdim  /// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime
576249261Sdim  /// of each instance.
577249261Sdim  struct ScopedContextCreator {
578249261Sdim    AnnotatingParser &P;
579249261Sdim
580249261Sdim    ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind,
581249261Sdim                         unsigned Increase)
582249261Sdim        : P(P) {
583263509Sdim      P.Contexts.push_back(Context(ContextKind,
584263509Sdim                                   P.Contexts.back().BindingStrength + Increase,
585263509Sdim                                   P.Contexts.back().IsExpression));
586249261Sdim    }
587249261Sdim
588249261Sdim    ~ScopedContextCreator() { P.Contexts.pop_back(); }
589249261Sdim  };
590249261Sdim
591263509Sdim  void determineTokenType(FormatToken &Current) {
592263509Sdim    if (Current.getPrecedence() == prec::Assignment &&
593263509Sdim        !Line.First->isOneOf(tok::kw_template, tok::kw_using) &&
594263509Sdim        (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
595249261Sdim      Contexts.back().IsExpression = true;
596263509Sdim      for (FormatToken *Previous = Current.Previous;
597263509Sdim           Previous && !Previous->isOneOf(tok::comma, tok::semi);
598263509Sdim           Previous = Previous->Previous) {
599249261Sdim        if (Previous->is(tok::r_square))
600249261Sdim          Previous = Previous->MatchingParen;
601249261Sdim        if (Previous->Type == TT_BinaryOperator &&
602249261Sdim            Previous->isOneOf(tok::star, tok::amp)) {
603249261Sdim          Previous->Type = TT_PointerOrReference;
604249261Sdim        }
605249261Sdim      }
606249261Sdim    } else if (Current.isOneOf(tok::kw_return, tok::kw_throw) ||
607249261Sdim               (Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
608263509Sdim                !Line.InPPDirective &&
609263509Sdim                (!Current.Previous ||
610263509Sdim                 !Current.Previous->isOneOf(tok::kw_for, tok::kw_catch)))) {
611249261Sdim      Contexts.back().IsExpression = true;
612249261Sdim    } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
613263509Sdim      for (FormatToken *Previous = Current.Previous;
614249261Sdim           Previous && Previous->isOneOf(tok::star, tok::amp);
615263509Sdim           Previous = Previous->Previous)
616249261Sdim        Previous->Type = TT_PointerOrReference;
617263509Sdim    } else if (Current.Previous &&
618263509Sdim               Current.Previous->Type == TT_CtorInitializerColon) {
619249261Sdim      Contexts.back().IsExpression = true;
620263509Sdim      Contexts.back().InCtorInitializer = true;
621249261Sdim    } else if (Current.is(tok::kw_new)) {
622249261Sdim      Contexts.back().CanBeExpression = false;
623263509Sdim    } else if (Current.is(tok::semi) || Current.is(tok::exclaim)) {
624252723Sdim      // This should be the condition or increment in a for-loop.
625252723Sdim      Contexts.back().IsExpression = true;
626249261Sdim    }
627249261Sdim
628249261Sdim    if (Current.Type == TT_Unknown) {
629263509Sdim      // Line.MightBeFunctionDecl can only be true after the parentheses of a
630263509Sdim      // function declaration have been found. In this case, 'Current' is a
631263509Sdim      // trailing token of this declaration and thus cannot be a name.
632263509Sdim      if (isStartOfName(Current) && !Line.MightBeFunctionDecl) {
633249261Sdim        Contexts.back().FirstStartOfName = &Current;
634249261Sdim        Current.Type = TT_StartOfName;
635263509Sdim      } else if (Current.is(tok::kw_auto)) {
636263509Sdim        AutoFound = true;
637263509Sdim      } else if (Current.is(tok::arrow) && AutoFound &&
638263509Sdim                 Line.MustBeDeclaration) {
639263509Sdim        Current.Type = TT_TrailingReturnArrow;
640249261Sdim      } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
641249261Sdim        Current.Type =
642263509Sdim            determineStarAmpUsage(Current, Contexts.back().CanBeExpression &&
643263509Sdim                                               Contexts.back().IsExpression);
644249261Sdim      } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
645249261Sdim        Current.Type = determinePlusMinusCaretUsage(Current);
646249261Sdim      } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {
647249261Sdim        Current.Type = determineIncrementUsage(Current);
648249261Sdim      } else if (Current.is(tok::exclaim)) {
649249261Sdim        Current.Type = TT_UnaryOperator;
650263509Sdim      } else if (Current.isBinaryOperator() &&
651263509Sdim                 (!Current.Previous ||
652263509Sdim                  Current.Previous->isNot(tok::l_square))) {
653249261Sdim        Current.Type = TT_BinaryOperator;
654249261Sdim      } else if (Current.is(tok::comment)) {
655263509Sdim        if (Current.TokenText.startswith("//"))
656249261Sdim          Current.Type = TT_LineComment;
657249261Sdim        else
658249261Sdim          Current.Type = TT_BlockComment;
659249261Sdim      } else if (Current.is(tok::r_paren)) {
660263509Sdim        FormatToken *LeftOfParens = NULL;
661263509Sdim        if (Current.MatchingParen)
662263509Sdim          LeftOfParens = Current.MatchingParen->getPreviousNonComment();
663263509Sdim        bool IsCast = false;
664263509Sdim        bool ParensAreEmpty = Current.Previous == Current.MatchingParen;
665263509Sdim        bool ParensAreType = !Current.Previous ||
666263509Sdim                             Current.Previous->Type == TT_PointerOrReference ||
667263509Sdim                             Current.Previous->Type == TT_TemplateCloser ||
668263509Sdim                             isSimpleTypeSpecifier(*Current.Previous);
669249261Sdim        bool ParensCouldEndDecl =
670263509Sdim            Current.Next &&
671263509Sdim            Current.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
672249261Sdim        bool IsSizeOfOrAlignOf =
673263509Sdim            LeftOfParens &&
674263509Sdim            LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
675263509Sdim        if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
676263509Sdim            (Contexts.back().IsExpression ||
677263509Sdim             (Current.Next && Current.Next->isBinaryOperator())))
678263509Sdim          IsCast = true;
679263509Sdim        if (Current.Next && Current.Next->isNot(tok::string_literal) &&
680263509Sdim            (Current.Next->Tok.isLiteral() ||
681263509Sdim             Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
682263509Sdim          IsCast = true;
683263509Sdim        // If there is an identifier after the (), it is likely a cast, unless
684263509Sdim        // there is also an identifier before the ().
685263509Sdim        if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL ||
686263509Sdim                             LeftOfParens->is(tok::kw_return)) &&
687263509Sdim            LeftOfParens->Type != TT_OverloadedOperator &&
688263509Sdim            LeftOfParens->Type != TT_TemplateCloser && Current.Next &&
689263509Sdim            Current.Next->is(tok::identifier))
690263509Sdim          IsCast = true;
691263509Sdim        if (IsCast && !ParensAreEmpty)
692249261Sdim          Current.Type = TT_CastRParen;
693263509Sdim      } else if (Current.is(tok::at) && Current.Next) {
694263509Sdim        switch (Current.Next->Tok.getObjCKeywordID()) {
695249261Sdim        case tok::objc_interface:
696249261Sdim        case tok::objc_implementation:
697249261Sdim        case tok::objc_protocol:
698249261Sdim          Current.Type = TT_ObjCDecl;
699249261Sdim          break;
700249261Sdim        case tok::objc_property:
701249261Sdim          Current.Type = TT_ObjCProperty;
702249261Sdim          break;
703249261Sdim        default:
704249261Sdim          break;
705249261Sdim        }
706263509Sdim      } else if (Current.is(tok::period)) {
707263509Sdim        FormatToken *PreviousNoComment = Current.getPreviousNonComment();
708263509Sdim        if (PreviousNoComment &&
709263509Sdim            PreviousNoComment->isOneOf(tok::comma, tok::l_brace))
710263509Sdim          Current.Type = TT_DesignatedInitializerPeriod;
711249261Sdim      }
712249261Sdim    }
713249261Sdim  }
714249261Sdim
715263509Sdim  /// \brief Take a guess at whether \p Tok starts a name of a function or
716263509Sdim  /// variable declaration.
717263509Sdim  ///
718263509Sdim  /// This is a heuristic based on whether \p Tok is an identifier following
719263509Sdim  /// something that is likely a type.
720263509Sdim  bool isStartOfName(const FormatToken &Tok) {
721263509Sdim    if (Tok.isNot(tok::identifier) || Tok.Previous == NULL)
722263509Sdim      return false;
723263509Sdim
724263509Sdim    // Skip "const" as it does not have an influence on whether this is a name.
725263509Sdim    FormatToken *PreviousNotConst = Tok.Previous;
726263509Sdim    while (PreviousNotConst != NULL && PreviousNotConst->is(tok::kw_const))
727263509Sdim      PreviousNotConst = PreviousNotConst->Previous;
728263509Sdim
729263509Sdim    if (PreviousNotConst == NULL)
730263509Sdim      return false;
731263509Sdim
732263509Sdim    bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&
733263509Sdim                       PreviousNotConst->Previous &&
734263509Sdim                       PreviousNotConst->Previous->is(tok::hash);
735263509Sdim
736263509Sdim    if (PreviousNotConst->Type == TT_TemplateCloser)
737263509Sdim      return PreviousNotConst && PreviousNotConst->MatchingParen &&
738263509Sdim             PreviousNotConst->MatchingParen->Previous &&
739263509Sdim             PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
740263509Sdim
741263509Sdim    return (!IsPPKeyword && PreviousNotConst->is(tok::identifier)) ||
742263509Sdim           PreviousNotConst->Type == TT_PointerOrReference ||
743263509Sdim           isSimpleTypeSpecifier(*PreviousNotConst);
744263509Sdim  }
745263509Sdim
746249261Sdim  /// \brief Return the type of the given token assuming it is * or &.
747263509Sdim  TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression) {
748263509Sdim    const FormatToken *PrevToken = Tok.getPreviousNonComment();
749249261Sdim    if (PrevToken == NULL)
750249261Sdim      return TT_UnaryOperator;
751249261Sdim
752263509Sdim    const FormatToken *NextToken = Tok.getNextNonComment();
753249261Sdim    if (NextToken == NULL)
754249261Sdim      return TT_Unknown;
755249261Sdim
756263509Sdim    if (PrevToken->is(tok::coloncolon) ||
757263509Sdim        (PrevToken->is(tok::l_paren) && !IsExpression))
758249261Sdim      return TT_PointerOrReference;
759249261Sdim
760249261Sdim    if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace,
761249261Sdim                           tok::comma, tok::semi, tok::kw_return, tok::colon,
762263509Sdim                           tok::equal, tok::kw_delete, tok::kw_sizeof) ||
763249261Sdim        PrevToken->Type == TT_BinaryOperator ||
764249261Sdim        PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen)
765249261Sdim      return TT_UnaryOperator;
766249261Sdim
767249261Sdim    if (NextToken->is(tok::l_square))
768249261Sdim      return TT_PointerOrReference;
769249261Sdim
770263509Sdim    if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
771263509Sdim        PrevToken->MatchingParen->Previous &&
772263509Sdim        PrevToken->MatchingParen->Previous->is(tok::kw_typeof))
773263509Sdim      return TT_PointerOrReference;
774263509Sdim
775263509Sdim    if (PrevToken->Tok.isLiteral() ||
776249261Sdim        PrevToken->isOneOf(tok::r_paren, tok::r_square) ||
777263509Sdim        NextToken->Tok.isLiteral() || NextToken->isUnaryOperator())
778249261Sdim      return TT_BinaryOperator;
779249261Sdim
780249261Sdim    // It is very unlikely that we are going to find a pointer or reference type
781249261Sdim    // definition on the RHS of an assignment.
782249261Sdim    if (IsExpression)
783249261Sdim      return TT_BinaryOperator;
784249261Sdim
785249261Sdim    return TT_PointerOrReference;
786249261Sdim  }
787249261Sdim
788263509Sdim  TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
789263509Sdim    const FormatToken *PrevToken = Tok.getPreviousNonComment();
790263509Sdim    if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
791249261Sdim      return TT_UnaryOperator;
792249261Sdim
793249261Sdim    // Use heuristics to recognize unary operators.
794249261Sdim    if (PrevToken->isOneOf(tok::equal, tok::l_paren, tok::comma, tok::l_square,
795249261Sdim                           tok::question, tok::colon, tok::kw_return,
796249261Sdim                           tok::kw_case, tok::at, tok::l_brace))
797249261Sdim      return TT_UnaryOperator;
798249261Sdim
799249261Sdim    // There can't be two consecutive binary operators.
800249261Sdim    if (PrevToken->Type == TT_BinaryOperator)
801249261Sdim      return TT_UnaryOperator;
802249261Sdim
803249261Sdim    // Fall back to marking the token as binary operator.
804249261Sdim    return TT_BinaryOperator;
805249261Sdim  }
806249261Sdim
807249261Sdim  /// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
808263509Sdim  TokenType determineIncrementUsage(const FormatToken &Tok) {
809263509Sdim    const FormatToken *PrevToken = Tok.getPreviousNonComment();
810263509Sdim    if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
811249261Sdim      return TT_UnaryOperator;
812249261Sdim    if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))
813249261Sdim      return TT_TrailingUnaryOperator;
814249261Sdim
815249261Sdim    return TT_UnaryOperator;
816249261Sdim  }
817249261Sdim
818249261Sdim  // FIXME: This is copy&pasted from Sema. Put it in a common place and remove
819249261Sdim  // duplication.
820249261Sdim  /// \brief Determine whether the token kind starts a simple-type-specifier.
821263509Sdim  bool isSimpleTypeSpecifier(const FormatToken &Tok) const {
822263509Sdim    switch (Tok.Tok.getKind()) {
823249261Sdim    case tok::kw_short:
824249261Sdim    case tok::kw_long:
825249261Sdim    case tok::kw___int64:
826249261Sdim    case tok::kw___int128:
827249261Sdim    case tok::kw_signed:
828249261Sdim    case tok::kw_unsigned:
829249261Sdim    case tok::kw_void:
830249261Sdim    case tok::kw_char:
831249261Sdim    case tok::kw_int:
832249261Sdim    case tok::kw_half:
833249261Sdim    case tok::kw_float:
834249261Sdim    case tok::kw_double:
835249261Sdim    case tok::kw_wchar_t:
836249261Sdim    case tok::kw_bool:
837249261Sdim    case tok::kw___underlying_type:
838249261Sdim    case tok::annot_typename:
839249261Sdim    case tok::kw_char16_t:
840249261Sdim    case tok::kw_char32_t:
841249261Sdim    case tok::kw_typeof:
842249261Sdim    case tok::kw_decltype:
843263509Sdim      return true;
844249261Sdim    default:
845263509Sdim      return false;
846249261Sdim    }
847249261Sdim  }
848249261Sdim
849249261Sdim  SmallVector<Context, 8> Contexts;
850249261Sdim
851263509Sdim  const FormatStyle &Style;
852249261Sdim  AnnotatedLine &Line;
853263509Sdim  FormatToken *CurrentToken;
854249261Sdim  bool KeywordVirtualFound;
855263509Sdim  bool AutoFound;
856249261Sdim  IdentifierInfo &Ident_in;
857249261Sdim};
858249261Sdim
859263509Sdimstatic int PrecedenceUnaryOperator = prec::PointerToMember + 1;
860263509Sdimstatic int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
861263509Sdim
862249261Sdim/// \brief Parses binary expressions by inserting fake parenthesis based on
863249261Sdim/// operator precedence.
864249261Sdimclass ExpressionParser {
865249261Sdimpublic:
866263509Sdim  ExpressionParser(AnnotatedLine &Line) : Current(Line.First) {
867263509Sdim    // Skip leading "}", e.g. in "} else if (...) {".
868263509Sdim    if (Current->is(tok::r_brace))
869263509Sdim      next();
870263509Sdim  }
871249261Sdim
872249261Sdim  /// \brief Parse expressions with the given operatore precedence.
873249261Sdim  void parse(int Precedence = 0) {
874263509Sdim    // Skip 'return' and ObjC selector colons as they are not part of a binary
875263509Sdim    // expression.
876263509Sdim    while (Current &&
877263509Sdim           (Current->is(tok::kw_return) ||
878263509Sdim            (Current->is(tok::colon) && Current->Type == TT_ObjCMethodExpr)))
879263509Sdim      next();
880263509Sdim
881263509Sdim    if (Current == NULL || Precedence > PrecedenceArrowAndPeriod)
882249261Sdim      return;
883249261Sdim
884263509Sdim    // Conditional expressions need to be parsed separately for proper nesting.
885263509Sdim    if (Precedence == prec::Conditional) {
886263509Sdim      parseConditionalExpr();
887263509Sdim      return;
888249261Sdim    }
889249261Sdim
890263509Sdim    // Parse unary operators, which all have a higher precedence than binary
891263509Sdim    // operators.
892263509Sdim    if (Precedence == PrecedenceUnaryOperator) {
893263509Sdim      parseUnaryOperator();
894263509Sdim      return;
895263509Sdim    }
896249261Sdim
897263509Sdim    FormatToken *Start = Current;
898263509Sdim    FormatToken *LatestOperator = NULL;
899263509Sdim
900249261Sdim    while (Current) {
901249261Sdim      // Consume operators with higher precedence.
902252723Sdim      parse(Precedence + 1);
903249261Sdim
904263509Sdim      int CurrentPrecedence = getCurrentPrecedence();
905249261Sdim
906263509Sdim      if (Current && Current->Type == TT_ObjCSelectorName &&
907263509Sdim          Precedence == CurrentPrecedence)
908263509Sdim        Start = Current;
909263509Sdim
910249261Sdim      // At the end of the line or when an operator with higher precedence is
911249261Sdim      // found, insert fake parenthesis and return.
912252723Sdim      if (Current == NULL || Current->closesScope() ||
913263509Sdim          (CurrentPrecedence != -1 && CurrentPrecedence < Precedence)) {
914263509Sdim        if (LatestOperator) {
915263509Sdim          if (Precedence == PrecedenceArrowAndPeriod) {
916263509Sdim            LatestOperator->LastInChainOfCalls = true;
917263509Sdim            // Call expressions don't have a binary operator precedence.
918263509Sdim            addFakeParenthesis(Start, prec::Unknown);
919263509Sdim          } else {
920263509Sdim            addFakeParenthesis(Start, prec::Level(Precedence));
921263509Sdim          }
922249261Sdim        }
923249261Sdim        return;
924249261Sdim      }
925249261Sdim
926249261Sdim      // Consume scopes: (), [], <> and {}
927252723Sdim      if (Current->opensScope()) {
928252723Sdim        while (Current && !Current->closesScope()) {
929249261Sdim          next();
930249261Sdim          parse();
931249261Sdim        }
932249261Sdim        next();
933249261Sdim      } else {
934249261Sdim        // Operator found.
935249261Sdim        if (CurrentPrecedence == Precedence)
936263509Sdim          LatestOperator = Current;
937249261Sdim
938249261Sdim        next();
939249261Sdim      }
940249261Sdim    }
941249261Sdim  }
942249261Sdim
943249261Sdimprivate:
944263509Sdim  /// \brief Gets the precedence (+1) of the given token for binary operators
945263509Sdim  /// and other tokens that we treat like binary operators.
946263509Sdim  int getCurrentPrecedence() {
947263509Sdim    if (Current) {
948263509Sdim      if (Current->Type == TT_ConditionalExpr)
949263509Sdim        return prec::Conditional;
950263509Sdim      else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon ||
951263509Sdim               Current->Type == TT_ObjCSelectorName)
952263509Sdim        return 0;
953263509Sdim      else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma))
954263509Sdim        return Current->getPrecedence();
955263509Sdim      else if (Current->isOneOf(tok::period, tok::arrow))
956263509Sdim        return PrecedenceArrowAndPeriod;
957263509Sdim    }
958263509Sdim    return -1;
959263509Sdim  }
960263509Sdim
961263509Sdim  void addFakeParenthesis(FormatToken *Start, prec::Level Precedence) {
962263509Sdim    Start->FakeLParens.push_back(Precedence);
963263509Sdim    if (Precedence > prec::Unknown)
964263509Sdim      Start->StartsBinaryExpression = true;
965263509Sdim    if (Current) {
966263509Sdim      ++Current->Previous->FakeRParens;
967263509Sdim      if (Precedence > prec::Unknown)
968263509Sdim        Current->Previous->EndsBinaryExpression = true;
969263509Sdim    }
970263509Sdim  }
971263509Sdim
972263509Sdim  /// \brief Parse unary operator expressions and surround them with fake
973263509Sdim  /// parentheses if appropriate.
974263509Sdim  void parseUnaryOperator() {
975263509Sdim    if (Current == NULL || Current->Type != TT_UnaryOperator) {
976263509Sdim      parse(PrecedenceArrowAndPeriod);
977263509Sdim      return;
978263509Sdim    }
979263509Sdim
980263509Sdim    FormatToken *Start = Current;
981263509Sdim    next();
982263509Sdim    parseUnaryOperator();
983263509Sdim
984263509Sdim    // The actual precedence doesn't matter.
985263509Sdim    addFakeParenthesis(Start, prec::Unknown);
986263509Sdim  }
987263509Sdim
988263509Sdim  void parseConditionalExpr() {
989263509Sdim    FormatToken *Start = Current;
990263509Sdim    parse(prec::LogicalOr);
991263509Sdim    if (!Current || !Current->is(tok::question))
992263509Sdim      return;
993263509Sdim    next();
994263509Sdim    parse(prec::LogicalOr);
995263509Sdim    if (!Current || Current->Type != TT_ConditionalExpr)
996263509Sdim      return;
997263509Sdim    next();
998263509Sdim    parseConditionalExpr();
999263509Sdim    addFakeParenthesis(Start, prec::Conditional);
1000263509Sdim  }
1001263509Sdim
1002249261Sdim  void next() {
1003263509Sdim    if (Current)
1004263509Sdim      Current = Current->Next;
1005263509Sdim    while (Current && Current->isTrailingComment())
1006263509Sdim      Current = Current->Next;
1007249261Sdim  }
1008249261Sdim
1009263509Sdim  FormatToken *Current;
1010249261Sdim};
1011249261Sdim
1012263509Sdim} // end anonymous namespace
1013263509Sdim
1014263509Sdimvoid
1015263509SdimTokenAnnotator::setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) {
1016263509Sdim  const AnnotatedLine *NextNonCommentLine = NULL;
1017263509Sdim  for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(),
1018263509Sdim                                                          E = Lines.rend();
1019263509Sdim       I != E; ++I) {
1020263509Sdim    if (NextNonCommentLine && (*I)->First->is(tok::comment) &&
1021263509Sdim        (*I)->First->Next == NULL)
1022263509Sdim      (*I)->Level = NextNonCommentLine->Level;
1023263509Sdim    else
1024263509Sdim      NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : NULL;
1025263509Sdim
1026263509Sdim    setCommentLineLevels((*I)->Children);
1027263509Sdim  }
1028263509Sdim}
1029263509Sdim
1030249261Sdimvoid TokenAnnotator::annotate(AnnotatedLine &Line) {
1031263509Sdim  for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
1032263509Sdim                                                  E = Line.Children.end();
1033263509Sdim       I != E; ++I) {
1034263509Sdim    annotate(**I);
1035263509Sdim  }
1036263509Sdim  AnnotatingParser Parser(Style, Line, Ident_in);
1037249261Sdim  Line.Type = Parser.parseLine();
1038249261Sdim  if (Line.Type == LT_Invalid)
1039249261Sdim    return;
1040249261Sdim
1041249261Sdim  ExpressionParser ExprParser(Line);
1042249261Sdim  ExprParser.parse();
1043249261Sdim
1044263509Sdim  if (Line.First->Type == TT_ObjCMethodSpecifier)
1045249261Sdim    Line.Type = LT_ObjCMethodDecl;
1046263509Sdim  else if (Line.First->Type == TT_ObjCDecl)
1047249261Sdim    Line.Type = LT_ObjCDecl;
1048263509Sdim  else if (Line.First->Type == TT_ObjCProperty)
1049249261Sdim    Line.Type = LT_ObjCProperty;
1050249261Sdim
1051263509Sdim  Line.First->SpacesRequiredBefore = 1;
1052263509Sdim  Line.First->CanBreakBefore = Line.First->MustBreakBefore;
1053249261Sdim}
1054249261Sdim
1055249261Sdimvoid TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
1056263509Sdim  Line.First->TotalLength =
1057263509Sdim      Line.First->IsMultiline ? Style.ColumnLimit : Line.First->ColumnWidth;
1058263509Sdim  if (!Line.First->Next)
1059249261Sdim    return;
1060263509Sdim  FormatToken *Current = Line.First->Next;
1061263509Sdim  bool InFunctionDecl = Line.MightBeFunctionDecl;
1062249261Sdim  while (Current != NULL) {
1063249261Sdim    if (Current->Type == TT_LineComment)
1064249261Sdim      Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;
1065263509Sdim    else if (Current->SpacesRequiredBefore == 0 &&
1066263509Sdim             spaceRequiredBefore(Line, *Current))
1067263509Sdim      Current->SpacesRequiredBefore = 1;
1068249261Sdim
1069263509Sdim    Current->MustBreakBefore =
1070263509Sdim        Current->MustBreakBefore || mustBreakBefore(Line, *Current);
1071263509Sdim
1072249261Sdim    Current->CanBreakBefore =
1073249261Sdim        Current->MustBreakBefore || canBreakBefore(Line, *Current);
1074263509Sdim    if (Current->MustBreakBefore || !Current->Children.empty() ||
1075263509Sdim        Current->IsMultiline)
1076263509Sdim      Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit;
1077249261Sdim    else
1078263509Sdim      Current->TotalLength = Current->Previous->TotalLength +
1079263509Sdim                             Current->ColumnWidth +
1080263509Sdim                             Current->SpacesRequiredBefore;
1081263509Sdim
1082263509Sdim    if (Current->Type == TT_CtorInitializerColon)
1083263509Sdim      InFunctionDecl = false;
1084263509Sdim
1085249261Sdim    // FIXME: Only calculate this if CanBreakBefore is true once static
1086249261Sdim    // initializers etc. are sorted out.
1087249261Sdim    // FIXME: Move magic numbers to a better place.
1088263509Sdim    Current->SplitPenalty = 20 * Current->BindingStrength +
1089263509Sdim                            splitPenalty(Line, *Current, InFunctionDecl);
1090249261Sdim
1091263509Sdim    Current = Current->Next;
1092249261Sdim  }
1093252723Sdim
1094263509Sdim  calculateUnbreakableTailLengths(Line);
1095263509Sdim  for (Current = Line.First; Current != NULL; Current = Current->Next) {
1096263509Sdim    if (Current->Role)
1097263509Sdim      Current->Role->precomputeFormattingInfos(Current);
1098263509Sdim  }
1099263509Sdim
1100263509Sdim  DEBUG({ printDebugInfo(Line); });
1101263509Sdim
1102263509Sdim  for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
1103263509Sdim                                                  E = Line.Children.end();
1104263509Sdim       I != E; ++I) {
1105263509Sdim    calculateFormattingInformation(**I);
1106263509Sdim  }
1107249261Sdim}
1108249261Sdim
1109263509Sdimvoid TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
1110263509Sdim  unsigned UnbreakableTailLength = 0;
1111263509Sdim  FormatToken *Current = Line.Last;
1112263509Sdim  while (Current != NULL) {
1113263509Sdim    Current->UnbreakableTailLength = UnbreakableTailLength;
1114263509Sdim    if (Current->CanBreakBefore ||
1115263509Sdim        Current->isOneOf(tok::comment, tok::string_literal)) {
1116263509Sdim      UnbreakableTailLength = 0;
1117263509Sdim    } else {
1118263509Sdim      UnbreakableTailLength +=
1119263509Sdim          Current->ColumnWidth + Current->SpacesRequiredBefore;
1120263509Sdim    }
1121263509Sdim    Current = Current->Previous;
1122263509Sdim  }
1123263509Sdim}
1124263509Sdim
1125249261Sdimunsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
1126263509Sdim                                      const FormatToken &Tok,
1127263509Sdim                                      bool InFunctionDecl) {
1128263509Sdim  const FormatToken &Left = *Tok.Previous;
1129263509Sdim  const FormatToken &Right = Tok;
1130249261Sdim
1131263509Sdim  if (Left.is(tok::semi))
1132263509Sdim    return 0;
1133263509Sdim  if (Left.is(tok::comma))
1134263509Sdim    return 1;
1135263509Sdim  if (Right.is(tok::l_square))
1136263509Sdim    return 150;
1137263509Sdim
1138263509Sdim  if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator)) {
1139263509Sdim    if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
1140249261Sdim      return 3;
1141263509Sdim    if (Left.Type == TT_StartOfName)
1142263509Sdim      return 20;
1143263509Sdim    if (InFunctionDecl && Right.BindingStrength == 1)
1144249261Sdim      // FIXME: Clean up hack of using BindingStrength to find top-level names.
1145249261Sdim      return Style.PenaltyReturnTypeOnItsOwnLine;
1146263509Sdim    return 200;
1147249261Sdim  }
1148249261Sdim  if (Left.is(tok::equal) && Right.is(tok::l_brace))
1149249261Sdim    return 150;
1150263509Sdim  if (Left.Type == TT_CastRParen)
1151263509Sdim    return 100;
1152249261Sdim  if (Left.is(tok::coloncolon))
1153249261Sdim    return 500;
1154252723Sdim  if (Left.isOneOf(tok::kw_class, tok::kw_struct))
1155252723Sdim    return 5000;
1156249261Sdim
1157249261Sdim  if (Left.Type == TT_RangeBasedForLoopColon ||
1158249261Sdim      Left.Type == TT_InheritanceColon)
1159249261Sdim    return 2;
1160249261Sdim
1161263509Sdim  if (Right.isMemberAccess()) {
1162249261Sdim    if (Left.isOneOf(tok::r_paren, tok::r_square) && Left.MatchingParen &&
1163249261Sdim        Left.MatchingParen->ParameterCount > 0)
1164249261Sdim      return 20; // Should be smaller than breaking at a nested comma.
1165249261Sdim    return 150;
1166249261Sdim  }
1167249261Sdim
1168263509Sdim  // Breaking before a trailing 'const' or not-function-like annotation is bad.
1169263509Sdim  if (Left.is(tok::r_paren) && Line.Type != LT_ObjCProperty &&
1170263509Sdim      (Right.is(tok::kw_const) || (Right.is(tok::identifier) && Right.Next &&
1171263509Sdim                                   Right.Next->isNot(tok::l_paren))))
1172263509Sdim    return 100;
1173263509Sdim
1174249261Sdim  // In for-loops, prefer breaking at ',' and ';'.
1175263509Sdim  if (Line.First->is(tok::kw_for) && Left.is(tok::equal))
1176249261Sdim    return 4;
1177249261Sdim
1178249261Sdim  // In Objective-C method expressions, prefer breaking before "param:" over
1179249261Sdim  // breaking after it.
1180249261Sdim  if (Right.Type == TT_ObjCSelectorName)
1181249261Sdim    return 0;
1182249261Sdim  if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
1183263509Sdim    return 50;
1184249261Sdim
1185263509Sdim  if (Left.is(tok::l_paren) && InFunctionDecl)
1186252723Sdim    return 100;
1187252723Sdim  if (Left.opensScope())
1188263509Sdim    return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter
1189263509Sdim                                   : 19;
1190249261Sdim
1191249261Sdim  if (Right.is(tok::lessless)) {
1192249261Sdim    if (Left.is(tok::string_literal)) {
1193263509Sdim      StringRef Content = Left.TokenText;
1194263509Sdim      if (Content.startswith("\""))
1195263509Sdim        Content = Content.drop_front(1);
1196263509Sdim      if (Content.endswith("\""))
1197263509Sdim        Content = Content.drop_back(1);
1198263509Sdim      Content = Content.trim();
1199249261Sdim      if (Content.size() > 1 &&
1200249261Sdim          (Content.back() == ':' || Content.back() == '='))
1201263509Sdim        return 25;
1202249261Sdim    }
1203263509Sdim    return 1; // Breaking at a << is really cheap.
1204249261Sdim  }
1205249261Sdim  if (Left.Type == TT_ConditionalExpr)
1206249261Sdim    return prec::Conditional;
1207263509Sdim  prec::Level Level = Left.getPrecedence();
1208249261Sdim
1209249261Sdim  if (Level != prec::Unknown)
1210249261Sdim    return Level;
1211249261Sdim
1212249261Sdim  return 3;
1213249261Sdim}
1214249261Sdim
1215249261Sdimbool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
1216263509Sdim                                          const FormatToken &Left,
1217263509Sdim                                          const FormatToken &Right) {
1218249261Sdim  if (Right.is(tok::hashhash))
1219249261Sdim    return Left.is(tok::hash);
1220249261Sdim  if (Left.isOneOf(tok::hashhash, tok::hash))
1221249261Sdim    return Right.is(tok::hash);
1222263509Sdim  if (Left.is(tok::l_paren) && Right.is(tok::r_paren))
1223263509Sdim    return Style.SpaceInEmptyParentheses;
1224263509Sdim  if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
1225263509Sdim    return (Right.Type == TT_CastRParen ||
1226263509Sdim            (Left.MatchingParen && Left.MatchingParen->Type == TT_CastRParen))
1227263509Sdim               ? Style.SpacesInCStyleCastParentheses
1228263509Sdim               : Style.SpacesInParentheses;
1229263509Sdim  if (Style.SpacesInAngles &&
1230263509Sdim      ((Left.Type == TT_TemplateOpener) != (Right.Type == TT_TemplateCloser)))
1231263509Sdim    return true;
1232263509Sdim  if (Right.isOneOf(tok::semi, tok::comma))
1233249261Sdim    return false;
1234249261Sdim  if (Right.is(tok::less) &&
1235249261Sdim      (Left.is(tok::kw_template) ||
1236249261Sdim       (Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
1237249261Sdim    return true;
1238249261Sdim  if (Left.is(tok::arrow) || Right.is(tok::arrow))
1239249261Sdim    return false;
1240249261Sdim  if (Left.isOneOf(tok::exclaim, tok::tilde))
1241249261Sdim    return false;
1242249261Sdim  if (Left.is(tok::at) &&
1243249261Sdim      Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant,
1244249261Sdim                    tok::numeric_constant, tok::l_paren, tok::l_brace,
1245249261Sdim                    tok::kw_true, tok::kw_false))
1246249261Sdim    return false;
1247249261Sdim  if (Left.is(tok::coloncolon))
1248249261Sdim    return false;
1249249261Sdim  if (Right.is(tok::coloncolon))
1250263509Sdim    return (Left.is(tok::less) && Style.Standard == FormatStyle::LS_Cpp03) ||
1251263509Sdim           !Left.isOneOf(tok::identifier, tok::greater, tok::l_paren,
1252263509Sdim                         tok::r_paren, tok::less);
1253249261Sdim  if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less))
1254249261Sdim    return false;
1255263509Sdim  if (Right.is(tok::ellipsis))
1256263509Sdim    return Left.Tok.isLiteral();
1257263509Sdim  if (Left.is(tok::l_square) && Right.is(tok::amp))
1258263509Sdim    return false;
1259249261Sdim  if (Right.Type == TT_PointerOrReference)
1260263509Sdim    return Left.Tok.isLiteral() ||
1261249261Sdim           ((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) &&
1262249261Sdim            !Style.PointerBindsToType);
1263263509Sdim  if (Right.Type == TT_FunctionTypeLParen && Left.isNot(tok::l_paren) &&
1264263509Sdim      (Left.Type != TT_PointerOrReference || Style.PointerBindsToType))
1265263509Sdim    return true;
1266249261Sdim  if (Left.Type == TT_PointerOrReference)
1267263509Sdim    return Right.Tok.isLiteral() || Right.Type == TT_BlockComment ||
1268249261Sdim           ((Right.Type != TT_PointerOrReference) &&
1269249261Sdim            Right.isNot(tok::l_paren) && Style.PointerBindsToType &&
1270263509Sdim            Left.Previous &&
1271263509Sdim            !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
1272249261Sdim  if (Right.is(tok::star) && Left.is(tok::l_paren))
1273249261Sdim    return false;
1274249261Sdim  if (Left.is(tok::l_square))
1275263509Sdim    return Left.Type == TT_ArrayInitializerLSquare &&
1276263509Sdim           Right.isNot(tok::r_square);
1277249261Sdim  if (Right.is(tok::r_square))
1278263509Sdim    return Right.MatchingParen &&
1279263509Sdim           Right.MatchingParen->Type == TT_ArrayInitializerLSquare;
1280263509Sdim  if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr &&
1281263509Sdim      Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant))
1282249261Sdim    return false;
1283249261Sdim  if (Left.is(tok::colon))
1284249261Sdim    return Left.Type != TT_ObjCMethodExpr;
1285249261Sdim  if (Right.is(tok::colon))
1286263509Sdim    return Right.Type != TT_ObjCMethodExpr && !Left.is(tok::question);
1287249261Sdim  if (Right.is(tok::l_paren)) {
1288263509Sdim    if (Left.is(tok::r_paren) && Left.MatchingParen &&
1289263509Sdim        Left.MatchingParen->Previous &&
1290263509Sdim        Left.MatchingParen->Previous->is(tok::kw___attribute))
1291263509Sdim      return true;
1292249261Sdim    return Line.Type == LT_ObjCDecl ||
1293263509Sdim           Left.isOneOf(tok::kw_return, tok::kw_new, tok::kw_delete,
1294263509Sdim                        tok::semi) ||
1295263509Sdim           (Style.SpaceAfterControlStatementKeyword &&
1296263509Sdim            Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,
1297263509Sdim                         tok::kw_catch));
1298249261Sdim  }
1299263509Sdim  if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
1300249261Sdim    return false;
1301249261Sdim  if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
1302263509Sdim    return !Left.Children.empty(); // No spaces in "{}".
1303263509Sdim  if (Left.is(tok::l_brace) || Right.is(tok::r_brace))
1304263509Sdim    return !Style.Cpp11BracedListStyle;
1305263509Sdim  if (Right.Type == TT_UnaryOperator)
1306263509Sdim    return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
1307263509Sdim           (Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr);
1308263509Sdim  if (Left.isOneOf(tok::identifier, tok::greater, tok::r_square) &&
1309263509Sdim      Right.is(tok::l_brace) && Right.getNextNonComment() &&
1310263509Sdim      Right.BlockKind != BK_Block)
1311249261Sdim    return false;
1312263509Sdim  if (Left.is(tok::period) || Right.is(tok::period))
1313252723Sdim    return false;
1314263509Sdim  if (Left.Type == TT_BlockComment && Left.TokenText.endswith("=*/"))
1315263509Sdim    return false;
1316263509Sdim  if (Right.is(tok::hash) && Left.is(tok::identifier) && Left.TokenText == "L")
1317263509Sdim    return false;
1318249261Sdim  return true;
1319249261Sdim}
1320249261Sdim
1321249261Sdimbool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
1322263509Sdim                                         const FormatToken &Tok) {
1323263509Sdim  if (Tok.Tok.getIdentifierInfo() && Tok.Previous->Tok.getIdentifierInfo())
1324249261Sdim    return true; // Never ever merge two identifiers.
1325263509Sdim  if (Tok.Previous->Type == TT_ImplicitStringLiteral)
1326263509Sdim    return Tok.WhitespaceRange.getBegin() != Tok.WhitespaceRange.getEnd();
1327249261Sdim  if (Line.Type == LT_ObjCMethodDecl) {
1328263509Sdim    if (Tok.Previous->Type == TT_ObjCMethodSpecifier)
1329249261Sdim      return true;
1330263509Sdim    if (Tok.Previous->is(tok::r_paren) && Tok.is(tok::identifier))
1331249261Sdim      // Don't space between ')' and <id>
1332249261Sdim      return false;
1333249261Sdim  }
1334249261Sdim  if (Line.Type == LT_ObjCProperty &&
1335263509Sdim      (Tok.is(tok::equal) || Tok.Previous->is(tok::equal)))
1336249261Sdim    return false;
1337249261Sdim
1338263509Sdim  if (Tok.Type == TT_TrailingReturnArrow ||
1339263509Sdim      Tok.Previous->Type == TT_TrailingReturnArrow)
1340249261Sdim    return true;
1341263509Sdim  if (Tok.Previous->is(tok::comma))
1342263509Sdim    return true;
1343249261Sdim  if (Tok.is(tok::comma))
1344249261Sdim    return false;
1345249261Sdim  if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
1346249261Sdim    return true;
1347263509Sdim  if (Tok.Previous->Tok.is(tok::kw_operator))
1348263509Sdim    return Tok.is(tok::coloncolon);
1349249261Sdim  if (Tok.Type == TT_OverloadedOperatorLParen)
1350249261Sdim    return false;
1351249261Sdim  if (Tok.is(tok::colon))
1352263509Sdim    return !Line.First->isOneOf(tok::kw_case, tok::kw_default) &&
1353263509Sdim           Tok.getNextNonComment() != NULL && Tok.Type != TT_ObjCMethodExpr &&
1354263509Sdim           !Tok.Previous->is(tok::question);
1355263509Sdim  if (Tok.Previous->Type == TT_UnaryOperator ||
1356263509Sdim      Tok.Previous->Type == TT_CastRParen)
1357249261Sdim    return false;
1358263509Sdim  if (Tok.Previous->is(tok::greater) && Tok.is(tok::greater)) {
1359249261Sdim    return Tok.Type == TT_TemplateCloser &&
1360263509Sdim           Tok.Previous->Type == TT_TemplateCloser &&
1361263509Sdim           (Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
1362249261Sdim  }
1363249261Sdim  if (Tok.isOneOf(tok::arrowstar, tok::periodstar) ||
1364263509Sdim      Tok.Previous->isOneOf(tok::arrowstar, tok::periodstar))
1365249261Sdim    return false;
1366263509Sdim  if (!Style.SpaceBeforeAssignmentOperators &&
1367263509Sdim      Tok.getPrecedence() == prec::Assignment)
1368263509Sdim    return false;
1369263509Sdim  if ((Tok.Type == TT_BinaryOperator && !Tok.Previous->is(tok::l_paren)) ||
1370263509Sdim      Tok.Previous->Type == TT_BinaryOperator)
1371249261Sdim    return true;
1372263509Sdim  if (Tok.Previous->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
1373249261Sdim    return false;
1374263509Sdim  if (Tok.is(tok::less) && Tok.Previous->isNot(tok::l_paren) &&
1375263509Sdim      Line.First->is(tok::hash))
1376249261Sdim    return true;
1377249261Sdim  if (Tok.Type == TT_TrailingUnaryOperator)
1378249261Sdim    return false;
1379263509Sdim  return spaceRequiredBetween(Line, *Tok.Previous, Tok);
1380249261Sdim}
1381249261Sdim
1382263509Sdimbool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
1383263509Sdim                                     const FormatToken &Right) {
1384263509Sdim  if (Right.is(tok::comment)) {
1385263509Sdim    return Right.NewlinesBefore > 0;
1386263509Sdim  } else if (Right.Previous->isTrailingComment() ||
1387263509Sdim             (Right.is(tok::string_literal) &&
1388263509Sdim              Right.Previous->is(tok::string_literal))) {
1389263509Sdim    return true;
1390263509Sdim  } else if (Right.Previous->IsUnterminatedLiteral) {
1391263509Sdim    return true;
1392263509Sdim  } else if (Right.is(tok::lessless) && Right.Next &&
1393263509Sdim             Right.Previous->is(tok::string_literal) &&
1394263509Sdim             Right.Next->is(tok::string_literal)) {
1395263509Sdim    return true;
1396263509Sdim  } else if (Right.Previous->ClosesTemplateDeclaration &&
1397263509Sdim             Right.Previous->MatchingParen &&
1398263509Sdim             Right.Previous->MatchingParen->BindingStrength == 1 &&
1399263509Sdim             Style.AlwaysBreakTemplateDeclarations) {
1400263509Sdim    // FIXME: Fix horrible hack of using BindingStrength to find top-level <>.
1401263509Sdim    return true;
1402263509Sdim  } else if (Right.Type == TT_CtorInitializerComma &&
1403263509Sdim             Style.BreakConstructorInitializersBeforeComma &&
1404263509Sdim             !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) {
1405263509Sdim    return true;
1406263509Sdim  } else if (Right.Previous->BlockKind == BK_Block &&
1407263509Sdim             Right.Previous->isNot(tok::r_brace) && Right.isNot(tok::r_brace)) {
1408263509Sdim    return true;
1409263509Sdim  } else if (Right.is(tok::l_brace) && (Right.BlockKind == BK_Block)) {
1410263509Sdim    return Style.BreakBeforeBraces == FormatStyle::BS_Allman;
1411263509Sdim  }
1412263509Sdim  return false;
1413263509Sdim}
1414263509Sdim
1415249261Sdimbool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
1416263509Sdim                                    const FormatToken &Right) {
1417263509Sdim  const FormatToken &Left = *Right.Previous;
1418263509Sdim  if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator))
1419249261Sdim    return true;
1420263509Sdim  if (Right.isTrailingComment())
1421263509Sdim    // We rely on MustBreakBefore being set correctly here as we should not
1422263509Sdim    // change the "binding" behavior of a comment.
1423249261Sdim    return false;
1424263509Sdim  if (Left.is(tok::question) && Right.is(tok::colon))
1425263509Sdim    return false;
1426263509Sdim  if (Right.Type == TT_ConditionalExpr || Right.is(tok::question))
1427263509Sdim    return Style.BreakBeforeTernaryOperators;
1428263509Sdim  if (Left.Type == TT_ConditionalExpr || Left.is(tok::question))
1429263509Sdim    return !Style.BreakBeforeTernaryOperators;
1430263509Sdim  if (Right.is(tok::colon) &&
1431263509Sdim      (Right.Type == TT_DictLiteral || Right.Type == TT_ObjCMethodExpr))
1432263509Sdim    return false;
1433263509Sdim  if (Left.is(tok::colon) &&
1434263509Sdim      (Left.Type == TT_DictLiteral || Left.Type == TT_ObjCMethodExpr))
1435249261Sdim    return true;
1436249261Sdim  if (Right.Type == TT_ObjCSelectorName)
1437249261Sdim    return true;
1438263509Sdim  if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
1439263509Sdim    return true;
1440249261Sdim  if (Left.ClosesTemplateDeclaration)
1441249261Sdim    return true;
1442249261Sdim  if (Right.Type == TT_RangeBasedForLoopColon ||
1443263509Sdim      Right.Type == TT_OverloadedOperatorLParen ||
1444263509Sdim      Right.Type == TT_OverloadedOperator)
1445249261Sdim    return false;
1446252723Sdim  if (Left.Type == TT_RangeBasedForLoopColon)
1447249261Sdim    return true;
1448249261Sdim  if (Right.Type == TT_RangeBasedForLoopColon)
1449249261Sdim    return false;
1450249261Sdim  if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser ||
1451263509Sdim      Left.Type == TT_UnaryOperator || Left.is(tok::kw_operator))
1452249261Sdim    return false;
1453249261Sdim  if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl)
1454249261Sdim    return false;
1455263509Sdim  if (Left.Previous) {
1456263509Sdim    if (Left.is(tok::l_paren) && Right.is(tok::l_paren) &&
1457263509Sdim        Left.Previous->is(tok::kw___attribute))
1458263509Sdim      return false;
1459263509Sdim    if (Left.is(tok::l_paren) && (Left.Previous->Type == TT_BinaryOperator ||
1460263509Sdim                                  Left.Previous->Type == TT_CastRParen))
1461263509Sdim      return false;
1462263509Sdim  }
1463263509Sdim  if (Right.Type == TT_ImplicitStringLiteral)
1464249261Sdim    return false;
1465249261Sdim
1466263509Sdim  if (Right.is(tok::r_paren) || Right.Type == TT_TemplateCloser)
1467249261Sdim    return false;
1468249261Sdim
1469263509Sdim  // We only break before r_brace if there was a corresponding break before
1470263509Sdim  // the l_brace, which is tracked by BreakBeforeClosingBrace.
1471263509Sdim  if (Right.is(tok::r_brace))
1472263509Sdim    return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block;
1473263509Sdim
1474249261Sdim  // Allow breaking after a trailing 'const', e.g. after a method declaration,
1475249261Sdim  // unless it is follow by ';', '{' or '='.
1476263509Sdim  if (Left.is(tok::kw_const) && Left.Previous != NULL &&
1477263509Sdim      Left.Previous->is(tok::r_paren))
1478249261Sdim    return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal);
1479249261Sdim
1480249261Sdim  if (Right.is(tok::kw___attribute))
1481249261Sdim    return true;
1482249261Sdim
1483249261Sdim  if (Left.is(tok::identifier) && Right.is(tok::string_literal))
1484249261Sdim    return true;
1485263509Sdim
1486263509Sdim  if (Left.Type == TT_CtorInitializerComma &&
1487263509Sdim      Style.BreakConstructorInitializersBeforeComma)
1488263509Sdim    return false;
1489263509Sdim  if (Right.Type == TT_CtorInitializerComma &&
1490263509Sdim      Style.BreakConstructorInitializersBeforeComma)
1491263509Sdim    return true;
1492263509Sdim  if (Right.isBinaryOperator() && Style.BreakBeforeBinaryOperators)
1493263509Sdim    return true;
1494263509Sdim  if (Left.is(tok::greater) && Right.is(tok::greater) &&
1495263509Sdim      Left.Type != TT_TemplateCloser)
1496263509Sdim    return false;
1497263509Sdim  if (Left.Type == TT_ArrayInitializerLSquare)
1498263509Sdim    return true;
1499263509Sdim  return (Left.isBinaryOperator() && Left.isNot(tok::lessless) &&
1500263509Sdim          !Style.BreakBeforeBinaryOperators) ||
1501252723Sdim         Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
1502252723Sdim                      tok::kw_class, tok::kw_struct) ||
1503263509Sdim         Right.isOneOf(tok::lessless, tok::arrow, tok::period, tok::colon,
1504263509Sdim                       tok::l_square, tok::at) ||
1505263509Sdim         (Left.is(tok::r_paren) &&
1506263509Sdim          Right.isOneOf(tok::identifier, tok::kw_const, tok::kw___attribute)) ||
1507263509Sdim         (Left.is(tok::l_paren) && !Right.is(tok::r_paren));
1508249261Sdim}
1509249261Sdim
1510252723Sdimvoid TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
1511252723Sdim  llvm::errs() << "AnnotatedTokens:\n";
1512263509Sdim  const FormatToken *Tok = Line.First;
1513252723Sdim  while (Tok) {
1514252723Sdim    llvm::errs() << " M=" << Tok->MustBreakBefore
1515252723Sdim                 << " C=" << Tok->CanBreakBefore << " T=" << Tok->Type
1516252723Sdim                 << " S=" << Tok->SpacesRequiredBefore
1517263509Sdim                 << " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName()
1518263509Sdim                 << " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind
1519263509Sdim                 << " FakeLParens=";
1520252723Sdim    for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
1521252723Sdim      llvm::errs() << Tok->FakeLParens[i] << "/";
1522252723Sdim    llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n";
1523263509Sdim    if (Tok->Next == NULL)
1524263509Sdim      assert(Tok == Line.Last);
1525263509Sdim    Tok = Tok->Next;
1526252723Sdim  }
1527252723Sdim  llvm::errs() << "----\n";
1528252723Sdim}
1529252723Sdim
1530249261Sdim} // namespace format
1531249261Sdim} // namespace clang
1532