text: //===--- TokenAnnotator.cpp - Format C++ code -----------------------------===//
  //
  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  // See https://llvm.org/LICENSE.txt for license information.
  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  //
  //===----------------------------------------------------------------------===//
  ///
  /// \file
  /// This file implements a token annotator, i.e. creates
  /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
  ///
  //===----------------------------------------------------------------------===//
  
  #include "TokenAnnotator.h"
  #include "FormatToken.h"
  #include "clang/Basic/SourceManager.h"
  #include "clang/Basic/TokenKinds.h"
  #include "llvm/ADT/SmallPtrSet.h"
  #include "llvm/Support/Debug.h"
  
  #define DEBUG_TYPE "format-token-annotator"
  
  namespace clang {
  namespace format {
  
  namespace {
  
  /// Returns \c true if the token can be used as an identifier in
  /// an Objective-C \c \@selector, \c false otherwise.
  ///
  /// Because getFormattingLangOpts() always lexes source code as
  /// Objective-C++, C++ keywords like \c new and \c delete are
  /// lexed as tok::kw_*, not tok::identifier, even for Objective-C.
  ///
  /// For Objective-C and Objective-C++, both identifiers and keywords
  /// are valid inside @selector(...) (or a macro which
  /// invokes @selector(...)). So, we allow treat any identifier or
  /// keyword as a potential Objective-C selector component.
  static bool canBeObjCSelectorComponent(const FormatToken &Tok) {
    return Tok.Tok.getIdentifierInfo() != nullptr;
  }
  
  /// With `Left` being '(', check if we're at either `[...](` or
  /// `[...]<...>(`, where the [ opens a lambda capture list.
  static bool isLambdaParameterList(const FormatToken *Left) {
    // Skip <...> if present.
    if (Left->Previous && Left->Previous->is(tok::greater) &&
        Left->Previous->MatchingParen &&
        Left->Previous->MatchingParen->is(TT_TemplateOpener))
      Left = Left->Previous->MatchingParen;
  
    // Check for `[...]`.
    return Left->Previous && Left->Previous->is(tok::r_square) &&
           Left->Previous->MatchingParen &&
           Left->Previous->MatchingParen->is(TT_LambdaLSquare);
  }
  
  /// Returns \c true if the token is followed by a boolean condition, \c false
  /// otherwise.
  static bool isKeywordWithCondition(const FormatToken &Tok) {
    return Tok.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,
                       tok::kw_constexpr, tok::kw_catch);
  }
  
  /// A parser that gathers additional information about tokens.
  ///
  /// The \c TokenAnnotator tries to match parenthesis and square brakets and
  /// store a parenthesis levels. It also tries to resolve matching "<" and ">"
  /// into template parameter lists.
  class AnnotatingParser {
  public:
    AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,
                     const AdditionalKeywords &Keywords)
        : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),
          Keywords(Keywords) {
      Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
      resetTokenMetadata(CurrentToken);
    }
  
  private:
    bool parseAngle() {
      if (!CurrentToken || !CurrentToken->Previous)
        return false;
      if (NonTemplateLess.count(CurrentToken->Previous))
        return false;
  
      const FormatToken &Previous = *CurrentToken->Previous; // The '<'.
      if (Previous.Previous) {
        if (Previous.Previous->Tok.isLiteral())
          return false;
        if (Previous.Previous->is(tok::r_paren) && Contexts.size() > 1 &&
            (!Previous.Previous->MatchingParen ||
             !Previous.Previous->MatchingParen->is(TT_OverloadedOperatorLParen)))
          return false;
      }
  
      FormatToken *Left = CurrentToken->Previous;
      Left->ParentBracket = Contexts.back().ContextKind;
      ScopedContextCreator ContextCreator(*this, tok::less, 12);
  
      // If this angle is in the context of an expression, we need to be more
      // hesitant to detect it as opening template parameters.
      bool InExprContext = Contexts.back().IsExpression;
  
      Contexts.back().IsExpression = false;
      // If there's a template keyword before the opening angle bracket, this is a
      // template parameter, not an argument.
      Contexts.back().InTemplateArgument =
          Left->Previous && Left->Previous->Tok.isNot(tok::kw_template);
  
      if (Style.Language == FormatStyle::LK_Java &&
          CurrentToken->is(tok::question))
        next();
  
      while (CurrentToken) {
        if (CurrentToken->is(tok::greater)) {
          // Try to do a better job at looking for ">>" within the condition of
          // a statement.
          if (CurrentToken->Next && CurrentToken->Next->is(tok::greater) &&
              Left->ParentBracket != tok::less &&
              isKeywordWithCondition(*Line.First))
            return false;
          Left->MatchingParen = CurrentToken;
          CurrentToken->MatchingParen = Left;
          // In TT_Proto, we must distignuish between:
          //   map<key, value>
          //   msg < item: data >
          //   msg: < item: data >
          // In TT_TextProto, map<key, value> does not occur.
          if (Style.Language == FormatStyle::LK_TextProto ||
              (Style.Language == FormatStyle::LK_Proto && Left->Previous &&
               Left->Previous->isOneOf(TT_SelectorName, TT_DictLiteral)))
            CurrentToken->setType(TT_DictLiteral);
          else
            CurrentToken->setType(TT_TemplateCloser);
          next();
          return true;
        }
        if (CurrentToken->is(tok::question) &&
            Style.Language == FormatStyle::LK_Java) {
          next();
          continue;
        }
        if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace) ||
            (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext &&
             !Style.isCSharp() && Style.Language != FormatStyle::LK_Proto &&
             Style.Language != FormatStyle::LK_TextProto))
          return false;
        // If a && or || is found and interpreted as a binary operator, this set
        // of angles is likely part of something like "a < b && c > d". If the
        // angles are inside an expression, the ||/&& might also be a binary
        // operator that was misinterpreted because we are parsing template
        // parameters.
        // FIXME: This is getting out of hand, write a decent parser.
        if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
            CurrentToken->Previous->is(TT_BinaryOperator) &&
            Contexts[Contexts.size() - 2].IsExpression &&
            !Line.startsWith(tok::kw_template))
          return false;
        updateParameterCount(Left, CurrentToken);
        if (Style.Language == FormatStyle::LK_Proto) {
          if (FormatToken *Previous = CurrentToken->getPreviousNonComment()) {
            if (CurrentToken->is(tok::colon) ||
                (CurrentToken->isOneOf(tok::l_brace, tok::less) &&
                 Previous->isNot(tok::colon)))
              Previous->setType(TT_SelectorName);
          }
        }
        if (!consumeToken())
          return false;
      }
      return false;
    }
  
    bool parseUntouchableParens() {
      while (CurrentToken) {
        CurrentToken->Finalized = true;
        switch (CurrentToken->Tok.getKind()) {
        case tok::l_paren:
          next();
          if (!parseUntouchableParens())
            return false;
          continue;
        case tok::r_paren:
          next();
          return true;
        default:
          // no-op
          break;
        }
        next();
      }
      return false;
    }
  
    bool parseParens(bool LookForDecls = false) {
      if (!CurrentToken)
        return false;
      FormatToken *Left = CurrentToken->Previous;
      assert(Left && "Unknown previous token");
      FormatToken *PrevNonComment = Left->getPreviousNonComment();
      Left->ParentBracket = Contexts.back().ContextKind;
      ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);
  
      // FIXME: This is a bit of a hack. Do better.
      Contexts.back().ColonIsForRangeExpr =
          Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
  
      if (Left->Previous && Left->Previous->is(TT_UntouchableMacroFunc)) {
        Left->Finalized = true;
        return parseUntouchableParens();
      }
  
      bool StartsObjCMethodExpr = false;
      if (FormatToken *MaybeSel = Left->Previous) {
        // @selector( starts a selector.
        if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous &&
            MaybeSel->Previous->is(tok::at)) {
          StartsObjCMethodExpr = true;
        }
      }
  
      if (Left->is(TT_OverloadedOperatorLParen)) {
        Contexts.back().IsExpression = false;
      } else if (Style.Language == FormatStyle::LK_JavaScript &&
                 (Line.startsWith(Keywords.kw_type, tok::identifier) ||
                  Line.startsWith(tok::kw_export, Keywords.kw_type,
                                  tok::identifier))) {
        // type X = (...);
        // export type X = (...);
        Contexts.back().IsExpression = false;
      } else if (Left->Previous &&
                 (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_while,
                                          tok::l_paren, tok::comma) ||
                  Left->Previous->isIf() ||
                  Left->Previous->is(TT_BinaryOperator))) {
        // static_assert, if and while usually contain expressions.
        Contexts.back().IsExpression = true;
      } else if (Style.Language == FormatStyle::LK_JavaScript && Left->Previous &&
                 (Left->Previous->is(Keywords.kw_function) ||
                  (Left->Previous->endsSequence(tok::identifier,
                                                Keywords.kw_function)))) {
        // function(...) or function f(...)
        Contexts.back().IsExpression = false;
      } else if (Style.Language == FormatStyle::LK_JavaScript && Left->Previous &&
                 Left->Previous->is(TT_JsTypeColon)) {
        // let x: (SomeType);
        Contexts.back().IsExpression = false;
      } else if (isLambdaParameterList(Left)) {
        // This is a parameter list of a lambda expression.
        Contexts.back().IsExpression = false;
      } else if (Line.InPPDirective &&
                 (!Left->Previous || !Left->Previous->is(tok::identifier))) {
        Contexts.back().IsExpression = true;
      } else if (Contexts[Contexts.size() - 2].CaretFound) {
        // This is the parameter list of an ObjC block.
        Contexts.back().IsExpression = false;
      } else if (Left->Previous && Left->Previous->is(TT_ForEachMacro)) {
        // The first argument to a foreach macro is a declaration.
        Contexts.back().IsForEachMacro = true;
        Contexts.back().IsExpression = false;
      } else if (Left->Previous && Left->Previous->MatchingParen &&
                 Left->Previous->MatchingParen->is(TT_ObjCBlockLParen)) {
        Contexts.back().IsExpression = false;
      } else if (!Line.MustBeDeclaration && !Line.InPPDirective) {
        bool IsForOrCatch =
            Left->Previous && Left->Previous->isOneOf(tok::kw_for, tok::kw_catch);
        Contexts.back().IsExpression = !IsForOrCatch;
      }
  
      // Infer the role of the l_paren based on the previous token if we haven't
      // detected one one yet.
      if (PrevNonComment && Left->is(TT_Unknown)) {
        if (PrevNonComment->is(tok::kw___attribute)) {
          Left->setType(TT_AttributeParen);
        } else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,
                                           tok::kw_typeof, tok::kw__Atomic,
                                           tok::kw___underlying_type)) {
          Left->setType(TT_TypeDeclarationParen);
          // decltype() and typeof() usually contain expressions.
          if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof))
            Contexts.back().IsExpression = true;
        }
      }
  
      if (StartsObjCMethodExpr) {
        Contexts.back().ColonIsObjCMethodExpr = true;
        Left->setType(TT_ObjCMethodExpr);
      }
  
      // MightBeFunctionType and ProbablyFunctionType are used for
      // function pointer and reference types as well as Objective-C
      // block types:
      //
      // void (*FunctionPointer)(void);
      // void (&FunctionReference)(void);
      // void (^ObjCBlock)(void);
      bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression;
      bool ProbablyFunctionType =
          CurrentToken->isOneOf(tok::star, tok::amp, tok::caret);
      bool HasMultipleLines = false;
      bool HasMultipleParametersOnALine = false;
      bool MightBeObjCForRangeLoop =
          Left->Previous && Left->Previous->is(tok::kw_for);
      FormatToken *PossibleObjCForInToken = nullptr;
      while (CurrentToken) {
        // LookForDecls is set when "if (" has been seen. Check for
        // 'identifier' '*' 'identifier' followed by not '=' -- this
        // '*' has to be a binary operator but determineStarAmpUsage() will
        // categorize it as an unary operator, so set the right type here.
        if (LookForDecls && CurrentToken->Next) {
          FormatToken *Prev = CurrentToken->getPreviousNonComment();
          if (Prev) {
            FormatToken *PrevPrev = Prev->getPreviousNonComment();
            FormatToken *Next = CurrentToken->Next;
            if (PrevPrev && PrevPrev->is(tok::identifier) &&
                Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
                CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
              Prev->setType(TT_BinaryOperator);
              LookForDecls = false;
            }
          }
        }
  
        if (CurrentToken->Previous->is(TT_PointerOrReference) &&
            CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
                                                      tok::coloncolon))
          ProbablyFunctionType = true;
        if (CurrentToken->is(tok::comma))
          MightBeFunctionType = false;
        if (CurrentToken->Previous->is(TT_BinaryOperator))
          Contexts.back().IsExpression = true;
        if (CurrentToken->is(tok::r_paren)) {
          if (MightBeFunctionType && ProbablyFunctionType && CurrentToken->Next &&
              (CurrentToken->Next->is(tok::l_paren) ||
               (CurrentToken->Next->is(tok::l_square) && Line.MustBeDeclaration)))
            Left->setType(Left->Next->is(tok::caret) ? TT_ObjCBlockLParen
                                                     : TT_FunctionTypeLParen);
          Left->MatchingParen = CurrentToken;
          CurrentToken->MatchingParen = Left;
  
          if (CurrentToken->Next && CurrentToken->Next->is(tok::l_brace) &&
              Left->Previous && Left->Previous->is(tok::l_paren)) {
            // Detect the case where macros are used to generate lambdas or
            // function bodies, e.g.:
            //   auto my_lambda = MARCO((Type *type, int i) { .. body .. });
            for (FormatToken *Tok = Left; Tok != CurrentToken; Tok = Tok->Next) {
              if (Tok->is(TT_BinaryOperator) &&
                  Tok->isOneOf(tok::star, tok::amp, tok::ampamp))
                Tok->setType(TT_PointerOrReference);
            }
          }
  
          if (StartsObjCMethodExpr) {
            CurrentToken->setType(TT_ObjCMethodExpr);
            if (Contexts.back().FirstObjCSelectorName) {
              Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
                  Contexts.back().LongestObjCSelectorName;
            }
          }
  
          if (Left->is(TT_AttributeParen))
            CurrentToken->setType(TT_AttributeParen);
          if (Left->is(TT_TypeDeclarationParen))
            CurrentToken->setType(TT_TypeDeclarationParen);
          if (Left->Previous && Left->Previous->is(TT_JavaAnnotation))
            CurrentToken->setType(TT_JavaAnnotation);
          if (Left->Previous && Left->Previous->is(TT_LeadingJavaAnnotation))
            CurrentToken->setType(TT_LeadingJavaAnnotation);
          if (Left->Previous && Left->Previous->is(TT_AttributeSquare))
            CurrentToken->setType(TT_AttributeSquare);
  
          if (!HasMultipleLines)
            Left->setPackingKind(PPK_Inconclusive);
          else if (HasMultipleParametersOnALine)
            Left->setPackingKind(PPK_BinPacked);
          else
            Left->setPackingKind(PPK_OnePerLine);
  
          next();
          return true;
        }
        if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
          return false;
  
        if (CurrentToken->is(tok::l_brace))
          Left->setType(TT_Unknown); // Not TT_ObjCBlockLParen
        if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
            !CurrentToken->Next->HasUnescapedNewline &&
            !CurrentToken->Next->isTrailingComment())
          HasMultipleParametersOnALine = true;
        if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) ||
             CurrentToken->Previous->isSimpleTypeSpecifier()) &&
            !CurrentToken->is(tok::l_brace))
          Contexts.back().IsExpression = false;
        if (CurrentToken->isOneOf(tok::semi, tok::colon)) {
          MightBeObjCForRangeLoop = false;
          if (PossibleObjCForInToken) {
            PossibleObjCForInToken->setType(TT_Unknown);
            PossibleObjCForInToken = nullptr;
          }
        }
        if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in)) {
          PossibleObjCForInToken = CurrentToken;
          PossibleObjCForInToken->setType(TT_ObjCForIn);
        }
        // When we discover a 'new', we set CanBeExpression to 'false' in order to
        // parse the type correctly. Reset that after a comma.
        if (CurrentToken->is(tok::comma))
          Contexts.back().CanBeExpression = true;
  
        FormatToken *Tok = CurrentToken;
        if (!consumeToken())
          return false;
        updateParameterCount(Left, Tok);
        if (CurrentToken && CurrentToken->HasUnescapedNewline)
          HasMultipleLines = true;
      }
      return false;
    }
  
    bool isCSharpAttributeSpecifier(const FormatToken &Tok) {
      if (!Style.isCSharp())
        return false;
  
      // `identifier[i]` is not an attribute.
      if (Tok.Previous && Tok.Previous->is(tok::identifier))
        return false;
  
      // Chains of [] in `identifier[i][j][k]` are not attributes.
      if (Tok.Previous && Tok.Previous->is(tok::r_square)) {
        auto *MatchingParen = Tok.Previous->MatchingParen;
        if (!MatchingParen || MatchingParen->is(TT_ArraySubscriptLSquare))
          return false;
      }
  
      const FormatToken *AttrTok = Tok.Next;
      if (!AttrTok)
        return false;
  
      // Just an empty declaration e.g. string [].
      if (AttrTok->is(tok::r_square))
        return false;
  
      // Move along the tokens inbetween the '[' and ']' e.g. [STAThread].
      while (AttrTok && AttrTok->isNot(tok::r_square)) {
        AttrTok = AttrTok->Next;
      }
  
      if (!AttrTok)
        return false;
  
      // Allow an attribute to be the only content of a file.
      AttrTok = AttrTok->Next;
      if (!AttrTok)
        return true;
  
      // Limit this to being an access modifier that follows.
      if (AttrTok->isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
                           tok::comment, tok::kw_class, tok::kw_static,
                           tok::l_square, Keywords.kw_internal)) {
        return true;
      }
  
      // incase its a [XXX] retval func(....
      if (AttrTok->Next &&
          AttrTok->Next->startsSequence(tok::identifier, tok::l_paren))
        return true;
  
      return false;
    }
  
    bool isCpp11AttributeSpecifier(const FormatToken &Tok) {
      if (!Style.isCpp() || !Tok.startsSequence(tok::l_square, tok::l_square))
        return false;
      // The first square bracket is part of an ObjC array literal
      if (Tok.Previous && Tok.Previous->is(tok::at)) {
        return false;
      }
      const FormatToken *AttrTok = Tok.Next->Next;
      if (!AttrTok)
        return false;
      // C++17 '[[using ns: foo, bar(baz, blech)]]'
      // We assume nobody will name an ObjC variable 'using'.
      if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))
        return true;
      if (AttrTok->isNot(tok::identifier))
        return false;
      while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {
        // ObjC message send. We assume nobody will use : in a C++11 attribute
        // specifier parameter, although this is technically valid:
        // [[foo(:)]].
        if (AttrTok->is(tok::colon) ||
            AttrTok->startsSequence(tok::identifier, tok::identifier) ||
            AttrTok->startsSequence(tok::r_paren, tok::identifier))
          return false;
        if (AttrTok->is(tok::ellipsis))
          return true;
        AttrTok = AttrTok->Next;
      }
      return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);
    }
  
    bool parseSquare() {
      if (!CurrentToken)
        return false;
  
      // A '[' could be an index subscript (after an identifier or after
      // ')' or ']'), it could be the start of an Objective-C method
      // expression, it could the start of an Objective-C array literal,
      // or it could be a C++ attribute specifier [[foo::bar]].
      FormatToken *Left = CurrentToken->Previous;
      Left->ParentBracket = Contexts.back().ContextKind;
      FormatToken *Parent = Left->getPreviousNonComment();
  
      // Cases where '>' is followed by '['.
      // In C++, this can happen either in array of templates (foo<int>[10])
      // or when array is a nested template type (unique_ptr<type1<type2>[]>).
      bool CppArrayTemplates =
          Style.isCpp() && Parent && Parent->is(TT_TemplateCloser) &&
          (Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
           Contexts.back().InTemplateArgument);
  
      bool IsCpp11AttributeSpecifier = isCpp11AttributeSpecifier(*Left) ||
                                       Contexts.back().InCpp11AttributeSpecifier;
  
      // Treat C# Attributes [STAThread] much like C++ attributes [[...]].
      bool IsCSharpAttributeSpecifier =
          isCSharpAttributeSpecifier(*Left) ||
          Contexts.back().InCSharpAttributeSpecifier;
  
      bool InsideInlineASM = Line.startsWith(tok::kw_asm);
      bool IsCppStructuredBinding = Left->isCppStructuredBinding(Style);
      bool StartsObjCMethodExpr =
          !IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&
          Style.isCpp() && !IsCpp11AttributeSpecifier &&
          !IsCSharpAttributeSpecifier && Contexts.back().CanBeExpression &&
          Left->isNot(TT_LambdaLSquare) &&
          !CurrentToken->isOneOf(tok::l_brace, tok::r_square) &&
          (!Parent ||
           Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
                           tok::kw_return, tok::kw_throw) ||
           Parent->isUnaryOperator() ||
           // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
           Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) ||
           (getBinOpPrecedence(Parent->Tok.getKind(), true, true) >
            prec::Unknown));
      bool ColonFound = false;
  
      unsigned BindingIncrease = 1;
      if (IsCppStructuredBinding) {
        Left->setType(TT_StructuredBindingLSquare);
      } else if (Left->is(TT_Unknown)) {
        if (StartsObjCMethodExpr) {
          Left->setType(TT_ObjCMethodExpr);
        } else if (InsideInlineASM) {
          Left->setType(TT_InlineASMSymbolicNameLSquare);
        } else if (IsCpp11AttributeSpecifier) {
          Left->setType(TT_AttributeSquare);
        } else if (Style.Language == FormatStyle::LK_JavaScript && Parent &&
                   Contexts.back().ContextKind == tok::l_brace &&
                   Parent->isOneOf(tok::l_brace, tok::comma)) {
          Left->setType(TT_JsComputedPropertyName);
        } else if (Style.isCpp() && Contexts.back().ContextKind == tok::l_brace &&
                   Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {
          Left->setType(TT_DesignatedInitializerLSquare);
        } else if (IsCSharpAttributeSpecifier) {
          Left->setType(TT_AttributeSquare);
        } else if (CurrentToken->is(tok::r_square) && Parent &&
                   Parent->is(TT_TemplateCloser)) {
          Left->setType(TT_ArraySubscriptLSquare);
        } else if (Style.Language == FormatStyle::LK_Proto ||
                   Style.Language == FormatStyle::LK_TextProto) {
          // Square braces in LK_Proto can either be message field attributes:
          //
          // optional Aaa aaa = 1 [
          //   (aaa) = aaa
          // ];
          //
          // extensions 123 [
          //   (aaa) = aaa
          // ];
          //
          // or text proto extensions (in options):
          //
          // option (Aaa.options) = {
          //   [type.type/type] {
          //     key: value
          //   }
          // }
          //
          // or repeated fields (in options):
          //
          // option (Aaa.options) = {
          //   keys: [ 1, 2, 3 ]
          // }
          //
          // In the first and the third case we want to spread the contents inside
          // the square braces; in the second we want to keep them inline.
          Left->setType(TT_ArrayInitializerLSquare);
          if (!Left->endsSequence(tok::l_square, tok::numeric_constant,
                                  tok::equal) &&
              !Left->endsSequence(tok::l_square, tok::numeric_constant,
                                  tok::identifier) &&
              !Left->endsSequence(tok::l_square, tok::colon, TT_SelectorName)) {
            Left->setType(TT_ProtoExtensionLSquare);
            BindingIncrease = 10;
          }
        } else if (!CppArrayTemplates && Parent &&
                   Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at,
                                   tok::comma, tok::l_paren, tok::l_square,
                                   tok::question, tok::colon, tok::kw_return,
                                   // Should only be relevant to JavaScript:
                                   tok::kw_default)) {
          Left->setType(TT_ArrayInitializerLSquare);
        } else {
          BindingIncrease = 10;
          Left->setType(TT_ArraySubscriptLSquare);
        }
      }
  
      ScopedContextCreator ContextCreator(*this, tok::l_square, BindingIncrease);
      Contexts.back().IsExpression = true;
      if (Style.Language == FormatStyle::LK_JavaScript && Parent &&
          Parent->is(TT_JsTypeColon))
        Contexts.back().IsExpression = false;
  
      Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;
      Contexts.back().InCpp11AttributeSpecifier = IsCpp11AttributeSpecifier;
      Contexts.back().InCSharpAttributeSpecifier = IsCSharpAttributeSpecifier;
  
      while (CurrentToken) {
        if (CurrentToken->is(tok::r_square)) {
          if (IsCpp11AttributeSpecifier)
            CurrentToken->setType(TT_AttributeSquare);
          if (IsCSharpAttributeSpecifier)
            CurrentToken->setType(TT_AttributeSquare);
          else if (((CurrentToken->Next &&
                     CurrentToken->Next->is(tok::l_paren)) ||
                    (CurrentToken->Previous &&
                     CurrentToken->Previous->Previous == Left)) &&
                   Left->is(TT_ObjCMethodExpr)) {
            // An ObjC method call is rarely followed by an open parenthesis. It
            // also can't be composed of just one token, unless it's a macro that
            // will be expanded to more tokens.
            // FIXME: Do we incorrectly label ":" with this?
            StartsObjCMethodExpr = false;
            Left->setType(TT_Unknown);
          }
          if (StartsObjCMethodExpr && CurrentToken->Previous != Left) {
            CurrentToken->setType(TT_ObjCMethodExpr);
            // If we haven't seen a colon yet, make sure the last identifier
            // before the r_square is tagged as a selector name component.
            if (!ColonFound && CurrentToken->Previous &&
                CurrentToken->Previous->is(TT_Unknown) &&
                canBeObjCSelectorComponent(*CurrentToken->Previous))
              CurrentToken->Previous->setType(TT_SelectorName);
            // determineStarAmpUsage() thinks that '*' '[' is allocating an
            // array of pointers, but if '[' starts a selector then '*' is a
            // binary operator.
            if (Parent && Parent->is(TT_PointerOrReference))
              Parent->setType(TT_BinaryOperator);
          }
          // An arrow after an ObjC method expression is not a lambda arrow.
          if (CurrentToken->getType() == TT_ObjCMethodExpr &&
              CurrentToken->Next && CurrentToken->Next->is(TT_LambdaArrow))
            CurrentToken->Next->setType(TT_Unknown);
          Left->MatchingParen = CurrentToken;
          CurrentToken->MatchingParen = Left;
          // FirstObjCSelectorName is set when a colon is found. This does
          // not work, however, when the method has no parameters.
          // Here, we set FirstObjCSelectorName when the end of the method call is
          // reached, in case it was not set already.
          if (!Contexts.back().FirstObjCSelectorName) {
            FormatToken *Previous = CurrentToken->getPreviousNonComment();
            if (Previous && Previous->is(TT_SelectorName)) {
              Previous->ObjCSelectorNameParts = 1;
              Contexts.back().FirstObjCSelectorName = Previous;
            }
          } else {
            Left->ParameterCount =
                Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
          }
          if (Contexts.back().FirstObjCSelectorName) {
            Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
                Contexts.back().LongestObjCSelectorName;
            if (Left->BlockParameterCount > 1)
              Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0;
          }
          next();
          return true;
        }
        if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
          return false;
        if (CurrentToken->is(tok::colon)) {
          if (IsCpp11AttributeSpecifier &&
              CurrentToken->endsSequence(tok::colon, tok::identifier,
                                         tok::kw_using)) {
            // Remember that this is a [[using ns: foo]] C++ attribute, so we
            // don't add a space before the colon (unlike other colons).
            CurrentToken->setType(TT_AttributeColon);
          } else if (Left->isOneOf(TT_ArraySubscriptLSquare,
                                   TT_DesignatedInitializerLSquare)) {
            Left->setType(TT_ObjCMethodExpr);
            StartsObjCMethodExpr = true;
            Contexts.back().ColonIsObjCMethodExpr = true;
            if (Parent && Parent->is(tok::r_paren))
              // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
              Parent->setType(TT_CastRParen);
          }
          ColonFound = true;
        }
        if (CurrentToken->is(tok::comma) && Left->is(TT_ObjCMethodExpr) &&
            !ColonFound)
          Left->setType(TT_ArrayInitializerLSquare);
        FormatToken *Tok = CurrentToken;
        if (!consumeToken())
          return false;
        updateParameterCount(Left, Tok);
      }
      return false;
    }
  
    bool parseBrace() {
      if (CurrentToken) {
        FormatToken *Left = CurrentToken->Previous;
        Left->ParentBracket = Contexts.back().ContextKind;
  
        if (Contexts.back().CaretFound)
          Left->setType(TT_ObjCBlockLBrace);
        Contexts.back().CaretFound = false;
  
        ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
        Contexts.back().ColonIsDictLiteral = true;
        if (Left->is(BK_BracedInit))
          Contexts.back().IsExpression = true;
        if (Style.Language == FormatStyle::LK_JavaScript && Left->Previous &&
            Left->Previous->is(TT_JsTypeColon))
          Contexts.back().IsExpression = false;
  
        while (CurrentToken) {
          if (CurrentToken->is(tok::r_brace)) {
            Left->MatchingParen = CurrentToken;
            CurrentToken->MatchingParen = Left;
            next();
            return true;
          }
          if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
            return false;
          updateParameterCount(Left, CurrentToken);
          if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {
            FormatToken *Previous = CurrentToken->getPreviousNonComment();
            if (Previous->is(TT_JsTypeOptionalQuestion))
              Previous = Previous->getPreviousNonComment();
            if ((CurrentToken->is(tok::colon) &&
                 (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
                Style.Language == FormatStyle::LK_Proto ||
                Style.Language == FormatStyle::LK_TextProto) {
              Left->setType(TT_DictLiteral);
              if (Previous->Tok.getIdentifierInfo() ||
                  Previous->is(tok::string_literal))
                Previous->setType(TT_SelectorName);
            }
            if (CurrentToken->is(tok::colon) ||
                Style.Language == FormatStyle::LK_JavaScript)
              Left->setType(TT_DictLiteral);
          }
          if (CurrentToken->is(tok::comma) &&
              Style.Language == FormatStyle::LK_JavaScript)
            Left->setType(TT_DictLiteral);
          if (!consumeToken())
            return false;
        }
      }
      return true;
    }
  
    void updateParameterCount(FormatToken *Left, FormatToken *Current) {
      // For ObjC methods, the number of parameters is calculated differently as
      // method declarations have a different structure (the parameters are not
      // inside a bracket scope).
      if (Current->is(tok::l_brace) && Current->is(BK_Block))
        ++Left->BlockParameterCount;
      if (Current->is(tok::comma)) {
        ++Left->ParameterCount;
        if (!Left->Role)
          Left->Role.reset(new CommaSeparatedList(Style));
        Left->Role->CommaFound(Current);
      } else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) {
        Left->ParameterCount = 1;
      }
    }
  
    bool parseConditional() {
      while (CurrentToken) {
        if (CurrentToken->is(tok::colon)) {
          CurrentToken->setType(TT_ConditionalExpr);
          next();
          return true;
        }
        if (!consumeToken())
          return false;
      }
      return false;
    }
  
    bool parseTemplateDeclaration() {
      if (CurrentToken && CurrentToken->is(tok::less)) {
        CurrentToken->setType(TT_TemplateOpener);
        next();
        if (!parseAngle())
          return false;
        if (CurrentToken)
          CurrentToken->Previous->ClosesTemplateDeclaration = true;
        return true;
      }
      return false;
    }
  
    bool consumeToken() {
      FormatToken *Tok = CurrentToken;
      next();
      switch (Tok->Tok.getKind()) {
      case tok::plus:
      case tok::minus:
        if (!Tok->Previous && Line.MustBeDeclaration)
          Tok->setType(TT_ObjCMethodSpecifier);
        break;
      case tok::colon:
        if (!Tok->Previous)
          return false;
        // Colons from ?: are handled in parseConditional().
        if (Style.Language == FormatStyle::LK_JavaScript) {
          if (Contexts.back().ColonIsForRangeExpr || // colon in for loop
              (Contexts.size() == 1 &&               // switch/case labels
               !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) ||
              Contexts.back().ContextKind == tok::l_paren ||  // function params
              Contexts.back().ContextKind == tok::l_square || // array type
              (!Contexts.back().IsExpression &&
               Contexts.back().ContextKind == tok::l_brace) || // object type
              (Contexts.size() == 1 &&
               Line.MustBeDeclaration)) { // method/property declaration
            Contexts.back().IsExpression = false;
            Tok->setType(TT_JsTypeColon);
            break;
          }
        } else if (Style.isCSharp()) {
          if (Contexts.back().InCSharpAttributeSpecifier) {
            Tok->setType(TT_AttributeColon);
            break;
          }
          if (Contexts.back().ContextKind == tok::l_paren) {
            Tok->setType(TT_CSharpNamedArgumentColon);
            break;
          }
        }
        if (Contexts.back().ColonIsDictLiteral ||
            Style.Language == FormatStyle::LK_Proto ||
            Style.Language == FormatStyle::LK_TextProto) {
          Tok->setType(TT_DictLiteral);
          if (Style.Language == FormatStyle::LK_TextProto) {
            if (FormatToken *Previous = Tok->getPreviousNonComment())
              Previous->setType(TT_SelectorName);
          }
        } else if (Contexts.back().ColonIsObjCMethodExpr ||
                   Line.startsWith(TT_ObjCMethodSpecifier)) {
          Tok->setType(TT_ObjCMethodExpr);
          const FormatToken *BeforePrevious = Tok->Previous->Previous;
          // Ensure we tag all identifiers in method declarations as
          // TT_SelectorName.
          bool UnknownIdentifierInMethodDeclaration =
              Line.startsWith(TT_ObjCMethodSpecifier) &&
              Tok->Previous->is(tok::identifier) && Tok->Previous->is(TT_Unknown);
          if (!BeforePrevious ||
              // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
              !(BeforePrevious->is(TT_CastRParen) ||
                (BeforePrevious->is(TT_ObjCMethodExpr) &&
                 BeforePrevious->is(tok::colon))) ||
              BeforePrevious->is(tok::r_square) ||
              Contexts.back().LongestObjCSelectorName == 0 ||
              UnknownIdentifierInMethodDeclaration) {
            Tok->Previous->setType(TT_SelectorName);
            if (!Contexts.back().FirstObjCSelectorName)
              Contexts.back().FirstObjCSelectorName = Tok->Previous;
            else if (Tok->Previous->ColumnWidth >
                     Contexts.back().LongestObjCSelectorName)
              Contexts.back().LongestObjCSelectorName =
                  Tok->Previous->ColumnWidth;
            Tok->Previous->ParameterIndex =
                Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
            ++Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
          }
        } else if (Contexts.back().ColonIsForRangeExpr) {
          Tok->setType(TT_RangeBasedForLoopColon);
        } else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
          Tok->setType(TT_BitFieldColon);
        } else if (Contexts.size() == 1 &&
                   !Line.First->isOneOf(tok::kw_enum, tok::kw_case,
                                        tok::kw_default)) {
          FormatToken *Prev = Tok->getPreviousNonComment();
          if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept))
            Tok->setType(TT_CtorInitializerColon);
          else if (Prev->is(tok::kw_try)) {
            // Member initializer list within function try block.
            FormatToken *PrevPrev = Prev->getPreviousNonComment();
            if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept))
              Tok->setType(TT_CtorInitializerColon);
          } else
            Tok->setType(TT_InheritanceColon);
        } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next &&
                   (Tok->Next->isOneOf(tok::r_paren, tok::comma) ||
                    (canBeObjCSelectorComponent(*Tok->Next) && Tok->Next->Next &&
                     Tok->Next->Next->is(tok::colon)))) {
          // This handles a special macro in ObjC code where selectors including
          // the colon are passed as macro arguments.
          Tok->setType(TT_ObjCMethodExpr);
        } else if (Contexts.back().ContextKind == tok::l_paren) {
          Tok->setType(TT_InlineASMColon);
        }
        break;
      case tok::pipe:
      case tok::amp:
        // | and & in declarations/type expressions represent union and
        // intersection types, respectively.
        if (Style.Language == FormatStyle::LK_JavaScript &&
            !Contexts.back().IsExpression)
          Tok->setType(TT_JsTypeOperator);
        break;
      case tok::kw_if:
      case tok::kw_while:
        if (Tok->is(tok::kw_if) && CurrentToken &&
            CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier))
          next();
        if (CurrentToken && CurrentToken->is(tok::l_paren)) {
          next();
          if (!parseParens(/*LookForDecls=*/true))
            return false;
        }
        break;
      case tok::kw_for:
        if (Style.Language == FormatStyle::LK_JavaScript) {
          // x.for and {for: ...}
          if ((Tok->Previous && Tok->Previous->is(tok::period)) ||
              (Tok->Next && Tok->Next->is(tok::colon)))
            break;
          // JS' for await ( ...
          if (CurrentToken && CurrentToken->is(Keywords.kw_await))
            next();
        }
        Contexts.back().ColonIsForRangeExpr = true;
        next();
        if (!parseParens())
          return false;
        break;
      case tok::l_paren:
        // When faced with 'operator()()', the kw_operator handler incorrectly
        // marks the first l_paren as a OverloadedOperatorLParen. Here, we make
        // the first two parens OverloadedOperators and the second l_paren an
        // OverloadedOperatorLParen.
        if (Tok->Previous && Tok->Previous->is(tok::r_paren) &&
            Tok->Previous->MatchingParen &&
            Tok->Previous->MatchingParen->is(TT_OverloadedOperatorLParen)) {
          Tok->Previous->setType(TT_OverloadedOperator);
          Tok->Previous->MatchingParen->setType(TT_OverloadedOperator);
          Tok->setType(TT_OverloadedOperatorLParen);
        }
  
        if (!parseParens())
          return false;
        if (Line.MustBeDeclaration && Contexts.size() == 1 &&
            !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
            !Tok->is(TT_TypeDeclarationParen) &&
            (!Tok->Previous || !Tok->Previous->isOneOf(tok::kw___attribute,
                                                       TT_LeadingJavaAnnotation)))
          Line.MightBeFunctionDecl = true;
        break;
      case tok::l_square:
        if (!parseSquare())
          return false;
        break;
      case tok::l_brace:
        if (Style.Language == FormatStyle::LK_TextProto) {
          FormatToken *Previous = Tok->getPreviousNonComment();
          if (Previous && Previous->getType() != TT_DictLiteral)
            Previous->setType(TT_SelectorName);
        }
        if (!parseBrace())
          return false;
        break;
      case tok::less:
        if (parseAngle()) {
          Tok->setType(TT_TemplateOpener);
          // In TT_Proto, we must distignuish between:
          //   map<key, value>
          //   msg < item: data >
          //   msg: < item: data >
          // In TT_TextProto, map<key, value> does not occur.
          if (Style.Language == FormatStyle::LK_TextProto ||
              (Style.Language == FormatStyle::LK_Proto && Tok->Previous &&
               Tok->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) {
            Tok->setType(TT_DictLiteral);
            FormatToken *Previous = Tok->getPreviousNonComment();
            if (Previous && Previous->getType() != TT_DictLiteral)
              Previous->setType(TT_SelectorName);
          }
        } else {
          Tok->setType(TT_BinaryOperator);
          NonTemplateLess.insert(Tok);
          CurrentToken = Tok;
          next();
        }
        break;
      case tok::r_paren:
      case tok::r_square:
        return false;
      case tok::r_brace:
        // Lines can start with '}'.
        if (Tok->Previous)
          return false;
        break;
      case tok::greater:
        if (Style.Language != FormatStyle::LK_TextProto)
          Tok->setType(TT_BinaryOperator);
        if (Tok->Previous && Tok->Previous->is(TT_TemplateCloser))
          Tok->SpacesRequiredBefore = 1;
        break;
      case tok::kw_operator:
        if (Style.Language == FormatStyle::LK_TextProto ||
            Style.Language == FormatStyle::LK_Proto)
          break;
        while (CurrentToken &&
               !CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) {
          if (CurrentToken->isOneOf(tok::star, tok::amp))
            CurrentToken->setType(TT_PointerOrReference);
          consumeToken();
          if (CurrentToken && CurrentToken->is(tok::comma) &&
              CurrentToken->Previous->isNot(tok::kw_operator))
            break;
          if (CurrentToken && CurrentToken->Previous->isOneOf(
                                  TT_BinaryOperator, TT_UnaryOperator, tok::comma,
                                  tok::star, tok::arrow, tok::amp, tok::ampamp))
            CurrentToken->Previous->setType(TT_OverloadedOperator);
        }
        if (CurrentToken && CurrentToken->is(tok::l_paren))
          CurrentToken->setType(TT_OverloadedOperatorLParen);
        if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator))
          CurrentToken->Previous->setType(TT_OverloadedOperator);
        break;
      case tok::question:
        if (Tok->is(TT_CSharpNullConditionalLSquare)) {
          if (!parseSquare())
            return false;
          break;
        }
        if (Tok->isOneOf(TT_CSharpNullConditional, TT_CSharpNullCoalescing))
          break;
        if (Style.Language == FormatStyle::LK_JavaScript && Tok->Next &&
            Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren,
                               tok::r_brace)) {
          // Question marks before semicolons, colons, etc. indicate optional
          // types (fields, parameters), e.g.
          //   function(x?: string, y?) {...}
          //   class X { y?; }
          Tok->setType(TT_JsTypeOptionalQuestion);
          break;
        }
        // Declarations cannot be conditional expressions, this can only be part
        // of a type declaration.
        if (Line.MustBeDeclaration && !Contexts.back().IsExpression &&
            Style.Language == FormatStyle::LK_JavaScript)
          break;
        if (Style.isCSharp()) {
          // `Type?)`, `Type?>`, `Type? name;` and `Type? name =` can only be
          // nullable types.
          // Line.MustBeDeclaration will be true for `Type? name;`.
          if ((!Contexts.back().IsExpression && Line.MustBeDeclaration) ||
              (Tok->Next && Tok->Next->isOneOf(tok::r_paren, tok::greater)) ||
              (Tok->Next && Tok->Next->is(tok::identifier) && Tok->Next->Next &&
               Tok->Next->Next->is(tok::equal))) {
            Tok->setType(TT_CSharpNullable);
            break;
          }
        }
        parseConditional();
        break;
      case tok::kw_template:
        parseTemplateDeclaration();
        break;
      case tok::comma:
        if (Contexts.back().InCtorInitializer)
          Tok->setType(TT_CtorInitializerComma);
        else if (Contexts.back().InInheritanceList)
          Tok->setType(TT_InheritanceComma);
        else if (Contexts.back().FirstStartOfName &&
                 (Contexts.size() == 1 || Line.startsWith(tok::kw_for))) {
          Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
          Line.IsMultiVariableDeclStmt = true;
        }
        if (Contexts.back().IsForEachMacro)
          Contexts.back().IsExpression = true;
        break;
      case tok::identifier:
        if (Tok->isOneOf(Keywords.kw___has_include,
                         Keywords.kw___has_include_next)) {
          parseHasInclude();
        }
        if (Style.isCSharp() && Tok->is(Keywords.kw_where) && Tok->Next &&
            Tok->Next->isNot(tok::l_paren)) {
          Tok->setType(TT_CSharpGenericTypeConstraint);
          parseCSharpGenericTypeConstraint();
        }
        break;
      default:
        break;
      }
      return true;
    }
  
    void parseCSharpGenericTypeConstraint() {
      int OpenAngleBracketsCount = 0;
      while (CurrentToken) {
        if (CurrentToken->is(tok::less)) {
          // parseAngle is too greedy and will consume the whole line.
          CurrentToken->setType(TT_TemplateOpener);
          ++OpenAngleBracketsCount;
          next();
        } else if (CurrentToken->is(tok::greater)) {
          CurrentToken->setType(TT_TemplateCloser);
          --OpenAngleBracketsCount;
          next();
        } else if (CurrentToken->is(tok::comma) && OpenAngleBracketsCount == 0) {
          // We allow line breaks after GenericTypeConstraintComma's
          // so do not flag commas in Generics as GenericTypeConstraintComma's.
          CurrentToken->setType(TT_CSharpGenericTypeConstraintComma);
          next();
        } else if (CurrentToken->is(Keywords.kw_where)) {
          CurrentToken->setType(TT_CSharpGenericTypeConstraint);
          next();
        } else if (CurrentToken->is(tok::colon)) {
          CurrentToken->setType(TT_CSharpGenericTypeConstraintColon);
          next();
        } else {
          next();
        }
      }
    }
  
    void parseIncludeDirective() {
      if (CurrentToken && CurrentToken->is(tok::less)) {
        next();
        while (CurrentToken) {
          // Mark tokens up to the trailing line comments as implicit string
          // literals.
          if (CurrentToken->isNot(tok::comment) &&
              !CurrentToken->TokenText.startswith("//"))
            CurrentToken->setType(TT_ImplicitStringLiteral);
          next();
        }
      }
    }
  
    void parseWarningOrError() {
      next();
      // We still want to format the whitespace left of the first token of the
      // warning or error.
      next();
      while (CurrentToken) {
        CurrentToken->setType(TT_ImplicitStringLiteral);
        next();
      }
    }
  
    void parsePragma() {
      next(); // Consume "pragma".
      if (CurrentToken &&
          CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_option)) {
        bool IsMark = CurrentToken->is(Keywords.kw_mark);
        next(); // Consume "mark".
        next(); // Consume first token (so we fix leading whitespace).
        while (CurrentToken) {
          if (IsMark || CurrentToken->Previous->is(TT_BinaryOperator))
            CurrentToken->setType(TT_ImplicitStringLiteral);
          next();
        }
      }
    }
  
    void parseHasInclude() {
      if (!CurrentToken || !CurrentToken->is(tok::l_paren))
        return;
      next(); // '('
      parseIncludeDirective();
      next(); // ')'
    }
  
    LineType parsePreprocessorDirective() {
      bool IsFirstToken = CurrentToken->IsFirst;
      LineType Type = LT_PreprocessorDirective;
      next();
      if (!CurrentToken)
        return Type;
  
      if (Style.Language == FormatStyle::LK_JavaScript && IsFirstToken) {
        // JavaScript files can contain shebang lines of the form:
        // #!/usr/bin/env node
        // Treat these like C++ #include directives.
        while (CurrentToken) {
          // Tokens cannot be comments here.
          CurrentToken->setType(TT_ImplicitStringLiteral);
          next();
        }
        return LT_ImportStatement;
      }
  
      if (CurrentToken->Tok.is(tok::numeric_constant)) {
        CurrentToken->SpacesRequiredBefore = 1;
        return Type;
      }
      // Hashes in the middle of a line can lead to any strange token
      // sequence.
      if (!CurrentToken->Tok.getIdentifierInfo())
        return Type;
      switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {
      case tok::pp_include:
      case tok::pp_include_next:
      case tok::pp_import:
        next();
        parseIncludeDirective();
        Type = LT_ImportStatement;
        break;
      case tok::pp_error:
      case tok::pp_warning:
        parseWarningOrError();
        break;
      case tok::pp_pragma:
        parsePragma();
        break;
      case tok::pp_if:
      case tok::pp_elif:
        Contexts.back().IsExpression = true;
        next();
        parseLine();
        break;
      default:
        break;
      }
      while (CurrentToken) {
        FormatToken *Tok = CurrentToken;
        next();
        if (Tok->is(tok::l_paren))
          parseParens();
        else if (Tok->isOneOf(Keywords.kw___has_include,
                              Keywords.kw___has_include_next))
          parseHasInclude();
      }
      return Type;
    }
  
  public:
    LineType parseLine() {
      if (!CurrentToken)
        return LT_Invalid;
      NonTemplateLess.clear();
      if (CurrentToken->is(tok::hash))
        return parsePreprocessorDirective();
  
      // Directly allow to 'import <string-literal>' to support protocol buffer
      // definitions (github.com/google/protobuf) or missing "#" (either way we
      // should not break the line).
      IdentifierInfo *Info = CurrentToken->Tok.getIdentifierInfo();
      if ((Style.Language == FormatStyle::LK_Java &&
           CurrentToken->is(Keywords.kw_package)) ||
          (Info && Info->getPPKeywordID() == tok::pp_import &&
           CurrentToken->Next &&
           CurrentToken->Next->isOneOf(tok::string_literal, tok::identifier,
                                       tok::kw_static))) {
        next();
        parseIncludeDirective();
        return LT_ImportStatement;
      }
  
      // If this line starts and ends in '<' and '>', respectively, it is likely
      // part of "#define <a/b.h>".
      if (CurrentToken->is(tok::less) && Line.Last->is(tok::greater)) {
        parseIncludeDirective();
        return LT_ImportStatement;
      }
  
      // In .proto files, top-level options and package statements are very
      // similar to import statements and should not be line-wrapped.
      if (Style.Language == FormatStyle::LK_Proto && Line.Level == 0 &&
          CurrentToken->isOneOf(Keywords.kw_option, Keywords.kw_package)) {
        next();
        if (CurrentToken && CurrentToken->is(tok::identifier)) {
          while (CurrentToken)
            next();
          return LT_ImportStatement;
        }
      }
  
      bool KeywordVirtualFound = false;
      bool ImportStatement = false;
  
      // import {...} from '...';
      if (Style.Language == FormatStyle::LK_JavaScript &&
          CurrentToken->is(Keywords.kw_import))
        ImportStatement = true;
  
      while (CurrentToken) {
        if (CurrentToken->is(tok::kw_virtual))
          KeywordVirtualFound = true;
        if (Style.Language == FormatStyle::LK_JavaScript) {
          // export {...} from '...';
          // An export followed by "from 'some string';" is a re-export from
          // another module identified by a URI and is treated as a
          // LT_ImportStatement (i.e. prevent wraps on it for long URIs).
          // Just "export {...};" or "export class ..." should not be treated as
          // an import in this sense.
          if (Line.First->is(tok::kw_export) &&
              CurrentToken->is(Keywords.kw_from) && CurrentToken->Next &&
              CurrentToken->Next->isStringLiteral())
            ImportStatement = true;
          if (isClosureImportStatement(*CurrentToken))
            ImportStatement = true;
        }
        if (!consumeToken())
          return LT_Invalid;
      }
      if (KeywordVirtualFound)
        return LT_VirtualFunctionDecl;
      if (ImportStatement)
        return LT_ImportStatement;
  
      if (Line.startsWith(TT_ObjCMethodSpecifier)) {
        if (Contexts.back().FirstObjCSelectorName)
          Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
              Contexts.back().LongestObjCSelectorName;
        return LT_ObjCMethodDecl;
      }
  
      return LT_Other;
    }
  
  private:
    bool isClosureImportStatement(const FormatToken &Tok) {
      // FIXME: Closure-library specific stuff should not be hard-coded but be
      // configurable.
      return Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) &&
             Tok.Next->Next &&
             (Tok.Next->Next->TokenText == "module" ||
              Tok.Next->Next->TokenText == "provide" ||
              Tok.Next->Next->TokenText == "require" ||
              Tok.Next->Next->TokenText == "requireType" ||
              Tok.Next->Next->TokenText == "forwardDeclare") &&
             Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);
    }
  
    void resetTokenMetadata(FormatToken *Token) {
      if (!Token)
        return;
  
      // Reset token type in case we have already looked at it and then
      // recovered from an error (e.g. failure to find the matching >).
      if (!CurrentToken->isOneOf(
              TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro,
              TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace,
              TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_JsFatArrow,
              TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,
              TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral,
              TT_UntouchableMacroFunc, TT_ConstraintJunctions,
              TT_StatementAttributeLikeMacro))
        CurrentToken->setType(TT_Unknown);
      CurrentToken->Role.reset();
      CurrentToken->MatchingParen = nullptr;
      CurrentToken->FakeLParens.clear();
      CurrentToken->FakeRParens = 0;
    }
  
    void next() {
      if (CurrentToken) {
        CurrentToken->NestingLevel = Contexts.size() - 1;
        CurrentToken->BindingStrength = Contexts.back().BindingStrength;
        modifyContext(*CurrentToken);
        determineTokenType(*CurrentToken);
        CurrentToken = CurrentToken->Next;
      }
  
      resetTokenMetadata(CurrentToken);
    }
  
    /// A struct to hold information valid in a specific context, e.g.
    /// a pair of parenthesis.
    struct Context {
      Context(tok::TokenKind ContextKind, unsigned BindingStrength,
              bool IsExpression)
          : ContextKind(ContextKind), BindingStrength(BindingStrength),
            IsExpression(IsExpression) {}
  
      tok::TokenKind ContextKind;
      unsigned BindingStrength;
      bool IsExpression;
      unsigned LongestObjCSelectorName = 0;
      bool ColonIsForRangeExpr = false;
      bool ColonIsDictLiteral = false;
      bool ColonIsObjCMethodExpr = false;
      FormatToken *FirstObjCSelectorName = nullptr;
      FormatToken *FirstStartOfName = nullptr;
      bool CanBeExpression = true;
      bool InTemplateArgument = false;
      bool InCtorInitializer = false;
      bool InInheritanceList = false;
      bool CaretFound = false;
      bool IsForEachMacro = false;
      bool InCpp11AttributeSpecifier = false;
      bool InCSharpAttributeSpecifier = false;
    };
  
    /// Puts a new \c Context onto the stack \c Contexts for the lifetime
    /// of each instance.
    struct ScopedContextCreator {
      AnnotatingParser &P;
  
      ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind,
                           unsigned Increase)
          : P(P) {
        P.Contexts.push_back(Context(ContextKind,
                                     P.Contexts.back().BindingStrength + Increase,
                                     P.Contexts.back().IsExpression));
      }
  
      ~ScopedContextCreator() { P.Contexts.pop_back(); }
    };
  
    void modifyContext(const FormatToken &Current) {
      if (Current.getPrecedence() == prec::Assignment &&
          !Line.First->isOneOf(tok::kw_template, tok::kw_using, tok::kw_return) &&
          // Type aliases use `type X = ...;` in TypeScript and can be exported
          // using `export type ...`.
          !(Style.Language == FormatStyle::LK_JavaScript &&
            (Line.startsWith(Keywords.kw_type, tok::identifier) ||
             Line.startsWith(tok::kw_export, Keywords.kw_type,
                             tok::identifier))) &&
          (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
        Contexts.back().IsExpression = true;
        if (!Line.startsWith(TT_UnaryOperator)) {
          for (FormatToken *Previous = Current.Previous;
               Previous && Previous->Previous &&
               !Previous->Previous->isOneOf(tok::comma, tok::semi);
               Previous = Previous->Previous) {
            if (Previous->isOneOf(tok::r_square, tok::r_paren)) {
              Previous = Previous->MatchingParen;
              if (!Previous)
                break;
            }
            if (Previous->opensScope())
              break;
            if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) &&
                Previous->isOneOf(tok::star, tok::amp, tok::ampamp) &&
                Previous->Previous && Previous->Previous->isNot(tok::equal))
              Previous->setType(TT_PointerOrReference);
          }
        }
      } else if (Current.is(tok::lessless) &&
                 (!Current.Previous || !Current.Previous->is(tok::kw_operator))) {
        Contexts.back().IsExpression = true;
      } else if (Current.isOneOf(tok::kw_return, tok::kw_throw)) {
        Contexts.back().IsExpression = true;
      } else if (Current.is(TT_TrailingReturnArrow)) {
        Contexts.back().IsExpression = false;
      } else if (Current.is(TT_LambdaArrow) || Current.is(Keywords.kw_assert)) {
        Contexts.back().IsExpression = Style.Language == FormatStyle::LK_Java;
      } else if (Current.Previous &&
                 Current.Previous->is(TT_CtorInitializerColon)) {
        Contexts.back().IsExpression = true;
        Contexts.back().InCtorInitializer = true;
      } else if (Current.Previous && Current.Previous->is(TT_InheritanceColon)) {
        Contexts.back().InInheritanceList = true;
      } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
        for (FormatToken *Previous = Current.Previous;
             Previous && Previous->isOneOf(tok::star, tok::amp);
             Previous = Previous->Previous)
          Previous->setType(TT_PointerOrReference);
        if (Line.MustBeDeclaration && !Contexts.front().InCtorInitializer)
          Contexts.back().IsExpression = false;
      } else if (Current.is(tok::kw_new)) {
        Contexts.back().CanBeExpression = false;
      } else if (Current.is(tok::semi) ||
                 (Current.is(tok::exclaim) && Current.Previous &&
                  !Current.Previous->is(tok::kw_operator))) {
        // This should be the condition or increment in a for-loop.
        // But not operator !() (can't use TT_OverloadedOperator here as its not
        // been annotated yet).
        Contexts.back().IsExpression = true;
      }
    }
  
    static FormatToken *untilMatchingParen(FormatToken *Current) {
      // Used when `MatchingParen` is not yet established.
      int ParenLevel = 0;
      while (Current) {
        if (Current->is(tok::l_paren))
          ParenLevel++;
        if (Current->is(tok::r_paren))
          ParenLevel--;
        if (ParenLevel < 1)
          break;
        Current = Current->Next;
      }
      return Current;
    }
  
    static bool isDeductionGuide(FormatToken &Current) {
      // Look for a deduction guide template<T> A(...) -> A<...>;
      if (Current.Previous && Current.Previous->is(tok::r_paren) &&
          Current.startsSequence(tok::arrow, tok::identifier, tok::less)) {
        // Find the TemplateCloser.
        FormatToken *TemplateCloser = Current.Next->Next;
        int NestingLevel = 0;
        while (TemplateCloser) {
          // Skip over an expressions in parens  A<(3 < 2)>;
          if (TemplateCloser->is(tok::l_paren)) {
            // No Matching Paren yet so skip to matching paren
            TemplateCloser = untilMatchingParen(TemplateCloser);
          }
          if (TemplateCloser->is(tok::less))
            NestingLevel++;
          if (TemplateCloser->is(tok::greater))
            NestingLevel--;
          if (NestingLevel < 1)
            break;
          TemplateCloser = TemplateCloser->Next;
        }
        // Assuming we have found the end of the template ensure its followed
        // with a semi-colon.
        if (TemplateCloser && TemplateCloser->Next &&
            TemplateCloser->Next->is(tok::semi) &&
            Current.Previous->MatchingParen) {
          // Determine if the identifier `A` prior to the A<..>; is the same as
          // prior to the A(..)
          FormatToken *LeadingIdentifier =
              Current.Previous->MatchingParen->Previous;
  
          // Differentiate a deduction guide by seeing the
          // > of the template prior to the leading identifier.
          if (LeadingIdentifier) {
            FormatToken *PriorLeadingIdentifier = LeadingIdentifier->Previous;
            // Skip back past explicit decoration
            if (PriorLeadingIdentifier &&
                PriorLeadingIdentifier->is(tok::kw_explicit))
              PriorLeadingIdentifier = PriorLeadingIdentifier->Previous;
  
            return (PriorLeadingIdentifier &&
                    PriorLeadingIdentifier->is(TT_TemplateCloser) &&
                    LeadingIdentifier->TokenText == Current.Next->TokenText);
          }
        }
      }
      return false;
    }
  
    void determineTokenType(FormatToken &Current) {
      if (!Current.is(TT_Unknown))
        // The token type is already known.
        return;
  
      if (Style.isCSharp() && CurrentToken->is(tok::question)) {
        if (CurrentToken->TokenText == "??") {
          Current.setType(TT_CSharpNullCoalescing);
          return;
        }
        if (CurrentToken->TokenText == "?.") {
          Current.setType(TT_CSharpNullConditional);
          return;
        }
        if (CurrentToken->TokenText == "?[") {
          Current.setType(TT_CSharpNullConditionalLSquare);
          return;
        }
      }
  
      if (Style.Language == FormatStyle::LK_JavaScript) {
        if (Current.is(tok::exclaim)) {
          if (Current.Previous &&
              (Keywords.IsJavaScriptIdentifier(
                   *Current.Previous, /* AcceptIdentifierName= */ true) ||
               Current.Previous->isOneOf(
                   tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace,
                   Keywords.kw_type, Keywords.kw_get, Keywords.kw_set) ||
               Current.Previous->Tok.isLiteral())) {
            Current.setType(TT_JsNonNullAssertion);
            return;
          }
          if (Current.Next &&
              Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) {
            Current.setType(TT_JsNonNullAssertion);
            return;
          }
        }
      }
  
      // Line.MightBeFunctionDecl can only be true after the parentheses of a
      // function declaration have been found. In this case, 'Current' is a
      // trailing token of this declaration and thus cannot be a name.
      if (Current.is(Keywords.kw_instanceof)) {
        Current.setType(TT_BinaryOperator);
      } else if (isStartOfName(Current) &&
                 (!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {
        Contexts.back().FirstStartOfName = &Current;
        Current.setType(TT_StartOfName);
      } else if (Current.is(tok::semi)) {
        // Reset FirstStartOfName after finding a semicolon so that a for loop
        // with multiple increment statements is not confused with a for loop
        // having multiple variable declarations.
        Contexts.back().FirstStartOfName = nullptr;
      } else if (Current.isOneOf(tok::kw_auto, tok::kw___auto_type)) {
        AutoFound = true;
      } else if (Current.is(tok::arrow) &&
                 Style.Language == FormatStyle::LK_Java) {
        Current.setType(TT_LambdaArrow);
      } else if (Current.is(tok::arrow) && AutoFound && Line.MustBeDeclaration &&
                 Current.NestingLevel == 0 &&
                 !Current.Previous->is(tok::kw_operator)) {
        // not auto operator->() -> xxx;
        Current.setType(TT_TrailingReturnArrow);
      } else if (Current.is(tok::arrow) && Current.Previous &&
                 Current.Previous->is(tok::r_brace)) {
        // Concept implicit conversion contraint needs to be treated like
        // a trailing return type  ... } -> <type>.
        Current.setType(TT_TrailingReturnArrow);
      } else if (isDeductionGuide(Current)) {
        // Deduction guides trailing arrow " A(...) -> A<T>;".
        Current.setType(TT_TrailingReturnArrow);
      } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
        Current.setType(determineStarAmpUsage(
            Current,
            Contexts.back().CanBeExpression && Contexts.back().IsExpression,
            Contexts.back().InTemplateArgument));
      } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
        Current.setType(determinePlusMinusCaretUsage(Current));
        if (Current.is(TT_UnaryOperator) && Current.is(tok::caret))
          Contexts.back().CaretFound = true;
      } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {
        Current.setType(determineIncrementUsage(Current));
      } else if (Current.isOneOf(tok::exclaim, tok::tilde)) {
        Current.setType(TT_UnaryOperator);
      } else if (Current.is(tok::question)) {
        if (Style.Language == FormatStyle::LK_JavaScript &&
            Line.MustBeDeclaration && !Contexts.back().IsExpression) {
          // In JavaScript, `interface X { foo?(): bar; }` is an optional method
          // on the interface, not a ternary expression.
          Current.setType(TT_JsTypeOptionalQuestion);
        } else {
          Current.setType(TT_ConditionalExpr);
        }
      } else if (Current.isBinaryOperator() &&
                 (!Current.Previous || Current.Previous->isNot(tok::l_square)) &&
                 (!Current.is(tok::greater) &&
                  Style.Language != FormatStyle::LK_TextProto)) {
        Current.setType(TT_BinaryOperator);
      } else if (Current.is(tok::comment)) {
        if (Current.TokenText.startswith("/*")) {
          if (Current.TokenText.endswith("*/"))
            Current.setType(TT_BlockComment);
          else
            // The lexer has for some reason determined a comment here. But we
            // cannot really handle it, if it isn't properly terminated.
            Current.Tok.setKind(tok::unknown);
        } else {
          Current.setType(TT_LineComment);
        }
      } else if (Current.is(tok::r_paren)) {
        if (rParenEndsCast(Current))
          Current.setType(TT_CastRParen);
        if (Current.MatchingParen && Current.Next &&
            !Current.Next->isBinaryOperator() &&
            !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace,
                                   tok::comma, tok::period, tok::arrow,
                                   tok::coloncolon))
          if (FormatToken *AfterParen = Current.MatchingParen->Next) {
            // Make sure this isn't the return type of an Obj-C block declaration
            if (AfterParen->Tok.isNot(tok::caret)) {
              if (FormatToken *BeforeParen = Current.MatchingParen->Previous)
                if (BeforeParen->is(tok::identifier) &&
                    !BeforeParen->is(TT_TypenameMacro) &&
                    BeforeParen->TokenText == BeforeParen->TokenText.upper() &&
                    (!BeforeParen->Previous ||
                     BeforeParen->Previous->ClosesTemplateDeclaration))
                  Current.setType(TT_FunctionAnnotationRParen);
            }
          }
      } else if (Current.is(tok::at) && Current.Next &&
                 Style.Language != FormatStyle::LK_JavaScript &&
                 Style.Language != FormatStyle::LK_Java) {
        // In Java & JavaScript, "@..." is a decorator or annotation. In ObjC, it
        // marks declarations and properties that need special formatting.
        switch (Current.Next->Tok.getObjCKeywordID()) {
        case tok::objc_interface:
        case tok::objc_implementation:
        case tok::objc_protocol:
          Current.setType(TT_ObjCDecl);
          break;
        case tok::objc_property:
          Current.setType(TT_ObjCProperty);
          break;
        default:
          break;
        }
      } else if (Current.is(tok::period)) {
        FormatToken *PreviousNoComment = Current.getPreviousNonComment();
        if (PreviousNoComment &&
            PreviousNoComment->isOneOf(tok::comma, tok::l_brace))
          Current.setType(TT_DesignatedInitializerPeriod);
        else if (Style.Language == FormatStyle::LK_Java && Current.Previous &&
                 Current.Previous->isOneOf(TT_JavaAnnotation,
                                           TT_LeadingJavaAnnotation)) {
          Current.setType(Current.Previous->getType());
        }
      } else if (canBeObjCSelectorComponent(Current) &&
                 // FIXME(bug 36976): ObjC return types shouldn't use
                 // TT_CastRParen.
                 Current.Previous && Current.Previous->is(TT_CastRParen) &&
                 Current.Previous->MatchingParen &&
                 Current.Previous->MatchingParen->Previous &&
                 Current.Previous->MatchingParen->Previous->is(
                     TT_ObjCMethodSpecifier)) {
        // This is the first part of an Objective-C selector name. (If there's no
        // colon after this, this is the only place which annotates the identifier
        // as a selector.)
        Current.setType(TT_SelectorName);
      } else if (Current.isOneOf(tok::identifier, tok::kw_const, tok::kw_noexcept,
                                 tok::kw_requires) &&
                 Current.Previous &&
                 !Current.Previous->isOneOf(tok::equal, tok::at) &&
                 Line.MightBeFunctionDecl && Contexts.size() == 1) {
        // Line.MightBeFunctionDecl can only be true after the parentheses of a
        // function declaration have been found.
        Current.setType(TT_TrailingAnnotation);
      } else if ((Style.Language == FormatStyle::LK_Java ||
                  Style.Language == FormatStyle::LK_JavaScript) &&
                 Current.Previous) {
        if (Current.Previous->is(tok::at) &&
            Current.isNot(Keywords.kw_interface)) {
          const FormatToken &AtToken = *Current.Previous;
          const FormatToken *Previous = AtToken.getPreviousNonComment();
          if (!Previous || Previous->is(TT_LeadingJavaAnnotation))
            Current.setType(TT_LeadingJavaAnnotation);
          else
            Current.setType(TT_JavaAnnotation);
        } else if (Current.Previous->is(tok::period) &&
                   Current.Previous->isOneOf(TT_JavaAnnotation,
                                             TT_LeadingJavaAnnotation)) {
          Current.setType(Current.Previous->getType());
        }
      }
    }
  
    /// Take a guess at whether \p Tok starts a name of a function or
    /// variable declaration.
    ///
    /// This is a heuristic based on whether \p Tok is an identifier following
    /// something that is likely a type.
    bool isStartOfName(const FormatToken &Tok) {
      if (Tok.isNot(tok::identifier) || !Tok.Previous)
        return false;
  
      if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof,
                                Keywords.kw_as))
        return false;
      if (Style.Language == FormatStyle::LK_JavaScript &&
          Tok.Previous->is(Keywords.kw_in))
        return false;
  
      // Skip "const" as it does not have an influence on whether this is a name.
      FormatToken *PreviousNotConst = Tok.getPreviousNonComment();
      while (PreviousNotConst && PreviousNotConst->is(tok::kw_const))
        PreviousNotConst = PreviousNotConst->getPreviousNonComment();
  
      if (!PreviousNotConst)
        return false;
  
      bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&
                         PreviousNotConst->Previous &&
                         PreviousNotConst->Previous->is(tok::hash);
  
      if (PreviousNotConst->is(TT_TemplateCloser))
        return PreviousNotConst && PreviousNotConst->MatchingParen &&
               PreviousNotConst->MatchingParen->Previous &&
               PreviousNotConst->MatchingParen->Previous->isNot(tok::period) &&
               PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
  
      if (PreviousNotConst->is(tok::r_paren) &&
          PreviousNotConst->is(TT_TypeDeclarationParen))
        return true;
  
      return (!IsPPKeyword &&
              PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto)) ||
             PreviousNotConst->is(TT_PointerOrReference) ||
             PreviousNotConst->isSimpleTypeSpecifier();
    }
  
    /// Determine whether ')' is ending a cast.
    bool rParenEndsCast(const FormatToken &Tok) {
      // C-style casts are only used in C++, C# and Java.
      if (!Style.isCSharp() && !Style.isCpp() &&
          Style.Language != FormatStyle::LK_Java)
        return false;
  
      // Empty parens aren't casts and there are no casts at the end of the line.
      if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen)
        return false;
  
      FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
      if (LeftOfParens) {
        // If there is a closing parenthesis left of the current parentheses,
        // look past it as these might be chained casts.
        if (LeftOfParens->is(tok::r_paren)) {
          if (!LeftOfParens->MatchingParen ||
              !LeftOfParens->MatchingParen->Previous)
            return false;
          LeftOfParens = LeftOfParens->MatchingParen->Previous;
        }
  
        // If there is an identifier (or with a few exceptions a keyword) right
        // before the parentheses, this is unlikely to be a cast.
        if (LeftOfParens->Tok.getIdentifierInfo() &&
            !LeftOfParens->isOneOf(Keywords.kw_in, tok::kw_return, tok::kw_case,
                                   tok::kw_delete))
          return false;
  
        // Certain other tokens right before the parentheses are also signals that
        // this cannot be a cast.
        if (LeftOfParens->isOneOf(tok::at, tok::r_square, TT_OverloadedOperator,
                                  TT_TemplateCloser, tok::ellipsis))
          return false;
      }
  
      if (Tok.Next->is(tok::question))
        return false;
  
      // `foreach((A a, B b) in someList)` should not be seen as a cast.
      if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp())
        return false;
  
      // Functions which end with decorations like volatile, noexcept are unlikely
      // to be casts.
      if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
                            tok::kw_requires, tok::kw_throw, tok::arrow,
                            Keywords.kw_override, Keywords.kw_final) ||
          isCpp11AttributeSpecifier(*Tok.Next))
        return false;
  
      // As Java has no function types, a "(" after the ")" likely means that this
      // is a cast.
      if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren))
        return true;
  
      // If a (non-string) literal follows, this is likely a cast.
      if (Tok.Next->isNot(tok::string_literal) &&
          (Tok.Next->Tok.isLiteral() ||
           Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
        return true;
  
      // Heuristically try to determine whether the parentheses contain a type.
      auto IsQualifiedPointerOrReference = [](FormatToken *T) {
        // This is used to handle cases such as x = (foo *const)&y;
        assert(!T->isSimpleTypeSpecifier() && "Should have already been checked");
        // Strip trailing qualifiers such as const or volatile when checking
        // whether the parens could be a cast to a pointer/reference type.
        while (T) {
          if (T->is(TT_AttributeParen)) {
            // Handle `x = (foo *__attribute__((foo)))&v;`:
            if (T->MatchingParen && T->MatchingParen->Previous &&
                T->MatchingParen->Previous->is(tok::kw___attribute)) {
              T = T->MatchingParen->Previous->Previous;
              continue;
            }
          } else if (T->is(TT_AttributeSquare)) {
            // Handle `x = (foo *[[clang::foo]])&v;`:
            if (T->MatchingParen && T->MatchingParen->Previous) {
              T = T->MatchingParen->Previous;
              continue;
            }
          } else if (T->canBePointerOrReferenceQualifier()) {
            T = T->Previous;
            continue;
          }
          break;
        }
        return T && T->is(TT_PointerOrReference);
      };
      bool ParensAreType =
          !Tok.Previous ||
          Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
          Tok.Previous->isSimpleTypeSpecifier() ||
          IsQualifiedPointerOrReference(Tok.Previous);
      bool ParensCouldEndDecl =
          Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
      if (ParensAreType && !ParensCouldEndDecl)
        return true;
  
      // At this point, we heuristically assume that there are no casts at the
      // start of the line. We assume that we have found most cases where there
      // are by the logic above, e.g. "(void)x;".
      if (!LeftOfParens)
        return false;
  
      // Certain token types inside the parentheses mean that this can't be a
      // cast.
      for (const FormatToken *Token = Tok.MatchingParen->Next; Token != &Tok;
           Token = Token->Next)
        if (Token->is(TT_BinaryOperator))
          return false;
  
      // If the following token is an identifier or 'this', this is a cast. All
      // cases where this can be something else are handled above.
      if (Tok.Next->isOneOf(tok::identifier, tok::kw_this))
        return true;
  
      // Look for a cast `( x ) (`.
      if (Tok.Next->is(tok::l_paren) && Tok.Previous && Tok.Previous->Previous) {
        if (Tok.Previous->is(tok::identifier) &&
            Tok.Previous->Previous->is(tok::l_paren))
          return true;
      }
  
      if (!Tok.Next->Next)
        return false;
  
      // If the next token after the parenthesis is a unary operator, assume
      // that this is cast, unless there are unexpected tokens inside the
      // parenthesis.
      bool NextIsUnary =
          Tok.Next->isUnaryOperator() || Tok.Next->isOneOf(tok::amp, tok::star);
      if (!NextIsUnary || Tok.Next->is(tok::plus) ||
          !Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant))
        return false;
      // Search for unexpected tokens.
      for (FormatToken *Prev = Tok.Previous; Prev != Tok.MatchingParen;
           Prev = Prev->Previous) {
        if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon))
          return false;
      }
      return true;
    }
  
    /// Return the type of the given token assuming it is * or &.
    TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression,
                                    bool InTemplateArgument) {
      if (Style.Language == FormatStyle::LK_JavaScript)
        return TT_BinaryOperator;
  
      // && in C# must be a binary operator.
      if (Style.isCSharp() && Tok.is(tok::ampamp))
        return TT_BinaryOperator;
  
      const FormatToken *PrevToken = Tok.getPreviousNonComment();
      if (!PrevToken)
        return TT_UnaryOperator;
  
      const FormatToken *NextToken = Tok.getNextNonComment();
      if (!NextToken ||
          NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_noexcept) ||
          NextToken->canBePointerOrReferenceQualifier() ||
          (NextToken->is(tok::l_brace) && !NextToken->getNextNonComment()))
        return TT_PointerOrReference;
  
      if (PrevToken->is(tok::coloncolon))
        return TT_PointerOrReference;
  
      if (PrevToken->is(tok::r_paren) && PrevToken->is(TT_TypeDeclarationParen))
        return TT_PointerOrReference;
  
      if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace,
                             tok::comma, tok::semi, tok::kw_return, tok::colon,
                             tok::kw_co_return, tok::kw_co_await,
                             tok::kw_co_yield, tok::equal, tok::kw_delete,
                             tok::kw_sizeof, tok::kw_throw) ||
          PrevToken->isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
                             TT_UnaryOperator, TT_CastRParen))
        return TT_UnaryOperator;
  
      if (NextToken->is(tok::l_square) && NextToken->isNot(TT_LambdaLSquare))
        return TT_PointerOrReference;
      if (NextToken->is(tok::kw_operator) && !IsExpression)
        return TT_PointerOrReference;
      if (NextToken->isOneOf(tok::comma, tok::semi))
        return TT_PointerOrReference;
  
      if (PrevToken->Tok.isLiteral() ||
          PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
                             tok::kw_false, tok::r_brace) ||
          NextToken->Tok.isLiteral() ||
          NextToken->isOneOf(tok::kw_true, tok::kw_false) ||
          NextToken->isUnaryOperator() ||
          // If we know we're in a template argument, there are no named
          // declarations. Thus, having an identifier on the right-hand side
          // indicates a binary operator.
          (InTemplateArgument && NextToken->Tok.isAnyIdentifier()))
        return TT_BinaryOperator;
  
      // "&&(" is quite unlikely to be two successive unary "&".
      if (Tok.is(tok::ampamp) && NextToken->is(tok::l_paren))
        return TT_BinaryOperator;
  
      // This catches some cases where evaluation order is used as control flow:
      //   aaa && aaa->f();
      if (NextToken->Tok.isAnyIdentifier()) {
        const FormatToken *NextNextToken = NextToken->getNextNonComment();
        if (NextNextToken && NextNextToken->is(tok::arrow))
          return TT_BinaryOperator;
      }
  
      // It is very unlikely that we are going to find a pointer or reference type
      // definition on the RHS of an assignment.
      if (IsExpression && !Contexts.back().CaretFound)
        return TT_BinaryOperator;
  
      return TT_PointerOrReference;
    }
  
    TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
      const FormatToken *PrevToken = Tok.getPreviousNonComment();
      if (!PrevToken)
        return TT_UnaryOperator;
  
      if (PrevToken->isOneOf(TT_CastRParen, TT_UnaryOperator))
        // This must be a sequence of leading unary operators.
        return TT_UnaryOperator;
  
      // Use heuristics to recognize unary operators.
      if (PrevToken->isOneOf(tok::equal, tok::l_paren, tok::comma, tok::l_square,
                             tok::question, tok::colon, tok::kw_return,
                             tok::kw_case, tok::at, tok::l_brace, tok::kw_throw,
                             tok::kw_co_return, tok::kw_co_yield))
        return TT_UnaryOperator;
  
      // There can't be two consecutive binary operators.
      if (PrevToken->is(TT_BinaryOperator))
        return TT_UnaryOperator;
  
      // Fall back to marking the token as binary operator.
      return TT_BinaryOperator;
    }
  
    /// Determine whether ++/-- are pre- or post-increments/-decrements.
    TokenType determineIncrementUsage(const FormatToken &Tok) {
      const FormatToken *PrevToken = Tok.getPreviousNonComment();
      if (!PrevToken || PrevToken->is(TT_CastRParen))
        return TT_UnaryOperator;
      if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))
        return TT_TrailingUnaryOperator;
  
      return TT_UnaryOperator;
    }
  
    SmallVector<Context, 8> Contexts;
  
    const FormatStyle &Style;
    AnnotatedLine &Line;
    FormatToken *CurrentToken;
    bool AutoFound;
    const AdditionalKeywords &Keywords;
  
    // Set of "<" tokens that do not open a template parameter list. If parseAngle
    // determines that a specific token can't be a template opener, it will make
    // same decision irrespective of the decisions for tokens leading up to it.
    // Store this information to prevent this from causing exponential runtime.
    llvm::SmallPtrSet<FormatToken *, 16> NonTemplateLess;
  };
  
  static const int PrecedenceUnaryOperator = prec::PointerToMember + 1;
  static const int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
  
  /// Parses binary expressions by inserting fake parenthesis based on
  /// operator precedence.
  class ExpressionParser {
  public:
    ExpressionParser(const FormatStyle &Style, const AdditionalKeywords &Keywords,
                     AnnotatedLine &Line)
        : Style(Style), Keywords(Keywords), Current(Line.First) {}
  
    /// Parse expressions with the given operator precedence.
    void parse(int Precedence = 0) {
      // Skip 'return' and ObjC selector colons as they are not part of a binary
      // expression.
      while (Current && (Current->is(tok::kw_return) ||
                         (Current->is(tok::colon) &&
                          Current->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral))))
        next();
  
      if (!Current || Precedence > PrecedenceArrowAndPeriod)
        return;
  
      // Conditional expressions need to be parsed separately for proper nesting.
      if (Precedence == prec::Conditional) {
        parseConditionalExpr();
        return;
      }
  
      // Parse unary operators, which all have a higher precedence than binary
      // operators.
      if (Precedence == PrecedenceUnaryOperator) {
        parseUnaryOperator();
        return;
      }
  
      FormatToken *Start = Current;
      FormatToken *LatestOperator = nullptr;
      unsigned OperatorIndex = 0;
  
      while (Current) {
        // Consume operators with higher precedence.
        parse(Precedence + 1);
  
        int CurrentPrecedence = getCurrentPrecedence();
  
        if (Current && Current->is(TT_SelectorName) &&
            Precedence == CurrentPrecedence) {
          if (LatestOperator)
            addFakeParenthesis(Start, prec::Level(Precedence));
          Start = Current;
        }
  
        // At the end of the line or when an operator with higher precedence is
        // found, insert fake parenthesis and return.
        if (!Current ||
            (Current->closesScope() &&
             (Current->MatchingParen || Current->is(TT_TemplateString))) ||
            (CurrentPrecedence != -1 && CurrentPrecedence < Precedence) ||
            (CurrentPrecedence == prec::Conditional &&
             Precedence == prec::Assignment && Current->is(tok::colon))) {
          break;
        }
  
        // Consume scopes: (), [], <> and {}
        if (Current->opensScope()) {
          // In fragment of a JavaScript template string can look like '}..${' and
          // thus close a scope and open a new one at the same time.
          while (Current && (!Current->closesScope() || Current->opensScope())) {
            next();
            parse();
          }
          next();
        } else {
          // Operator found.
          if (CurrentPrecedence == Precedence) {
            if (LatestOperator)
              LatestOperator->NextOperator = Current;
            LatestOperator = Current;
            Current->OperatorIndex = OperatorIndex;
            ++OperatorIndex;
          }
          next(/*SkipPastLeadingComments=*/Precedence > 0);
        }
      }
  
      if (LatestOperator && (Current || Precedence > 0)) {
        // LatestOperator->LastOperator = true;
        if (Precedence == PrecedenceArrowAndPeriod) {
          // Call expressions don't have a binary operator precedence.
          addFakeParenthesis(Start, prec::Unknown);
        } else {
          addFakeParenthesis(Start, prec::Level(Precedence));
        }
      }
    }
  
  private:
    /// Gets the precedence (+1) of the given token for binary operators
    /// and other tokens that we treat like binary operators.
    int getCurrentPrecedence() {
      if (Current) {
        const FormatToken *NextNonComment = Current->getNextNonComment();
        if (Current->is(TT_ConditionalExpr))
          return prec::Conditional;
        if (NextNonComment && Current->is(TT_SelectorName) &&
            (NextNonComment->isOneOf(TT_DictLiteral, TT_JsTypeColon) ||
             ((Style.Language == FormatStyle::LK_Proto ||
               Style.Language == FormatStyle::LK_TextProto) &&
              NextNonComment->is(tok::less))))
          return prec::Assignment;
        if (Current->is(TT_JsComputedPropertyName))
          return prec::Assignment;
        if (Current->is(TT_LambdaArrow))
          return prec::Comma;
        if (Current->is(TT_JsFatArrow))
          return prec::Assignment;
        if (Current->isOneOf(tok::semi, TT_InlineASMColon, TT_SelectorName) ||
            (Current->is(tok::comment) && NextNonComment &&
             NextNonComment->is(TT_SelectorName)))
          return 0;
        if (Current->is(TT_RangeBasedForLoopColon))
          return prec::Comma;
        if ((Style.Language == FormatStyle::LK_Java ||
             Style.Language == FormatStyle::LK_JavaScript) &&
            Current->is(Keywords.kw_instanceof))
          return prec::Relational;
        if (Style.Language == FormatStyle::LK_JavaScript &&
            Current->isOneOf(Keywords.kw_in, Keywords.kw_as))
          return prec::Relational;
        if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))
          return Current->getPrecedence();
        if (Current->isOneOf(tok::period, tok::arrow))
          return PrecedenceArrowAndPeriod;
        if ((Style.Language == FormatStyle::LK_Java ||
             Style.Language == FormatStyle::LK_JavaScript) &&
            Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,
                             Keywords.kw_throws))
          return 0;
      }
      return -1;
    }
  
    void addFakeParenthesis(FormatToken *Start, prec::Level Precedence) {
      Start->FakeLParens.push_back(Precedence);
      if (Precedence > prec::Unknown)
        Start->StartsBinaryExpression = true;
      if (Current) {
        FormatToken *Previous = Current->Previous;
        while (Previous->is(tok::comment) && Previous->Previous)
          Previous = Previous->Previous;
        ++Previous->FakeRParens;
        if (Precedence > prec::Unknown)
          Previous->EndsBinaryExpression = true;
      }
    }
  
    /// Parse unary operator expressions and surround them with fake
    /// parentheses if appropriate.
    void parseUnaryOperator() {
      llvm::SmallVector<FormatToken *, 2> Tokens;
      while (Current && Current->is(TT_UnaryOperator)) {
        Tokens.push_back(Current);
        next();
      }
      parse(PrecedenceArrowAndPeriod);
      for (FormatToken *Token : llvm::reverse(Tokens))
        // The actual precedence doesn't matter.
        addFakeParenthesis(Token, prec::Unknown);
    }
  
    void parseConditionalExpr() {
      while (Current && Current->isTrailingComment()) {
        next();
      }
      FormatToken *Start = Current;
      parse(prec::LogicalOr);
      if (!Current || !Current->is(tok::question))
        return;
      next();
      parse(prec::Assignment);
      if (!Current || Current->isNot(TT_ConditionalExpr))
        return;
      next();
      parse(prec::Assignment);
      addFakeParenthesis(Start, prec::Conditional);
    }
  
    void next(bool SkipPastLeadingComments = true) {
      if (Current)
        Current = Current->Next;
      while (Current &&
             (Current->NewlinesBefore == 0 || SkipPastLeadingComments) &&
             Current->isTrailingComment())
        Current = Current->Next;
    }
  
    const FormatStyle &Style;
    const AdditionalKeywords &Keywords;
    FormatToken *Current;
  };
  
  } // end anonymous namespace
  
  void TokenAnnotator::setCommentLineLevels(
      SmallVectorImpl<AnnotatedLine *> &Lines) {
    const AnnotatedLine *NextNonCommentLine = nullptr;
    for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(),
                                                            E = Lines.rend();
         I != E; ++I) {
      bool CommentLine = true;
      for (const FormatToken *Tok = (*I)->First; Tok; Tok = Tok->Next) {
        if (!Tok->is(tok::comment)) {
          CommentLine = false;
          break;
        }
      }
  
      // If the comment is currently aligned with the line immediately following
      // it, that's probably intentional and we should keep it.
      if (NextNonCommentLine && CommentLine &&
          NextNonCommentLine->First->NewlinesBefore <= 1 &&
          NextNonCommentLine->First->OriginalColumn ==
              (*I)->First->OriginalColumn) {
        // Align comments for preprocessor lines with the # in column 0 if
        // preprocessor lines are not indented. Otherwise, align with the next
        // line.
        (*I)->Level =
            (Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
             (NextNonCommentLine->Type == LT_PreprocessorDirective ||
              NextNonCommentLine->Type == LT_ImportStatement))
                ? 0
                : NextNonCommentLine->Level;
      } else {
        NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : nullptr;
      }
  
      setCommentLineLevels((*I)->Children);
    }
  }
  
  static unsigned maxNestingDepth(const AnnotatedLine &Line) {
    unsigned Result = 0;
    for (const auto *Tok = Line.First; Tok != nullptr; Tok = Tok->Next)
      Result = std::max(Result, Tok->NestingLevel);
    return Result;
  }
  
  void TokenAnnotator::annotate(AnnotatedLine &Line) {
    for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
                                                    E = Line.Children.end();
         I != E; ++I) {
      annotate(**I);
    }
    AnnotatingParser Parser(Style, Line, Keywords);
    Line.Type = Parser.parseLine();
  
    // With very deep nesting, ExpressionParser uses lots of stack and the
    // formatting algorithm is very slow. We're not going to do a good job here
    // anyway - it's probably generated code being formatted by mistake.
    // Just skip the whole line.
    if (maxNestingDepth(Line) > 50)
      Line.Type = LT_Invalid;
  
    if (Line.Type == LT_Invalid)
      return;
  
    ExpressionParser ExprParser(Style, Keywords, Line);
    ExprParser.parse();
  
    if (Line.startsWith(TT_ObjCMethodSpecifier))
      Line.Type = LT_ObjCMethodDecl;
    else if (Line.startsWith(TT_ObjCDecl))
      Line.Type = LT_ObjCDecl;
    else if (Line.startsWith(TT_ObjCProperty))
      Line.Type = LT_ObjCProperty;
  
    Line.First->SpacesRequiredBefore = 1;
    Line.First->CanBreakBefore = Line.First->MustBreakBefore;
  }
  
  // This function heuristically determines whether 'Current' starts the name of a
  // function declaration.
  static bool isFunctionDeclarationName(const FormatToken &Current,
                                        const AnnotatedLine &Line) {
    auto skipOperatorName = [](const FormatToken *Next) -> const FormatToken * {
      for (; Next; Next = Next->Next) {
        if (Next->is(TT_OverloadedOperatorLParen))
          return Next;
        if (Next->is(TT_OverloadedOperator))
          continue;
        if (Next->isOneOf(tok::kw_new, tok::kw_delete)) {
          // For 'new[]' and 'delete[]'.
          if (Next->Next &&
              Next->Next->startsSequence(tok::l_square, tok::r_square))
            Next = Next->Next->Next;
          continue;
        }
        if (Next->startsSequence(tok::l_square, tok::r_square)) {
          // For operator[]().
          Next = Next->Next;
          continue;
        }
        if ((Next->isSimpleTypeSpecifier() || Next->is(tok::identifier)) &&
            Next->Next && Next->Next->isOneOf(tok::star, tok::amp, tok::ampamp)) {
          // For operator void*(), operator char*(), operator Foo*().
          Next = Next->Next;
          continue;
        }
        if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {
          Next = Next->MatchingParen;
          continue;
        }
  
        break;
      }
      return nullptr;
    };
  
    // Find parentheses of parameter list.
    const FormatToken *Next = Current.Next;
    if (Current.is(tok::kw_operator)) {
      if (Current.Previous && Current.Previous->is(tok::coloncolon))
        return false;
      Next = skipOperatorName(Next);
    } else {
      if (!Current.is(TT_StartOfName) || Current.NestingLevel != 0)
        return false;
      for (; Next; Next = Next->Next) {
        if (Next->is(TT_TemplateOpener)) {
          Next = Next->MatchingParen;
        } else if (Next->is(tok::coloncolon)) {
          Next = Next->Next;
          if (!Next)
            return false;
          if (Next->is(tok::kw_operator)) {
            Next = skipOperatorName(Next->Next);
            break;
          }
          if (!Next->is(tok::identifier))
            return false;
        } else if (Next->is(tok::l_paren)) {
          break;
        } else {
          return false;
        }
      }
    }
  
    // Check whether parameter list can belong to a function declaration.
    if (!Next || !Next->is(tok::l_paren) || !Next->MatchingParen)
      return false;
    // If the lines ends with "{", this is likely an function definition.
    if (Line.Last->is(tok::l_brace))
      return true;
    if (Next->Next == Next->MatchingParen)
      return true; // Empty parentheses.
    // If there is an &/&& after the r_paren, this is likely a function.
    if (Next->MatchingParen->Next &&
        Next->MatchingParen->Next->is(TT_PointerOrReference))
      return true;
    for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen;
         Tok = Tok->Next) {
      if (Tok->is(TT_TypeDeclarationParen))
        return true;
      if (Tok->isOneOf(tok::l_paren, TT_TemplateOpener) && Tok->MatchingParen) {
        Tok = Tok->MatchingParen;
        continue;
      }
      if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() ||
          Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis))
        return true;
      if (Tok->isOneOf(tok::l_brace, tok::string_literal, TT_ObjCMethodExpr) ||
          Tok->Tok.isLiteral())
        return false;
    }
    return false;
  }
  
  bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {
    assert(Line.MightBeFunctionDecl);
  
    if ((Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_TopLevel ||
         Style.AlwaysBreakAfterReturnType ==
             FormatStyle::RTBS_TopLevelDefinitions) &&
        Line.Level > 0)
      return false;
  
    switch (Style.AlwaysBreakAfterReturnType) {
    case FormatStyle::RTBS_None:
      return false;
    case FormatStyle::RTBS_All:
    case FormatStyle::RTBS_TopLevel:
      return true;
    case FormatStyle::RTBS_AllDefinitions:
    case FormatStyle::RTBS_TopLevelDefinitions:
      return Line.mightBeFunctionDefinition();
    }
  
    return false;
  }
  
  void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
    for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
                                                    E = Line.Children.end();
         I != E; ++I) {
      calculateFormattingInformation(**I);
    }
  
    Line.First->TotalLength =
        Line.First->IsMultiline ? Style.ColumnLimit
                                : Line.FirstStartColumn + Line.First->ColumnWidth;
    FormatToken *Current = Line.First->Next;
    bool InFunctionDecl = Line.MightBeFunctionDecl;
    while (Current) {
      if (isFunctionDeclarationName(*Current, Line))
        Current->setType(TT_FunctionDeclarationName);
      if (Current->is(TT_LineComment)) {
        if (Current->Previous->is(BK_BracedInit) &&
            Current->Previous->opensScope())
          Current->SpacesRequiredBefore =
              (Style.Cpp11BracedListStyle && !Style.SpacesInParentheses) ? 0 : 1;
        else
          Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;
  
        // If we find a trailing comment, iterate backwards to determine whether
        // it seems to relate to a specific parameter. If so, break before that
        // parameter to avoid changing the comment's meaning. E.g. don't move 'b'
        // to the previous line in:
        //   SomeFunction(a,
        //                b, // comment
        //                c);
        if (!Current->HasUnescapedNewline) {
          for (FormatToken *Parameter = Current->Previous; Parameter;
               Parameter = Parameter->Previous) {
            if (Parameter->isOneOf(tok::comment, tok::r_brace))
              break;
            if (Parameter->Previous && Parameter->Previous->is(tok::comma)) {
              if (!Parameter->Previous->is(TT_CtorInitializerComma) &&
                  Parameter->HasUnescapedNewline)
                Parameter->MustBreakBefore = true;
              break;
            }
          }
        }
      } else if (Current->SpacesRequiredBefore == 0 &&
                 spaceRequiredBefore(Line, *Current)) {
        Current->SpacesRequiredBefore = 1;
      }
  
      Current->MustBreakBefore =
          Current->MustBreakBefore || mustBreakBefore(Line, *Current);
  
      if (!Current->MustBreakBefore && InFunctionDecl &&
          Current->is(TT_FunctionDeclarationName))
        Current->MustBreakBefore = mustBreakForReturnType(Line);
  
      Current->CanBreakBefore =
          Current->MustBreakBefore || canBreakBefore(Line, *Current);
      unsigned ChildSize = 0;
      if (Current->Previous->Children.size() == 1) {
        FormatToken &LastOfChild = *Current->Previous->Children[0]->Last;
        ChildSize = LastOfChild.isTrailingComment() ? Style.ColumnLimit
                                                    : LastOfChild.TotalLength + 1;
      }
      const FormatToken *Prev = Current->Previous;
      if (Current->MustBreakBefore || Prev->Children.size() > 1 ||
          (Prev->Children.size() == 1 &&
           Prev->Children[0]->First->MustBreakBefore) ||
          Current->IsMultiline)
        Current->TotalLength = Prev->TotalLength + Style.ColumnLimit;
      else
        Current->TotalLength = Prev->TotalLength + Current->ColumnWidth +
                               ChildSize + Current->SpacesRequiredBefore;
  
      if (Current->is(TT_CtorInitializerColon))
        InFunctionDecl = false;
  
      // FIXME: Only calculate this if CanBreakBefore is true once static
      // initializers etc. are sorted out.
      // FIXME: Move magic numbers to a better place.
  
      // Reduce penalty for aligning ObjC method arguments using the colon
      // alignment as this is the canonical way (still prefer fitting everything
      // into one line if possible). Trying to fit a whole expression into one
      // line should not force other line breaks (e.g. when ObjC method
      // expression is a part of other expression).
      Current->SplitPenalty = splitPenalty(Line, *Current, InFunctionDecl);
      if (Style.Language == FormatStyle::LK_ObjC &&
          Current->is(TT_SelectorName) && Current->ParameterIndex > 0) {
        if (Current->ParameterIndex == 1)
          Current->SplitPenalty += 5 * Current->BindingStrength;
      } else {
        Current->SplitPenalty += 20 * Current->BindingStrength;
      }
  
      Current = Current->Next;
    }
  
    calculateUnbreakableTailLengths(Line);
    unsigned IndentLevel = Line.Level;
    for (Current = Line.First; Current != nullptr; Current = Current->Next) {
      if (Current->Role)
        Current->Role->precomputeFormattingInfos(Current);
      if (Current->MatchingParen &&
          Current->MatchingParen->opensBlockOrBlockTypeList(Style)) {
        assert(IndentLevel > 0);
        --IndentLevel;
      }
      Current->IndentLevel = IndentLevel;
      if (Current->opensBlockOrBlockTypeList(Style))
        ++IndentLevel;
    }
  
    LLVM_DEBUG({ printDebugInfo(Line); });
  }
  
  void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
    unsigned UnbreakableTailLength = 0;
    FormatToken *Current = Line.Last;
    while (Current) {
      Current->UnbreakableTailLength = UnbreakableTailLength;
      if (Current->CanBreakBefore ||
          Current->isOneOf(tok::comment, tok::string_literal)) {
        UnbreakableTailLength = 0;
      } else {
        UnbreakableTailLength +=
            Current->ColumnWidth + Current->SpacesRequiredBefore;
      }
      Current = Current->Previous;
    }
  }
  
  unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
                                        const FormatToken &Tok,
                                        bool InFunctionDecl) {
    const FormatToken &Left = *Tok.Previous;
    const FormatToken &Right = Tok;
  
    if (Left.is(tok::semi))
      return 0;
  
    if (Style.Language == FormatStyle::LK_Java) {
      if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_throws))
        return 1;
      if (Right.is(Keywords.kw_implements))
        return 2;
      if (Left.is(tok::comma) && Left.NestingLevel == 0)
        return 3;
    } else if (Style.Language == FormatStyle::LK_JavaScript) {
      if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma))
        return 100;
      if (Left.is(TT_JsTypeColon))
        return 35;
      if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
          (Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
        return 100;
      // Prefer breaking call chains (".foo") over empty "{}", "[]" or "()".
      if (Left.opensScope() && Right.closesScope())
        return 200;
    }
  
    if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
      return 1;
    if (Right.is(tok::l_square)) {
      if (Style.Language == FormatStyle::LK_Proto)
        return 1;
      if (Left.is(tok::r_square))
        return 200;
      // Slightly prefer formatting local lambda definitions like functions.
      if (Right.is(TT_LambdaLSquare) && Left.is(tok::equal))
        return 35;
      if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
                         TT_ArrayInitializerLSquare,
                         TT_DesignatedInitializerLSquare, TT_AttributeSquare))
        return 500;
    }
  
    if (Left.is(tok::coloncolon) ||
        (Right.is(tok::period) && Style.Language == FormatStyle::LK_Proto))
      return 500;
    if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
        Right.is(tok::kw_operator)) {
      if (Line.startsWith(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
        return 3;
      if (Left.is(TT_StartOfName))
        return 110;
      if (InFunctionDecl && Right.NestingLevel == 0)
        return Style.PenaltyReturnTypeOnItsOwnLine;
      return 200;
    }
    if (Right.is(TT_PointerOrReference))
      return 190;
    if (Right.is(TT_LambdaArrow))
      return 110;
    if (Left.is(tok::equal) && Right.is(tok::l_brace))
      return 160;
    if (Left.is(TT_CastRParen))
      return 100;
    if (Left.isOneOf(tok::kw_class, tok::kw_struct))
      return 5000;
    if (Left.is(tok::comment))
      return 1000;
  
    if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon,
                     TT_CtorInitializerColon))
      return 2;
  
    if (Right.isMemberAccess()) {
      // Breaking before the "./->" of a chained call/member access is reasonably
      // cheap, as formatting those with one call per line is generally
      // desirable. In particular, it should be cheaper to break before the call
      // than it is to break inside a call's parameters, which could lead to weird
      // "hanging" indents. The exception is the very last "./->" to support this
      // frequent pattern:
      //
      //   aaaaaaaa.aaaaaaaa.bbbbbbb().ccccccccccccccccccccc(
      //       dddddddd);
      //
      // which might otherwise be blown up onto many lines. Here, clang-format
      // won't produce "hanging" indents anyway as there is no other trailing
      // call.
      //
      // Also apply higher penalty is not a call as that might lead to a wrapping
      // like:
      //
      //   aaaaaaa
      //       .aaaaaaaaa.bbbbbbbb(cccccccc);
      return !Right.NextOperator || !Right.NextOperator->Previous->closesScope()
                 ? 150
                 : 35;
    }
  
    if (Right.is(TT_TrailingAnnotation) &&
        (!Right.Next || Right.Next->isNot(tok::l_paren))) {
      // Moving trailing annotations to the next line is fine for ObjC method
      // declarations.
      if (Line.startsWith(TT_ObjCMethodSpecifier))
        return 10;
      // Generally, breaking before a trailing annotation is bad unless it is
      // function-like. It seems to be especially preferable to keep standard
      // annotations (i.e. "const", "final" and "override") on the same line.
      // Use a slightly higher penalty after ")" so that annotations like
      // "const override" are kept together.
      bool is_short_annotation = Right.TokenText.size() < 10;
      return (Left.is(tok::r_paren) ? 100 : 120) + (is_short_annotation ? 50 : 0);
    }
  
    // In for-loops, prefer breaking at ',' and ';'.
    if (Line.startsWith(tok::kw_for) && Left.is(tok::equal))
      return 4;
  
    // In Objective-C method expressions, prefer breaking before "param:" over
    // breaking after it.
    if (Right.is(TT_SelectorName))
      return 0;
    if (Left.is(tok::colon) && Left.is(TT_ObjCMethodExpr))
      return Line.MightBeFunctionDecl ? 50 : 500;
  
    // In Objective-C type declarations, avoid breaking after the category's
    // open paren (we'll prefer breaking after the protocol list's opening
    // angle bracket, if present).
    if (Line.Type == LT_ObjCDecl && Left.is(tok::l_paren) && Left.Previous &&
        Left.Previous->isOneOf(tok::identifier, tok::greater))
      return 500;
  
    if (Left.is(tok::l_paren) && InFunctionDecl &&
        Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign)
      return 100;
    if (Left.is(tok::l_paren) && Left.Previous &&
        (Left.Previous->is(tok::kw_for) || Left.Previous->isIf()))
      return 1000;
    if (Left.is(tok::equal) && InFunctionDecl)
      return 110;
    if (Right.is(tok::r_brace))
      return 1;
    if (Left.is(TT_TemplateOpener))
      return 100;
    if (Left.opensScope()) {
      // If we aren't aligning after opening parens/braces we can always break
      // here unless the style does not want us to place all arguments on the
      // next line.
      if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign &&
          (Left.ParameterCount <= 1 || Style.AllowAllArgumentsOnNextLine))
        return 0;
      if (Left.is(tok::l_brace) && !Style.Cpp11BracedListStyle)
        return 19;
      return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter
                                     : 19;
    }
    if (Left.is(TT_JavaAnnotation))
      return 50;
  
    if (Left.is(TT_UnaryOperator))
      return 60;
    if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous &&
        Left.Previous->isLabelString() &&
        (Left.NextOperator || Left.OperatorIndex != 0))
      return 50;
    if (Right.is(tok::plus) && Left.isLabelString() &&
        (Right.NextOperator || Right.OperatorIndex != 0))
      return 25;
    if (Left.is(tok::comma))
      return 1;
    if (Right.is(tok::lessless) && Left.isLabelString() &&
        (Right.NextOperator || Right.OperatorIndex != 1))
      return 25;
    if (Right.is(tok::lessless)) {
      // Breaking at a << is really cheap.
      if (!Left.is(tok::r_paren) || Right.OperatorIndex > 0)
        // Slightly prefer to break before the first one in log-like statements.
        return 2;
      return 1;
    }
    if (Left.ClosesTemplateDeclaration)
      return Style.PenaltyBreakTemplateDeclaration;
    if (Left.is(TT_ConditionalExpr))
      return prec::Conditional;
    prec::Level Level = Left.getPrecedence();
    if (Level == prec::Unknown)
      Level = Right.getPrecedence();
    if (Level == prec::Assignment)
      return Style.PenaltyBreakAssignment;
    if (Level != prec::Unknown)
      return Level;
  
    return 3;
  }
  
  bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const {
    return Style.SpaceBeforeParens == FormatStyle::SBPO_Always ||
           (Style.SpaceBeforeParens == FormatStyle::SBPO_NonEmptyParentheses &&
            Right.ParameterCount > 0);
  }
  
  bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
                                            const FormatToken &Left,
                                            const FormatToken &Right) {
    if (Left.is(tok::kw_return) && Right.isNot(tok::semi))
      return true;
    if (Left.is(Keywords.kw_assert) && Style.Language == FormatStyle::LK_Java)
      return true;
    if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty &&
        Left.Tok.getObjCKeywordID() == tok::objc_property)
      return true;
    if (Right.is(tok::hashhash))
      return Left.is(tok::hash);
    if (Left.isOneOf(tok::hashhash, tok::hash))
      return Right.is(tok::hash);
    if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||
        (Left.is(tok::l_brace) && Left.isNot(BK_Block) &&
         Right.is(tok::r_brace) && Right.isNot(BK_Block)))
      return Style.SpaceInEmptyParentheses;
    if (Style.SpacesInConditionalStatement) {
      if (Left.is(tok::l_paren) && Left.Previous &&
          isKeywordWithCondition(*Left.Previous))
        return true;
      if (Right.is(tok::r_paren) && Right.MatchingParen &&
          Right.MatchingParen->Previous &&
          isKeywordWithCondition(*Right.MatchingParen->Previous))
        return true;
    }
  
    // requires ( or requires(
    if (Right.is(tok::l_paren) && Left.is(tok::kw_requires))
      return spaceRequiredBeforeParens(Right);
    // requires clause Concept1<T> && Concept2<T>
    if (Left.is(TT_ConstraintJunctions) && Right.is(tok::identifier))
      return true;
  
    if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
      return (Right.is(TT_CastRParen) ||
              (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen)))
                 ? Style.SpacesInCStyleCastParentheses
                 : Style.SpacesInParentheses;
    if (Right.isOneOf(tok::semi, tok::comma))
      return false;
    if (Right.is(tok::less) && Line.Type == LT_ObjCDecl) {
      bool IsLightweightGeneric = Right.MatchingParen &&
                                  Right.MatchingParen->Next &&
                                  Right.MatchingParen->Next->is(tok::colon);
      return !IsLightweightGeneric && Style.ObjCSpaceBeforeProtocolList;
    }
    if (Right.is(tok::less) && Left.is(tok::kw_template))
      return Style.SpaceAfterTemplateKeyword;
    if (Left.isOneOf(tok::exclaim, tok::tilde))
      return false;
    if (Left.is(tok::at) &&
        Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant,
                      tok::numeric_constant, tok::l_paren, tok::l_brace,
                      tok::kw_true, tok::kw_false))
      return false;
    if (Left.is(tok::colon))
      return !Left.is(TT_ObjCMethodExpr);
    if (Left.is(tok::coloncolon))
      return false;
    if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) {
      if (Style.Language == FormatStyle::LK_TextProto ||
          (Style.Language == FormatStyle::LK_Proto &&
           (Left.is(TT_DictLiteral) || Right.is(TT_DictLiteral)))) {
        // Format empty list as `<>`.
        if (Left.is(tok::less) && Right.is(tok::greater))
          return false;
        return !Style.Cpp11BracedListStyle;
      }
      return false;
    }
    if (Right.is(tok::ellipsis))
      return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous &&
                                      Left.Previous->is(tok::kw_case));
    if (Left.is(tok::l_square) && Right.is(tok::amp))
      return Style.SpacesInSquareBrackets;
    if (Right.is(TT_PointerOrReference)) {
      if (Left.is(tok::r_paren) && Line.MightBeFunctionDecl) {
        if (!Left.MatchingParen)
          return true;
        FormatToken *TokenBeforeMatchingParen =
            Left.MatchingParen->getPreviousNonComment();
        if (!TokenBeforeMatchingParen || !Left.is(TT_TypeDeclarationParen))
          return true;
      }
      // Add a space if the previous token is a pointer qualifer or the closing
      // parenthesis of __attribute__(()) expression and the style requires spaces
      // after pointer qualifiers.
      if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_After ||
           Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
          (Left.is(TT_AttributeParen) || Left.canBePointerOrReferenceQualifier()))
        return true;
      return (Left.Tok.isLiteral() ||
              (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
               (Style.PointerAlignment != FormatStyle::PAS_Left ||
                (Line.IsMultiVariableDeclStmt &&
                 (Left.NestingLevel == 0 ||
                  (Left.NestingLevel == 1 && Line.First->is(tok::kw_for)))))));
    }
    if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&
        (!Left.is(TT_PointerOrReference) ||
         (Style.PointerAlignment != FormatStyle::PAS_Right &&
          !Line.IsMultiVariableDeclStmt)))
      return true;
    if (Left.is(TT_PointerOrReference)) {
      // Add a space if the next token is a pointer qualifer and the style
      // requires spaces before pointer qualifiers.
      if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Before ||
           Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
          Right.canBePointerOrReferenceQualifier())
        return true;
      return Right.Tok.isLiteral() || Right.is(TT_BlockComment) ||
             (Right.isOneOf(Keywords.kw_override, Keywords.kw_final) &&
              !Right.is(TT_StartOfName)) ||
             (Right.is(tok::l_brace) && Right.is(BK_Block)) ||
             (!Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,
                             tok::l_paren) &&
              (Style.PointerAlignment != FormatStyle::PAS_Right &&
               !Line.IsMultiVariableDeclStmt) &&
              Left.Previous &&
              !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon,
                                      tok::l_square));
    }
    // Ensure right pointer alignement with ellipsis e.g. int *...P
    if (Left.is(tok::ellipsis) && Left.Previous &&
        Left.Previous->isOneOf(tok::star, tok::amp, tok::ampamp))
      return Style.PointerAlignment != FormatStyle::PAS_Right;
  
    if (Right.is(tok::star) && Left.is(tok::l_paren))
      return false;
    if (Left.is(tok::star) && Right.isOneOf(tok::star, tok::amp, tok::ampamp))
      return false;
    if (Right.isOneOf(tok::star, tok::amp, tok::ampamp)) {
      const FormatToken *Previous = &Left;
      while (Previous && !Previous->is(tok::kw_operator)) {
        if (Previous->is(tok::identifier) || Previous->isSimpleTypeSpecifier()) {
          Previous = Previous->getPreviousNonComment();
          continue;
        }
        if (Previous->is(TT_TemplateCloser) && Previous->MatchingParen) {
          Previous = Previous->MatchingParen->getPreviousNonComment();
          continue;
        }
        if (Previous->is(tok::coloncolon)) {
          Previous = Previous->getPreviousNonComment();
          continue;
        }
        break;
      }
      // Space between the type and the * in:
      //   operator void*()
      //   operator char*()
      //   operator /*comment*/ const char*()
      //   operator volatile /*comment*/ char*()
      //   operator Foo*()
      //   operator C<T>*()
      //   operator std::Foo*()
      //   operator C<T>::D<U>*()
      // dependent on PointerAlignment style.
      if (Previous &&
          (Previous->endsSequence(tok::kw_operator) ||
           Previous->endsSequence(tok::kw_const, tok::kw_operator) ||
           Previous->endsSequence(tok::kw_volatile, tok::kw_operator)))
        return (Style.PointerAlignment != FormatStyle::PAS_Left);
    }
    const auto SpaceRequiredForArrayInitializerLSquare =
        [](const FormatToken &LSquareTok, const FormatStyle &Style) {
          return Style.SpacesInContainerLiterals ||
                 ((Style.Language == FormatStyle::LK_Proto ||
                   Style.Language == FormatStyle::LK_TextProto) &&
                  !Style.Cpp11BracedListStyle &&
                  LSquareTok.endsSequence(tok::l_square, tok::colon,
                                          TT_SelectorName));
        };
    if (Left.is(tok::l_square))
      return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) &&
              SpaceRequiredForArrayInitializerLSquare(Left, Style)) ||
             (Left.isOneOf(TT_ArraySubscriptLSquare, TT_StructuredBindingLSquare,
                           TT_LambdaLSquare) &&
              Style.SpacesInSquareBrackets && Right.isNot(tok::r_square));
    if (Right.is(tok::r_square))
      return Right.MatchingParen &&
             ((Right.MatchingParen->is(TT_ArrayInitializerLSquare) &&
               SpaceRequiredForArrayInitializerLSquare(*Right.MatchingParen,
                                                       Style)) ||
              (Style.SpacesInSquareBrackets &&
               Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
                                            TT_StructuredBindingLSquare,
                                            TT_LambdaLSquare)) ||
              Right.MatchingParen->is(TT_AttributeParen));
    if (Right.is(tok::l_square) &&
        !Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
                       TT_DesignatedInitializerLSquare,
                       TT_StructuredBindingLSquare, TT_AttributeSquare) &&
        !Left.isOneOf(tok::numeric_constant, TT_DictLiteral) &&
        !(!Left.is(tok::r_square) && Style.SpaceBeforeSquareBrackets &&
          Right.is(TT_ArraySubscriptLSquare)))
      return false;
    if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
      return !Left.Children.empty(); // No spaces in "{}".
    if ((Left.is(tok::l_brace) && Left.isNot(BK_Block)) ||
        (Right.is(tok::r_brace) && Right.MatchingParen &&
         Right.MatchingParen->isNot(BK_Block)))
      return Style.Cpp11BracedListStyle ? Style.SpacesInParentheses : true;
    if (Left.is(TT_BlockComment))
      // No whitespace in x(/*foo=*/1), except for JavaScript.
      return Style.Language == FormatStyle::LK_JavaScript ||
             !Left.TokenText.endswith("=*/");
  
    // Space between template and attribute.
    // e.g. template <typename T> [[nodiscard]] ...
    if (Left.is(TT_TemplateCloser) && Right.is(TT_AttributeSquare))
      return true;
    if (Right.is(tok::l_paren)) {
      if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
          (Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
        return true;
      if (Style.SpaceBeforeParens ==
              FormatStyle::SBPO_ControlStatementsExceptForEachMacros &&
          Left.is(TT_ForEachMacro))
        return false;
      return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
             (Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
              (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while,
                            tok::kw_switch, tok::kw_case, TT_ForEachMacro,
                            TT_ObjCForIn) ||
               Left.isIf(Line.Type != LT_PreprocessorDirective) ||
               (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch,
                             tok::kw_new, tok::kw_delete) &&
                (!Left.Previous || Left.Previous->isNot(tok::period))))) ||
             (spaceRequiredBeforeParens(Right) &&
              (Left.is(tok::identifier) || Left.isFunctionLikeKeyword() ||
               Left.is(tok::r_paren) || Left.isSimpleTypeSpecifier() ||
               (Left.is(tok::r_square) && Left.MatchingParen &&
                Left.MatchingParen->is(TT_LambdaLSquare))) &&
              Line.Type != LT_PreprocessorDirective);
    }
    if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
      return false;
    if (Right.is(TT_UnaryOperator))
      return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
             (Left.isNot(tok::colon) || Left.isNot(TT_ObjCMethodExpr));
    if ((Left.isOneOf(tok::identifier, tok::greater, tok::r_square,
                      tok::r_paren) ||
         Left.isSimpleTypeSpecifier()) &&
        Right.is(tok::l_brace) && Right.getNextNonComment() &&
        Right.isNot(BK_Block))
      return false;
    if (Left.is(tok::period) || Right.is(tok::period))
      return false;
    if (Right.is(tok::hash) && Left.is(tok::identifier) && Left.TokenText == "L")
      return false;
    if (Left.is(TT_TemplateCloser) && Left.MatchingParen &&
        Left.MatchingParen->Previous &&
        (Left.MatchingParen->Previous->is(tok::period) ||
         Left.MatchingParen->Previous->is(tok::coloncolon)))
      // Java call to generic function with explicit type:
      // A.<B<C<...>>>DoSomething();
      // A::<B<C<...>>>DoSomething();  // With a Java 8 method reference.
      return false;
    if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square))
      return false;
    if (Left.is(tok::l_brace) && Left.endsSequence(TT_DictLiteral, tok::at))
      // Objective-C dictionary literal -> no space after opening brace.
      return false;
    if (Right.is(tok::r_brace) && Right.MatchingParen &&
        Right.MatchingParen->endsSequence(TT_DictLiteral, tok::at))
      // Objective-C dictionary literal -> no space before closing brace.
      return false;
    if (Right.getType() == TT_TrailingAnnotation &&
        Right.isOneOf(tok::amp, tok::ampamp) &&
        Left.isOneOf(tok::kw_const, tok::kw_volatile) &&
        (!Right.Next || Right.Next->is(tok::semi)))
      // Match const and volatile ref-qualifiers without any additional
      // qualifiers such as
      // void Fn() const &;
      return Style.PointerAlignment != FormatStyle::PAS_Left;
    return true;
  }
  
  bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
                                           const FormatToken &Right) {
    const FormatToken &Left = *Right.Previous;
    if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo())
      return true; // Never ever merge two identifiers.
    if (Style.isCpp()) {
      if (Left.is(tok::kw_operator))
        return Right.is(tok::coloncolon);
      if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&
          !Left.opensScope() && Style.SpaceBeforeCpp11BracedList)
        return true;
    } else if (Style.Language == FormatStyle::LK_Proto ||
               Style.Language == FormatStyle::LK_TextProto) {
      if (Right.is(tok::period) &&
          Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
                       Keywords.kw_repeated, Keywords.kw_extend))
        return true;
      if (Right.is(tok::l_paren) &&
          Left.isOneOf(Keywords.kw_returns, Keywords.kw_option))
        return true;
      if (Right.isOneOf(tok::l_brace, tok::less) && Left.is(TT_SelectorName))
        return true;
      // Slashes occur in text protocol extension syntax: [type/type] { ... }.
      if (Left.is(tok::slash) || Right.is(tok::slash))
        return false;
      if (Left.MatchingParen &&
          Left.MatchingParen->is(TT_ProtoExtensionLSquare) &&
          Right.isOneOf(tok::l_brace, tok::less))
        return !Style.Cpp11BracedListStyle;
      // A percent is probably part of a formatting specification, such as %lld.
      if (Left.is(tok::percent))
        return false;
      // Preserve the existence of a space before a percent for cases like 0x%04x
      // and "%d %d"
      if (Left.is(tok::numeric_constant) && Right.is(tok::percent))
        return Right.WhitespaceRange.getEnd() != Right.WhitespaceRange.getBegin();
    } else if (Style.isCSharp()) {
      // Require spaces around '{' and  before '}' unless they appear in
      // interpolated strings. Interpolated strings are merged into a single token
      // so cannot have spaces inserted by this function.
  
      // No space between 'this' and '['
      if (Left.is(tok::kw_this) && Right.is(tok::l_square))
        return false;
  
      // No space between 'new' and '('
      if (Left.is(tok::kw_new) && Right.is(tok::l_paren))
        return false;
  
      // Space before { (including space within '{ {').
      if (Right.is(tok::l_brace))
        return true;
  
      // Spaces inside braces.
      if (Left.is(tok::l_brace) && Right.isNot(tok::r_brace))
        return true;
  
      if (Left.isNot(tok::l_brace) && Right.is(tok::r_brace))
        return true;
  
      // Spaces around '=>'.
      if (Left.is(TT_JsFatArrow) || Right.is(TT_JsFatArrow))
        return true;
  
      // No spaces around attribute target colons
      if (Left.is(TT_AttributeColon) || Right.is(TT_AttributeColon))
        return false;
  
      // space between type and variable e.g. Dictionary<string,string> foo;
      if (Left.is(TT_TemplateCloser) && Right.is(TT_StartOfName))
        return true;
  
      // spaces inside square brackets.
      if (Left.is(tok::l_square) || Right.is(tok::r_square))
        return Style.SpacesInSquareBrackets;
  
      // No space before ? in nullable types.
      if (Right.is(TT_CSharpNullable))
        return false;
  
      // Require space after ? in nullable types except in generics and casts.
      if (Left.is(TT_CSharpNullable))
        return !Right.isOneOf(TT_TemplateCloser, tok::r_paren);
  
      // No space before or after '?.'.
      if (Left.is(TT_CSharpNullConditional) || Right.is(TT_CSharpNullConditional))
        return false;
  
      // Space before and after '??'.
      if (Left.is(TT_CSharpNullCoalescing) || Right.is(TT_CSharpNullCoalescing))
        return true;
  
      // No space before '?['.
      if (Right.is(TT_CSharpNullConditionalLSquare))
        return false;
  
      // No space between consecutive commas '[,,]'.
      if (Left.is(tok::comma) && Right.is(tok::comma))
        return false;
  
      // Possible space inside `?[ 0 ]`.
      if (Left.is(TT_CSharpNullConditionalLSquare))
        return Style.SpacesInSquareBrackets;
  
      // space after var in `var (key, value)`
      if (Left.is(Keywords.kw_var) && Right.is(tok::l_paren))
        return true;
  
      // space between keywords and paren e.g. "using ("
      if (Right.is(tok::l_paren))
        if (Left.isOneOf(tok::kw_using, Keywords.kw_async, Keywords.kw_when,
                         Keywords.kw_lock))
          return Style.SpaceBeforeParens == FormatStyle::SBPO_ControlStatements ||
                 spaceRequiredBeforeParens(Right);
  
      // space between method modifier and opening parenthesis of a tuple return
      // type
      if (Left.isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
                       tok::kw_virtual, tok::kw_extern, tok::kw_static,
                       Keywords.kw_internal, Keywords.kw_abstract,
                       Keywords.kw_sealed, Keywords.kw_override,
                       Keywords.kw_async, Keywords.kw_unsafe) &&
          Right.is(tok::l_paren))
        return true;
    } else if (Style.Language == FormatStyle::LK_JavaScript) {
      if (Left.is(TT_JsFatArrow))
        return true;
      // for await ( ...
      if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous &&
          Left.Previous->is(tok::kw_for))
        return true;
      if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&
          Right.MatchingParen) {
        const FormatToken *Next = Right.MatchingParen->getNextNonComment();
        // An async arrow function, for example: `x = async () => foo();`,
        // as opposed to calling a function called async: `x = async();`
        if (Next && Next->is(TT_JsFatArrow))
          return true;
      }
      if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
          (Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
        return false;
      // In tagged template literals ("html`bar baz`"), there is no space between
      // the tag identifier and the template string.
      if (Keywords.IsJavaScriptIdentifier(Left,
                                          /* AcceptIdentifierName= */ false) &&
          Right.is(TT_TemplateString))
        return false;
      if (Right.is(tok::star) &&
          Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
        return false;
      if (Right.isOneOf(tok::l_brace, tok::l_square) &&
          Left.isOneOf(Keywords.kw_function, Keywords.kw_yield,
                       Keywords.kw_extends, Keywords.kw_implements))
        return true;
      if (Right.is(tok::l_paren)) {
        // JS methods can use some keywords as names (e.g. `delete()`).
        if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo())
          return false;
        // Valid JS method names can include keywords, e.g. `foo.delete()` or
        // `bar.instanceof()`. Recognize call positions by preceding period.
        if (Left.Previous && Left.Previous->is(tok::period) &&
            Left.Tok.getIdentifierInfo())
          return false;
        // Additional unary JavaScript operators that need a space after.
        if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof,
                         tok::kw_void))
          return true;
      }
      // `foo as const;` casts into a const type.
      if (Left.endsSequence(tok::kw_const, Keywords.kw_as)) {
        return false;
      }
      if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
                        tok::kw_const) ||
           // "of" is only a keyword if it appears after another identifier
           // (e.g. as "const x of y" in a for loop), or after a destructuring
           // operation (const [x, y] of z, const {a, b} of c).
           (Left.is(Keywords.kw_of) && Left.Previous &&
            (Left.Previous->Tok.is(tok::identifier) ||
             Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) &&
          (!Left.Previous || !Left.Previous->is(tok::period)))
        return true;
      if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&
          Left.Previous->is(tok::period) && Right.is(tok::l_paren))
        return false;
      if (Left.is(Keywords.kw_as) &&
          Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
        return true;
      if (Left.is(tok::kw_default) && Left.Previous &&
          Left.Previous->is(tok::kw_export))
        return true;
      if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace))
        return true;
      if (Right.isOneOf(TT_JsTypeColon, TT_JsTypeOptionalQuestion))
        return false;
      if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator))
        return false;
      if ((Left.is(tok::l_brace) || Right.is(tok::r_brace)) &&
          Line.First->isOneOf(Keywords.kw_import, tok::kw_export))
        return false;
      if (Left.is(tok::ellipsis))
        return false;
      if (Left.is(TT_TemplateCloser) &&
          !Right.isOneOf(tok::equal, tok::l_brace, tok::comma, tok::l_square,
                         Keywords.kw_implements, Keywords.kw_extends))
        // Type assertions ('<type>expr') are not followed by whitespace. Other
        // locations that should have whitespace following are identified by the
        // above set of follower tokens.
        return false;
      if (Right.is(TT_JsNonNullAssertion))
        return false;
      if (Left.is(TT_JsNonNullAssertion) &&
          Right.isOneOf(Keywords.kw_as, Keywords.kw_in))
        return true; // "x! as string", "x! in y"
    } else if (Style.Language == FormatStyle::LK_Java) {
      if (Left.is(tok::r_square) && Right.is(tok::l_brace))
        return true;
      if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren))
        return Style.SpaceBeforeParens != FormatStyle::SBPO_Never;
      if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private,
                        tok::kw_protected) ||
           Left.isOneOf(Keywords.kw_final, Keywords.kw_abstract,
                        Keywords.kw_native)) &&
          Right.is(TT_TemplateOpener))
        return true;
    }
    if (Left.is(TT_ImplicitStringLiteral))
      return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
    if (Line.Type == LT_ObjCMethodDecl) {
      if (Left.is(TT_ObjCMethodSpecifier))
        return true;
      if (Left.is(tok::r_paren) && canBeObjCSelectorComponent(Right))
        // Don't space between ')' and <id> or ')' and 'new'. 'new' is not a
        // keyword in Objective-C, and '+ (instancetype)new;' is a standard class
        // method declaration.
        return false;
    }
    if (Line.Type == LT_ObjCProperty &&
        (Right.is(tok::equal) || Left.is(tok::equal)))
      return false;
  
    if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||
        Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
      return true;
    if (Right.is(TT_OverloadedOperatorLParen))
      return spaceRequiredBeforeParens(Right);
    if (Left.is(tok::comma))
      return true;
    if (Right.is(tok::comma))
      return false;
    if (Right.is(TT_ObjCBlockLParen))
      return true;
    if (Right.is(TT_CtorInitializerColon))
      return Style.SpaceBeforeCtorInitializerColon;
    if (Right.is(TT_InheritanceColon) && !Style.SpaceBeforeInheritanceColon)
      return false;
    if (Right.is(TT_RangeBasedForLoopColon) &&
        !Style.SpaceBeforeRangeBasedForLoopColon)
      return false;
    if (Left.is(TT_BitFieldColon))
      return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
             Style.BitFieldColonSpacing == FormatStyle::BFCS_After;
    if (Right.is(tok::colon)) {
      if (Line.First->isOneOf(tok::kw_default, tok::kw_case))
        return Style.SpaceBeforeCaseColon;
      if (!Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi))
        return false;
      if (Right.is(TT_ObjCMethodExpr))
        return false;
      if (Left.is(tok::question))
        return false;
      if (Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon))
        return false;
      if (Right.is(TT_DictLiteral))
        return Style.SpacesInContainerLiterals;
      if (Right.is(TT_AttributeColon))
        return false;
      if (Right.is(TT_CSharpNamedArgumentColon))
        return false;
      if (Right.is(TT_BitFieldColon))
        return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
               Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
      return true;
    }
    if (Left.is(TT_UnaryOperator)) {
      if (!Right.is(tok::l_paren)) {
        // The alternative operators for ~ and ! are "compl" and "not".
        // If they are used instead, we do not want to combine them with
        // the token to the right, unless that is a left paren.
        if (Left.is(tok::exclaim) && Left.TokenText == "not")
          return true;
        if (Left.is(tok::tilde) && Left.TokenText == "compl")
          return true;
        // Lambda captures allow for a lone &, so "&]" needs to be properly
        // handled.
        if (Left.is(tok::amp) && Right.is(tok::r_square))
          return Style.SpacesInSquareBrackets;
      }
      return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) ||
             Right.is(TT_BinaryOperator);
    }
  
    // If the next token is a binary operator or a selector name, we have
    // incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.
    if (Left.is(TT_CastRParen))
      return Style.SpaceAfterCStyleCast ||
             Right.isOneOf(TT_BinaryOperator, TT_SelectorName);
  
    if (Left.is(tok::greater) && Right.is(tok::greater)) {
      if (Style.Language == FormatStyle::LK_TextProto ||
          (Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral)))
        return !Style.Cpp11BracedListStyle;
      return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
             (Style.Standard < FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
    }
    if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
        Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
        (Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod)))
      return false;
    if (!Style.SpaceBeforeAssignmentOperators && Left.isNot(TT_TemplateCloser) &&
        Right.getPrecedence() == prec::Assignment)
      return false;
    if (Style.Language == FormatStyle::LK_Java && Right.is(tok::coloncolon) &&
        (Left.is(tok::identifier) || Left.is(tok::kw_this)))
      return false;
    if (Right.is(tok::coloncolon) && Left.is(tok::identifier))
      // Generally don't remove existing spaces between an identifier and "::".
      // The identifier might actually be a macro name such as ALWAYS_INLINE. If
      // this turns out to be too lenient, add analysis of the identifier itself.
      return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
    if (Right.is(tok::coloncolon) &&
        !Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren))
      // Put a space between < and :: in vector< ::std::string >
      return (Left.is(TT_TemplateOpener) &&
              (Style.Standard < FormatStyle::LS_Cpp11 || Style.SpacesInAngles)) ||
             !(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
                            tok::kw___super, TT_TemplateOpener,
                            TT_TemplateCloser)) ||
             (Left.is(tok::l_paren) && Style.SpacesInParentheses);
    if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
      return Style.SpacesInAngles;
    // Space before TT_StructuredBindingLSquare.
    if (Right.is(TT_StructuredBindingLSquare))
      return !Left.isOneOf(tok::amp, tok::ampamp) ||
             Style.PointerAlignment != FormatStyle::PAS_Right;
    // Space before & or && following a TT_StructuredBindingLSquare.
    if (Right.Next && Right.Next->is(TT_StructuredBindingLSquare) &&
        Right.isOneOf(tok::amp, tok::ampamp))
      return Style.PointerAlignment != FormatStyle::PAS_Left;
    if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) ||
        (Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
         !Right.is(tok::r_paren)))
      return true;
    if (Left.is(TT_TemplateCloser) && Right.is(tok::l_paren) &&
        Right.isNot(TT_FunctionTypeLParen))
      return spaceRequiredBeforeParens(Right);
    if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&
        Left.MatchingParen && Left.MatchingParen->is(TT_OverloadedOperatorLParen))
      return false;
    if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&
        Line.startsWith(tok::hash))
      return true;
    if (Right.is(TT_TrailingUnaryOperator))
      return false;
    if (Left.is(TT_RegexLiteral))
      return false;
    return spaceRequiredBetween(Line, Left, Right);
  }
  
  // Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style.
  static bool isAllmanBrace(const FormatToken &Tok) {
    return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&
           !Tok.isOneOf(TT_ObjCBlockLBrace, TT_LambdaLBrace, TT_DictLiteral);
  }
  
  // Returns 'true' if 'Tok' is an function argument.
  static bool IsFunctionArgument(const FormatToken &Tok) {
    return Tok.MatchingParen && Tok.MatchingParen->Next &&
           Tok.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren);
  }
  
  static bool
  isItAnEmptyLambdaAllowed(const FormatToken &Tok,
                           FormatStyle::ShortLambdaStyle ShortLambdaOption) {
    return Tok.Children.empty() && ShortLambdaOption != FormatStyle::SLS_None;
  }
  
  static bool
  isItAInlineLambdaAllowed(const FormatToken &Tok,
                           FormatStyle::ShortLambdaStyle ShortLambdaOption) {
    return (ShortLambdaOption == FormatStyle::SLS_Inline &&
            IsFunctionArgument(Tok)) ||
           (ShortLambdaOption == FormatStyle::SLS_All);
  }
  
  static bool isOneChildWithoutMustBreakBefore(const FormatToken &Tok) {
    if (Tok.Children.size() != 1)
      return false;
    FormatToken *curElt = Tok.Children[0]->First;
    while (curElt) {
      if (curElt->MustBreakBefore)
        return false;
      curElt = curElt->Next;
    }
    return true;
  }
  static bool isAllmanLambdaBrace(const FormatToken &Tok) {
    return (Tok.is(tok::l_brace) && Tok.is(BK_Block) &&
            !Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral));
  }
  
  static bool isAllmanBraceIncludedBreakableLambda(
      const FormatToken &Tok, FormatStyle::ShortLambdaStyle ShortLambdaOption) {
    if (!isAllmanLambdaBrace(Tok))
      return false;
  
    if (isItAnEmptyLambdaAllowed(Tok, ShortLambdaOption))
      return false;
  
    return !isItAInlineLambdaAllowed(Tok, ShortLambdaOption) ||
           !isOneChildWithoutMustBreakBefore(Tok);
  }
  
  bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
                                       const FormatToken &Right) {
    const FormatToken &Left = *Right.Previous;
    if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0)
      return true;
  
    if (Style.isCSharp()) {
      if (Right.is(TT_CSharpNamedArgumentColon) ||
          Left.is(TT_CSharpNamedArgumentColon))
        return false;
      if (Right.is(TT_CSharpGenericTypeConstraint))
        return true;
    } else if (Style.Language == FormatStyle::LK_JavaScript) {
      // FIXME: This might apply to other languages and token kinds.
      if (Right.is(tok::string_literal) && Left.is(tok::plus) && Left.Previous &&
          Left.Previous->is(tok::string_literal))
        return true;
      if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 &&
          Left.Previous && Left.Previous->is(tok::equal) &&
          Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export,
                              tok::kw_const) &&
          // kw_var/kw_let are pseudo-tokens that are tok::identifier, so match
          // above.
          !Line.First->isOneOf(Keywords.kw_var, Keywords.kw_let))
        // Object literals on the top level of a file are treated as "enum-style".
        // Each key/value pair is put on a separate line, instead of bin-packing.
        return true;
      if (Left.is(tok::l_brace) && Line.Level == 0 &&
          (Line.startsWith(tok::kw_enum) ||
           Line.startsWith(tok::kw_const, tok::kw_enum) ||
           Line.startsWith(tok::kw_export, tok::kw_enum) ||
           Line.startsWith(tok::kw_export, tok::kw_const, tok::kw_enum)))
        // JavaScript top-level enum key/value pairs are put on separate lines
        // instead of bin-packing.
        return true;
      if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && Left.Previous &&
          Left.Previous->is(TT_JsFatArrow)) {
        // JS arrow function (=> {...}).
        switch (Style.AllowShortLambdasOnASingleLine) {
        case FormatStyle::SLS_All:
          return false;
        case FormatStyle::SLS_None:
          return true;
        case FormatStyle::SLS_Empty:
          return !Left.Children.empty();
        case FormatStyle::SLS_Inline:
          // allow one-lining inline (e.g. in function call args) and empty arrow
          // functions.
          return (Left.NestingLevel == 0 && Line.Level == 0) &&
                 !Left.Children.empty();
        }
        llvm_unreachable("Unknown FormatStyle::ShortLambdaStyle enum");
      }
  
      if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
          !Left.Children.empty())
        // Support AllowShortFunctionsOnASingleLine for JavaScript.
        return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
               Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty ||
               (Left.NestingLevel == 0 && Line.Level == 0 &&
                Style.AllowShortFunctionsOnASingleLine &
                    FormatStyle::SFS_InlineOnly);
    } else if (Style.Language == FormatStyle::LK_Java) {
      if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next &&
          Right.Next->is(tok::string_literal))
        return true;
    } else if (Style.Language == FormatStyle::LK_Cpp ||
               Style.Language == FormatStyle::LK_ObjC ||
               Style.Language == FormatStyle::LK_Proto ||
               Style.Language == FormatStyle::LK_TableGen ||
               Style.Language == FormatStyle::LK_TextProto) {
      if (Left.isStringLiteral() && Right.isStringLiteral())
        return true;
    }
  
    // If the last token before a '}', ']', or ')' is a comma or a trailing
    // comment, the intention is to insert a line break after it in order to make
    // shuffling around entries easier. Import statements, especially in
    // JavaScript, can be an exception to this rule.
    if (Style.JavaScriptWrapImports || Line.Type != LT_ImportStatement) {
      const FormatToken *BeforeClosingBrace = nullptr;
      if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
           (Style.Language == FormatStyle::LK_JavaScript &&
            Left.is(tok::l_paren))) &&
          Left.isNot(BK_Block) && Left.MatchingParen)
        BeforeClosingBrace = Left.MatchingParen->Previous;
      else if (Right.MatchingParen &&
               (Right.MatchingParen->isOneOf(tok::l_brace,
                                             TT_ArrayInitializerLSquare) ||
                (Style.Language == FormatStyle::LK_JavaScript &&
                 Right.MatchingParen->is(tok::l_paren))))
        BeforeClosingBrace = &Left;
      if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||
                                 BeforeClosingBrace->isTrailingComment()))
        return true;
    }
  
    if (Right.is(tok::comment))
      return Left.isNot(BK_BracedInit) && Left.isNot(TT_CtorInitializerColon) &&
             (Right.NewlinesBefore > 0 && Right.HasUnescapedNewline);
    if (Left.isTrailingComment())
      return true;
    if (Right.Previous->IsUnterminatedLiteral)
      return true;
    if (Right.is(tok::lessless) && Right.Next &&
        Right.Previous->is(tok::string_literal) &&
        Right.Next->is(tok::string_literal))
      return true;
    // Can break after template<> declaration
    if (Right.Previous->ClosesTemplateDeclaration &&
        Right.Previous->MatchingParen &&
        Right.Previous->MatchingParen->NestingLevel == 0) {
      // Put concepts on the next line e.g.
      // template<typename T>
      // concept ...
      if (Right.is(tok::kw_concept))
        return Style.BreakBeforeConceptDeclarations;
      return (Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes);
    }
    if (Right.is(TT_CtorInitializerComma) &&
        Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
        !Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
      return true;
    if (Right.is(TT_CtorInitializerColon) &&
        Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
        !Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
      return true;
    // Break only if we have multiple inheritance.
    if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&
        Right.is(TT_InheritanceComma))
      return true;
    if (Right.is(tok::string_literal) && Right.TokenText.startswith("R\""))
      // Multiline raw string literals are special wrt. line breaks. The author
      // has made a deliberate choice and might have aligned the contents of the
      // string literal accordingly. Thus, we try keep existing line breaks.
      return Right.IsMultiline && Right.NewlinesBefore > 0;
    if ((Right.Previous->is(tok::l_brace) ||
         (Right.Previous->is(tok::less) && Right.Previous->Previous &&
          Right.Previous->Previous->is(tok::equal))) &&
        Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) {
      // Don't put enums or option definitions onto single lines in protocol
      // buffers.
      return true;
    }
    if (Right.is(TT_InlineASMBrace))
      return Right.HasUnescapedNewline;
  
    auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
    if (Style.BraceWrapping.BeforeLambdaBody &&
        (isAllmanBraceIncludedBreakableLambda(Left, ShortLambdaOption) ||
         isAllmanBraceIncludedBreakableLambda(Right, ShortLambdaOption))) {
      return true;
    }
  
    if (isAllmanBrace(Left) || isAllmanBrace(Right))
      return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) ||
             (Line.startsWith(tok::kw_typedef, tok::kw_enum) &&
              Style.BraceWrapping.AfterEnum) ||
             (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) ||
             (Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct);
    if (Left.is(TT_ObjCBlockLBrace) &&
        Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never)
      return true;
  
    if (Left.is(TT_LambdaLBrace)) {
      if (IsFunctionArgument(Left) &&
          Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline)
        return false;
  
      if (Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_None ||
          Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline ||
          (!Left.Children.empty() &&
           Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Empty))
        return true;
    }
  
    // Put multiple Java annotation on a new line.
    if ((Style.Language == FormatStyle::LK_Java ||
         Style.Language == FormatStyle::LK_JavaScript) &&
        Left.is(TT_LeadingJavaAnnotation) &&
        Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
        (Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations))
      return true;
  
    if (Right.is(TT_ProtoExtensionLSquare))
      return true;
  
    // In text proto instances if a submessage contains at least 2 entries and at
    // least one of them is a submessage, like A { ... B { ... } ... },
    // put all of the entries of A on separate lines by forcing the selector of
    // the submessage B to be put on a newline.
    //
    // Example: these can stay on one line:
    // a { scalar_1: 1 scalar_2: 2 }
    // a { b { key: value } }
    //
    // and these entries need to be on a new line even if putting them all in one
    // line is under the column limit:
    // a {
    //   scalar: 1
    //   b { key: value }
    // }
    //
    // We enforce this by breaking before a submessage field that has previous
    // siblings, *and* breaking before a field that follows a submessage field.
    //
    // Be careful to exclude the case  [proto.ext] { ... } since the `]` is
    // the TT_SelectorName there, but we don't want to break inside the brackets.
    //
    // Another edge case is @submessage { key: value }, which is a common
    // substitution placeholder. In this case we want to keep `@` and `submessage`
    // together.
    //
    // We ensure elsewhere that extensions are always on their own line.
    if ((Style.Language == FormatStyle::LK_Proto ||
         Style.Language == FormatStyle::LK_TextProto) &&
        Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) {
      // Keep `@submessage` together in:
      // @submessage { key: value }
      if (Right.Previous && Right.Previous->is(tok::at))
        return false;
      // Look for the scope opener after selector in cases like:
      // selector { ...
      // selector: { ...
      // selector: @base { ...
      FormatToken *LBrace = Right.Next;
      if (LBrace && LBrace->is(tok::colon)) {
        LBrace = LBrace->Next;
        if (LBrace && LBrace->is(tok::at)) {
          LBrace = LBrace->Next;
          if (LBrace)
            LBrace = LBrace->Next;
        }
      }
      if (LBrace &&
          // The scope opener is one of {, [, <:
          // selector { ... }
          // selector [ ... ]
          // selector < ... >
          //
          // In case of selector { ... }, the l_brace is TT_DictLiteral.
          // In case of an empty selector {}, the l_brace is not TT_DictLiteral,
          // so we check for immediately following r_brace.
          ((LBrace->is(tok::l_brace) &&
            (LBrace->is(TT_DictLiteral) ||
             (LBrace->Next && LBrace->Next->is(tok::r_brace)))) ||
           LBrace->is(TT_ArrayInitializerLSquare) || LBrace->is(tok::less))) {
        // If Left.ParameterCount is 0, then this submessage entry is not the
        // first in its parent submessage, and we want to break before this entry.
        // If Left.ParameterCount is greater than 0, then its parent submessage
        // might contain 1 or more entries and we want to break before this entry
        // if it contains at least 2 entries. We deal with this case later by
        // detecting and breaking before the next entry in the parent submessage.
        if (Left.ParameterCount == 0)
          return true;
        // However, if this submessage is the first entry in its parent
        // submessage, Left.ParameterCount might be 1 in some cases.
        // We deal with this case later by detecting an entry
        // following a closing paren of this submessage.
      }
  
      // If this is an entry immediately following a submessage, it will be
      // preceded by a closing paren of that submessage, like in:
      //     left---.  .---right
      //            v  v
      // sub: { ... } key: value
      // If there was a comment between `}` an `key` above, then `key` would be
      // put on a new line anyways.
      if (Left.isOneOf(tok::r_brace, tok::greater, tok::r_square))
        return true;
    }
  
    // Deal with lambda arguments in C++ - we want consistent line breaks whether
    // they happen to be at arg0, arg1 or argN. The selection is a bit nuanced
    // as aggressive line breaks are placed when the lambda is not the last arg.
    if ((Style.Language == FormatStyle::LK_Cpp ||
         Style.Language == FormatStyle::LK_ObjC) &&
        Left.is(tok::l_paren) && Left.BlockParameterCount > 0 &&
        !Right.isOneOf(tok::l_paren, TT_LambdaLSquare)) {
      // Multiple lambdas in the same function call force line breaks.
      if (Left.BlockParameterCount > 1)
        return true;
  
      // A lambda followed by another arg forces a line break.
      if (!Left.Role)
        return false;
      auto Comma = Left.Role->lastComma();
      if (!Comma)
        return false;
      auto Next = Comma->getNextNonComment();
      if (!Next)
        return false;
      if (!Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret))
        return true;
    }
  
    return false;
  }
  
  bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
                                      const FormatToken &Right) {
    const FormatToken &Left = *Right.Previous;
    // Language-specific stuff.
    if (Style.isCSharp()) {
      if (Left.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon) ||
          Right.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon))
        return false;
      // Only break after commas for generic type constraints.
      if (Line.First->is(TT_CSharpGenericTypeConstraint))
        return Left.is(TT_CSharpGenericTypeConstraintComma);
    } else if (Style.Language == FormatStyle::LK_Java) {
      if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
                       Keywords.kw_implements))
        return false;
      if (Right.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
                        Keywords.kw_implements))
        return true;
    } else if (Style.Language == FormatStyle::LK_JavaScript) {
      const FormatToken *NonComment = Right.getPreviousNonComment();
      if (NonComment &&
          NonComment->isOneOf(
              tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,
              tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,
              tok::kw_static, tok::kw_public, tok::kw_private, tok::kw_protected,
              Keywords.kw_readonly, Keywords.kw_abstract, Keywords.kw_get,
              Keywords.kw_set, Keywords.kw_async, Keywords.kw_await))
        return false; // Otherwise automatic semicolon insertion would trigger.
      if (Right.NestingLevel == 0 &&
          (Left.Tok.getIdentifierInfo() ||
           Left.isOneOf(tok::r_square, tok::r_paren)) &&
          Right.isOneOf(tok::l_square, tok::l_paren))
        return false; // Otherwise automatic semicolon insertion would trigger.
      if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
        return false;
      if (Left.is(TT_JsTypeColon))
        return true;
      // Don't wrap between ":" and "!" of a strict prop init ("field!: type;").
      if (Left.is(tok::exclaim) && Right.is(tok::colon))
        return false;
      // Look for is type annotations like:
      // function f(): a is B { ... }
      // Do not break before is in these cases.
      if (Right.is(Keywords.kw_is)) {
        const FormatToken *Next = Right.getNextNonComment();
        // If `is` is followed by a colon, it's likely that it's a dict key, so
        // ignore it for this check.
        // For example this is common in Polymer:
        // Polymer({
        //   is: 'name',
        //   ...
        // });
        if (!Next || !Next->is(tok::colon))
          return false;
      }
      if (Left.is(Keywords.kw_in))
        return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None;
      if (Right.is(Keywords.kw_in))
        return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;
      if (Right.is(Keywords.kw_as))
        return false; // must not break before as in 'x as type' casts
      if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) {
        // extends and infer can appear as keywords in conditional types:
        //   https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types
        // do not break before them, as the expressions are subject to ASI.
        return false;
      }
      if (Left.is(Keywords.kw_as))
        return true;
      if (Left.is(TT_JsNonNullAssertion))
        return true;
      if (Left.is(Keywords.kw_declare) &&
          Right.isOneOf(Keywords.kw_module, tok::kw_namespace,
                        Keywords.kw_function, tok::kw_class, tok::kw_enum,
                        Keywords.kw_interface, Keywords.kw_type, Keywords.kw_var,
                        Keywords.kw_let, tok::kw_const))
        // See grammar for 'declare' statements at:
        // https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#A.10
        return false;
      if (Left.isOneOf(Keywords.kw_module, tok::kw_namespace) &&
          Right.isOneOf(tok::identifier, tok::string_literal))
        return false; // must not break in "module foo { ...}"
      if (Right.is(TT_TemplateString) && Right.closesScope())
        return false;
      // Don't split tagged template literal so there is a break between the tag
      // identifier and template string.
      if (Left.is(tok::identifier) && Right.is(TT_TemplateString)) {
        return false;
      }
      if (Left.is(TT_TemplateString) && Left.opensScope())
        return true;
    }
  
    if (Left.is(tok::at))
      return false;
    if (Left.Tok.getObjCKeywordID() == tok::objc_interface)
      return false;
    if (Left.isOneOf(TT_JavaAnnotation, TT_LeadingJavaAnnotation))
      return !Right.is(tok::l_paren);
    if (Right.is(TT_PointerOrReference))
      return Line.IsMultiVariableDeclStmt ||
             (Style.PointerAlignment == FormatStyle::PAS_Right &&
              (!Right.Next || Right.Next->isNot(TT_FunctionDeclarationName)));
    if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
        Right.is(tok::kw_operator))
      return true;
    if (Left.is(TT_PointerOrReference))
      return false;
    if (Right.isTrailingComment())
      // We rely on MustBreakBefore being set correctly here as we should not
      // change the "binding" behavior of a comment.
      // The first comment in a braced lists is always interpreted as belonging to
      // the first list element. Otherwise, it should be placed outside of the
      // list.
      return Left.is(BK_BracedInit) ||
             (Left.is(TT_CtorInitializerColon) &&
              Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon);
    if (Left.is(tok::question) && Right.is(tok::colon))
      return false;
    if (Right.is(TT_ConditionalExpr) || Right.is(tok::question))
      return Style.BreakBeforeTernaryOperators;
    if (Left.is(TT_ConditionalExpr) || Left.is(tok::question))
      return !Style.BreakBeforeTernaryOperators;
    if (Left.is(TT_InheritanceColon))
      return Style.BreakInheritanceList == FormatStyle::BILS_AfterColon;
    if (Right.is(TT_InheritanceColon))
      return Style.BreakInheritanceList != FormatStyle::BILS_AfterColon;
    if (Right.is(TT_ObjCMethodExpr) && !Right.is(tok::r_square) &&
        Left.isNot(TT_SelectorName))
      return true;
  
    if (Right.is(tok::colon) &&
        !Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon))
      return false;
    if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
      if (Style.Language == FormatStyle::LK_Proto ||
          Style.Language == FormatStyle::LK_TextProto) {
        if (!Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral())
          return false;
        // Prevent cases like:
        //
        // submessage:
        //     { key: valueeeeeeeeeeee }
        //
        // when the snippet does not fit into one line.
        // Prefer:
        //
        // submessage: {
        //   key: valueeeeeeeeeeee
        // }
        //
        // instead, even if it is longer by one line.
        //
        // Note that this allows allows the "{" to go over the column limit
        // when the column limit is just between ":" and "{", but that does
        // not happen too often and alternative formattings in this case are
        // not much better.
        //
        // The code covers the cases:
        //
        // submessage: { ... }
        // submessage: < ... >
        // repeated: [ ... ]
        if (((Right.is(tok::l_brace) || Right.is(tok::less)) &&
             Right.is(TT_DictLiteral)) ||
            Right.is(TT_ArrayInitializerLSquare))
          return false;
      }
      return true;
    }
    if (Right.is(tok::r_square) && Right.MatchingParen &&
        Right.MatchingParen->is(TT_ProtoExtensionLSquare))
      return false;
    if (Right.is(TT_SelectorName) || (Right.is(tok::identifier) && Right.Next &&
                                      Right.Next->is(TT_ObjCMethodExpr)))
      return Left.isNot(tok::period); // FIXME: Properly parse ObjC calls.
    if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
      return true;
    if (Left.ClosesTemplateDeclaration || Left.is(TT_FunctionAnnotationRParen))
      return true;
    if (Right.isOneOf(TT_RangeBasedForLoopColon, TT_OverloadedOperatorLParen,
                      TT_OverloadedOperator))
      return false;
    if (Left.is(TT_RangeBasedForLoopColon))
      return true;
    if (Right.is(TT_RangeBasedForLoopColon))
      return false;
    if (Left.is(TT_TemplateCloser) && Right.is(TT_TemplateOpener))
      return true;
    if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator) ||
        Left.is(tok::kw_operator))
      return false;
    if (Left.is(tok::equal) && !Right.isOneOf(tok::kw_default, tok::kw_delete) &&
        Line.Type == LT_VirtualFunctionDecl && Left.NestingLevel == 0)
      return false;
    if (Left.is(tok::equal) && Right.is(tok::l_brace) &&
        !Style.Cpp11BracedListStyle)
      return false;
    if (Left.is(tok::l_paren) &&
        Left.isOneOf(TT_AttributeParen, TT_TypeDeclarationParen))
      return false;
    if (Left.is(tok::l_paren) && Left.Previous &&
        (Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen)))
      return false;
    if (Right.is(TT_ImplicitStringLiteral))
      return false;
  
    if (Right.is(tok::r_paren) || Right.is(TT_TemplateCloser))
      return false;
    if (Right.is(tok::r_square) && Right.MatchingParen &&
        Right.MatchingParen->is(TT_LambdaLSquare))
      return false;
  
    // We only break before r_brace if there was a corresponding break before
    // the l_brace, which is tracked by BreakBeforeClosingBrace.
    if (Right.is(tok::r_brace))
      return Right.MatchingParen && Right.MatchingParen->is(BK_Block);
  
    // Allow breaking after a trailing annotation, e.g. after a method
    // declaration.
    if (Left.is(TT_TrailingAnnotation))
      return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren,
                            tok::less, tok::coloncolon);
  
    if (Right.is(tok::kw___attribute) ||
        (Right.is(tok::l_square) && Right.is(TT_AttributeSquare)))
      return !Left.is(TT_AttributeSquare);
  
    if (Left.is(tok::identifier) && Right.is(tok::string_literal))
      return true;
  
    if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
      return true;
  
    if (Left.is(TT_CtorInitializerColon))
      return Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon;
    if (Right.is(TT_CtorInitializerColon))
      return Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon;
    if (Left.is(TT_CtorInitializerComma) &&
        Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma)
      return false;
    if (Right.is(TT_CtorInitializerComma) &&
        Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma)
      return true;
    if (Left.is(TT_InheritanceComma) &&
        Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma)
      return false;
    if (Right.is(TT_InheritanceComma) &&
        Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma)
      return true;
    if ((Left.is(tok::greater) && Right.is(tok::greater)) ||
        (Left.is(tok::less) && Right.is(tok::less)))
      return false;
    if (Right.is(TT_BinaryOperator) &&
        Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None &&
        (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_All ||
         Right.getPrecedence() != prec::Assignment))
      return true;
    if (Left.is(TT_ArrayInitializerLSquare))
      return true;
    if (Right.is(tok::kw_typename) && Left.isNot(tok::kw_const))
      return true;
    if ((Left.isBinaryOperator() || Left.is(TT_BinaryOperator)) &&
        !Left.isOneOf(tok::arrowstar, tok::lessless) &&
        Style.BreakBeforeBinaryOperators != FormatStyle::BOS_All &&
        (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None ||
         Left.getPrecedence() == prec::Assignment))
      return true;
    if ((Left.is(TT_AttributeSquare) && Right.is(tok::l_square)) ||
        (Left.is(tok::r_square) && Right.is(TT_AttributeSquare)))
      return false;
  
    auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
    if (Style.BraceWrapping.BeforeLambdaBody) {
      if (isAllmanLambdaBrace(Left))
        return !isItAnEmptyLambdaAllowed(Left, ShortLambdaOption);
      if (isAllmanLambdaBrace(Right))
        return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption);
    }
  
    return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
                        tok::kw_class, tok::kw_struct, tok::comment) ||
           Right.isMemberAccess() ||
           Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless,
                         tok::colon, tok::l_square, tok::at) ||
           (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace)) ||
           (Left.is(tok::r_paren) &&
            Right.isOneOf(tok::identifier, tok::kw_const)) ||
           (Left.is(tok::l_paren) && !Right.is(tok::r_paren)) ||
           (Left.is(TT_TemplateOpener) && !Right.is(TT_TemplateCloser));
  }
  
  void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
    llvm::errs() << "AnnotatedTokens(L=" << Line.Level << "):\n";
    const FormatToken *Tok = Line.First;
    while (Tok) {
      llvm::errs() << " M=" << Tok->MustBreakBefore
                   << " C=" << Tok->CanBreakBefore
                   << " T=" << getTokenTypeName(Tok->getType())
                   << " S=" << Tok->SpacesRequiredBefore
                   << " F=" << Tok->Finalized << " B=" << Tok->BlockParameterCount
                   << " BK=" << Tok->getBlockKind() << " P=" << Tok->SplitPenalty
                   << " Name=" << Tok->Tok.getName() << " L=" << Tok->TotalLength
                   << " PPK=" << Tok->getPackingKind() << " FakeLParens=";
      for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
        llvm::errs() << Tok->FakeLParens[i] << "/";
      llvm::errs() << " FakeRParens=" << Tok->FakeRParens;
      llvm::errs() << " II=" << Tok->Tok.getIdentifierInfo();
      llvm::errs() << " Text='" << Tok->TokenText << "'\n";
      if (!Tok->Next)
        assert(Tok == Line.Last);
      Tok = Tok->Next;
    }
    llvm::errs() << "----\n";
  }
  
  } // namespace format
  } // namespace clang
  