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"
18251662Sdim#include "llvm/Support/Debug.h"
19249261Sdim
20249261Sdimnamespace clang {
21249261Sdimnamespace format {
22249261Sdim
23263508Sdimnamespace {
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:
32263508Sdim  AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,
33249261Sdim                   IdentifierInfo &Ident_in)
34263508Sdim      : Style(Style), Line(Line), CurrentToken(Line.First),
35263508Sdim        KeywordVirtualFound(false), AutoFound(false), Ident_in(Ident_in) {
36263508Sdim    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);
44263508Sdim    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,
55263508Sdim                                tok::question, tok::colon))
56249261Sdim        return false;
57263508Sdim      // If a && or || is found and interpreted as a binary operator, this set
58263508Sdim      // of angles is likely part of something like "a < b && c > d". If the
59263508Sdim      // angles are inside an expression, the ||/&& might also be a binary
60263508Sdim      // operator that was misinterpreted because we are parsing template
61263508Sdim      // parameters.
62263508Sdim      // FIXME: This is getting out of hand, write a decent parser.
63263508Sdim      if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
64263508Sdim          (CurrentToken->Previous->Type == TT_BinaryOperator ||
65263508Sdim           Contexts[Contexts.size() - 2].IsExpression) &&
66263508Sdim          Line.First->isNot(tok::kw_template))
67263508Sdim        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;
85263508Sdim    FormatToken *Left = CurrentToken->Previous;
86249261Sdim    if (CurrentToken->is(tok::caret)) {
87249261Sdim      // ^( starts a block.
88249261Sdim      Left->Type = TT_ObjCBlockLParen;
89263508Sdim    } else if (FormatToken *MaybeSel = Left->Previous) {
90249261Sdim      // @selector( starts a selector.
91263508Sdim      if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous &&
92263508Sdim          MaybeSel->Previous->is(tok::at)) {
93249261Sdim        StartsObjCMethodExpr = true;
94249261Sdim      }
95249261Sdim    }
96249261Sdim
97263508Sdim    if (Left->Previous && Left->Previous->isOneOf(tok::kw_static_assert,
98263508Sdim                                                  tok::kw_if, tok::kw_while)) {
99263508Sdim      // static_assert, if and while usually contain expressions.
100263508Sdim      Contexts.back().IsExpression = true;
101263508Sdim    } else if (Left->Previous && Left->Previous->is(tok::r_square) &&
102263508Sdim               Left->Previous->MatchingParen &&
103263508Sdim               Left->Previous->MatchingParen->Type == TT_LambdaLSquare) {
104263508Sdim      // This is a parameter list of a lambda expression.
105263508Sdim      Contexts.back().IsExpression = false;
106263508Sdim    }
107263508Sdim
108249261Sdim    if (StartsObjCMethodExpr) {
109249261Sdim      Contexts.back().ColonIsObjCMethodExpr = true;
110249261Sdim      Left->Type = TT_ObjCMethodExpr;
111249261Sdim    }
112249261Sdim
113263508Sdim    bool MightBeFunctionType = CurrentToken->is(tok::star);
114263508Sdim    bool HasMultipleLines = false;
115263508Sdim    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.
121263508Sdim      if (LookForDecls && CurrentToken->Next) {
122263508Sdim        FormatToken *Prev = CurrentToken->getPreviousNonComment();
123263508Sdim        if (Prev) {
124263508Sdim          FormatToken *PrevPrev = Prev->getPreviousNonComment();
125263508Sdim          FormatToken *Next = CurrentToken->Next;
126263508Sdim          if (PrevPrev && PrevPrev->is(tok::identifier) &&
127263508Sdim              Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
128263508Sdim              CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
129263508Sdim            Prev->Type = TT_BinaryOperator;
130263508Sdim            LookForDecls = false;
131263508Sdim          }
132249261Sdim        }
133249261Sdim      }
134249261Sdim
135263508Sdim      if (CurrentToken->Previous->Type == TT_PointerOrReference &&
136263508Sdim          CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
137263508Sdim                                                    tok::coloncolon))
138263508Sdim        MightBeFunctionType = true;
139249261Sdim      if (CurrentToken->is(tok::r_paren)) {
140263508Sdim        if (MightBeFunctionType && CurrentToken->Next &&
141263508Sdim            (CurrentToken->Next->is(tok::l_paren) ||
142263508Sdim             (CurrentToken->Next->is(tok::l_square) &&
143263508Sdim              !Contexts.back().IsExpression)))
144263508Sdim          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
156263508Sdim        if (!HasMultipleLines)
157263508Sdim          Left->PackingKind = PPK_Inconclusive;
158263508Sdim        else if (HasMultipleParametersOnALine)
159263508Sdim          Left->PackingKind = PPK_BinPacked;
160263508Sdim        else
161263508Sdim          Left->PackingKind = PPK_OnePerLine;
162263508Sdim
163249261Sdim        next();
164249261Sdim        return true;
165249261Sdim      }
166249261Sdim      if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
167249261Sdim        return false;
168249261Sdim      updateParameterCount(Left, CurrentToken);
169263508Sdim      if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
170263508Sdim          !CurrentToken->Next->HasUnescapedNewline &&
171263508Sdim          !CurrentToken->Next->isTrailingComment())
172263508Sdim        HasMultipleParametersOnALine = true;
173249261Sdim      if (!consumeToken())
174249261Sdim        return false;
175263508Sdim      if (CurrentToken && CurrentToken->HasUnescapedNewline)
176263508Sdim        HasMultipleLines = true;
177249261Sdim    }
178249261Sdim    return false;
179249261Sdim  }
180249261Sdim
181249261Sdim  bool parseSquare() {
182249261Sdim    if (!CurrentToken)
183249261Sdim      return false;
184249261Sdim
185263508Sdim    // 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.
188263508Sdim    FormatToken *Left = CurrentToken->Previous;
189263508Sdim    FormatToken *Parent = Left->getPreviousNonComment();
190249261Sdim    bool StartsObjCMethodExpr =
191263508Sdim        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) ||
194251662Sdim         Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn ||
195249261Sdim         Parent->Type == TT_CastRParen ||
196263508Sdim         getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown);
197249261Sdim    ScopedContextCreator ContextCreator(*this, tok::l_square, 10);
198249261Sdim    Contexts.back().IsExpression = true;
199263508Sdim    bool ColonFound = false;
200249261Sdim
201249261Sdim    if (StartsObjCMethodExpr) {
202249261Sdim      Contexts.back().ColonIsObjCMethodExpr = true;
203249261Sdim      Left->Type = TT_ObjCMethodExpr;
204263508Sdim    } else if (Parent && Parent->is(tok::at)) {
205263508Sdim      Left->Type = TT_ArrayInitializerLSquare;
206263508Sdim    } else if (Left->Type == TT_Unknown) {
207263508Sdim      Left->Type = TT_ArraySubscriptLSquare;
208249261Sdim    }
209249261Sdim
210249261Sdim    while (CurrentToken != NULL) {
211249261Sdim      if (CurrentToken->is(tok::r_square)) {
212263508Sdim        if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) &&
213263508Sdim            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;
237263508Sdim      if (CurrentToken->is(tok::colon))
238263508Sdim        ColonFound = true;
239263508Sdim      if (CurrentToken->is(tok::comma) &&
240263508Sdim          (Left->Type == TT_ArraySubscriptLSquare ||
241263508Sdim           (Left->Type == TT_ObjCMethodExpr && !ColonFound)))
242263508Sdim        Left->Type = TT_ArrayInitializerLSquare;
243249261Sdim      updateParameterCount(Left, CurrentToken);
244249261Sdim      if (!consumeToken())
245249261Sdim        return false;
246249261Sdim    }
247249261Sdim    return false;
248249261Sdim  }
249249261Sdim
250249261Sdim  bool parseBrace() {
251251662Sdim    if (CurrentToken != NULL) {
252263508Sdim      FormatToken *Left = CurrentToken->Previous;
253251662Sdim      ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
254263508Sdim      Contexts.back().ColonIsDictLiteral = true;
255263508Sdim
256251662Sdim      while (CurrentToken != NULL) {
257251662Sdim        if (CurrentToken->is(tok::r_brace)) {
258251662Sdim          Left->MatchingParen = CurrentToken;
259251662Sdim          CurrentToken->MatchingParen = Left;
260251662Sdim          next();
261251662Sdim          return true;
262251662Sdim        }
263251662Sdim        if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
264251662Sdim          return false;
265251662Sdim        updateParameterCount(Left, CurrentToken);
266263508Sdim        if (CurrentToken->is(tok::colon))
267263508Sdim          Left->Type = TT_DictLiteral;
268251662Sdim        if (!consumeToken())
269251662Sdim          return false;
270249261Sdim      }
271249261Sdim    }
272251662Sdim    // No closing "}" found, this probably starts a definition.
273251662Sdim    Line.StartsDefinition = true;
274249261Sdim    return true;
275249261Sdim  }
276249261Sdim
277263508Sdim  void updateParameterCount(FormatToken *Left, FormatToken *Current) {
278263508Sdim    if (Current->is(tok::comma)) {
279249261Sdim      ++Left->ParameterCount;
280263508Sdim      if (!Left->Role)
281263508Sdim        Left->Role.reset(new CommaSeparatedList(Style));
282263508Sdim      Left->Role->CommaFound(Current);
283263508Sdim    } else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) {
284249261Sdim      Left->ParameterCount = 1;
285263508Sdim    }
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)
308263508Sdim        CurrentToken->Previous->ClosesTemplateDeclaration = true;
309249261Sdim      return true;
310249261Sdim    }
311249261Sdim    return false;
312249261Sdim  }
313249261Sdim
314249261Sdim  bool consumeToken() {
315263508Sdim    FormatToken *Tok = CurrentToken;
316249261Sdim    next();
317263508Sdim    switch (Tok->Tok.getKind()) {
318249261Sdim    case tok::plus:
319249261Sdim    case tok::minus:
320263508Sdim      if (Tok->Previous == NULL && Line.MustBeDeclaration)
321249261Sdim        Tok->Type = TT_ObjCMethodSpecifier;
322249261Sdim      break;
323249261Sdim    case tok::colon:
324263508Sdim      if (Tok->Previous == NULL)
325249261Sdim        return false;
326249261Sdim      // Colons from ?: are handled in parseConditional().
327263508Sdim      if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1) {
328249261Sdim        Tok->Type = TT_CtorInitializerColon;
329263508Sdim      } else if (Contexts.back().ColonIsDictLiteral) {
330263508Sdim        Tok->Type = TT_DictLiteral;
331249261Sdim      } else if (Contexts.back().ColonIsObjCMethodExpr ||
332263508Sdim                 Line.First->Type == TT_ObjCMethodSpecifier) {
333249261Sdim        Tok->Type = TT_ObjCMethodExpr;
334263508Sdim        Tok->Previous->Type = TT_ObjCSelectorName;
335263508Sdim        if (Tok->Previous->ColumnWidth >
336263508Sdim            Contexts.back().LongestObjCSelectorName) {
337263508Sdim          Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth;
338263508Sdim        }
339249261Sdim        if (Contexts.back().FirstObjCSelectorName == NULL)
340263508Sdim          Contexts.back().FirstObjCSelectorName = Tok->Previous;
341249261Sdim      } else if (Contexts.back().ColonIsForRangeExpr) {
342249261Sdim        Tok->Type = TT_RangeBasedForLoopColon;
343263508Sdim      } else if (CurrentToken != NULL &&
344263508Sdim                 CurrentToken->is(tok::numeric_constant)) {
345263508Sdim        Tok->Type = TT_BitFieldColon;
346263508Sdim      } 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();
356263508Sdim        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;
369263508Sdim      if (Line.MustBeDeclaration && Contexts.size() == 1 &&
370263508Sdim          !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:
382263508Sdim      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 '}'.
395263508Sdim      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:
402263508Sdim      while (CurrentToken &&
403263508Sdim             !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();
407263508Sdim        if (CurrentToken && CurrentToken->Previous->Type == TT_BinaryOperator)
408263508Sdim          CurrentToken->Previous->Type = TT_OverloadedOperator;
409249261Sdim      }
410263508Sdim      if (CurrentToken) {
411249261Sdim        CurrentToken->Type = TT_OverloadedOperatorLParen;
412263508Sdim        if (CurrentToken->Previous->Type == TT_BinaryOperator)
413263508Sdim          CurrentToken->Previous->Type = TT_OverloadedOperator;
414263508Sdim      }
415249261Sdim      break;
416249261Sdim    case tok::question:
417249261Sdim      parseConditional();
418249261Sdim      break;
419249261Sdim    case tok::kw_template:
420249261Sdim      parseTemplateDeclaration();
421249261Sdim      break;
422249261Sdim    case tok::identifier:
423263508Sdim      if (Line.First->is(tok::kw_for) &&
424263508Sdim          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;
430263508Sdim      if (Contexts.back().InCtorInitializer)
431263508Sdim        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) {
444263508Sdim        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;
474263508Sdim    if (CurrentToken->Tok.is(tok::numeric_constant)) {
475263508Sdim      CurrentToken->SpacesRequiredBefore = 1;
476263508Sdim      return;
477263508Sdim    }
478249261Sdim    // Hashes in the middle of a line can lead to any strange token
479249261Sdim    // sequence.
480263508Sdim    if (CurrentToken->Tok.getIdentifierInfo() == NULL)
481249261Sdim      return;
482263508Sdim    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;
491251662Sdim    case tok::pp_if:
492251662Sdim    case tok::pp_elif:
493251662Sdim      parseLine();
494251662Sdim      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
517263508Sdim    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
534263508Sdim    if (CurrentToken != NULL)
535263508Sdim      CurrentToken = CurrentToken->Next;
536249261Sdim
537263508Sdim    if (CurrentToken != NULL) {
538263508Sdim      // Reset token type in case we have already looked at it and then
539263508Sdim      // recovered from an error (e.g. failure to find the matching >).
540263508Sdim      if (CurrentToken->Type != TT_LambdaLSquare &&
541263508Sdim          CurrentToken->Type != TT_ImplicitStringLiteral)
542263508Sdim        CurrentToken->Type = TT_Unknown;
543263508Sdim      if (CurrentToken->Role)
544263508Sdim        CurrentToken->Role.reset(NULL);
545263508Sdim      CurrentToken->FakeLParens.clear();
546263508Sdim      CurrentToken->FakeRParens = 0;
547263508Sdim    }
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),
557263508Sdim          ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false),
558263508Sdim          FirstObjCSelectorName(NULL), FirstStartOfName(NULL),
559263508Sdim          IsExpression(IsExpression), CanBeExpression(true),
560263508Sdim          InCtorInitializer(false) {}
561249261Sdim
562249261Sdim    tok::TokenKind ContextKind;
563249261Sdim    unsigned BindingStrength;
564249261Sdim    unsigned LongestObjCSelectorName;
565249261Sdim    bool ColonIsForRangeExpr;
566263508Sdim    bool ColonIsDictLiteral;
567249261Sdim    bool ColonIsObjCMethodExpr;
568263508Sdim    FormatToken *FirstObjCSelectorName;
569263508Sdim    FormatToken *FirstStartOfName;
570249261Sdim    bool IsExpression;
571249261Sdim    bool CanBeExpression;
572263508Sdim    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) {
583263508Sdim      P.Contexts.push_back(Context(ContextKind,
584263508Sdim                                   P.Contexts.back().BindingStrength + Increase,
585263508Sdim                                   P.Contexts.back().IsExpression));
586249261Sdim    }
587249261Sdim
588249261Sdim    ~ScopedContextCreator() { P.Contexts.pop_back(); }
589249261Sdim  };
590249261Sdim
591263508Sdim  void determineTokenType(FormatToken &Current) {
592263508Sdim    if (Current.getPrecedence() == prec::Assignment &&
593263508Sdim        !Line.First->isOneOf(tok::kw_template, tok::kw_using) &&
594263508Sdim        (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
595249261Sdim      Contexts.back().IsExpression = true;
596263508Sdim      for (FormatToken *Previous = Current.Previous;
597263508Sdim           Previous && !Previous->isOneOf(tok::comma, tok::semi);
598263508Sdim           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 &&
608263508Sdim                !Line.InPPDirective &&
609263508Sdim                (!Current.Previous ||
610263508Sdim                 !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)) {
613263508Sdim      for (FormatToken *Previous = Current.Previous;
614249261Sdim           Previous && Previous->isOneOf(tok::star, tok::amp);
615263508Sdim           Previous = Previous->Previous)
616249261Sdim        Previous->Type = TT_PointerOrReference;
617263508Sdim    } else if (Current.Previous &&
618263508Sdim               Current.Previous->Type == TT_CtorInitializerColon) {
619249261Sdim      Contexts.back().IsExpression = true;
620263508Sdim      Contexts.back().InCtorInitializer = true;
621249261Sdim    } else if (Current.is(tok::kw_new)) {
622249261Sdim      Contexts.back().CanBeExpression = false;
623263508Sdim    } else if (Current.is(tok::semi) || Current.is(tok::exclaim)) {
624251662Sdim      // This should be the condition or increment in a for-loop.
625251662Sdim      Contexts.back().IsExpression = true;
626249261Sdim    }
627249261Sdim
628249261Sdim    if (Current.Type == TT_Unknown) {
629263508Sdim      // Line.MightBeFunctionDecl can only be true after the parentheses of a
630263508Sdim      // function declaration have been found. In this case, 'Current' is a
631263508Sdim      // trailing token of this declaration and thus cannot be a name.
632263508Sdim      if (isStartOfName(Current) && !Line.MightBeFunctionDecl) {
633249261Sdim        Contexts.back().FirstStartOfName = &Current;
634249261Sdim        Current.Type = TT_StartOfName;
635263508Sdim      } else if (Current.is(tok::kw_auto)) {
636263508Sdim        AutoFound = true;
637263508Sdim      } else if (Current.is(tok::arrow) && AutoFound &&
638263508Sdim                 Line.MustBeDeclaration) {
639263508Sdim        Current.Type = TT_TrailingReturnArrow;
640249261Sdim      } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
641249261Sdim        Current.Type =
642263508Sdim            determineStarAmpUsage(Current, Contexts.back().CanBeExpression &&
643263508Sdim                                               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;
650263508Sdim      } else if (Current.isBinaryOperator() &&
651263508Sdim                 (!Current.Previous ||
652263508Sdim                  Current.Previous->isNot(tok::l_square))) {
653249261Sdim        Current.Type = TT_BinaryOperator;
654249261Sdim      } else if (Current.is(tok::comment)) {
655263508Sdim        if (Current.TokenText.startswith("//"))
656249261Sdim          Current.Type = TT_LineComment;
657249261Sdim        else
658249261Sdim          Current.Type = TT_BlockComment;
659249261Sdim      } else if (Current.is(tok::r_paren)) {
660263508Sdim        FormatToken *LeftOfParens = NULL;
661263508Sdim        if (Current.MatchingParen)
662263508Sdim          LeftOfParens = Current.MatchingParen->getPreviousNonComment();
663263508Sdim        bool IsCast = false;
664263508Sdim        bool ParensAreEmpty = Current.Previous == Current.MatchingParen;
665263508Sdim        bool ParensAreType = !Current.Previous ||
666263508Sdim                             Current.Previous->Type == TT_PointerOrReference ||
667263508Sdim                             Current.Previous->Type == TT_TemplateCloser ||
668263508Sdim                             isSimpleTypeSpecifier(*Current.Previous);
669249261Sdim        bool ParensCouldEndDecl =
670263508Sdim            Current.Next &&
671263508Sdim            Current.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
672249261Sdim        bool IsSizeOfOrAlignOf =
673263508Sdim            LeftOfParens &&
674263508Sdim            LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
675263508Sdim        if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
676263508Sdim            (Contexts.back().IsExpression ||
677263508Sdim             (Current.Next && Current.Next->isBinaryOperator())))
678263508Sdim          IsCast = true;
679263508Sdim        if (Current.Next && Current.Next->isNot(tok::string_literal) &&
680263508Sdim            (Current.Next->Tok.isLiteral() ||
681263508Sdim             Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
682263508Sdim          IsCast = true;
683263508Sdim        // If there is an identifier after the (), it is likely a cast, unless
684263508Sdim        // there is also an identifier before the ().
685263508Sdim        if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL ||
686263508Sdim                             LeftOfParens->is(tok::kw_return)) &&
687263508Sdim            LeftOfParens->Type != TT_OverloadedOperator &&
688263508Sdim            LeftOfParens->Type != TT_TemplateCloser && Current.Next &&
689263508Sdim            Current.Next->is(tok::identifier))
690263508Sdim          IsCast = true;
691263508Sdim        if (IsCast && !ParensAreEmpty)
692249261Sdim          Current.Type = TT_CastRParen;
693263508Sdim      } else if (Current.is(tok::at) && Current.Next) {
694263508Sdim        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        }
706263508Sdim      } else if (Current.is(tok::period)) {
707263508Sdim        FormatToken *PreviousNoComment = Current.getPreviousNonComment();
708263508Sdim        if (PreviousNoComment &&
709263508Sdim            PreviousNoComment->isOneOf(tok::comma, tok::l_brace))
710263508Sdim          Current.Type = TT_DesignatedInitializerPeriod;
711249261Sdim      }
712249261Sdim    }
713249261Sdim  }
714249261Sdim
715263508Sdim  /// \brief Take a guess at whether \p Tok starts a name of a function or
716263508Sdim  /// variable declaration.
717263508Sdim  ///
718263508Sdim  /// This is a heuristic based on whether \p Tok is an identifier following
719263508Sdim  /// something that is likely a type.
720263508Sdim  bool isStartOfName(const FormatToken &Tok) {
721263508Sdim    if (Tok.isNot(tok::identifier) || Tok.Previous == NULL)
722263508Sdim      return false;
723263508Sdim
724263508Sdim    // Skip "const" as it does not have an influence on whether this is a name.
725263508Sdim    FormatToken *PreviousNotConst = Tok.Previous;
726263508Sdim    while (PreviousNotConst != NULL && PreviousNotConst->is(tok::kw_const))
727263508Sdim      PreviousNotConst = PreviousNotConst->Previous;
728263508Sdim
729263508Sdim    if (PreviousNotConst == NULL)
730263508Sdim      return false;
731263508Sdim
732263508Sdim    bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&
733263508Sdim                       PreviousNotConst->Previous &&
734263508Sdim                       PreviousNotConst->Previous->is(tok::hash);
735263508Sdim
736263508Sdim    if (PreviousNotConst->Type == TT_TemplateCloser)
737263508Sdim      return PreviousNotConst && PreviousNotConst->MatchingParen &&
738263508Sdim             PreviousNotConst->MatchingParen->Previous &&
739263508Sdim             PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
740263508Sdim
741263508Sdim    return (!IsPPKeyword && PreviousNotConst->is(tok::identifier)) ||
742263508Sdim           PreviousNotConst->Type == TT_PointerOrReference ||
743263508Sdim           isSimpleTypeSpecifier(*PreviousNotConst);
744263508Sdim  }
745263508Sdim
746249261Sdim  /// \brief Return the type of the given token assuming it is * or &.
747263508Sdim  TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression) {
748263508Sdim    const FormatToken *PrevToken = Tok.getPreviousNonComment();
749249261Sdim    if (PrevToken == NULL)
750249261Sdim      return TT_UnaryOperator;
751249261Sdim
752263508Sdim    const FormatToken *NextToken = Tok.getNextNonComment();
753249261Sdim    if (NextToken == NULL)
754249261Sdim      return TT_Unknown;
755249261Sdim
756263508Sdim    if (PrevToken->is(tok::coloncolon) ||
757263508Sdim        (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,
762263508Sdim                           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
770263508Sdim    if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
771263508Sdim        PrevToken->MatchingParen->Previous &&
772263508Sdim        PrevToken->MatchingParen->Previous->is(tok::kw_typeof))
773263508Sdim      return TT_PointerOrReference;
774263508Sdim
775263508Sdim    if (PrevToken->Tok.isLiteral() ||
776249261Sdim        PrevToken->isOneOf(tok::r_paren, tok::r_square) ||
777263508Sdim        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
788263508Sdim  TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
789263508Sdim    const FormatToken *PrevToken = Tok.getPreviousNonComment();
790263508Sdim    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.
808263508Sdim  TokenType determineIncrementUsage(const FormatToken &Tok) {
809263508Sdim    const FormatToken *PrevToken = Tok.getPreviousNonComment();
810263508Sdim    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.
821263508Sdim  bool isSimpleTypeSpecifier(const FormatToken &Tok) const {
822263508Sdim    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:
843263508Sdim      return true;
844249261Sdim    default:
845263508Sdim      return false;
846249261Sdim    }
847249261Sdim  }
848249261Sdim
849249261Sdim  SmallVector<Context, 8> Contexts;
850249261Sdim
851263508Sdim  const FormatStyle &Style;
852249261Sdim  AnnotatedLine &Line;
853263508Sdim  FormatToken *CurrentToken;
854249261Sdim  bool KeywordVirtualFound;
855263508Sdim  bool AutoFound;
856249261Sdim  IdentifierInfo &Ident_in;
857249261Sdim};
858249261Sdim
859263508Sdimstatic int PrecedenceUnaryOperator = prec::PointerToMember + 1;
860263508Sdimstatic int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
861263508Sdim
862249261Sdim/// \brief Parses binary expressions by inserting fake parenthesis based on
863249261Sdim/// operator precedence.
864249261Sdimclass ExpressionParser {
865249261Sdimpublic:
866263508Sdim  ExpressionParser(AnnotatedLine &Line) : Current(Line.First) {
867263508Sdim    // Skip leading "}", e.g. in "} else if (...) {".
868263508Sdim    if (Current->is(tok::r_brace))
869263508Sdim      next();
870263508Sdim  }
871249261Sdim
872249261Sdim  /// \brief Parse expressions with the given operatore precedence.
873249261Sdim  void parse(int Precedence = 0) {
874263508Sdim    // Skip 'return' and ObjC selector colons as they are not part of a binary
875263508Sdim    // expression.
876263508Sdim    while (Current &&
877263508Sdim           (Current->is(tok::kw_return) ||
878263508Sdim            (Current->is(tok::colon) && Current->Type == TT_ObjCMethodExpr)))
879263508Sdim      next();
880263508Sdim
881263508Sdim    if (Current == NULL || Precedence > PrecedenceArrowAndPeriod)
882249261Sdim      return;
883249261Sdim
884263508Sdim    // Conditional expressions need to be parsed separately for proper nesting.
885263508Sdim    if (Precedence == prec::Conditional) {
886263508Sdim      parseConditionalExpr();
887263508Sdim      return;
888249261Sdim    }
889249261Sdim
890263508Sdim    // Parse unary operators, which all have a higher precedence than binary
891263508Sdim    // operators.
892263508Sdim    if (Precedence == PrecedenceUnaryOperator) {
893263508Sdim      parseUnaryOperator();
894263508Sdim      return;
895263508Sdim    }
896249261Sdim
897263508Sdim    FormatToken *Start = Current;
898263508Sdim    FormatToken *LatestOperator = NULL;
899263508Sdim
900249261Sdim    while (Current) {
901249261Sdim      // Consume operators with higher precedence.
902251662Sdim      parse(Precedence + 1);
903249261Sdim
904263508Sdim      int CurrentPrecedence = getCurrentPrecedence();
905249261Sdim
906263508Sdim      if (Current && Current->Type == TT_ObjCSelectorName &&
907263508Sdim          Precedence == CurrentPrecedence)
908263508Sdim        Start = Current;
909263508Sdim
910249261Sdim      // At the end of the line or when an operator with higher precedence is
911249261Sdim      // found, insert fake parenthesis and return.
912251662Sdim      if (Current == NULL || Current->closesScope() ||
913263508Sdim          (CurrentPrecedence != -1 && CurrentPrecedence < Precedence)) {
914263508Sdim        if (LatestOperator) {
915263508Sdim          if (Precedence == PrecedenceArrowAndPeriod) {
916263508Sdim            LatestOperator->LastInChainOfCalls = true;
917263508Sdim            // Call expressions don't have a binary operator precedence.
918263508Sdim            addFakeParenthesis(Start, prec::Unknown);
919263508Sdim          } else {
920263508Sdim            addFakeParenthesis(Start, prec::Level(Precedence));
921263508Sdim          }
922249261Sdim        }
923249261Sdim        return;
924249261Sdim      }
925249261Sdim
926249261Sdim      // Consume scopes: (), [], <> and {}
927251662Sdim      if (Current->opensScope()) {
928251662Sdim        while (Current && !Current->closesScope()) {
929249261Sdim          next();
930249261Sdim          parse();
931249261Sdim        }
932249261Sdim        next();
933249261Sdim      } else {
934249261Sdim        // Operator found.
935249261Sdim        if (CurrentPrecedence == Precedence)
936263508Sdim          LatestOperator = Current;
937249261Sdim
938249261Sdim        next();
939249261Sdim      }
940249261Sdim    }
941249261Sdim  }
942249261Sdim
943249261Sdimprivate:
944263508Sdim  /// \brief Gets the precedence (+1) of the given token for binary operators
945263508Sdim  /// and other tokens that we treat like binary operators.
946263508Sdim  int getCurrentPrecedence() {
947263508Sdim    if (Current) {
948263508Sdim      if (Current->Type == TT_ConditionalExpr)
949263508Sdim        return prec::Conditional;
950263508Sdim      else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon ||
951263508Sdim               Current->Type == TT_ObjCSelectorName)
952263508Sdim        return 0;
953263508Sdim      else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma))
954263508Sdim        return Current->getPrecedence();
955263508Sdim      else if (Current->isOneOf(tok::period, tok::arrow))
956263508Sdim        return PrecedenceArrowAndPeriod;
957263508Sdim    }
958263508Sdim    return -1;
959263508Sdim  }
960263508Sdim
961263508Sdim  void addFakeParenthesis(FormatToken *Start, prec::Level Precedence) {
962263508Sdim    Start->FakeLParens.push_back(Precedence);
963263508Sdim    if (Precedence > prec::Unknown)
964263508Sdim      Start->StartsBinaryExpression = true;
965263508Sdim    if (Current) {
966263508Sdim      ++Current->Previous->FakeRParens;
967263508Sdim      if (Precedence > prec::Unknown)
968263508Sdim        Current->Previous->EndsBinaryExpression = true;
969263508Sdim    }
970263508Sdim  }
971263508Sdim
972263508Sdim  /// \brief Parse unary operator expressions and surround them with fake
973263508Sdim  /// parentheses if appropriate.
974263508Sdim  void parseUnaryOperator() {
975263508Sdim    if (Current == NULL || Current->Type != TT_UnaryOperator) {
976263508Sdim      parse(PrecedenceArrowAndPeriod);
977263508Sdim      return;
978263508Sdim    }
979263508Sdim
980263508Sdim    FormatToken *Start = Current;
981263508Sdim    next();
982263508Sdim    parseUnaryOperator();
983263508Sdim
984263508Sdim    // The actual precedence doesn't matter.
985263508Sdim    addFakeParenthesis(Start, prec::Unknown);
986263508Sdim  }
987263508Sdim
988263508Sdim  void parseConditionalExpr() {
989263508Sdim    FormatToken *Start = Current;
990263508Sdim    parse(prec::LogicalOr);
991263508Sdim    if (!Current || !Current->is(tok::question))
992263508Sdim      return;
993263508Sdim    next();
994263508Sdim    parse(prec::LogicalOr);
995263508Sdim    if (!Current || Current->Type != TT_ConditionalExpr)
996263508Sdim      return;
997263508Sdim    next();
998263508Sdim    parseConditionalExpr();
999263508Sdim    addFakeParenthesis(Start, prec::Conditional);
1000263508Sdim  }
1001263508Sdim
1002249261Sdim  void next() {
1003263508Sdim    if (Current)
1004263508Sdim      Current = Current->Next;
1005263508Sdim    while (Current && Current->isTrailingComment())
1006263508Sdim      Current = Current->Next;
1007249261Sdim  }
1008249261Sdim
1009263508Sdim  FormatToken *Current;
1010249261Sdim};
1011249261Sdim
1012263508Sdim} // end anonymous namespace
1013263508Sdim
1014263508Sdimvoid
1015263508SdimTokenAnnotator::setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) {
1016263508Sdim  const AnnotatedLine *NextNonCommentLine = NULL;
1017263508Sdim  for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(),
1018263508Sdim                                                          E = Lines.rend();
1019263508Sdim       I != E; ++I) {
1020263508Sdim    if (NextNonCommentLine && (*I)->First->is(tok::comment) &&
1021263508Sdim        (*I)->First->Next == NULL)
1022263508Sdim      (*I)->Level = NextNonCommentLine->Level;
1023263508Sdim    else
1024263508Sdim      NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : NULL;
1025263508Sdim
1026263508Sdim    setCommentLineLevels((*I)->Children);
1027263508Sdim  }
1028263508Sdim}
1029263508Sdim
1030249261Sdimvoid TokenAnnotator::annotate(AnnotatedLine &Line) {
1031263508Sdim  for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
1032263508Sdim                                                  E = Line.Children.end();
1033263508Sdim       I != E; ++I) {
1034263508Sdim    annotate(**I);
1035263508Sdim  }
1036263508Sdim  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
1044263508Sdim  if (Line.First->Type == TT_ObjCMethodSpecifier)
1045249261Sdim    Line.Type = LT_ObjCMethodDecl;
1046263508Sdim  else if (Line.First->Type == TT_ObjCDecl)
1047249261Sdim    Line.Type = LT_ObjCDecl;
1048263508Sdim  else if (Line.First->Type == TT_ObjCProperty)
1049249261Sdim    Line.Type = LT_ObjCProperty;
1050249261Sdim
1051263508Sdim  Line.First->SpacesRequiredBefore = 1;
1052263508Sdim  Line.First->CanBreakBefore = Line.First->MustBreakBefore;
1053249261Sdim}
1054249261Sdim
1055249261Sdimvoid TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
1056263508Sdim  Line.First->TotalLength =
1057263508Sdim      Line.First->IsMultiline ? Style.ColumnLimit : Line.First->ColumnWidth;
1058263508Sdim  if (!Line.First->Next)
1059249261Sdim    return;
1060263508Sdim  FormatToken *Current = Line.First->Next;
1061263508Sdim  bool InFunctionDecl = Line.MightBeFunctionDecl;
1062249261Sdim  while (Current != NULL) {
1063249261Sdim    if (Current->Type == TT_LineComment)
1064249261Sdim      Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;
1065263508Sdim    else if (Current->SpacesRequiredBefore == 0 &&
1066263508Sdim             spaceRequiredBefore(Line, *Current))
1067263508Sdim      Current->SpacesRequiredBefore = 1;
1068249261Sdim
1069263508Sdim    Current->MustBreakBefore =
1070263508Sdim        Current->MustBreakBefore || mustBreakBefore(Line, *Current);
1071263508Sdim
1072249261Sdim    Current->CanBreakBefore =
1073249261Sdim        Current->MustBreakBefore || canBreakBefore(Line, *Current);
1074263508Sdim    if (Current->MustBreakBefore || !Current->Children.empty() ||
1075263508Sdim        Current->IsMultiline)
1076263508Sdim      Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit;
1077249261Sdim    else
1078263508Sdim      Current->TotalLength = Current->Previous->TotalLength +
1079263508Sdim                             Current->ColumnWidth +
1080263508Sdim                             Current->SpacesRequiredBefore;
1081263508Sdim
1082263508Sdim    if (Current->Type == TT_CtorInitializerColon)
1083263508Sdim      InFunctionDecl = false;
1084263508Sdim
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.
1088263508Sdim    Current->SplitPenalty = 20 * Current->BindingStrength +
1089263508Sdim                            splitPenalty(Line, *Current, InFunctionDecl);
1090249261Sdim
1091263508Sdim    Current = Current->Next;
1092249261Sdim  }
1093251662Sdim
1094263508Sdim  calculateUnbreakableTailLengths(Line);
1095263508Sdim  for (Current = Line.First; Current != NULL; Current = Current->Next) {
1096263508Sdim    if (Current->Role)
1097263508Sdim      Current->Role->precomputeFormattingInfos(Current);
1098263508Sdim  }
1099263508Sdim
1100263508Sdim  DEBUG({ printDebugInfo(Line); });
1101263508Sdim
1102263508Sdim  for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
1103263508Sdim                                                  E = Line.Children.end();
1104263508Sdim       I != E; ++I) {
1105263508Sdim    calculateFormattingInformation(**I);
1106263508Sdim  }
1107249261Sdim}
1108249261Sdim
1109263508Sdimvoid TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
1110263508Sdim  unsigned UnbreakableTailLength = 0;
1111263508Sdim  FormatToken *Current = Line.Last;
1112263508Sdim  while (Current != NULL) {
1113263508Sdim    Current->UnbreakableTailLength = UnbreakableTailLength;
1114263508Sdim    if (Current->CanBreakBefore ||
1115263508Sdim        Current->isOneOf(tok::comment, tok::string_literal)) {
1116263508Sdim      UnbreakableTailLength = 0;
1117263508Sdim    } else {
1118263508Sdim      UnbreakableTailLength +=
1119263508Sdim          Current->ColumnWidth + Current->SpacesRequiredBefore;
1120263508Sdim    }
1121263508Sdim    Current = Current->Previous;
1122263508Sdim  }
1123263508Sdim}
1124263508Sdim
1125249261Sdimunsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
1126263508Sdim                                      const FormatToken &Tok,
1127263508Sdim                                      bool InFunctionDecl) {
1128263508Sdim  const FormatToken &Left = *Tok.Previous;
1129263508Sdim  const FormatToken &Right = Tok;
1130249261Sdim
1131263508Sdim  if (Left.is(tok::semi))
1132263508Sdim    return 0;
1133263508Sdim  if (Left.is(tok::comma))
1134263508Sdim    return 1;
1135263508Sdim  if (Right.is(tok::l_square))
1136263508Sdim    return 150;
1137263508Sdim
1138263508Sdim  if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator)) {
1139263508Sdim    if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
1140249261Sdim      return 3;
1141263508Sdim    if (Left.Type == TT_StartOfName)
1142263508Sdim      return 20;
1143263508Sdim    if (InFunctionDecl && Right.BindingStrength == 1)
1144249261Sdim      // FIXME: Clean up hack of using BindingStrength to find top-level names.
1145249261Sdim      return Style.PenaltyReturnTypeOnItsOwnLine;
1146263508Sdim    return 200;
1147249261Sdim  }
1148249261Sdim  if (Left.is(tok::equal) && Right.is(tok::l_brace))
1149249261Sdim    return 150;
1150263508Sdim  if (Left.Type == TT_CastRParen)
1151263508Sdim    return 100;
1152249261Sdim  if (Left.is(tok::coloncolon))
1153249261Sdim    return 500;
1154251662Sdim  if (Left.isOneOf(tok::kw_class, tok::kw_struct))
1155251662Sdim    return 5000;
1156249261Sdim
1157249261Sdim  if (Left.Type == TT_RangeBasedForLoopColon ||
1158249261Sdim      Left.Type == TT_InheritanceColon)
1159249261Sdim    return 2;
1160249261Sdim
1161263508Sdim  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
1168263508Sdim  // Breaking before a trailing 'const' or not-function-like annotation is bad.
1169263508Sdim  if (Left.is(tok::r_paren) && Line.Type != LT_ObjCProperty &&
1170263508Sdim      (Right.is(tok::kw_const) || (Right.is(tok::identifier) && Right.Next &&
1171263508Sdim                                   Right.Next->isNot(tok::l_paren))))
1172263508Sdim    return 100;
1173263508Sdim
1174249261Sdim  // In for-loops, prefer breaking at ',' and ';'.
1175263508Sdim  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)
1183263508Sdim    return 50;
1184249261Sdim
1185263508Sdim  if (Left.is(tok::l_paren) && InFunctionDecl)
1186251662Sdim    return 100;
1187251662Sdim  if (Left.opensScope())
1188263508Sdim    return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter
1189263508Sdim                                   : 19;
1190249261Sdim
1191249261Sdim  if (Right.is(tok::lessless)) {
1192249261Sdim    if (Left.is(tok::string_literal)) {
1193263508Sdim      StringRef Content = Left.TokenText;
1194263508Sdim      if (Content.startswith("\""))
1195263508Sdim        Content = Content.drop_front(1);
1196263508Sdim      if (Content.endswith("\""))
1197263508Sdim        Content = Content.drop_back(1);
1198263508Sdim      Content = Content.trim();
1199249261Sdim      if (Content.size() > 1 &&
1200249261Sdim          (Content.back() == ':' || Content.back() == '='))
1201263508Sdim        return 25;
1202249261Sdim    }
1203263508Sdim    return 1; // Breaking at a << is really cheap.
1204249261Sdim  }
1205249261Sdim  if (Left.Type == TT_ConditionalExpr)
1206249261Sdim    return prec::Conditional;
1207263508Sdim  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,
1216263508Sdim                                          const FormatToken &Left,
1217263508Sdim                                          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);
1222263508Sdim  if (Left.is(tok::l_paren) && Right.is(tok::r_paren))
1223263508Sdim    return Style.SpaceInEmptyParentheses;
1224263508Sdim  if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
1225263508Sdim    return (Right.Type == TT_CastRParen ||
1226263508Sdim            (Left.MatchingParen && Left.MatchingParen->Type == TT_CastRParen))
1227263508Sdim               ? Style.SpacesInCStyleCastParentheses
1228263508Sdim               : Style.SpacesInParentheses;
1229263508Sdim  if (Style.SpacesInAngles &&
1230263508Sdim      ((Left.Type == TT_TemplateOpener) != (Right.Type == TT_TemplateCloser)))
1231263508Sdim    return true;
1232263508Sdim  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))
1250263508Sdim    return (Left.is(tok::less) && Style.Standard == FormatStyle::LS_Cpp03) ||
1251263508Sdim           !Left.isOneOf(tok::identifier, tok::greater, tok::l_paren,
1252263508Sdim                         tok::r_paren, tok::less);
1253249261Sdim  if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less))
1254249261Sdim    return false;
1255263508Sdim  if (Right.is(tok::ellipsis))
1256263508Sdim    return Left.Tok.isLiteral();
1257263508Sdim  if (Left.is(tok::l_square) && Right.is(tok::amp))
1258263508Sdim    return false;
1259249261Sdim  if (Right.Type == TT_PointerOrReference)
1260263508Sdim    return Left.Tok.isLiteral() ||
1261249261Sdim           ((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) &&
1262249261Sdim            !Style.PointerBindsToType);
1263263508Sdim  if (Right.Type == TT_FunctionTypeLParen && Left.isNot(tok::l_paren) &&
1264263508Sdim      (Left.Type != TT_PointerOrReference || Style.PointerBindsToType))
1265263508Sdim    return true;
1266249261Sdim  if (Left.Type == TT_PointerOrReference)
1267263508Sdim    return Right.Tok.isLiteral() || Right.Type == TT_BlockComment ||
1268249261Sdim           ((Right.Type != TT_PointerOrReference) &&
1269249261Sdim            Right.isNot(tok::l_paren) && Style.PointerBindsToType &&
1270263508Sdim            Left.Previous &&
1271263508Sdim            !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))
1275263508Sdim    return Left.Type == TT_ArrayInitializerLSquare &&
1276263508Sdim           Right.isNot(tok::r_square);
1277249261Sdim  if (Right.is(tok::r_square))
1278263508Sdim    return Right.MatchingParen &&
1279263508Sdim           Right.MatchingParen->Type == TT_ArrayInitializerLSquare;
1280263508Sdim  if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr &&
1281263508Sdim      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))
1286263508Sdim    return Right.Type != TT_ObjCMethodExpr && !Left.is(tok::question);
1287249261Sdim  if (Right.is(tok::l_paren)) {
1288263508Sdim    if (Left.is(tok::r_paren) && Left.MatchingParen &&
1289263508Sdim        Left.MatchingParen->Previous &&
1290263508Sdim        Left.MatchingParen->Previous->is(tok::kw___attribute))
1291263508Sdim      return true;
1292249261Sdim    return Line.Type == LT_ObjCDecl ||
1293263508Sdim           Left.isOneOf(tok::kw_return, tok::kw_new, tok::kw_delete,
1294263508Sdim                        tok::semi) ||
1295263508Sdim           (Style.SpaceAfterControlStatementKeyword &&
1296263508Sdim            Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,
1297263508Sdim                         tok::kw_catch));
1298249261Sdim  }
1299263508Sdim  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))
1302263508Sdim    return !Left.Children.empty(); // No spaces in "{}".
1303263508Sdim  if (Left.is(tok::l_brace) || Right.is(tok::r_brace))
1304263508Sdim    return !Style.Cpp11BracedListStyle;
1305263508Sdim  if (Right.Type == TT_UnaryOperator)
1306263508Sdim    return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
1307263508Sdim           (Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr);
1308263508Sdim  if (Left.isOneOf(tok::identifier, tok::greater, tok::r_square) &&
1309263508Sdim      Right.is(tok::l_brace) && Right.getNextNonComment() &&
1310263508Sdim      Right.BlockKind != BK_Block)
1311249261Sdim    return false;
1312263508Sdim  if (Left.is(tok::period) || Right.is(tok::period))
1313251662Sdim    return false;
1314263508Sdim  if (Left.Type == TT_BlockComment && Left.TokenText.endswith("=*/"))
1315263508Sdim    return false;
1316263508Sdim  if (Right.is(tok::hash) && Left.is(tok::identifier) && Left.TokenText == "L")
1317263508Sdim    return false;
1318249261Sdim  return true;
1319249261Sdim}
1320249261Sdim
1321249261Sdimbool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
1322263508Sdim                                         const FormatToken &Tok) {
1323263508Sdim  if (Tok.Tok.getIdentifierInfo() && Tok.Previous->Tok.getIdentifierInfo())
1324249261Sdim    return true; // Never ever merge two identifiers.
1325263508Sdim  if (Tok.Previous->Type == TT_ImplicitStringLiteral)
1326263508Sdim    return Tok.WhitespaceRange.getBegin() != Tok.WhitespaceRange.getEnd();
1327249261Sdim  if (Line.Type == LT_ObjCMethodDecl) {
1328263508Sdim    if (Tok.Previous->Type == TT_ObjCMethodSpecifier)
1329249261Sdim      return true;
1330263508Sdim    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 &&
1335263508Sdim      (Tok.is(tok::equal) || Tok.Previous->is(tok::equal)))
1336249261Sdim    return false;
1337249261Sdim
1338263508Sdim  if (Tok.Type == TT_TrailingReturnArrow ||
1339263508Sdim      Tok.Previous->Type == TT_TrailingReturnArrow)
1340249261Sdim    return true;
1341263508Sdim  if (Tok.Previous->is(tok::comma))
1342263508Sdim    return true;
1343249261Sdim  if (Tok.is(tok::comma))
1344249261Sdim    return false;
1345249261Sdim  if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
1346249261Sdim    return true;
1347263508Sdim  if (Tok.Previous->Tok.is(tok::kw_operator))
1348263508Sdim    return Tok.is(tok::coloncolon);
1349249261Sdim  if (Tok.Type == TT_OverloadedOperatorLParen)
1350249261Sdim    return false;
1351249261Sdim  if (Tok.is(tok::colon))
1352263508Sdim    return !Line.First->isOneOf(tok::kw_case, tok::kw_default) &&
1353263508Sdim           Tok.getNextNonComment() != NULL && Tok.Type != TT_ObjCMethodExpr &&
1354263508Sdim           !Tok.Previous->is(tok::question);
1355263508Sdim  if (Tok.Previous->Type == TT_UnaryOperator ||
1356263508Sdim      Tok.Previous->Type == TT_CastRParen)
1357249261Sdim    return false;
1358263508Sdim  if (Tok.Previous->is(tok::greater) && Tok.is(tok::greater)) {
1359249261Sdim    return Tok.Type == TT_TemplateCloser &&
1360263508Sdim           Tok.Previous->Type == TT_TemplateCloser &&
1361263508Sdim           (Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
1362249261Sdim  }
1363249261Sdim  if (Tok.isOneOf(tok::arrowstar, tok::periodstar) ||
1364263508Sdim      Tok.Previous->isOneOf(tok::arrowstar, tok::periodstar))
1365249261Sdim    return false;
1366263508Sdim  if (!Style.SpaceBeforeAssignmentOperators &&
1367263508Sdim      Tok.getPrecedence() == prec::Assignment)
1368263508Sdim    return false;
1369263508Sdim  if ((Tok.Type == TT_BinaryOperator && !Tok.Previous->is(tok::l_paren)) ||
1370263508Sdim      Tok.Previous->Type == TT_BinaryOperator)
1371249261Sdim    return true;
1372263508Sdim  if (Tok.Previous->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
1373249261Sdim    return false;
1374263508Sdim  if (Tok.is(tok::less) && Tok.Previous->isNot(tok::l_paren) &&
1375263508Sdim      Line.First->is(tok::hash))
1376249261Sdim    return true;
1377249261Sdim  if (Tok.Type == TT_TrailingUnaryOperator)
1378249261Sdim    return false;
1379263508Sdim  return spaceRequiredBetween(Line, *Tok.Previous, Tok);
1380249261Sdim}
1381249261Sdim
1382263508Sdimbool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
1383263508Sdim                                     const FormatToken &Right) {
1384263508Sdim  if (Right.is(tok::comment)) {
1385263508Sdim    return Right.NewlinesBefore > 0;
1386263508Sdim  } else if (Right.Previous->isTrailingComment() ||
1387263508Sdim             (Right.is(tok::string_literal) &&
1388263508Sdim              Right.Previous->is(tok::string_literal))) {
1389263508Sdim    return true;
1390263508Sdim  } else if (Right.Previous->IsUnterminatedLiteral) {
1391263508Sdim    return true;
1392263508Sdim  } else if (Right.is(tok::lessless) && Right.Next &&
1393263508Sdim             Right.Previous->is(tok::string_literal) &&
1394263508Sdim             Right.Next->is(tok::string_literal)) {
1395263508Sdim    return true;
1396263508Sdim  } else if (Right.Previous->ClosesTemplateDeclaration &&
1397263508Sdim             Right.Previous->MatchingParen &&
1398263508Sdim             Right.Previous->MatchingParen->BindingStrength == 1 &&
1399263508Sdim             Style.AlwaysBreakTemplateDeclarations) {
1400263508Sdim    // FIXME: Fix horrible hack of using BindingStrength to find top-level <>.
1401263508Sdim    return true;
1402263508Sdim  } else if (Right.Type == TT_CtorInitializerComma &&
1403263508Sdim             Style.BreakConstructorInitializersBeforeComma &&
1404263508Sdim             !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) {
1405263508Sdim    return true;
1406263508Sdim  } else if (Right.Previous->BlockKind == BK_Block &&
1407263508Sdim             Right.Previous->isNot(tok::r_brace) && Right.isNot(tok::r_brace)) {
1408263508Sdim    return true;
1409263508Sdim  } else if (Right.is(tok::l_brace) && (Right.BlockKind == BK_Block)) {
1410263508Sdim    return Style.BreakBeforeBraces == FormatStyle::BS_Allman;
1411263508Sdim  }
1412263508Sdim  return false;
1413263508Sdim}
1414263508Sdim
1415249261Sdimbool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
1416263508Sdim                                    const FormatToken &Right) {
1417263508Sdim  const FormatToken &Left = *Right.Previous;
1418263508Sdim  if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator))
1419249261Sdim    return true;
1420263508Sdim  if (Right.isTrailingComment())
1421263508Sdim    // We rely on MustBreakBefore being set correctly here as we should not
1422263508Sdim    // change the "binding" behavior of a comment.
1423249261Sdim    return false;
1424263508Sdim  if (Left.is(tok::question) && Right.is(tok::colon))
1425263508Sdim    return false;
1426263508Sdim  if (Right.Type == TT_ConditionalExpr || Right.is(tok::question))
1427263508Sdim    return Style.BreakBeforeTernaryOperators;
1428263508Sdim  if (Left.Type == TT_ConditionalExpr || Left.is(tok::question))
1429263508Sdim    return !Style.BreakBeforeTernaryOperators;
1430263508Sdim  if (Right.is(tok::colon) &&
1431263508Sdim      (Right.Type == TT_DictLiteral || Right.Type == TT_ObjCMethodExpr))
1432263508Sdim    return false;
1433263508Sdim  if (Left.is(tok::colon) &&
1434263508Sdim      (Left.Type == TT_DictLiteral || Left.Type == TT_ObjCMethodExpr))
1435249261Sdim    return true;
1436249261Sdim  if (Right.Type == TT_ObjCSelectorName)
1437249261Sdim    return true;
1438263508Sdim  if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
1439263508Sdim    return true;
1440249261Sdim  if (Left.ClosesTemplateDeclaration)
1441249261Sdim    return true;
1442249261Sdim  if (Right.Type == TT_RangeBasedForLoopColon ||
1443263508Sdim      Right.Type == TT_OverloadedOperatorLParen ||
1444263508Sdim      Right.Type == TT_OverloadedOperator)
1445249261Sdim    return false;
1446251662Sdim  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 ||
1451263508Sdim      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;
1455263508Sdim  if (Left.Previous) {
1456263508Sdim    if (Left.is(tok::l_paren) && Right.is(tok::l_paren) &&
1457263508Sdim        Left.Previous->is(tok::kw___attribute))
1458263508Sdim      return false;
1459263508Sdim    if (Left.is(tok::l_paren) && (Left.Previous->Type == TT_BinaryOperator ||
1460263508Sdim                                  Left.Previous->Type == TT_CastRParen))
1461263508Sdim      return false;
1462263508Sdim  }
1463263508Sdim  if (Right.Type == TT_ImplicitStringLiteral)
1464249261Sdim    return false;
1465249261Sdim
1466263508Sdim  if (Right.is(tok::r_paren) || Right.Type == TT_TemplateCloser)
1467249261Sdim    return false;
1468249261Sdim
1469263508Sdim  // We only break before r_brace if there was a corresponding break before
1470263508Sdim  // the l_brace, which is tracked by BreakBeforeClosingBrace.
1471263508Sdim  if (Right.is(tok::r_brace))
1472263508Sdim    return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block;
1473263508Sdim
1474249261Sdim  // Allow breaking after a trailing 'const', e.g. after a method declaration,
1475249261Sdim  // unless it is follow by ';', '{' or '='.
1476263508Sdim  if (Left.is(tok::kw_const) && Left.Previous != NULL &&
1477263508Sdim      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;
1485263508Sdim
1486263508Sdim  if (Left.Type == TT_CtorInitializerComma &&
1487263508Sdim      Style.BreakConstructorInitializersBeforeComma)
1488263508Sdim    return false;
1489263508Sdim  if (Right.Type == TT_CtorInitializerComma &&
1490263508Sdim      Style.BreakConstructorInitializersBeforeComma)
1491263508Sdim    return true;
1492263508Sdim  if (Right.isBinaryOperator() && Style.BreakBeforeBinaryOperators)
1493263508Sdim    return true;
1494263508Sdim  if (Left.is(tok::greater) && Right.is(tok::greater) &&
1495263508Sdim      Left.Type != TT_TemplateCloser)
1496263508Sdim    return false;
1497263508Sdim  if (Left.Type == TT_ArrayInitializerLSquare)
1498263508Sdim    return true;
1499263508Sdim  return (Left.isBinaryOperator() && Left.isNot(tok::lessless) &&
1500263508Sdim          !Style.BreakBeforeBinaryOperators) ||
1501251662Sdim         Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
1502251662Sdim                      tok::kw_class, tok::kw_struct) ||
1503263508Sdim         Right.isOneOf(tok::lessless, tok::arrow, tok::period, tok::colon,
1504263508Sdim                       tok::l_square, tok::at) ||
1505263508Sdim         (Left.is(tok::r_paren) &&
1506263508Sdim          Right.isOneOf(tok::identifier, tok::kw_const, tok::kw___attribute)) ||
1507263508Sdim         (Left.is(tok::l_paren) && !Right.is(tok::r_paren));
1508249261Sdim}
1509249261Sdim
1510251662Sdimvoid TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
1511251662Sdim  llvm::errs() << "AnnotatedTokens:\n";
1512263508Sdim  const FormatToken *Tok = Line.First;
1513251662Sdim  while (Tok) {
1514251662Sdim    llvm::errs() << " M=" << Tok->MustBreakBefore
1515251662Sdim                 << " C=" << Tok->CanBreakBefore << " T=" << Tok->Type
1516251662Sdim                 << " S=" << Tok->SpacesRequiredBefore
1517263508Sdim                 << " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName()
1518263508Sdim                 << " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind
1519263508Sdim                 << " FakeLParens=";
1520251662Sdim    for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
1521251662Sdim      llvm::errs() << Tok->FakeLParens[i] << "/";
1522251662Sdim    llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n";
1523263508Sdim    if (Tok->Next == NULL)
1524263508Sdim      assert(Tok == Line.Last);
1525263508Sdim    Tok = Tok->Next;
1526251662Sdim  }
1527251662Sdim  llvm::errs() << "----\n";
1528251662Sdim}
1529251662Sdim
1530249261Sdim} // namespace format
1531249261Sdim} // namespace clang
1532