//===--- 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 {

static bool mustBreakAfterAttributes(const FormatToken &Tok,
                                     const FormatStyle &Style) {
  switch (Style.BreakAfterAttributes) {
  case FormatStyle::ABS_Always:
    return true;
  case FormatStyle::ABS_Leave:
    return Tok.NewlinesBefore > 0;
  default:
    return false;
  }
}

namespace {

/// Returns \c true if the line starts with a token that can start a statement
/// with an initializer.
static bool startsWithInitStatement(const AnnotatedLine &Line) {
  return Line.startsWith(tok::kw_for) || Line.startsWith(tok::kw_if) ||
         Line.startsWith(tok::kw_switch);
}

/// 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();
}

/// With `Left` being '(', check if we're at either `[...](` or
/// `[...]<...>(`, where the [ opens a lambda capture list.
// FIXME: this doesn't cover attributes/constraints before the l_paren.
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);
}

/// Returns \c true if the token starts a C++ attribute, \c false otherwise.
static bool isCppAttribute(bool IsCpp, const FormatToken &Tok) {
  if (!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);
}

/// 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,
                   SmallVector<ScopeType> &Scopes)
      : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),
        IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)),
        Keywords(Keywords), Scopes(Scopes), TemplateDeclarationDepth(0) {
    assert(IsCpp == (LangOpts.CXXOperatorNames || LangOpts.C17));
    Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
    resetTokenMetadata();
  }

private:
  ScopeType getScopeType(const FormatToken &Token) const {
    switch (Token.getType()) {
    case TT_ClassLBrace:
    case TT_StructLBrace:
    case TT_UnionLBrace:
      return ST_Class;
    case TT_CompoundRequirementLBrace:
      return ST_CompoundRequirement;
    default:
      return ST_Other;
    }
  }

  bool parseAngle() {
    if (!CurrentToken)
      return false;

    auto *Left = CurrentToken->Previous; // The '<'.
    if (!Left)
      return false;

    if (NonTemplateLess.count(Left) > 0)
      return false;

    const auto *BeforeLess = Left->Previous;

    if (BeforeLess) {
      if (BeforeLess->Tok.isLiteral())
        return false;
      if (BeforeLess->is(tok::r_brace))
        return false;
      if (BeforeLess->is(tok::r_paren) && Contexts.size() > 1 &&
          !(BeforeLess->MatchingParen &&
            BeforeLess->MatchingParen->is(TT_OverloadedOperatorLParen))) {
        return false;
      }
      if (BeforeLess->is(tok::kw_operator) && CurrentToken->is(tok::l_paren))
        return false;
    }

    Left->ParentBracket = Contexts.back().ContextKind;
    ScopedContextCreator ContextCreator(*this, tok::less, 12);
    Contexts.back().IsExpression = false;

    // If there's a template keyword before the opening angle bracket, this is a
    // template parameter, not an argument.
    if (BeforeLess && BeforeLess->isNot(tok::kw_template))
      Contexts.back().ContextType = Context::TemplateArgument;

    if (Style.Language == FormatStyle::LK_Java &&
        CurrentToken->is(tok::question)) {
      next();
    }

    for (bool SeenTernaryOperator = false, MaybeAngles = true; CurrentToken;) {
      const bool InExpr = Contexts[Contexts.size() - 2].IsExpression;
      if (CurrentToken->is(tok::greater)) {
        const auto *Next = CurrentToken->Next;
        if (CurrentToken->isNot(TT_TemplateCloser)) {
          // Try to do a better job at looking for ">>" within the condition of
          // a statement. Conservatively insert spaces between consecutive ">"
          // tokens to prevent splitting right shift operators and potentially
          // altering program semantics. This check is overly conservative and
          // will prevent spaces from being inserted in select nested template
          // parameter cases, but should not alter program semantics.
          if (Next && Next->is(tok::greater) &&
              Left->ParentBracket != tok::less &&
              CurrentToken->getStartOfNonWhitespace() ==
                  Next->getStartOfNonWhitespace().getLocWithOffset(-1)) {
            return false;
          }
          if (InExpr && SeenTernaryOperator &&
              (!Next || !Next->isOneOf(tok::l_paren, tok::l_brace))) {
            return false;
          }
          if (!MaybeAngles)
            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 && BeforeLess &&
             BeforeLess->isOneOf(TT_SelectorName, TT_DictLiteral))) {
          CurrentToken->setType(TT_DictLiteral);
        } else {
          CurrentToken->setType(TT_TemplateCloser);
          CurrentToken->Tok.setLength(1);
        }
        if (Next && Next->Tok.isLiteral())
          return false;
        next();
        return true;
      }
      if (BeforeLess && BeforeLess->is(TT_TemplateName)) {
        next();
        continue;
      }
      if (CurrentToken->is(tok::question) &&
          Style.Language == FormatStyle::LK_Java) {
        next();
        continue;
      }
      if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace))
        return false;
      const auto &Prev = *CurrentToken->Previous;
      // 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 (MaybeAngles && InExpr && !Line.startsWith(tok::kw_template) &&
          Prev.is(TT_BinaryOperator) &&
          (Prev.isOneOf(tok::pipepipe, tok::ampamp) ||
           Prev.getPrecedence() == prec::Equality)) {
        MaybeAngles = false;
      }
      if (Prev.isOneOf(tok::question, tok::colon) && !Style.isProto())
        SeenTernaryOperator = true;
      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 (Style.isTableGen()) {
        if (CurrentToken->isOneOf(tok::comma, tok::equal)) {
          // They appear as separators. Unless they are not in class definition.
          next();
          continue;
        }
        // In angle, there must be Value like tokens. Types are also able to be
        // parsed in the same way with Values.
        if (!parseTableGenValue())
          return false;
        continue;
      }
      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 IsIf = false) {
    if (!CurrentToken)
      return false;
    assert(CurrentToken->Previous && "Unknown previous token");
    FormatToken &OpeningParen = *CurrentToken->Previous;
    assert(OpeningParen.is(tok::l_paren));
    FormatToken *PrevNonComment = OpeningParen.getPreviousNonComment();
    OpeningParen.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 (OpeningParen.Previous &&
        OpeningParen.Previous->is(TT_UntouchableMacroFunc)) {
      OpeningParen.Finalized = true;
      return parseUntouchableParens();
    }

    bool StartsObjCMethodExpr = false;
    if (!Style.isVerilog()) {
      if (FormatToken *MaybeSel = OpeningParen.Previous) {
        // @selector( starts a selector.
        if (MaybeSel->isObjCAtKeyword(tok::objc_selector) &&
            MaybeSel->Previous && MaybeSel->Previous->is(tok::at)) {
          StartsObjCMethodExpr = true;
        }
      }
    }

    if (OpeningParen.is(TT_OverloadedOperatorLParen)) {
      // Find the previous kw_operator token.
      FormatToken *Prev = &OpeningParen;
      while (Prev->isNot(tok::kw_operator)) {
        Prev = Prev->Previous;
        assert(Prev && "Expect a kw_operator prior to the OperatorLParen!");
      }

      // If faced with "a.operator*(argument)" or "a->operator*(argument)",
      // i.e. the operator is called as a member function,
      // then the argument must be an expression.
      bool OperatorCalledAsMemberFunction =
          Prev->Previous && Prev->Previous->isOneOf(tok::period, tok::arrow);
      Contexts.back().IsExpression = OperatorCalledAsMemberFunction;
    } else if (OpeningParen.is(TT_VerilogInstancePortLParen)) {
      Contexts.back().IsExpression = true;
      Contexts.back().ContextType = Context::VerilogInstancePortList;
    } else if (Style.isJavaScript() &&
               (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 (OpeningParen.Previous &&
               (OpeningParen.Previous->isOneOf(
                    tok::kw_static_assert, tok::kw_noexcept, tok::kw_explicit,
                    tok::kw_while, tok::l_paren, tok::comma, TT_CastRParen,
                    TT_BinaryOperator) ||
                OpeningParen.Previous->isIf())) {
      // static_assert, if and while usually contain expressions.
      Contexts.back().IsExpression = true;
    } else if (Style.isJavaScript() && OpeningParen.Previous &&
               (OpeningParen.Previous->is(Keywords.kw_function) ||
                (OpeningParen.Previous->endsSequence(tok::identifier,
                                                     Keywords.kw_function)))) {
      // function(...) or function f(...)
      Contexts.back().IsExpression = false;
    } else if (Style.isJavaScript() && OpeningParen.Previous &&
               OpeningParen.Previous->is(TT_JsTypeColon)) {
      // let x: (SomeType);
      Contexts.back().IsExpression = false;
    } else if (isLambdaParameterList(&OpeningParen)) {
      // This is a parameter list of a lambda expression.
      OpeningParen.setType(TT_LambdaDefinitionLParen);
      Contexts.back().IsExpression = false;
    } else if (OpeningParen.is(TT_RequiresExpressionLParen)) {
      Contexts.back().IsExpression = false;
    } else if (OpeningParen.Previous &&
               OpeningParen.Previous->is(tok::kw__Generic)) {
      Contexts.back().ContextType = Context::C11GenericSelection;
      Contexts.back().IsExpression = true;
    } else if (Line.InPPDirective &&
               (!OpeningParen.Previous ||
                OpeningParen.Previous->isNot(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 (OpeningParen.Previous &&
               OpeningParen.Previous->is(TT_ForEachMacro)) {
      // The first argument to a foreach macro is a declaration.
      Contexts.back().ContextType = Context::ForEachMacro;
      Contexts.back().IsExpression = false;
    } else if (OpeningParen.Previous && OpeningParen.Previous->MatchingParen &&
               OpeningParen.Previous->MatchingParen->isOneOf(
                   TT_ObjCBlockLParen, TT_FunctionTypeLParen)) {
      Contexts.back().IsExpression = false;
    } else if (!Line.MustBeDeclaration &&
               (!Line.InPPDirective || (Line.InMacroBody && !Scopes.empty()))) {
      bool IsForOrCatch =
          OpeningParen.Previous &&
          OpeningParen.Previous->isOneOf(tok::kw_for, tok::kw_catch);
      Contexts.back().IsExpression = !IsForOrCatch;
    }

    if (Style.isTableGen()) {
      if (FormatToken *Prev = OpeningParen.Previous) {
        if (Prev->is(TT_TableGenCondOperator)) {
          Contexts.back().IsTableGenCondOpe = true;
          Contexts.back().IsExpression = true;
        } else if (Contexts.size() > 1 &&
                   Contexts[Contexts.size() - 2].IsTableGenBangOpe) {
          // Hack to handle bang operators. The parent context's flag
          // was set by parseTableGenSimpleValue().
          // We have to specify the context outside because the prev of "(" may
          // be ">", not the bang operator in this case.
          Contexts.back().IsTableGenBangOpe = true;
          Contexts.back().IsExpression = true;
        } else {
          // Otherwise, this paren seems DAGArg.
          if (!parseTableGenDAGArg())
            return false;
          return parseTableGenDAGArgAndList(&OpeningParen);
        }
      }
    }

    // Infer the role of the l_paren based on the previous token if we haven't
    // detected one yet.
    if (PrevNonComment && OpeningParen.is(TT_Unknown)) {
      if (PrevNonComment->isAttribute()) {
        OpeningParen.setType(TT_AttributeLParen);
      } else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,
                                         tok::kw_typeof,
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
#include "clang/Basic/TransformTypeTraits.def"
                                         tok::kw__Atomic)) {
        OpeningParen.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;
      OpeningParen.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 (&&FunctionReference)(void);
    // void (^ObjCBlock)(void);
    bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression;
    bool ProbablyFunctionType =
        CurrentToken->isPointerOrReference() || CurrentToken->is(tok::caret);
    bool HasMultipleLines = false;
    bool HasMultipleParametersOnALine = false;
    bool MightBeObjCForRangeLoop =
        OpeningParen.Previous && OpeningParen.Previous->is(tok::kw_for);
    FormatToken *PossibleObjCForInToken = nullptr;
    while (CurrentToken) {
      const auto &Prev = *CurrentToken->Previous;
      const auto *PrevPrev = Prev.Previous;
      if (Prev.is(TT_PointerOrReference) &&
          PrevPrev->isOneOf(tok::l_paren, tok::coloncolon)) {
        ProbablyFunctionType = true;
      }
      if (CurrentToken->is(tok::comma))
        MightBeFunctionType = false;
      if (Prev.is(TT_BinaryOperator))
        Contexts.back().IsExpression = true;
      if (CurrentToken->is(tok::r_paren)) {
        if (Prev.is(TT_PointerOrReference) &&
            (PrevPrev == &OpeningParen || PrevPrev->is(tok::coloncolon))) {
          MightBeFunctionType = true;
        }
        if (OpeningParen.isNot(TT_CppCastLParen) && MightBeFunctionType &&
            ProbablyFunctionType && CurrentToken->Next &&
            (CurrentToken->Next->is(tok::l_paren) ||
             (CurrentToken->Next->is(tok::l_square) &&
              (Line.MustBeDeclaration ||
               (PrevNonComment && PrevNonComment->isTypeName(LangOpts)))))) {
          OpeningParen.setType(OpeningParen.Next->is(tok::caret)
                                   ? TT_ObjCBlockLParen
                                   : TT_FunctionTypeLParen);
        }
        OpeningParen.MatchingParen = CurrentToken;
        CurrentToken->MatchingParen = &OpeningParen;

        if (CurrentToken->Next && CurrentToken->Next->is(tok::l_brace) &&
            OpeningParen.Previous && OpeningParen.Previous->is(tok::l_paren)) {
          // Detect the case where macros are used to generate lambdas or
          // function bodies, e.g.:
          //   auto my_lambda = MACRO((Type *type, int i) { .. body .. });
          for (FormatToken *Tok = &OpeningParen; Tok != CurrentToken;
               Tok = Tok->Next) {
            if (Tok->is(TT_BinaryOperator) && Tok->isPointerOrReference())
              Tok->setType(TT_PointerOrReference);
          }
        }

        if (StartsObjCMethodExpr) {
          CurrentToken->setType(TT_ObjCMethodExpr);
          if (Contexts.back().FirstObjCSelectorName) {
            Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
                Contexts.back().LongestObjCSelectorName;
          }
        }

        if (OpeningParen.is(TT_AttributeLParen))
          CurrentToken->setType(TT_AttributeRParen);
        if (OpeningParen.is(TT_TypeDeclarationParen))
          CurrentToken->setType(TT_TypeDeclarationParen);
        if (OpeningParen.Previous &&
            OpeningParen.Previous->is(TT_JavaAnnotation)) {
          CurrentToken->setType(TT_JavaAnnotation);
        }
        if (OpeningParen.Previous &&
            OpeningParen.Previous->is(TT_LeadingJavaAnnotation)) {
          CurrentToken->setType(TT_LeadingJavaAnnotation);
        }
        if (OpeningParen.Previous &&
            OpeningParen.Previous->is(TT_AttributeSquare)) {
          CurrentToken->setType(TT_AttributeSquare);
        }

        if (!HasMultipleLines)
          OpeningParen.setPackingKind(PPK_Inconclusive);
        else if (HasMultipleParametersOnALine)
          OpeningParen.setPackingKind(PPK_BinPacked);
        else
          OpeningParen.setPackingKind(PPK_OnePerLine);

        next();
        return true;
      }
      if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
        return false;

      if (CurrentToken->is(tok::l_brace) && OpeningParen.is(TT_ObjCBlockLParen))
        OpeningParen.setType(TT_Unknown);
      if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
          !CurrentToken->Next->HasUnescapedNewline &&
          !CurrentToken->Next->isTrailingComment()) {
        HasMultipleParametersOnALine = true;
      }
      bool ProbablyFunctionTypeLParen =
          (CurrentToken->is(tok::l_paren) && CurrentToken->Next &&
           CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret));
      if ((Prev.isOneOf(tok::kw_const, tok::kw_auto) ||
           Prev.isTypeName(LangOpts)) &&
          !(CurrentToken->is(tok::l_brace) ||
            (CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) {
        Contexts.back().IsExpression = false;
      }
      if (CurrentToken->isOneOf(tok::semi, tok::colon)) {
        MightBeObjCForRangeLoop = false;
        if (PossibleObjCForInToken) {
          PossibleObjCForInToken->setType(TT_Unknown);
          PossibleObjCForInToken = nullptr;
        }
      }
      if (IsIf && CurrentToken->is(tok::semi)) {
        for (auto *Tok = OpeningParen.Next;
             Tok != CurrentToken &&
             !Tok->isOneOf(tok::equal, tok::l_paren, tok::l_brace);
             Tok = Tok->Next) {
          if (Tok->isPointerOrReference())
            Tok->setFinalizedType(TT_PointerOrReference);
        }
      }
      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;

      if (Style.isTableGen()) {
        if (CurrentToken->is(tok::comma)) {
          if (Contexts.back().IsTableGenCondOpe)
            CurrentToken->setType(TT_TableGenCondOperatorComma);
          next();
        } else if (CurrentToken->is(tok::colon)) {
          if (Contexts.back().IsTableGenCondOpe)
            CurrentToken->setType(TT_TableGenCondOperatorColon);
          next();
        }
        // In TableGen there must be Values in parens.
        if (!parseTableGenValue())
          return false;
        continue;
      }

      FormatToken *Tok = CurrentToken;
      if (!consumeToken())
        return false;
      updateParameterCount(&OpeningParen, 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->isAccessSpecifierKeyword() ||
        AttrTok->isOneOf(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 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 =
        IsCpp && Parent && Parent->is(TT_TemplateCloser) &&
        (Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
         Contexts.back().ContextType == Context::TemplateArgument);

    const bool IsInnerSquare = Contexts.back().InCpp11AttributeSpecifier;
    const bool IsCpp11AttributeSpecifier =
        isCppAttribute(IsCpp, *Left) || IsInnerSquare;

    // 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(IsCpp);
    bool StartsObjCMethodExpr =
        !IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&
        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);
        if (!IsInnerSquare && Left->Previous)
          Left->Previous->EndsCppAttributeGroup = false;
      } else if (Style.isJavaScript() && Parent &&
                 Contexts.back().ContextKind == tok::l_brace &&
                 Parent->isOneOf(tok::l_brace, tok::comma)) {
        Left->setType(TT_JsComputedPropertyName);
      } else if (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.isProto()) {
        // 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.isJavaScript() && 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 (!IsInnerSquare)
            CurrentToken->EndsCppAttributeGroup = true;
        }
        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->overwriteFixedType(TT_BinaryOperator);
        }
        // An arrow after an ObjC method expression is not a lambda arrow.
        if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next &&
            CurrentToken->Next->is(TT_LambdaArrow)) {
          CurrentToken->Next->overwriteFixedType(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;
        }
        if (Style.isTableGen() && Left->is(TT_TableGenListOpener))
          CurrentToken->setType(TT_TableGenListCloser);
        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 (!Style.isVerilog() && !Line.InPragmaDirective &&
                   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 (Style.isTableGen()) {
        if (CurrentToken->isOneOf(tok::comma, tok::minus, tok::ellipsis)) {
          // '-' and '...' appears as a separator in slice.
          next();
        } else {
          // In TableGen there must be a list of Values in square brackets.
          // It must be ValueList or SliceElements.
          if (!parseTableGenValue())
            return false;
        }
        updateParameterCount(Left, Tok);
        continue;
      }
      if (!consumeToken())
        return false;
      updateParameterCount(Left, Tok);
    }
    return false;
  }

  void skipToNextNonComment() {
    next();
    while (CurrentToken && CurrentToken->is(tok::comment))
      next();
  }

  // Simplified parser for TableGen Value. Returns true on success.
  // It consists of SimpleValues, SimpleValues with Suffixes, and Value followed
  // by '#', paste operator.
  // There also exists the case the Value is parsed as NameValue.
  // In this case, the Value ends if '{' is found.
  bool parseTableGenValue(bool ParseNameMode = false) {
    if (!CurrentToken)
      return false;
    while (CurrentToken->is(tok::comment))
      next();
    if (!parseTableGenSimpleValue())
      return false;
    if (!CurrentToken)
      return true;
    // Value "#" [Value]
    if (CurrentToken->is(tok::hash)) {
      if (CurrentToken->Next &&
          CurrentToken->Next->isOneOf(tok::colon, tok::semi, tok::l_brace)) {
        // Trailing paste operator.
        // These are only the allowed cases in TGParser::ParseValue().
        CurrentToken->setType(TT_TableGenTrailingPasteOperator);
        next();
        return true;
      }
      FormatToken *HashTok = CurrentToken;
      skipToNextNonComment();
      HashTok->setType(TT_Unknown);
      if (!parseTableGenValue(ParseNameMode))
        return false;
    }
    // In name mode, '{' is regarded as the end of the value.
    // See TGParser::ParseValue in TGParser.cpp
    if (ParseNameMode && CurrentToken->is(tok::l_brace))
      return true;
    // These tokens indicates this is a value with suffixes.
    if (CurrentToken->isOneOf(tok::l_brace, tok::l_square, tok::period)) {
      CurrentToken->setType(TT_TableGenValueSuffix);
      FormatToken *Suffix = CurrentToken;
      skipToNextNonComment();
      if (Suffix->is(tok::l_square))
        return parseSquare();
      if (Suffix->is(tok::l_brace)) {
        Scopes.push_back(getScopeType(*Suffix));
        return parseBrace();
      }
    }
    return true;
  }

  // TokVarName    ::=  "$" ualpha (ualpha |  "0"..."9")*
  // Appears as a part of DagArg.
  // This does not change the current token on fail.
  bool tryToParseTableGenTokVar() {
    if (!CurrentToken)
      return false;
    if (CurrentToken->is(tok::identifier) &&
        CurrentToken->TokenText.front() == '$') {
      skipToNextNonComment();
      return true;
    }
    return false;
  }

  // DagArg       ::=  Value [":" TokVarName] | TokVarName
  // Appears as a part of SimpleValue6.
  bool parseTableGenDAGArg(bool AlignColon = false) {
    if (tryToParseTableGenTokVar())
      return true;
    if (parseTableGenValue()) {
      if (CurrentToken && CurrentToken->is(tok::colon)) {
        if (AlignColon)
          CurrentToken->setType(TT_TableGenDAGArgListColonToAlign);
        else
          CurrentToken->setType(TT_TableGenDAGArgListColon);
        skipToNextNonComment();
        return tryToParseTableGenTokVar();
      }
      return true;
    }
    return false;
  }

  // Judge if the token is a operator ID to insert line break in DAGArg.
  // That is, TableGenBreakingDAGArgOperators is empty (by the definition of the
  // option) or the token is in the list.
  bool isTableGenDAGArgBreakingOperator(const FormatToken &Tok) {
    auto &Opes = Style.TableGenBreakingDAGArgOperators;
    // If the list is empty, all operators are breaking operators.
    if (Opes.empty())
      return true;
    // Otherwise, the operator is limited to normal identifiers.
    if (Tok.isNot(tok::identifier) ||
        Tok.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {
      return false;
    }
    // The case next is colon, it is not a operator of identifier.
    if (!Tok.Next || Tok.Next->is(tok::colon))
      return false;
    return llvm::is_contained(Opes, Tok.TokenText.str());
  }

  // SimpleValue6 ::=  "(" DagArg [DagArgList] ")"
  // This parses SimpleValue 6's inside part of "(" ")"
  bool parseTableGenDAGArgAndList(FormatToken *Opener) {
    FormatToken *FirstTok = CurrentToken;
    if (!parseTableGenDAGArg())
      return false;
    bool BreakInside = false;
    if (Style.TableGenBreakInsideDAGArg != FormatStyle::DAS_DontBreak) {
      // Specialized detection for DAGArgOperator, that determines the way of
      // line break for this DAGArg elements.
      if (isTableGenDAGArgBreakingOperator(*FirstTok)) {
        // Special case for identifier DAGArg operator.
        BreakInside = true;
        Opener->setType(TT_TableGenDAGArgOpenerToBreak);
        if (FirstTok->isOneOf(TT_TableGenBangOperator,
                              TT_TableGenCondOperator)) {
          // Special case for bang/cond operators. Set the whole operator as
          // the DAGArg operator. Always break after it.
          CurrentToken->Previous->setType(TT_TableGenDAGArgOperatorToBreak);
        } else if (FirstTok->is(tok::identifier)) {
          if (Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll)
            FirstTok->setType(TT_TableGenDAGArgOperatorToBreak);
          else
            FirstTok->setType(TT_TableGenDAGArgOperatorID);
        }
      }
    }
    // Parse the [DagArgList] part
    bool FirstDAGArgListElm = true;
    while (CurrentToken) {
      if (!FirstDAGArgListElm && CurrentToken->is(tok::comma)) {
        CurrentToken->setType(BreakInside ? TT_TableGenDAGArgListCommaToBreak
                                          : TT_TableGenDAGArgListComma);
        skipToNextNonComment();
      }
      if (CurrentToken && CurrentToken->is(tok::r_paren)) {
        CurrentToken->setType(TT_TableGenDAGArgCloser);
        Opener->MatchingParen = CurrentToken;
        CurrentToken->MatchingParen = Opener;
        skipToNextNonComment();
        return true;
      }
      if (!parseTableGenDAGArg(
              BreakInside &&
              Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled)) {
        return false;
      }
      FirstDAGArgListElm = false;
    }
    return false;
  }

  bool parseTableGenSimpleValue() {
    assert(Style.isTableGen());
    if (!CurrentToken)
      return false;
    FormatToken *Tok = CurrentToken;
    skipToNextNonComment();
    // SimpleValue 1, 2, 3: Literals
    if (Tok->isOneOf(tok::numeric_constant, tok::string_literal,
                     TT_TableGenMultiLineString, tok::kw_true, tok::kw_false,
                     tok::question, tok::kw_int)) {
      return true;
    }
    // SimpleValue 4: ValueList, Type
    if (Tok->is(tok::l_brace)) {
      Scopes.push_back(getScopeType(*Tok));
      return parseBrace();
    }
    // SimpleValue 5: List initializer
    if (Tok->is(tok::l_square)) {
      Tok->setType(TT_TableGenListOpener);
      if (!parseSquare())
        return false;
      if (Tok->is(tok::less)) {
        CurrentToken->setType(TT_TemplateOpener);
        return parseAngle();
      }
      return true;
    }
    // SimpleValue 6: DAGArg [DAGArgList]
    // SimpleValue6 ::=  "(" DagArg [DagArgList] ")"
    if (Tok->is(tok::l_paren)) {
      Tok->setType(TT_TableGenDAGArgOpener);
      return parseTableGenDAGArgAndList(Tok);
    }
    // SimpleValue 9: Bang operator
    if (Tok->is(TT_TableGenBangOperator)) {
      if (CurrentToken && CurrentToken->is(tok::less)) {
        CurrentToken->setType(TT_TemplateOpener);
        skipToNextNonComment();
        if (!parseAngle())
          return false;
      }
      if (!CurrentToken || CurrentToken->isNot(tok::l_paren))
        return false;
      next();
      // FIXME: Hack using inheritance to child context
      Contexts.back().IsTableGenBangOpe = true;
      bool Result = parseParens();
      Contexts.back().IsTableGenBangOpe = false;
      return Result;
    }
    // SimpleValue 9: Cond operator
    if (Tok->is(TT_TableGenCondOperator)) {
      if (!CurrentToken || CurrentToken->isNot(tok::l_paren))
        return false;
      next();
      return parseParens();
    }
    // We have to check identifier at the last because the kind of bang/cond
    // operators are also identifier.
    // SimpleValue 7: Identifiers
    if (Tok->is(tok::identifier)) {
      // SimpleValue 8: Anonymous record
      if (CurrentToken && CurrentToken->is(tok::less)) {
        CurrentToken->setType(TT_TemplateOpener);
        skipToNextNonComment();
        return parseAngle();
      }
      return true;
    }

    return false;
  }

  bool couldBeInStructArrayInitializer() const {
    if (Contexts.size() < 2)
      return false;
    // We want to back up no more then 2 context levels i.e.
    // . { { <-
    const auto End = std::next(Contexts.rbegin(), 2);
    auto Last = Contexts.rbegin();
    unsigned Depth = 0;
    for (; Last != End; ++Last)
      if (Last->ContextKind == tok::l_brace)
        ++Depth;
    return Depth == 2 && Last->ContextKind != tok::l_brace;
  }

  bool parseBrace() {
    if (!CurrentToken)
      return true;

    assert(CurrentToken->Previous);
    FormatToken &OpeningBrace = *CurrentToken->Previous;
    assert(OpeningBrace.is(tok::l_brace));
    OpeningBrace.ParentBracket = Contexts.back().ContextKind;

    if (Contexts.back().CaretFound)
      OpeningBrace.overwriteFixedType(TT_ObjCBlockLBrace);
    Contexts.back().CaretFound = false;

    ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
    Contexts.back().ColonIsDictLiteral = true;
    if (OpeningBrace.is(BK_BracedInit))
      Contexts.back().IsExpression = true;
    if (Style.isJavaScript() && OpeningBrace.Previous &&
        OpeningBrace.Previous->is(TT_JsTypeColon)) {
      Contexts.back().IsExpression = false;
    }
    if (Style.isVerilog() &&
        (!OpeningBrace.getPreviousNonComment() ||
         OpeningBrace.getPreviousNonComment()->isNot(Keywords.kw_apostrophe))) {
      Contexts.back().VerilogMayBeConcatenation = true;
    }
    if (Style.isTableGen())
      Contexts.back().ColonIsDictLiteral = false;

    unsigned CommaCount = 0;
    while (CurrentToken) {
      if (CurrentToken->is(tok::r_brace)) {
        assert(!Scopes.empty());
        assert(Scopes.back() == getScopeType(OpeningBrace));
        Scopes.pop_back();
        assert(OpeningBrace.Optional == CurrentToken->Optional);
        OpeningBrace.MatchingParen = CurrentToken;
        CurrentToken->MatchingParen = &OpeningBrace;
        if (Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
          if (OpeningBrace.ParentBracket == tok::l_brace &&
              couldBeInStructArrayInitializer() && CommaCount > 0) {
            Contexts.back().ContextType = Context::StructArrayInitializer;
          }
        }
        next();
        return true;
      }
      if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
        return false;
      updateParameterCount(&OpeningBrace, 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) && !Style.isTableGen() &&
             (!Contexts.back().ColonIsDictLiteral || !IsCpp)) ||
            Style.isProto()) {
          OpeningBrace.setType(TT_DictLiteral);
          if (Previous->Tok.getIdentifierInfo() ||
              Previous->is(tok::string_literal)) {
            Previous->setType(TT_SelectorName);
          }
        }
        if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown) &&
            !Style.isTableGen()) {
          OpeningBrace.setType(TT_DictLiteral);
        } else if (Style.isJavaScript()) {
          OpeningBrace.overwriteFixedType(TT_DictLiteral);
        }
      }
      if (CurrentToken->is(tok::comma)) {
        if (Style.isJavaScript())
          OpeningBrace.overwriteFixedType(TT_DictLiteral);
        ++CommaCount;
      }
      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->is(TT_Unknown)) {
        CurrentToken->setType(TT_ConditionalExpr);
        next();
        return true;
      }
      if (!consumeToken())
        return false;
    }
    return false;
  }

  bool parseTemplateDeclaration() {
    if (!CurrentToken || CurrentToken->isNot(tok::less))
      return false;

    CurrentToken->setType(TT_TemplateOpener);
    next();

    TemplateDeclarationDepth++;
    const bool WellFormed = parseAngle();
    TemplateDeclarationDepth--;
    if (!WellFormed)
      return false;

    if (CurrentToken && TemplateDeclarationDepth == 0)
      CurrentToken->Previous->ClosesTemplateDeclaration = true;

    return true;
  }

  bool consumeToken() {
    if (IsCpp) {
      const auto *Prev = CurrentToken->getPreviousNonComment();
      if (Prev && Prev->is(tok::r_square) && Prev->is(TT_AttributeSquare) &&
          CurrentToken->isOneOf(tok::kw_if, tok::kw_switch, tok::kw_case,
                                tok::kw_default, tok::kw_for, tok::kw_while) &&
          mustBreakAfterAttributes(*CurrentToken, Style)) {
        CurrentToken->MustBreakBefore = true;
      }
    }
    FormatToken *Tok = CurrentToken;
    next();
    // In Verilog primitives' state tables, `:`, `?`, and `-` aren't normal
    // operators.
    if (Tok->is(TT_VerilogTableItem))
      return true;
    // Multi-line string itself is a single annotated token.
    if (Tok->is(TT_TableGenMultiLineString))
      return true;
    switch (bool IsIf = false; Tok->Tok.getKind()) {
    case tok::plus:
    case tok::minus:
      if (!Tok->getPreviousNonComment() && Line.MustBeDeclaration)
        Tok->setType(TT_ObjCMethodSpecifier);
      break;
    case tok::colon:
      if (!Tok->Previous)
        return false;
      // Goto labels and case labels are already identified in
      // UnwrappedLineParser.
      if (Tok->isTypeFinalized())
        break;
      // Colons from ?: are handled in parseConditional().
      if (Style.isJavaScript()) {
        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;
        }
      } else if (Style.isVerilog() && Tok->isNot(TT_BinaryOperator)) {
        // The distribution weight operators are labeled
        // TT_BinaryOperator by the lexer.
        if (Keywords.isVerilogEnd(*Tok->Previous) ||
            Keywords.isVerilogBegin(*Tok->Previous)) {
          Tok->setType(TT_VerilogBlockLabelColon);
        } else if (Contexts.back().ContextKind == tok::l_square) {
          Tok->setType(TT_BitFieldColon);
        } else if (Contexts.back().ColonIsDictLiteral) {
          Tok->setType(TT_DictLiteral);
        } else if (Contexts.size() == 1) {
          // In Verilog a case label doesn't have the case keyword. We
          // assume a colon following an expression is a case label.
          // Colons from ?: are annotated in parseConditional().
          Tok->setType(TT_CaseLabelColon);
          if (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))
            --Line.Level;
        }
        break;
      }
      if (Line.First->isOneOf(Keywords.kw_module, Keywords.kw_import) ||
          Line.First->startsSequence(tok::kw_export, Keywords.kw_module) ||
          Line.First->startsSequence(tok::kw_export, Keywords.kw_import)) {
        Tok->setType(TT_ModulePartitionColon);
      } else if (Line.First->is(tok::kw_asm)) {
        Tok->setType(TT_InlineASMColon);
      } else if (Contexts.back().ColonIsDictLiteral || Style.isProto()) {
        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);
        for (auto *Prev = Tok->Previous;
             Prev && !Prev->isOneOf(tok::semi, tok::l_paren);
             Prev = Prev->Previous) {
          if (Prev->isPointerOrReference())
            Prev->setFinalizedType(TT_PointerOrReference);
        }
      } else if (Contexts.back().ContextType == Context::C11GenericSelection) {
        Tok->setType(TT_GenericSelectionColon);
      } 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)
          break;
        if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept) ||
            Prev->ClosesRequiresClause) {
          Tok->setType(TT_CtorInitializerColon);
        } else if (Prev->is(tok::kw_try)) {
          // Member initializer list within function try block.
          FormatToken *PrevPrev = Prev->getPreviousNonComment();
          if (!PrevPrev)
            break;
          if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept))
            Tok->setType(TT_CtorInitializerColon);
        } else {
          Tok->setType(TT_InheritanceColon);
          if (Prev->isAccessSpecifierKeyword())
            Line.Type = LT_AccessModifier;
        }
      } 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);
      }
      break;
    case tok::pipe:
    case tok::amp:
      // | and & in declarations/type expressions represent union and
      // intersection types, respectively.
      if (Style.isJavaScript() && !Contexts.back().IsExpression)
        Tok->setType(TT_JsTypeOperator);
      break;
    case tok::kw_if:
      if (Style.isTableGen()) {
        // In TableGen it has the form 'if' <value> 'then'.
        if (!parseTableGenValue())
          return false;
        if (CurrentToken && CurrentToken->is(Keywords.kw_then))
          next(); // skip then
        break;
      }
      if (CurrentToken &&
          CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier)) {
        next();
      }
      IsIf = true;
      [[fallthrough]];
    case tok::kw_while:
      if (CurrentToken && CurrentToken->is(tok::l_paren)) {
        next();
        if (!parseParens(IsIf))
          return false;
      }
      break;
    case tok::kw_for:
      if (Style.isJavaScript()) {
        // 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();
      }
      if (IsCpp && CurrentToken && CurrentToken->is(tok::kw_co_await))
        next();
      Contexts.back().ColonIsForRangeExpr = true;
      if (!CurrentToken || CurrentToken->isNot(tok::l_paren))
        return false;
      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 (Style.isVerilog()) {
        // Identify the parameter list and port list in a module instantiation.
        // This is still needed when we already have
        // UnwrappedLineParser::parseVerilogHierarchyHeader because that
        // function is only responsible for the definition, not the
        // instantiation.
        auto IsInstancePort = [&]() {
          const FormatToken *Prev = Tok->getPreviousNonComment();
          const FormatToken *PrevPrev;
          // In the following example all 4 left parentheses will be treated as
          // 'TT_VerilogInstancePortLParen'.
          //
          //   module_x instance_1(port_1); // Case A.
          //   module_x #(parameter_1)      // Case B.
          //       instance_2(port_1),      // Case C.
          //       instance_3(port_1);      // Case D.
          if (!Prev || !(PrevPrev = Prev->getPreviousNonComment()))
            return false;
          // Case A.
          if (Keywords.isVerilogIdentifier(*Prev) &&
              Keywords.isVerilogIdentifier(*PrevPrev)) {
            return true;
          }
          // Case B.
          if (Prev->is(Keywords.kw_verilogHash) &&
              Keywords.isVerilogIdentifier(*PrevPrev)) {
            return true;
          }
          // Case C.
          if (Keywords.isVerilogIdentifier(*Prev) && PrevPrev->is(tok::r_paren))
            return true;
          // Case D.
          if (Keywords.isVerilogIdentifier(*Prev) && PrevPrev->is(tok::comma)) {
            const FormatToken *PrevParen = PrevPrev->getPreviousNonComment();
            if (PrevParen && PrevParen->is(tok::r_paren) &&
                PrevParen->MatchingParen &&
                PrevParen->MatchingParen->is(TT_VerilogInstancePortLParen)) {
              return true;
            }
          }
          return false;
        };

        if (IsInstancePort())
          Tok->setType(TT_VerilogInstancePortLParen);
      }

      if (!parseParens())
        return false;
      if (Line.MustBeDeclaration && Contexts.size() == 1 &&
          !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
          !Line.startsWith(tok::l_paren) &&
          !Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) {
        if (const auto *Previous = Tok->Previous;
            !Previous ||
            (!Previous->isAttribute() &&
             !Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation,
                                TT_BinaryOperator))) {
          Line.MightBeFunctionDecl = true;
          Tok->MightBeFunctionDeclParen = true;
        }
      }
      break;
    case tok::l_square:
      if (Style.isTableGen())
        Tok->setType(TT_TableGenListOpener);
      if (!parseSquare())
        return false;
      break;
    case tok::l_brace:
      if (IsCpp) {
        if (Tok->is(TT_RequiresExpressionLBrace))
          Line.Type = LT_RequiresExpression;
      } else if (Style.Language == FormatStyle::LK_TextProto) {
        FormatToken *Previous = Tok->getPreviousNonComment();
        if (Previous && Previous->isNot(TT_DictLiteral))
          Previous->setType(TT_SelectorName);
      }
      Scopes.push_back(getScopeType(*Tok));
      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->isNot(TT_DictLiteral))
            Previous->setType(TT_SelectorName);
        }
        if (Style.isTableGen())
          Tok->setType(TT_TemplateOpener);
      } 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:
      // Don't pop scope when encountering unbalanced r_brace.
      if (!Scopes.empty())
        Scopes.pop_back();
      // Lines can start with '}'.
      if (Tok->Previous)
        return false;
      break;
    case tok::greater:
      if (Style.Language != FormatStyle::LK_TextProto && Tok->is(TT_Unknown))
        Tok->setType(TT_BinaryOperator);
      if (Tok->Previous && Tok->Previous->is(TT_TemplateCloser))
        Tok->SpacesRequiredBefore = 1;
      break;
    case tok::kw_operator:
      if (Style.isProto())
        break;
      while (CurrentToken &&
             !CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) {
        if (CurrentToken->isOneOf(tok::star, tok::amp))
          CurrentToken->setType(TT_PointerOrReference);
        auto Next = CurrentToken->getNextNonComment();
        if (!Next)
          break;
        if (Next->is(tok::less))
          next();
        else
          consumeToken();
        if (!CurrentToken)
          break;
        auto Previous = CurrentToken->getPreviousNonComment();
        assert(Previous);
        if (CurrentToken->is(tok::comma) && Previous->isNot(tok::kw_operator))
          break;
        if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator, tok::comma,
                              tok::star, tok::arrow, tok::amp, tok::ampamp) ||
            // User defined literal.
            Previous->TokenText.starts_with("\"\"")) {
          Previous->setType(TT_OverloadedOperator);
          if (CurrentToken->isOneOf(tok::less, tok::greater))
            break;
        }
      }
      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 (Style.isJavaScript() && Tok->Next &&
          Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren,
                             tok::r_brace, tok::r_square)) {
        // 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.isJavaScript()) {
        break;
      }
      if (Style.isCSharp()) {
        // `Type?)`, `Type?>`, `Type? name;` and `Type? name =` can only be
        // nullable types.

        // `Type?)`, `Type?>`, `Type? name;`
        if (Tok->Next &&
            (Tok->Next->startsSequence(tok::question, tok::r_paren) ||
             Tok->Next->startsSequence(tok::question, tok::greater) ||
             Tok->Next->startsSequence(tok::question, tok::identifier,
                                       tok::semi))) {
          Tok->setType(TT_CSharpNullable);
          break;
        }

        // `Type? name =`
        if (Tok->Next && Tok->Next->is(tok::identifier) && Tok->Next->Next &&
            Tok->Next->Next->is(tok::equal)) {
          Tok->setType(TT_CSharpNullable);
          break;
        }

        // Line.MustBeDeclaration will be true for `Type? name;`.
        // But not
        // cond ? "A" : "B";
        // cond ? id : "B";
        // cond ? cond2 ? "A" : "B" : "C";
        if (!Contexts.back().IsExpression && Line.MustBeDeclaration &&
            (!Tok->Next ||
             !Tok->Next->isOneOf(tok::identifier, tok::string_literal) ||
             !Tok->Next->Next ||
             !Tok->Next->Next->isOneOf(tok::colon, tok::question))) {
          Tok->setType(TT_CSharpNullable);
          break;
        }
      }
      parseConditional();
      break;
    case tok::kw_template:
      parseTemplateDeclaration();
      break;
    case tok::comma:
      switch (Contexts.back().ContextType) {
      case Context::CtorInitializer:
        Tok->setType(TT_CtorInitializerComma);
        break;
      case Context::InheritanceList:
        Tok->setType(TT_InheritanceComma);
        break;
      case Context::VerilogInstancePortList:
        Tok->setType(TT_VerilogInstancePortComma);
        break;
      default:
        if (Style.isVerilog() && Contexts.size() == 1 &&
            Line.startsWith(Keywords.kw_assign)) {
          Tok->setFinalizedType(TT_VerilogAssignComma);
        } else if (Contexts.back().FirstStartOfName &&
                   (Contexts.size() == 1 || startsWithInitStatement(Line))) {
          Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
          Line.IsMultiVariableDeclStmt = true;
        }
        break;
      }
      if (Contexts.back().ContextType == Context::ForEachMacro)
        Contexts.back().IsExpression = true;
      break;
    case tok::kw_default:
      // Unindent case labels.
      if (Style.isVerilog() && Keywords.isVerilogEndOfLabel(*Tok) &&
          (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))) {
        --Line.Level;
      }
      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();
        if (!Tok->getPreviousNonComment())
          Line.IsContinuation = true;
      }
      if (Style.isTableGen()) {
        if (Tok->is(Keywords.kw_assert)) {
          if (!parseTableGenValue())
            return false;
        } else if (Tok->isOneOf(Keywords.kw_def, Keywords.kw_defm) &&
                   (!Tok->Next ||
                    !Tok->Next->isOneOf(tok::colon, tok::l_brace))) {
          // The case NameValue appears.
          if (!parseTableGenValue(true))
            return false;
        }
      }
      break;
    case tok::arrow:
      if (Tok->isNot(TT_LambdaArrow) && Tok->Previous &&
          Tok->Previous->is(tok::kw_noexcept)) {
        Tok->setType(TT_TrailingReturnArrow);
      }
      break;
    case tok::equal:
      // In TableGen, there must be a value after "=";
      if (Style.isTableGen() && !parseTableGenValue())
        return false;
      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.starts_with("//")) {
          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,
                              Keywords.kw_region)) {
      bool IsMarkOrRegion =
          CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_region);
      next();
      next(); // Consume first token (so we fix leading whitespace).
      while (CurrentToken) {
        if (IsMarkOrRegion || CurrentToken->Previous->is(TT_BinaryOperator))
          CurrentToken->setType(TT_ImplicitStringLiteral);
        next();
      }
    }
  }

  void parseHasInclude() {
    if (!CurrentToken || CurrentToken->isNot(tok::l_paren))
      return;
    next(); // '('
    parseIncludeDirective();
    next(); // ')'
  }

  LineType parsePreprocessorDirective() {
    bool IsFirstToken = CurrentToken->IsFirst;
    LineType Type = LT_PreprocessorDirective;
    next();
    if (!CurrentToken)
      return Type;

    if (Style.isJavaScript() && 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->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;
    // In Verilog macro expansions start with a backtick just like preprocessor
    // directives. Thus we stop if the word is not a preprocessor directive.
    if (Style.isVerilog() && !Keywords.isVerilogPPDirective(*CurrentToken))
      return LT_Invalid;
    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();
      if (CurrentToken)
        CurrentToken->SpacesRequiredBefore = true;
      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 (!Line.InMacroBody && CurrentToken->is(tok::hash)) {
      // We were not yet allowed to use C++17 optional when this was being
      // written. So we used LT_Invalid to mark that the line is not a
      // preprocessor directive.
      auto Type = parsePreprocessorDirective();
      if (Type != LT_Invalid)
        return Type;
    }

    // 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)) ||
        (!Style.isVerilog() && 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.isJavaScript() && CurrentToken->is(Keywords.kw_import))
      ImportStatement = true;

    while (CurrentToken) {
      if (CurrentToken->is(tok::kw_virtual))
        KeywordVirtualFound = true;
      if (Style.isJavaScript()) {
        // 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 (const auto Type = Line.Type; Type == LT_AccessModifier ||
                                     Type == LT_RequiresExpression ||
                                     Type == LT_SimpleRequirement) {
      return Type;
    }
    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;
    }

    for (const auto &ctx : Contexts)
      if (ctx.ContextType == Context::StructArrayInitializer)
        return LT_ArrayOfStructInitializer;

    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() {
    if (!CurrentToken)
      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->isTypeFinalized() &&
        !CurrentToken->isOneOf(
            TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro, TT_IfMacro,
            TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace,
            TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_FatArrow,
            TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,
            TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral,
            TT_UntouchableMacroFunc, TT_StatementAttributeLikeMacro,
            TT_FunctionLikeOrFreestandingMacro, TT_ClassLBrace, TT_EnumLBrace,
            TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause,
            TT_RequiresClauseInARequiresExpression, TT_RequiresExpression,
            TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace,
            TT_CompoundRequirementLBrace, TT_BracedListLBrace)) {
      CurrentToken->setType(TT_Unknown);
    }
    CurrentToken->Role.reset();
    CurrentToken->MatchingParen = nullptr;
    CurrentToken->FakeLParens.clear();
    CurrentToken->FakeRParens = 0;
  }

  void next() {
    if (!CurrentToken)
      return;

    CurrentToken->NestingLevel = Contexts.size() - 1;
    CurrentToken->BindingStrength = Contexts.back().BindingStrength;
    modifyContext(*CurrentToken);
    determineTokenType(*CurrentToken);
    CurrentToken = CurrentToken->Next;

    resetTokenMetadata();
  }

  /// 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 CaretFound = false;
    bool InCpp11AttributeSpecifier = false;
    bool InCSharpAttributeSpecifier = false;
    bool VerilogAssignmentFound = false;
    // Whether the braces may mean concatenation instead of structure or array
    // literal.
    bool VerilogMayBeConcatenation = false;
    bool IsTableGenDAGArg = false;
    bool IsTableGenBangOpe = false;
    bool IsTableGenCondOpe = false;
    enum {
      Unknown,
      // Like the part after `:` in a constructor.
      //   Context(...) : IsExpression(IsExpression)
      CtorInitializer,
      // Like in the parentheses in a foreach.
      ForEachMacro,
      // Like the inheritance list in a class declaration.
      //   class Input : public IO
      InheritanceList,
      // Like in the braced list.
      //   int x[] = {};
      StructArrayInitializer,
      // Like in `static_cast<int>`.
      TemplateArgument,
      // C11 _Generic selection.
      C11GenericSelection,
      // Like in the outer parentheses in `ffnand ff1(.q());`.
      VerilogInstancePortList,
    } ContextType = Unknown;
  };

  /// 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() {
      if (P.Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
        if (P.Contexts.back().ContextType == Context::StructArrayInitializer) {
          P.Contexts.pop_back();
          P.Contexts.back().ContextType = Context::StructArrayInitializer;
          return;
        }
      }
      P.Contexts.pop_back();
    }
  };

  void modifyContext(const FormatToken &Current) {
    auto AssignmentStartsExpression = [&]() {
      if (Current.getPrecedence() != prec::Assignment)
        return false;

      if (Line.First->isOneOf(tok::kw_using, tok::kw_return))
        return false;
      if (Line.First->is(tok::kw_template)) {
        assert(Current.Previous);
        if (Current.Previous->is(tok::kw_operator)) {
          // `template ... operator=` cannot be an expression.
          return false;
        }

        // `template` keyword can start a variable template.
        const FormatToken *Tok = Line.First->getNextNonComment();
        assert(Tok); // Current token is on the same line.
        if (Tok->isNot(TT_TemplateOpener)) {
          // Explicit template instantiations do not have `<>`.
          return false;
        }

        // This is the default value of a template parameter, determine if it's
        // type or non-type.
        if (Contexts.back().ContextKind == tok::less) {
          assert(Current.Previous->Previous);
          return !Current.Previous->Previous->isOneOf(tok::kw_typename,
                                                      tok::kw_class);
        }

        Tok = Tok->MatchingParen;
        if (!Tok)
          return false;
        Tok = Tok->getNextNonComment();
        if (!Tok)
          return false;

        if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_struct,
                         tok::kw_using)) {
          return false;
        }

        return true;
      }

      // Type aliases use `type X = ...;` in TypeScript and can be exported
      // using `export type ...`.
      if (Style.isJavaScript() &&
          (Line.startsWith(Keywords.kw_type, tok::identifier) ||
           Line.startsWith(tok::kw_export, Keywords.kw_type,
                           tok::identifier))) {
        return false;
      }

      return !Current.Previous || Current.Previous->isNot(tok::kw_operator);
    };

    if (AssignmentStartsExpression()) {
      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, tok::greater)) {
            Previous = Previous->MatchingParen;
            if (!Previous)
              break;
          }
          if (Previous->opensScope())
            break;
          if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) &&
              Previous->isPointerOrReference() && Previous->Previous &&
              Previous->Previous->isNot(tok::equal)) {
            Previous->setType(TT_PointerOrReference);
          }
        }
      }
    } else if (Current.is(tok::lessless) &&
               (!Current.Previous ||
                Current.Previous->isNot(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.isOneOf(TT_LambdaArrow, 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().ContextType = Context::CtorInitializer;
    } else if (Current.Previous && Current.Previous->is(TT_InheritanceColon)) {
      Contexts.back().ContextType = Context::InheritanceList;
    } 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().ContextType != Context::CtorInitializer) {
        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->isNot(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)
            break;
        }
        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;

        return LeadingIdentifier &&
               LeadingIdentifier->TokenText == Current.Next->TokenText;
      }
    }
    return false;
  }

  void determineTokenType(FormatToken &Current) {
    if (Current.isNot(TT_Unknown)) {
      // The token type is already known.
      return;
    }

    if ((Style.isJavaScript() || Style.isCSharp()) &&
        Current.is(tok::exclaim)) {
      if (Current.Previous) {
        bool IsIdentifier =
            Style.isJavaScript()
                ? Keywords.isJavaScriptIdentifier(
                      *Current.Previous, /* AcceptIdentifierName= */ true)
                : Current.Previous->is(tok::identifier);
        if (IsIdentifier ||
            Current.Previous->isOneOf(
                tok::kw_default, tok::kw_namespace, tok::r_paren, tok::r_square,
                tok::r_brace, tok::kw_false, tok::kw_true, Keywords.kw_type,
                Keywords.kw_get, Keywords.kw_init, Keywords.kw_set) ||
            Current.Previous->Tok.isLiteral()) {
          Current.setType(TT_NonNullAssertion);
          return;
        }
      }
      if (Current.Next &&
          Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) {
        Current.setType(TT_NonNullAssertion);
        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 ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) &&
        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) && Style.isVerilog()) {
      // The implication operator.
      Current.setType(TT_BinaryOperator);
    } else if (Current.is(tok::arrow) && AutoFound &&
               Line.MightBeFunctionDecl && Current.NestingLevel == 0 &&
               !Current.Previous->isOneOf(tok::kw_operator, tok::identifier)) {
      // not auto operator->() -> xxx;
      Current.setType(TT_TrailingReturnArrow);
    } else if (Current.is(tok::arrow) && Current.Previous &&
               Current.Previous->is(tok::r_brace) &&
               Current.Previous->is(BK_Block)) {
      // Concept implicit conversion constraint 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.isPointerOrReference()) {
      Current.setType(determineStarAmpUsage(
          Current,
          Contexts.back().CanBeExpression && Contexts.back().IsExpression,
          Contexts.back().ContextType == Context::TemplateArgument));
    } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) ||
               (Style.isVerilog() && Current.is(tok::pipe))) {
      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.isJavaScript() && 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 if (Style.isTableGen()) {
        // In TableGen, '?' is just an identifier like token.
        Current.setType(TT_Unknown);
      } else {
        Current.setType(TT_ConditionalExpr);
      }
    } else if (Current.isBinaryOperator() &&
               (!Current.Previous || Current.Previous->isNot(tok::l_square)) &&
               (Current.isNot(tok::greater) &&
                Style.Language != FormatStyle::LK_TextProto)) {
      if (Style.isVerilog()) {
        if (Current.is(tok::lessequal) && Contexts.size() == 1 &&
            !Contexts.back().VerilogAssignmentFound) {
          // In Verilog `<=` is assignment if in its own statement. It is a
          // statement instead of an expression, that is it can not be chained.
          Current.ForcedPrecedence = prec::Assignment;
          Current.setFinalizedType(TT_BinaryOperator);
        }
        if (Current.getPrecedence() == prec::Assignment)
          Contexts.back().VerilogAssignmentFound = true;
      }
      Current.setType(TT_BinaryOperator);
    } else if (Current.is(tok::comment)) {
      if (Current.TokenText.starts_with("/*")) {
        if (Current.TokenText.ends_with("*/")) {
          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::string_literal)) {
      if (Style.isVerilog() && Contexts.back().VerilogMayBeConcatenation &&
          Current.getPreviousNonComment() &&
          Current.getPreviousNonComment()->isOneOf(tok::comma, tok::l_brace) &&
          Current.getNextNonComment() &&
          Current.getNextNonComment()->isOneOf(tok::comma, tok::r_brace)) {
        Current.setType(TT_StringInConcatenation);
      }
    } else if (Current.is(tok::l_paren)) {
      if (lParenStartsCppCast(Current))
        Current.setType(TT_CppCastLParen);
    } 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::l_paren, tok::comma,
              tok::period, tok::arrow, tok::coloncolon, tok::kw_noexcept)) {
        if (FormatToken *AfterParen = Current.MatchingParen->Next;
            AfterParen && AfterParen->isNot(tok::caret)) {
          // Make sure this isn't the return type of an Obj-C block declaration.
          if (FormatToken *BeforeParen = Current.MatchingParen->Previous;
              BeforeParen && BeforeParen->is(tok::identifier) &&
              BeforeParen->isNot(TT_TypenameMacro) &&
              BeforeParen->TokenText == BeforeParen->TokenText.upper() &&
              (!BeforeParen->Previous ||
               BeforeParen->Previous->ClosesTemplateDeclaration ||
               BeforeParen->Previous->ClosesRequiresClause)) {
            Current.setType(TT_FunctionAnnotationRParen);
          }
        }
      }
    } else if (Current.is(tok::at) && Current.Next && !Style.isJavaScript() &&
               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,
                                          TT_CtorInitializerComma,
                                          TT_CtorInitializerColon) &&
               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.isJavaScript()) &&
               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) {
    // Handled in ExpressionParser for Verilog.
    if (Style.isVerilog())
      return false;

    if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName))
      return false;

    if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) &&
        Tok.is(Keywords.kw_extends)) {
      return false;
    }

    if (const auto *NextNonComment = Tok.getNextNonComment();
        (!NextNonComment && !Line.InMacroBody) ||
        (NextNonComment &&
         (NextNonComment->isPointerOrReference() ||
          NextNonComment->isOneOf(TT_ClassHeadName, tok::string_literal) ||
          (Line.InPragmaDirective && NextNonComment->is(tok::identifier))))) {
      return false;
    }

    if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof,
                              Keywords.kw_as)) {
      return false;
    }
    if (Style.isJavaScript() && 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();

    // For javascript const can be like "let" or "var"
    if (!Style.isJavaScript())
      while (PreviousNotConst && PreviousNotConst->is(tok::kw_const))
        PreviousNotConst = PreviousNotConst->getPreviousNonComment();

    if (!PreviousNotConst)
      return false;

    if (PreviousNotConst->ClosesRequiresClause)
      return false;

    if (Style.isTableGen()) {
      // keywords such as let and def* defines names.
      if (Keywords.isTableGenDefinition(*PreviousNotConst))
        return true;
      // Otherwise C++ style declarations is available only inside the brace.
      if (Contexts.back().ContextKind != tok::l_brace)
        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)) ||
        PreviousNotConst->is(TT_AttributeRParen)) {
      return true;
    }

    // If is a preprocess keyword like #define.
    if (IsPPKeyword)
      return false;

    // int a or auto a.
    if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto) &&
        PreviousNotConst->isNot(TT_StatementAttributeLikeMacro)) {
      return true;
    }

    // *a or &a or &&a.
    if (PreviousNotConst->is(TT_PointerOrReference))
      return true;

    // MyClass a;
    if (PreviousNotConst->isTypeName(LangOpts))
      return true;

    // type[] a in Java
    if (Style.Language == FormatStyle::LK_Java &&
        PreviousNotConst->is(tok::r_square)) {
      return true;
    }

    // const a = in JavaScript.
    return Style.isJavaScript() && PreviousNotConst->is(tok::kw_const);
  }

  /// Determine whether '(' is starting a C++ cast.
  bool lParenStartsCppCast(const FormatToken &Tok) {
    // C-style casts are only used in C++.
    if (!IsCpp)
      return false;

    FormatToken *LeftOfParens = Tok.getPreviousNonComment();
    if (LeftOfParens && LeftOfParens->is(TT_TemplateCloser) &&
        LeftOfParens->MatchingParen) {
      auto *Prev = LeftOfParens->MatchingParen->getPreviousNonComment();
      if (Prev &&
          Prev->isOneOf(tok::kw_const_cast, tok::kw_dynamic_cast,
                        tok::kw_reinterpret_cast, tok::kw_static_cast)) {
        // FIXME: Maybe we should handle identifiers ending with "_cast",
        // e.g. any_cast?
        return true;
      }
    }
    return false;
  }

  /// Determine whether ')' is ending a cast.
  bool rParenEndsCast(const FormatToken &Tok) {
    assert(Tok.is(tok::r_paren));

    if (!Tok.MatchingParen || !Tok.Previous)
      return false;

    // C-style casts are only used in C++, C# and Java.
    if (!IsCpp && !Style.isCSharp() && Style.Language != FormatStyle::LK_Java)
      return false;

    const auto *LParen = Tok.MatchingParen;
    const auto *BeforeRParen = Tok.Previous;
    const auto *AfterRParen = Tok.Next;

    // Empty parens aren't casts and there are no casts at the end of the line.
    if (BeforeRParen == LParen || !AfterRParen)
      return false;

    if (LParen->is(TT_OverloadedOperatorLParen))
      return false;

    auto *LeftOfParens = LParen->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) &&
          LeftOfParens->isNot(TT_CastRParen)) {
        if (!LeftOfParens->MatchingParen ||
            !LeftOfParens->MatchingParen->Previous) {
          return false;
        }
        LeftOfParens = LeftOfParens->MatchingParen->Previous;
      }

      if (LeftOfParens->is(tok::r_square)) {
        //   delete[] (void *)ptr;
        auto MayBeArrayDelete = [](FormatToken *Tok) -> FormatToken * {
          if (Tok->isNot(tok::r_square))
            return nullptr;

          Tok = Tok->getPreviousNonComment();
          if (!Tok || Tok->isNot(tok::l_square))
            return nullptr;

          Tok = Tok->getPreviousNonComment();
          if (!Tok || Tok->isNot(tok::kw_delete))
            return nullptr;
          return Tok;
        };
        if (FormatToken *MaybeDelete = MayBeArrayDelete(LeftOfParens))
          LeftOfParens = MaybeDelete;
      }

      // The Condition directly below this one will see the operator arguments
      // as a (void *foo) cast.
      //   void operator delete(void *foo) ATTRIB;
      if (LeftOfParens->Tok.getIdentifierInfo() && LeftOfParens->Previous &&
          LeftOfParens->Previous->is(tok::kw_operator)) {
        return false;
      }

      // 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, tok::kw_throw)) {
        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 (AfterRParen->is(tok::question) ||
        (AfterRParen->is(tok::ampamp) && !BeforeRParen->isTypeName(LangOpts))) {
      return false;
    }

    // `foreach((A a, B b) in someList)` should not be seen as a cast.
    if (AfterRParen->is(Keywords.kw_in) && Style.isCSharp())
      return false;

    // Functions which end with decorations like volatile, noexcept are unlikely
    // to be casts.
    if (AfterRParen->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
                             tok::kw_requires, tok::kw_throw, tok::arrow,
                             Keywords.kw_override, Keywords.kw_final) ||
        isCppAttribute(IsCpp, *AfterRParen)) {
      return false;
    }

    // As Java has no function types, a "(" after the ")" likely means that this
    // is a cast.
    if (Style.Language == FormatStyle::LK_Java && AfterRParen->is(tok::l_paren))
      return true;

    // If a (non-string) literal follows, this is likely a cast.
    if (AfterRParen->isOneOf(tok::kw_sizeof, tok::kw_alignof) ||
        (AfterRParen->Tok.isLiteral() &&
         AfterRParen->isNot(tok::string_literal))) {
      return true;
    }

    auto IsNonVariableTemplate = [](const FormatToken &Tok) {
      if (Tok.isNot(TT_TemplateCloser))
        return false;
      const auto *Less = Tok.MatchingParen;
      if (!Less)
        return false;
      const auto *BeforeLess = Less->getPreviousNonComment();
      return BeforeLess && BeforeLess->isNot(TT_VariableTemplate);
    };

    // Heuristically try to determine whether the parentheses contain a type.
    auto IsQualifiedPointerOrReference = [](const FormatToken *T,
                                            const LangOptions &LangOpts) {
      // This is used to handle cases such as x = (foo *const)&y;
      assert(!T->isTypeName(LangOpts) && "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_AttributeRParen)) {
          // Handle `x = (foo *__attribute__((foo)))&v;`:
          assert(T->is(tok::r_paren));
          assert(T->MatchingParen);
          assert(T->MatchingParen->is(tok::l_paren));
          assert(T->MatchingParen->is(TT_AttributeLParen));
          if (const auto *Tok = T->MatchingParen->Previous;
              Tok && Tok->isAttribute()) {
            T = Tok->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 = IsNonVariableTemplate(*BeforeRParen) ||
                         BeforeRParen->is(TT_TypeDeclarationParen) ||
                         BeforeRParen->isTypeName(LangOpts) ||
                         IsQualifiedPointerOrReference(BeforeRParen, LangOpts);
    bool ParensCouldEndDecl =
        AfterRParen->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 auto *Token = LParen->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 (AfterRParen->isOneOf(tok::identifier, tok::kw_this))
      return true;

    // Look for a cast `( x ) (`, where x may be a qualified identifier.
    if (AfterRParen->is(tok::l_paren)) {
      for (const auto *Prev = BeforeRParen; Prev->is(tok::identifier);) {
        Prev = Prev->Previous;
        if (Prev->is(tok::coloncolon))
          Prev = Prev->Previous;
        if (Prev == LParen)
          return true;
      }
    }

    if (!AfterRParen->Next)
      return false;

    if (AfterRParen->is(tok::l_brace) &&
        AfterRParen->getBlockKind() == BK_BracedInit) {
      return true;
    }

    // If the next token after the parenthesis is a unary operator, assume
    // that this is cast, unless there are unexpected tokens inside the
    // parenthesis.
    const bool NextIsAmpOrStar = AfterRParen->isOneOf(tok::amp, tok::star);
    if (!(AfterRParen->isUnaryOperator() || NextIsAmpOrStar) ||
        AfterRParen->is(tok::plus) ||
        !AfterRParen->Next->isOneOf(tok::identifier, tok::numeric_constant)) {
      return false;
    }

    if (NextIsAmpOrStar &&
        (AfterRParen->Next->is(tok::numeric_constant) || Line.InPPDirective)) {
      return false;
    }

    if (Line.InPPDirective && AfterRParen->is(tok::minus))
      return false;

    const auto *Prev = BeforeRParen;

    // Look for a function pointer type, e.g. `(*)()`.
    if (Prev->is(tok::r_paren)) {
      if (Prev->is(TT_CastRParen))
        return false;
      Prev = Prev->MatchingParen;
      if (!Prev)
        return false;
      Prev = Prev->Previous;
      if (!Prev || Prev->isNot(tok::r_paren))
        return false;
      Prev = Prev->MatchingParen;
      return Prev && Prev->is(TT_FunctionTypeLParen);
    }

    // Search for unexpected tokens.
    for (Prev = BeforeRParen; Prev != LParen; Prev = Prev->Previous)
      if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon))
        return false;

    return true;
  }

  /// Returns true if the token is used as a unary operator.
  bool determineUnaryOperatorByUsage(const FormatToken &Tok) {
    const FormatToken *PrevToken = Tok.getPreviousNonComment();
    if (!PrevToken)
      return true;

    // These keywords are deliberately not included here because they may
    // precede only one of unary star/amp and plus/minus but not both.  They are
    // either included in determineStarAmpUsage or determinePlusMinusCaretUsage.
    //
    // @ - It may be followed by a unary `-` in Objective-C literals. We don't
    //   know how they can be followed by a star or amp.
    if (PrevToken->isOneOf(
            TT_ConditionalExpr, tok::l_paren, tok::comma, tok::colon, tok::semi,
            tok::equal, tok::question, tok::l_square, tok::l_brace,
            tok::kw_case, tok::kw_co_await, tok::kw_co_return, tok::kw_co_yield,
            tok::kw_delete, tok::kw_return, tok::kw_throw)) {
      return true;
    }

    // We put sizeof here instead of only in determineStarAmpUsage. In the cases
    // where the unary `+` operator is overloaded, it is reasonable to write
    // things like `sizeof +x`. Like commit 446d6ec996c6c3.
    if (PrevToken->is(tok::kw_sizeof))
      return true;

    // A sequence of leading unary operators.
    if (PrevToken->isOneOf(TT_CastRParen, TT_UnaryOperator))
      return true;

    // There can't be two consecutive binary operators.
    if (PrevToken->is(TT_BinaryOperator))
      return true;

    return false;
  }

  /// Return the type of the given token assuming it is * or &.
  TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression,
                                  bool InTemplateArgument) {
    if (Style.isJavaScript())
      return TT_BinaryOperator;

    // && in C# must be a binary operator.
    if (Style.isCSharp() && Tok.is(tok::ampamp))
      return TT_BinaryOperator;

    if (Style.isVerilog()) {
      // In Verilog, `*` can only be a binary operator.  `&` can be either unary
      // or binary.  `*` also includes `*>` in module path declarations in
      // specify blocks because merged tokens take the type of the first one by
      // default.
      if (Tok.is(tok::star))
        return TT_BinaryOperator;
      return determineUnaryOperatorByUsage(Tok) ? TT_UnaryOperator
                                                : TT_BinaryOperator;
    }

    const FormatToken *PrevToken = Tok.getPreviousNonComment();
    if (!PrevToken)
      return TT_UnaryOperator;
    if (PrevToken->is(TT_TypeName))
      return TT_PointerOrReference;
    if (PrevToken->isOneOf(tok::kw_new, tok::kw_delete) && Tok.is(tok::ampamp))
      return TT_BinaryOperator;

    const FormatToken *NextToken = Tok.getNextNonComment();

    if (InTemplateArgument && NextToken && NextToken->is(tok::kw_noexcept))
      return TT_BinaryOperator;

    if (!NextToken ||
        NextToken->isOneOf(tok::arrow, tok::equal, tok::comma, tok::r_paren,
                           TT_RequiresClause) ||
        (NextToken->is(tok::kw_noexcept) && !IsExpression) ||
        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 (determineUnaryOperatorByUsage(Tok))
      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;

    // After right braces, star tokens are likely to be pointers to struct,
    // union, or class.
    //   struct {} *ptr;
    // This by itself is not sufficient to distinguish from multiplication
    // following a brace-initialized expression, as in:
    // int i = int{42} * 2;
    // In the struct case, the part of the struct declaration until the `{` and
    // the `}` are put on separate unwrapped lines; in the brace-initialized
    // case, the matching `{` is on the same unwrapped line, so check for the
    // presence of the matching brace to distinguish between those.
    if (PrevToken->is(tok::r_brace) && Tok.is(tok::star) &&
        !PrevToken->MatchingParen) {
      return TT_PointerOrReference;
    }

    if (PrevToken->endsSequence(tok::r_square, tok::l_square, tok::kw_delete))
      return TT_UnaryOperator;

    if (PrevToken->Tok.isLiteral() ||
        PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
                           tok::kw_false, tok::r_brace)) {
      return TT_BinaryOperator;
    }

    const FormatToken *NextNonParen = NextToken;
    while (NextNonParen && NextNonParen->is(tok::l_paren))
      NextNonParen = NextNonParen->getNextNonComment();
    if (NextNonParen && (NextNonParen->Tok.isLiteral() ||
                         NextNonParen->isOneOf(tok::kw_true, tok::kw_false) ||
                         NextNonParen->isUnaryOperator())) {
      return TT_BinaryOperator;
    }

    // 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.
    if (InTemplateArgument && NextToken->Tok.isAnyIdentifier())
      return TT_BinaryOperator;

    // "&&" followed by "(", "*", or "&" is quite unlikely to be two successive
    // unary "&".
    if (Tok.is(tok::ampamp) &&
        NextToken->isOneOf(tok::l_paren, tok::star, tok::amp)) {
      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;

    // Opeartors at class scope are likely pointer or reference members.
    if (!Scopes.empty() && Scopes.back() == ST_Class)
      return TT_PointerOrReference;

    // Tokens that indicate member access or chained operator& use.
    auto IsChainedOperatorAmpOrMember = [](const FormatToken *token) {
      return !token || token->isOneOf(tok::amp, tok::period, tok::arrow,
                                      tok::arrowstar, tok::periodstar);
    };

    // It's more likely that & represents operator& than an uninitialized
    // reference.
    if (Tok.is(tok::amp) && PrevToken && PrevToken->Tok.isAnyIdentifier() &&
        IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) &&
        NextToken && NextToken->Tok.isAnyIdentifier()) {
      if (auto NextNext = NextToken->getNextNonComment();
          NextNext &&
          (IsChainedOperatorAmpOrMember(NextNext) || NextNext->is(tok::semi))) {
        return TT_BinaryOperator;
      }
    }

    if (Line.Type == LT_SimpleRequirement ||
        (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)) {
      return TT_BinaryOperator;
    }

    return TT_PointerOrReference;
  }

  TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
    if (determineUnaryOperatorByUsage(Tok))
      return TT_UnaryOperator;

    const FormatToken *PrevToken = Tok.getPreviousNonComment();
    if (!PrevToken)
      return TT_UnaryOperator;

    if (PrevToken->is(tok::at))
      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;
  bool IsCpp;
  LangOptions LangOpts;
  const AdditionalKeywords &Keywords;

  SmallVector<ScopeType> &Scopes;

  // 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;

  int TemplateDeclarationDepth;
};

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), Line(Line), 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;
    // The first name of the current type in a port list.
    FormatToken *VerilogFirstOfType = nullptr;

    while (Current) {
      // In Verilog ports in a module header that don't have a type take the
      // type of the previous one.  For example,
      //   module a(output b,
      //                   c,
      //            output d);
      // In this case there need to be fake parentheses around b and c.
      if (Style.isVerilog() && Precedence == prec::Comma) {
        VerilogFirstOfType =
            verilogGroupDecl(VerilogFirstOfType, LatestOperator);
      }

      // Consume operators with higher precedence.
      parse(Precedence + 1);

      int CurrentPrecedence = getCurrentPrecedence();
      if (Style.BreakBinaryOperations == FormatStyle::BBO_OnePerLine &&
          CurrentPrecedence > prec::Conditional &&
          CurrentPrecedence < prec::PointerToMember) {
        // When BreakBinaryOperations is set to BreakAll,
        // all operations will be on the same line or on individual lines.
        // Override precedence to avoid adding fake parenthesis which could
        // group operations of a different precedence level on the same line
        CurrentPrecedence = prec::Additive;
      }

      if (Precedence == CurrentPrecedence && Current &&
          Current->is(TT_SelectorName)) {
        if (LatestOperator)
          addFakeParenthesis(Start, prec::Level(Precedence));
        Start = Current;
      }

      if ((Style.isCSharp() || Style.isJavaScript() ||
           Style.Language == FormatStyle::LK_Java) &&
          Precedence == prec::Additive && Current) {
        // A string can be broken without parentheses around it when it is
        // already in a sequence of strings joined by `+` signs.
        FormatToken *Prev = Current->getPreviousNonComment();
        if (Prev && Prev->is(tok::string_literal) &&
            (Prev == Start || Prev->endsSequence(tok::string_literal, tok::plus,
                                                 TT_StringInConcatenation))) {
          Prev->setType(TT_StringInConcatenation);
        }
      }

      // At the end of the line or when an operator with lower 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 {}
      // In addition to that we handle require clauses as scope, so that the
      // constraints in that are correctly indented.
      if (Current->opensScope() ||
          Current->isOneOf(TT_RequiresClause,
                           TT_RequiresClauseInARequiresExpression)) {
        // 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);
      }
    }

    // Group variables of the same type.
    if (Style.isVerilog() && Precedence == prec::Comma && VerilogFirstOfType)
      addFakeParenthesis(VerilogFirstOfType, prec::Comma);

    if (LatestOperator && (Current || Precedence > 0)) {
      // The requires clauses do not neccessarily end in a semicolon or a brace,
      // but just go over to struct/class or a function declaration, we need to
      // intervene so that the fake right paren is inserted correctly.
      auto End =
          (Start->Previous &&
           Start->Previous->isOneOf(TT_RequiresClause,
                                    TT_RequiresClauseInARequiresExpression))
              ? [this]() {
                  auto Ret = Current ? Current : Line.Last;
                  while (!Ret->ClosesRequiresClause && Ret->Previous)
                    Ret = Ret->Previous;
                  return Ret;
                }()
              : nullptr;

      if (Precedence == PrecedenceArrowAndPeriod) {
        // Call expressions don't have a binary operator precedence.
        addFakeParenthesis(Start, prec::Unknown, End);
      } else {
        addFakeParenthesis(Start, prec::Level(Precedence), End);
      }
    }
  }

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.isProto() && 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_FatArrow))
        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.isJavaScript()) &&
          Current->is(Keywords.kw_instanceof)) {
        return prec::Relational;
      }
      if (Style.isJavaScript() &&
          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) &&
          Current->isNot(TT_TrailingReturnArrow)) {
        return PrecedenceArrowAndPeriod;
      }
      if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
          Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,
                           Keywords.kw_throws)) {
        return 0;
      }
      // In Verilog case labels are not on separate lines straight out of
      // UnwrappedLineParser. The colon is not part of an expression.
      if (Style.isVerilog() && Current->is(tok::colon))
        return 0;
    }
    return -1;
  }

  void addFakeParenthesis(FormatToken *Start, prec::Level Precedence,
                          FormatToken *End = nullptr) {
    // Do not assign fake parenthesis to tokens that are part of an
    // unexpanded macro call. The line within the macro call contains
    // the parenthesis and commas, and we will not find operators within
    // that structure.
    if (Start->MacroParent)
      return;

    Start->FakeLParens.push_back(Precedence);
    if (Precedence > prec::Unknown)
      Start->StartsBinaryExpression = true;
    if (!End && Current)
      End = Current->getPreviousNonComment();
    if (End) {
      ++End->FakeRParens;
      if (Precedence > prec::Unknown)
        End->EndsBinaryExpression = true;
    }
  }

  /// Parse unary operator expressions and surround them with fake
  /// parentheses if appropriate.
  void parseUnaryOperator() {
    SmallVector<FormatToken *, 2> Tokens;
    while (Current && Current->is(TT_UnaryOperator)) {
      Tokens.push_back(Current);
      next();
    }
    parse(PrecedenceArrowAndPeriod);
    for (FormatToken *Token : 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->isNot(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;
    }
  }

  // Add fake parenthesis around declarations of the same type for example in a
  // module prototype. Return the first port / variable of the current type.
  FormatToken *verilogGroupDecl(FormatToken *FirstOfType,
                                FormatToken *PreviousComma) {
    if (!Current)
      return nullptr;

    FormatToken *Start = Current;

    // Skip attributes.
    while (Start->startsSequence(tok::l_paren, tok::star)) {
      if (!(Start = Start->MatchingParen) ||
          !(Start = Start->getNextNonComment())) {
        return nullptr;
      }
    }

    FormatToken *Tok = Start;

    if (Tok->is(Keywords.kw_assign))
      Tok = Tok->getNextNonComment();

    // Skip any type qualifiers to find the first identifier. It may be either a
    // new type name or a variable name. There can be several type qualifiers
    // preceding a variable name, and we can not tell them apart by looking at
    // the word alone since a macro can be defined as either a type qualifier or
    // a variable name. Thus we use the last word before the dimensions instead
    // of the first word as the candidate for the variable or type name.
    FormatToken *First = nullptr;
    while (Tok) {
      FormatToken *Next = Tok->getNextNonComment();

      if (Tok->is(tok::hash)) {
        // Start of a macro expansion.
        First = Tok;
        Tok = Next;
        if (Tok)
          Tok = Tok->getNextNonComment();
      } else if (Tok->is(tok::hashhash)) {
        // Concatenation. Skip.
        Tok = Next;
        if (Tok)
          Tok = Tok->getNextNonComment();
      } else if (Keywords.isVerilogQualifier(*Tok) ||
                 Keywords.isVerilogIdentifier(*Tok)) {
        First = Tok;
        Tok = Next;
        // The name may have dots like `interface_foo.modport_foo`.
        while (Tok && Tok->isOneOf(tok::period, tok::coloncolon) &&
               (Tok = Tok->getNextNonComment())) {
          if (Keywords.isVerilogIdentifier(*Tok))
            Tok = Tok->getNextNonComment();
        }
      } else if (!Next) {
        Tok = nullptr;
      } else if (Tok->is(tok::l_paren)) {
        // Make sure the parenthesized list is a drive strength. Otherwise the
        // statement may be a module instantiation in which case we have already
        // found the instance name.
        if (Next->isOneOf(
                Keywords.kw_highz0, Keywords.kw_highz1, Keywords.kw_large,
                Keywords.kw_medium, Keywords.kw_pull0, Keywords.kw_pull1,
                Keywords.kw_small, Keywords.kw_strong0, Keywords.kw_strong1,
                Keywords.kw_supply0, Keywords.kw_supply1, Keywords.kw_weak0,
                Keywords.kw_weak1)) {
          Tok->setType(TT_VerilogStrength);
          Tok = Tok->MatchingParen;
          if (Tok) {
            Tok->setType(TT_VerilogStrength);
            Tok = Tok->getNextNonComment();
          }
        } else {
          break;
        }
      } else if (Tok->is(Keywords.kw_verilogHash)) {
        // Delay control.
        if (Next->is(tok::l_paren))
          Next = Next->MatchingParen;
        if (Next)
          Tok = Next->getNextNonComment();
      } else {
        break;
      }
    }

    // Find the second identifier. If it exists it will be the name.
    FormatToken *Second = nullptr;
    // Dimensions.
    while (Tok && Tok->is(tok::l_square) && (Tok = Tok->MatchingParen))
      Tok = Tok->getNextNonComment();
    if (Tok && (Tok->is(tok::hash) || Keywords.isVerilogIdentifier(*Tok)))
      Second = Tok;

    // If the second identifier doesn't exist and there are qualifiers, the type
    // is implied.
    FormatToken *TypedName = nullptr;
    if (Second) {
      TypedName = Second;
      if (First && First->is(TT_Unknown))
        First->setType(TT_VerilogDimensionedTypeName);
    } else if (First != Start) {
      // If 'First' is null, then this isn't a declaration, 'TypedName' gets set
      // to null as intended.
      TypedName = First;
    }

    if (TypedName) {
      // This is a declaration with a new type.
      if (TypedName->is(TT_Unknown))
        TypedName->setType(TT_StartOfName);
      // Group variables of the previous type.
      if (FirstOfType && PreviousComma) {
        PreviousComma->setType(TT_VerilogTypeComma);
        addFakeParenthesis(FirstOfType, prec::Comma, PreviousComma->Previous);
      }

      FirstOfType = TypedName;

      // Don't let higher precedence handle the qualifiers. For example if we
      // have:
      //    parameter x = 0
      // We skip `parameter` here. This way the fake parentheses for the
      // assignment will be around `x = 0`.
      while (Current && Current != FirstOfType) {
        if (Current->opensScope()) {
          next();
          parse();
        }
        next();
      }
    }

    return FirstOfType;
  }

  const FormatStyle &Style;
  const AdditionalKeywords &Keywords;
  const AnnotatedLine &Line;
  FormatToken *Current;
};

} // end anonymous namespace

void TokenAnnotator::setCommentLineLevels(
    SmallVectorImpl<AnnotatedLine *> &Lines) const {
  const AnnotatedLine *NextNonCommentLine = nullptr;
  for (AnnotatedLine *Line : reverse(Lines)) {
    assert(Line->First);

    // If the comment is currently aligned with the line immediately following
    // it, that's probably intentional and we should keep it.
    if (NextNonCommentLine && NextNonCommentLine->First->NewlinesBefore < 2 &&
        Line->isComment() && !isClangFormatOff(Line->First->TokenText) &&
        NextNonCommentLine->First->OriginalColumn ==
            Line->First->OriginalColumn) {
      const bool PPDirectiveOrImportStmt =
          NextNonCommentLine->Type == LT_PreprocessorDirective ||
          NextNonCommentLine->Type == LT_ImportStatement;
      if (PPDirectiveOrImportStmt)
        Line->Type = LT_CommentAbovePPDirective;
      // Align comments for preprocessor lines with the # in column 0 if
      // preprocessor lines are not indented. Otherwise, align with the next
      // line.
      Line->Level = Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
                            PPDirectiveOrImportStmt
                        ? 0
                        : NextNonCommentLine->Level;
    } else {
      NextNonCommentLine = Line->First->isNot(tok::r_brace) ? Line : nullptr;
    }

    setCommentLineLevels(Line->Children);
  }
}

static unsigned maxNestingDepth(const AnnotatedLine &Line) {
  unsigned Result = 0;
  for (const auto *Tok = Line.First; Tok; Tok = Tok->Next)
    Result = std::max(Result, Tok->NestingLevel);
  return Result;
}

// Returns the name of a function with no return type, e.g. a constructor or
// destructor.
static FormatToken *getFunctionName(const AnnotatedLine &Line,
                                    FormatToken *&OpeningParen) {
  for (FormatToken *Tok = Line.getFirstNonComment(), *Name = nullptr; Tok;
       Tok = Tok->getNextNonComment()) {
    // Skip C++11 attributes both before and after the function name.
    if (Tok->is(tok::l_square) && Tok->is(TT_AttributeSquare)) {
      Tok = Tok->MatchingParen;
      if (!Tok)
        break;
      continue;
    }

    // Make sure the name is followed by a pair of parentheses.
    if (Name) {
      if (Tok->is(tok::l_paren) && Tok->is(TT_Unknown) && Tok->MatchingParen) {
        OpeningParen = Tok;
        return Name;
      }
      return nullptr;
    }

    // Skip keywords that may precede the constructor/destructor name.
    if (Tok->isOneOf(tok::kw_friend, tok::kw_inline, tok::kw_virtual,
                     tok::kw_constexpr, tok::kw_consteval, tok::kw_explicit)) {
      continue;
    }

    // A qualified name may start from the global namespace.
    if (Tok->is(tok::coloncolon)) {
      Tok = Tok->Next;
      if (!Tok)
        break;
    }

    // Skip to the unqualified part of the name.
    while (Tok->startsSequence(tok::identifier, tok::coloncolon)) {
      assert(Tok->Next);
      Tok = Tok->Next->Next;
      if (!Tok)
        return nullptr;
    }

    // Skip the `~` if a destructor name.
    if (Tok->is(tok::tilde)) {
      Tok = Tok->Next;
      if (!Tok)
        break;
    }

    // Make sure the name is not already annotated, e.g. as NamespaceMacro.
    if (Tok->isNot(tok::identifier) || Tok->isNot(TT_Unknown))
      break;

    Name = Tok;
  }

  return nullptr;
}

// Checks if Tok is a constructor/destructor name qualified by its class name.
static bool isCtorOrDtorName(const FormatToken *Tok) {
  assert(Tok && Tok->is(tok::identifier));
  const auto *Prev = Tok->Previous;

  if (Prev && Prev->is(tok::tilde))
    Prev = Prev->Previous;

  if (!Prev || !Prev->endsSequence(tok::coloncolon, tok::identifier))
    return false;

  assert(Prev->Previous);
  return Prev->Previous->TokenText == Tok->TokenText;
}

void TokenAnnotator::annotate(AnnotatedLine &Line) {
  if (!Line.InMacroBody)
    MacroBodyScopes.clear();

  auto &ScopeStack = Line.InMacroBody ? MacroBodyScopes : Scopes;
  AnnotatingParser Parser(Style, Line, Keywords, ScopeStack);
  Line.Type = Parser.parseLine();

  if (!Line.Children.empty()) {
    ScopeStack.push_back(ST_Other);
    const bool InRequiresExpression = Line.Type == LT_RequiresExpression;
    for (auto &Child : Line.Children) {
      if (InRequiresExpression &&
          !Child->First->isOneOf(tok::kw_typename, tok::kw_requires,
                                 TT_CompoundRequirementLBrace)) {
        Child->Type = LT_SimpleRequirement;
      }
      annotate(*Child);
    }
    // ScopeStack can become empty if Child has an unmatched `}`.
    if (!ScopeStack.empty())
      ScopeStack.pop_back();
  }

  // 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 (IsCpp) {
    FormatToken *OpeningParen = nullptr;
    auto *Tok = getFunctionName(Line, OpeningParen);
    if (Tok && ((!ScopeStack.empty() && ScopeStack.back() == ST_Class) ||
                Line.endsWith(TT_FunctionLBrace) || isCtorOrDtorName(Tok))) {
      Tok->setFinalizedType(TT_CtorDtorDeclName);
      assert(OpeningParen);
      OpeningParen->setFinalizedType(TT_FunctionDeclarationLParen);
    }
  }

  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;

  auto *First = Line.First;
  First->SpacesRequiredBefore = 1;
  First->CanBreakBefore = First->MustBreakBefore;
}

// This function heuristically determines whether 'Current' starts the name of a
// function declaration.
static bool isFunctionDeclarationName(const LangOptions &LangOpts,
                                      const FormatToken &Current,
                                      const AnnotatedLine &Line,
                                      FormatToken *&ClosingParen) {
  if (Current.is(TT_FunctionDeclarationName))
    return true;

  if (!Current.Tok.getIdentifierInfo())
    return false;

  const auto *Prev = Current.getPreviousNonComment();
  assert(Prev);

  if (Prev->is(tok::coloncolon))
    Prev = Prev->Previous;

  if (!Prev)
    return false;

  const auto &Previous = *Prev;

  if (const auto *PrevPrev = Previous.getPreviousNonComment();
      PrevPrev && PrevPrev->is(TT_ObjCDecl)) {
    return false;
  }

  auto skipOperatorName =
      [&LangOpts](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, tok::kw_co_await)) {
        // 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->isTypeName(LangOpts) || Next->is(tok::identifier)) &&
          Next->Next && Next->Next->isPointerOrReference()) {
        // 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;
  };

  const auto *Next = Current.Next;
  const bool IsCpp = LangOpts.CXXOperatorNames || LangOpts.C17;

  // Find parentheses of parameter list.
  if (Current.is(tok::kw_operator)) {
    if (Previous.Tok.getIdentifierInfo() &&
        !Previous.isOneOf(tok::kw_return, tok::kw_co_return)) {
      return true;
    }
    if (Previous.is(tok::r_paren) && Previous.is(TT_TypeDeclarationParen)) {
      assert(Previous.MatchingParen);
      assert(Previous.MatchingParen->is(tok::l_paren));
      assert(Previous.MatchingParen->is(TT_TypeDeclarationParen));
      return true;
    }
    if (!Previous.isPointerOrReference() && Previous.isNot(TT_TemplateCloser))
      return false;
    Next = skipOperatorName(Next);
  } else {
    if (Current.isNot(TT_StartOfName) || Current.NestingLevel != 0)
      return false;
    for (; Next; Next = Next->Next) {
      if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {
        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->isNot(tok::identifier))
          return false;
      } else if (isCppAttribute(IsCpp, *Next)) {
        Next = Next->MatchingParen;
        if (!Next)
          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->isNot(tok::l_paren) || !Next->MatchingParen)
    return false;
  ClosingParen = Next->MatchingParen;
  assert(ClosingParen->is(tok::r_paren));
  // If the lines ends with "{", this is likely a function definition.
  if (Line.Last->is(tok::l_brace))
    return true;
  if (Next->Next == ClosingParen)
    return true; // Empty parentheses.
  // If there is an &/&& after the r_paren, this is likely a function.
  if (ClosingParen->Next && ClosingParen->Next->is(TT_PointerOrReference))
    return true;

  // Check for K&R C function definitions (and C++ function definitions with
  // unnamed parameters), e.g.:
  //   int f(i)
  //   {
  //     return i + 1;
  //   }
  //   bool g(size_t = 0, bool b = false)
  //   {
  //     return !b;
  //   }
  if (IsCpp && Next->Next && Next->Next->is(tok::identifier) &&
      !Line.endsWith(tok::semi)) {
    return true;
  }

  for (const FormatToken *Tok = Next->Next; Tok && Tok != ClosingParen;
       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->isTypeName(LangOpts) ||
        Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) {
      return true;
    }
    if (Tok->isOneOf(tok::l_brace, TT_ObjCMethodExpr) || Tok->Tok.isLiteral())
      return false;
  }
  return false;
}

bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {
  assert(Line.MightBeFunctionDecl);

  if ((Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevel ||
       Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevelDefinitions) &&
      Line.Level > 0) {
    return false;
  }

  switch (Style.BreakAfterReturnType) {
  case FormatStyle::RTBS_None:
  case FormatStyle::RTBS_Automatic:
  case FormatStyle::RTBS_ExceptShortType:
    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) const {
  if (Line.Computed)
    return;

  Line.Computed = true;

  for (AnnotatedLine *ChildLine : Line.Children)
    calculateFormattingInformation(*ChildLine);

  auto *First = Line.First;
  First->TotalLength = First->IsMultiline
                           ? Style.ColumnLimit
                           : Line.FirstStartColumn + First->ColumnWidth;
  bool AlignArrayOfStructures =
      (Style.AlignArrayOfStructures != FormatStyle::AIAS_None &&
       Line.Type == LT_ArrayOfStructInitializer);
  if (AlignArrayOfStructures)
    calculateArrayInitializerColumnList(Line);

  const auto *FirstNonComment = Line.getFirstNonComment();
  bool SeenName = false;
  bool LineIsFunctionDeclaration = false;
  FormatToken *AfterLastAttribute = nullptr;
  FormatToken *ClosingParen = nullptr;

  for (auto *Tok = FirstNonComment ? FirstNonComment->Next : nullptr; Tok;
       Tok = Tok->Next) {
    if (Tok->is(TT_StartOfName))
      SeenName = true;
    if (Tok->Previous->EndsCppAttributeGroup)
      AfterLastAttribute = Tok;
    if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName);
        IsCtorOrDtor ||
        isFunctionDeclarationName(LangOpts, *Tok, Line, ClosingParen)) {
      if (!IsCtorOrDtor)
        Tok->setFinalizedType(TT_FunctionDeclarationName);
      LineIsFunctionDeclaration = true;
      SeenName = true;
      if (ClosingParen) {
        auto *OpeningParen = ClosingParen->MatchingParen;
        assert(OpeningParen);
        if (OpeningParen->is(TT_Unknown))
          OpeningParen->setType(TT_FunctionDeclarationLParen);
      }
      break;
    }
  }

  if (IsCpp &&
      (LineIsFunctionDeclaration ||
       (FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) &&
      Line.endsWith(tok::semi, tok::r_brace)) {
    auto *Tok = Line.Last->Previous;
    while (Tok->isNot(tok::r_brace))
      Tok = Tok->Previous;
    if (auto *LBrace = Tok->MatchingParen; LBrace) {
      assert(LBrace->is(tok::l_brace));
      Tok->setBlockKind(BK_Block);
      LBrace->setBlockKind(BK_Block);
      LBrace->setFinalizedType(TT_FunctionLBrace);
    }
  }

  if (IsCpp && SeenName && AfterLastAttribute &&
      mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
    AfterLastAttribute->MustBreakBefore = true;
    if (LineIsFunctionDeclaration)
      Line.ReturnTypeWrapped = true;
  }

  if (IsCpp) {
    if (!LineIsFunctionDeclaration) {
      // Annotate */&/&& in `operator` function calls as binary operators.
      for (const auto *Tok = FirstNonComment; Tok; Tok = Tok->Next) {
        if (Tok->isNot(tok::kw_operator))
          continue;
        do {
          Tok = Tok->Next;
        } while (Tok && Tok->isNot(TT_OverloadedOperatorLParen));
        if (!Tok || !Tok->MatchingParen)
          break;
        const auto *LeftParen = Tok;
        for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen;
             Tok = Tok->Next) {
          if (Tok->isNot(tok::identifier))
            continue;
          auto *Next = Tok->Next;
          const bool NextIsBinaryOperator =
              Next && Next->isPointerOrReference() && Next->Next &&
              Next->Next->is(tok::identifier);
          if (!NextIsBinaryOperator)
            continue;
          Next->setType(TT_BinaryOperator);
          Tok = Next;
        }
      }
    } else if (ClosingParen) {
      for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) {
        if (Tok->is(TT_CtorInitializerColon))
          break;
        if (Tok->is(tok::arrow)) {
          Tok->setType(TT_TrailingReturnArrow);
          break;
        }
        if (Tok->isNot(TT_TrailingAnnotation))
          continue;
        const auto *Next = Tok->Next;
        if (!Next || Next->isNot(tok::l_paren))
          continue;
        Tok = Next->MatchingParen;
        if (!Tok)
          break;
      }
    }
  }

  bool InFunctionDecl = Line.MightBeFunctionDecl;
  for (auto *Current = First->Next; Current; Current = Current->Next) {
    const FormatToken *Prev = Current->Previous;
    if (Current->is(TT_LineComment)) {
      if (Prev->is(BK_BracedInit) && Prev->opensScope()) {
        Current->SpacesRequiredBefore =
            (Style.Cpp11BracedListStyle && !Style.SpacesInParensOptions.Other)
                ? 0
                : 1;
      } else if (Prev->is(TT_VerilogMultiLineListLParen)) {
        Current->SpacesRequiredBefore = 0;
      } 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->isNot(TT_CtorInitializerComma) &&
                Parameter->HasUnescapedNewline) {
              Parameter->MustBreakBefore = true;
            }
            break;
          }
        }
      }
    } else if (!Current->Finalized && Current->SpacesRequiredBefore == 0 &&
               spaceRequiredBefore(Line, *Current)) {
      Current->SpacesRequiredBefore = 1;
    }

    const auto &Children = Prev->Children;
    if (!Children.empty() && Children.back()->Last->is(TT_LineComment)) {
      Current->MustBreakBefore = true;
    } else {
      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 (Prev->Children.size() == 1) {
      FormatToken &LastOfChild = *Prev->Children[0]->Last;
      ChildSize = LastOfChild.isTrailingComment() ? Style.ColumnLimit
                                                  : LastOfChild.TotalLength + 1;
    }
    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;
    }
  }

  calculateUnbreakableTailLengths(Line);
  unsigned IndentLevel = Line.Level;
  for (auto *Current = First; Current; Current = Current->Next) {
    if (Current->Role)
      Current->Role->precomputeFormattingInfos(Current);
    if (Current->MatchingParen &&
        Current->MatchingParen->opensBlockOrBlockTypeList(Style) &&
        IndentLevel > 0) {
      --IndentLevel;
    }
    Current->IndentLevel = IndentLevel;
    if (Current->opensBlockOrBlockTypeList(Style))
      ++IndentLevel;
  }

  LLVM_DEBUG({ printDebugInfo(Line); });
}

void TokenAnnotator::calculateUnbreakableTailLengths(
    AnnotatedLine &Line) const {
  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;
  }
}

void TokenAnnotator::calculateArrayInitializerColumnList(
    AnnotatedLine &Line) const {
  if (Line.First == Line.Last)
    return;
  auto *CurrentToken = Line.First;
  CurrentToken->ArrayInitializerLineStart = true;
  unsigned Depth = 0;
  while (CurrentToken && CurrentToken != Line.Last) {
    if (CurrentToken->is(tok::l_brace)) {
      CurrentToken->IsArrayInitializer = true;
      if (CurrentToken->Next)
        CurrentToken->Next->MustBreakBefore = true;
      CurrentToken =
          calculateInitializerColumnList(Line, CurrentToken->Next, Depth + 1);
    } else {
      CurrentToken = CurrentToken->Next;
    }
  }
}

FormatToken *TokenAnnotator::calculateInitializerColumnList(
    AnnotatedLine &Line, FormatToken *CurrentToken, unsigned Depth) const {
  while (CurrentToken && CurrentToken != Line.Last) {
    if (CurrentToken->is(tok::l_brace))
      ++Depth;
    else if (CurrentToken->is(tok::r_brace))
      --Depth;
    if (Depth == 2 && CurrentToken->isOneOf(tok::l_brace, tok::comma)) {
      CurrentToken = CurrentToken->Next;
      if (!CurrentToken)
        break;
      CurrentToken->StartsColumn = true;
      CurrentToken = CurrentToken->Previous;
    }
    CurrentToken = CurrentToken->Next;
  }
  return CurrentToken;
}

unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
                                      const FormatToken &Tok,
                                      bool InFunctionDecl) const {
  const FormatToken &Left = *Tok.Previous;
  const FormatToken &Right = Tok;

  if (Left.is(tok::semi))
    return 0;

  // Language specific handling.
  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.isJavaScript()) {
    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.ends_with("${")) ||
        (Right.is(TT_TemplateString) && Right.TokenText.starts_with("}"))) {
      return 100;
    }
    // Prefer breaking call chains (".foo") over empty "{}", "[]" or "()".
    if (Left.opensScope() && Right.closesScope())
      return 200;
  } else if (Style.Language == FormatStyle::LK_Proto) {
    if (Right.is(tok::l_square))
      return 1;
    if (Right.is(tok::period))
      return 500;
  }

  if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
    return 1;
  if (Right.is(tok::l_square)) {
    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))
    return Style.PenaltyBreakScopeResolution;
  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, tok::kw_union))
    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);
    const auto *NextOperator = Right.NextOperator;
    const auto Penalty = Style.PenaltyBreakBeforeMemberAccess;
    return NextOperator && NextOperator->Previous->closesScope()
               ? std::min(Penalty, 35u)
               : Penalty;
  }

  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) && Style.PenaltyBreakOpenParenthesis != 0)
    return Style.PenaltyBreakOpenParenthesis;
  if (Left.is(tok::l_paren) && InFunctionDecl &&
      Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign) {
    return 100;
  }
  if (Left.is(tok::l_paren) && Left.Previous &&
      (Left.Previous->isOneOf(tok::kw_for, tok::kw__Generic) ||
       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.isNot(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.ClosesRequiresClause)
    return 0;
  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 {
  if (Style.SpaceBeforeParens == FormatStyle::SBPO_Always)
    return true;
  if (Right.is(TT_OverloadedOperatorLParen) &&
      Style.SpaceBeforeParensOptions.AfterOverloadedOperator) {
    return true;
  }
  if (Style.SpaceBeforeParensOptions.BeforeNonEmptyParentheses &&
      Right.ParameterCount > 0) {
    return true;
  }
  return false;
}

bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
                                          const FormatToken &Left,
                                          const FormatToken &Right) const {
  if (Left.is(tok::kw_return) &&
      !Right.isOneOf(tok::semi, tok::r_paren, tok::hashhash)) {
    return true;
  }
  if (Left.is(tok::kw_throw) && Right.is(tok::l_paren) && Right.MatchingParen &&
      Right.MatchingParen->is(TT_CastRParen)) {
    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(BK_Block) && Right.is(tok::r_brace) &&
      Right.MatchingParen == &Left && Line.Children.empty()) {
    return Style.SpaceInEmptyBlock;
  }
  if (Style.SpacesInParens == FormatStyle::SIPO_Custom) {
    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.SpacesInParensOptions.InEmptyParentheses;
    }
    if (Style.SpacesInParensOptions.ExceptDoubleParentheses &&
        Left.is(tok::r_paren) && Right.is(tok::r_paren)) {
      auto *InnerLParen = Left.MatchingParen;
      if (InnerLParen && InnerLParen->Previous == Right.MatchingParen) {
        InnerLParen->SpacesRequiredBefore = 0;
        return false;
      }
    }
    const FormatToken *LeftParen = nullptr;
    if (Left.is(tok::l_paren))
      LeftParen = &Left;
    else if (Right.is(tok::r_paren) && Right.MatchingParen)
      LeftParen = Right.MatchingParen;
    if (LeftParen && (LeftParen->is(TT_ConditionLParen) ||
                      (LeftParen->Previous &&
                       isKeywordWithCondition(*LeftParen->Previous)))) {
      return Style.SpacesInParensOptions.InConditionalStatements;
    }
  }

  // trailing return type 'auto': []() -> auto {}, auto foo() -> auto {}
  if (Left.is(tok::kw_auto) && Right.isOneOf(TT_LambdaLBrace, TT_FunctionLBrace,
                                             // function return type 'auto'
                                             TT_FunctionTypeLParen)) {
    return true;
  }

  // auto{x} auto(x)
  if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace))
    return false;

  const auto *BeforeLeft = Left.Previous;

  // operator co_await(x)
  if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && BeforeLeft &&
      BeforeLeft->is(tok::kw_operator)) {
    return false;
  }
  // co_await (x), co_yield (x), co_return (x)
  if (Left.isOneOf(tok::kw_co_await, tok::kw_co_yield, tok::kw_co_return) &&
      !Right.isOneOf(tok::semi, tok::r_paren)) {
    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.SpacesInParensOptions.InCStyleCasts
               : Style.SpacesInParensOptions.Other;
  }
  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.isNot(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;
    }
    // Don't attempt to format operator<(), as it is handled later.
    if (Right.isNot(TT_OverloadedOperatorLParen))
      return false;
  }
  if (Right.is(tok::ellipsis)) {
    return Left.Tok.isLiteral() || (Left.is(tok::identifier) && BeforeLeft &&
                                    BeforeLeft->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.isNot(TT_TypeDeclarationParen))
        return true;
    }
    // Add a space if the previous token is a pointer qualifier 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_AttributeRParen) ||
         Left.canBePointerOrReferenceQualifier())) {
      return true;
    }
    if (Left.Tok.isLiteral())
      return true;
    // for (auto a = 0, b = 0; const auto & c : {1, 2, 3})
    if (Left.isTypeOrIdentifier(LangOpts) && Right.Next && Right.Next->Next &&
        Right.Next->Next->is(TT_RangeBasedForLoopColon)) {
      return getTokenPointerOrReferenceAlignment(Right) !=
             FormatStyle::PAS_Left;
    }
    return !Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
           (getTokenPointerOrReferenceAlignment(Right) !=
                FormatStyle::PAS_Left ||
            (Line.IsMultiVariableDeclStmt &&
             (Left.NestingLevel == 0 ||
              (Left.NestingLevel == 1 && startsWithInitStatement(Line)))));
  }
  if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&
      (Left.isNot(TT_PointerOrReference) ||
       (getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right &&
        !Line.IsMultiVariableDeclStmt))) {
    return true;
  }
  if (Left.is(TT_PointerOrReference)) {
    // Add a space if the next token is a pointer qualifier and the style
    // requires spaces before pointer qualifiers.
    if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Before ||
         Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
        Right.canBePointerOrReferenceQualifier()) {
      return true;
    }
    // & 1
    if (Right.Tok.isLiteral())
      return true;
    // & /* comment
    if (Right.is(TT_BlockComment))
      return true;
    // foo() -> const Bar * override/final
    // S::foo() & noexcept/requires
    if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final, tok::kw_noexcept,
                      TT_RequiresClause) &&
        Right.isNot(TT_StartOfName)) {
      return true;
    }
    // & {
    if (Right.is(tok::l_brace) && Right.is(BK_Block))
      return true;
    // for (auto a = 0, b = 0; const auto& c : {1, 2, 3})
    if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(LangOpts) && Right.Next &&
        Right.Next->is(TT_RangeBasedForLoopColon)) {
      return getTokenPointerOrReferenceAlignment(Left) !=
             FormatStyle::PAS_Right;
    }
    if (Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,
                      tok::l_paren)) {
      return false;
    }
    if (getTokenPointerOrReferenceAlignment(Left) == FormatStyle::PAS_Right)
      return false;
    // FIXME: Setting IsMultiVariableDeclStmt for the whole line is error-prone,
    // because it does not take into account nested scopes like lambdas.
    // In multi-variable declaration statements, attach */& to the variable
    // independently of the style. However, avoid doing it if we are in a nested
    // scope, e.g. lambda. We still need to special-case statements with
    // initializers.
    if (Line.IsMultiVariableDeclStmt &&
        (Left.NestingLevel == Line.First->NestingLevel ||
         ((Left.NestingLevel == Line.First->NestingLevel + 1) &&
          startsWithInitStatement(Line)))) {
      return false;
    }
    if (!BeforeLeft)
      return false;
    if (BeforeLeft->is(tok::coloncolon)) {
      if (Left.isNot(tok::star))
        return false;
      assert(Style.PointerAlignment != FormatStyle::PAS_Right);
      if (!Right.startsSequence(tok::identifier, tok::r_paren))
        return true;
      assert(Right.Next);
      const auto *LParen = Right.Next->MatchingParen;
      return !LParen || LParen->isNot(TT_FunctionTypeLParen);
    }
    return !BeforeLeft->isOneOf(tok::l_paren, tok::l_square);
  }
  // Ensure right pointer alignment with ellipsis e.g. int *...P
  if (Left.is(tok::ellipsis) && BeforeLeft &&
      BeforeLeft->isPointerOrReference()) {
    return Style.PointerAlignment != FormatStyle::PAS_Right;
  }

  if (Right.is(tok::star) && Left.is(tok::l_paren))
    return false;
  if (Left.is(tok::star) && Right.isPointerOrReference())
    return false;
  if (Right.isPointerOrReference()) {
    const FormatToken *Previous = &Left;
    while (Previous && Previous->isNot(tok::kw_operator)) {
      if (Previous->is(tok::identifier) || Previous->isTypeName(LangOpts)) {
        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 void const*()
    //   operator void volatile*()
    //   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) {
      if (Previous->endsSequence(tok::kw_operator))
        return Style.PointerAlignment != FormatStyle::PAS_Left;
      if (Previous->is(tok::kw_const) || Previous->is(tok::kw_volatile)) {
        return (Style.PointerAlignment != FormatStyle::PAS_Left) ||
               (Style.SpaceAroundPointerQualifiers ==
                FormatStyle::SAPQ_After) ||
               (Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both);
      }
    }
  }
  if (Style.isCSharp() && Left.is(Keywords.kw_is) && Right.is(tok::l_square))
    return true;
  const auto SpaceRequiredForArrayInitializerLSquare =
      [](const FormatToken &LSquareTok, const FormatStyle &Style) {
        return Style.SpacesInContainerLiterals ||
               (Style.isProto() && !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)));
  }
  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.isNot(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.SpacesInParensOptions.Other;
  }
  if (Left.is(TT_BlockComment)) {
    // No whitespace in x(/*foo=*/1), except for JavaScript.
    return Style.isJavaScript() || !Left.TokenText.ends_with("=*/");
  }

  // Space between template and attribute.
  // e.g. template <typename T> [[nodiscard]] ...
  if (Left.is(TT_TemplateCloser) && Right.is(TT_AttributeSquare))
    return true;
  // Space before parentheses common for all languages
  if (Right.is(tok::l_paren)) {
    if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen))
      return spaceRequiredBeforeParens(Right);
    if (Left.isOneOf(TT_RequiresClause,
                     TT_RequiresClauseInARequiresExpression)) {
      return Style.SpaceBeforeParensOptions.AfterRequiresInClause ||
             spaceRequiredBeforeParens(Right);
    }
    if (Left.is(TT_RequiresExpression)) {
      return Style.SpaceBeforeParensOptions.AfterRequiresInExpression ||
             spaceRequiredBeforeParens(Right);
    }
    if (Left.is(TT_AttributeRParen) ||
        (Left.is(tok::r_square) && Left.is(TT_AttributeSquare))) {
      return true;
    }
    if (Left.is(TT_ForEachMacro)) {
      return Style.SpaceBeforeParensOptions.AfterForeachMacros ||
             spaceRequiredBeforeParens(Right);
    }
    if (Left.is(TT_IfMacro)) {
      return Style.SpaceBeforeParensOptions.AfterIfMacros ||
             spaceRequiredBeforeParens(Right);
    }
    if (Style.SpaceBeforeParens == FormatStyle::SBPO_Custom &&
        Left.isOneOf(tok::kw_new, tok::kw_delete) &&
        Right.isNot(TT_OverloadedOperatorLParen) &&
        !(Line.MightBeFunctionDecl && Left.is(TT_FunctionDeclarationName))) {
      const auto *RParen = Right.MatchingParen;
      return Style.SpaceBeforeParensOptions.AfterPlacementOperator ||
             (RParen && RParen->is(TT_CastRParen));
    }
    if (Line.Type == LT_ObjCDecl)
      return true;
    if (Left.is(tok::semi))
      return true;
    if (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) ||
        Right.is(TT_ConditionLParen)) {
      return Style.SpaceBeforeParensOptions.AfterControlStatements ||
             spaceRequiredBeforeParens(Right);
    }

    // TODO add Operator overloading specific Options to
    // SpaceBeforeParensOptions
    if (Right.is(TT_OverloadedOperatorLParen))
      return spaceRequiredBeforeParens(Right);
    // Function declaration or definition
    if (Line.MightBeFunctionDecl && Right.is(TT_FunctionDeclarationLParen)) {
      if (spaceRequiredBeforeParens(Right))
        return true;
      const auto &Options = Style.SpaceBeforeParensOptions;
      return Line.mightBeFunctionDefinition()
                 ? Options.AfterFunctionDefinitionName
                 : Options.AfterFunctionDeclarationName;
    }
    // Lambda
    if (Line.Type != LT_PreprocessorDirective && Left.is(tok::r_square) &&
        Left.MatchingParen && Left.MatchingParen->is(TT_LambdaLSquare)) {
      return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName ||
             spaceRequiredBeforeParens(Right);
    }
    if (!BeforeLeft || !BeforeLeft->isOneOf(tok::period, tok::arrow)) {
      if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) {
        return Style.SpaceBeforeParensOptions.AfterControlStatements ||
               spaceRequiredBeforeParens(Right);
      }
      if (Left.isOneOf(tok::kw_new, tok::kw_delete)) {
        return ((!Line.MightBeFunctionDecl || !BeforeLeft) &&
                Style.SpaceBeforeParens != FormatStyle::SBPO_Never) ||
               spaceRequiredBeforeParens(Right);
      }

      if (Left.is(tok::r_square) && Left.MatchingParen &&
          Left.MatchingParen->Previous &&
          Left.MatchingParen->Previous->is(tok::kw_delete)) {
        return (Style.SpaceBeforeParens != FormatStyle::SBPO_Never) ||
               spaceRequiredBeforeParens(Right);
      }
    }
    // Handle builtins like identifiers.
    if (Line.Type != LT_PreprocessorDirective &&
        (Left.Tok.getIdentifierInfo() || Left.is(tok::r_paren))) {
      return spaceRequiredBeforeParens(Right);
    }
    return false;
  }
  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));
  }
  // No space between the variable name and the initializer list.
  // A a1{1};
  // Verilog doesn't have such syntax, but it has word operators that are C++
  // identifiers like `a inside {b, c}`. So the rule is not applicable.
  if (!Style.isVerilog() &&
      (Left.isOneOf(tok::identifier, tok::greater, tok::r_square,
                    tok::r_paren) ||
       Left.isTypeName(LangOpts)) &&
      Right.is(tok::l_brace) && Right.getNextNonComment() &&
      Right.isNot(BK_Block)) {
    return false;
  }
  if (Left.is(tok::period) || Right.is(tok::period))
    return false;
  // u#str, U#str, L#str, u8#str
  // uR#str, UR#str, LR#str, u8R#str
  if (Right.is(tok::hash) && Left.is(tok::identifier) &&
      (Left.TokenText == "L" || Left.TokenText == "u" ||
       Left.TokenText == "U" || Left.TokenText == "u8" ||
       Left.TokenText == "LR" || Left.TokenText == "uR" ||
       Left.TokenText == "UR" || Left.TokenText == "u8R")) {
    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.is(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 getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
  }

  return true;
}

bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
                                         const FormatToken &Right) const {
  const FormatToken &Left = *Right.Previous;

  // If the token is finalized don't touch it (as it could be in a
  // clang-format-off section).
  if (Left.Finalized)
    return Right.hasWhitespaceBefore();

  const bool IsVerilog = Style.isVerilog();
  assert(!IsVerilog || !IsCpp);

  // Never ever merge two words.
  if (Keywords.isWordLike(Right, IsVerilog) &&
      Keywords.isWordLike(Left, IsVerilog)) {
    return true;
  }

  // Leave a space between * and /* to avoid C4138 `comment end` found outside
  // of comment.
  if (Left.is(tok::star) && Right.is(tok::comment))
    return true;

  const auto *BeforeLeft = Left.Previous;

  if (IsCpp) {
    if (Left.is(TT_OverloadedOperator) &&
        Right.isOneOf(TT_TemplateOpener, TT_TemplateCloser)) {
      return true;
    }
    // Space between UDL and dot: auto b = 4s .count();
    if (Right.is(tok::period) && Left.is(tok::numeric_constant))
      return true;
    // Space between import <iostream>.
    // or import .....;
    if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis))
      return true;
    // Space between `module :` and `import :`.
    if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) &&
        Right.is(TT_ModulePartitionColon)) {
      return true;
    }

    if (Right.is(TT_AfterPPDirective))
      return true;

    // No space between import foo:bar but keep a space between import :bar;
    if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon))
      return false;
    // No space between :bar;
    if (Left.is(TT_ModulePartitionColon) &&
        Right.isOneOf(tok::identifier, tok::kw_private)) {
      return false;
    }
    if (Left.is(tok::ellipsis) && Right.is(tok::identifier) &&
        Line.First->is(Keywords.kw_import)) {
      return false;
    }
    // Space in __attribute__((attr)) ::type.
    if (Left.isOneOf(TT_AttributeRParen, TT_AttributeMacro) &&
        Right.is(tok::coloncolon)) {
      return true;
    }

    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;
    }
    if (Left.is(tok::less) && Left.is(TT_OverloadedOperator) &&
        Right.is(TT_TemplateOpener)) {
      return true;
    }
    // C++ Core Guidelines suppression tag, e.g. `[[suppress(type.5)]]`.
    if (Left.is(tok::identifier) && Right.is(tok::numeric_constant))
      return Right.TokenText[0] != '.';
    // `Left` is a keyword (including C++ alternative operator) or identifier.
    if (Left.Tok.getIdentifierInfo() && Right.Tok.isLiteral())
      return true;
  } else if (Style.isProto()) {
    if (Right.is(tok::period) && !(BeforeLeft && BeforeLeft->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.hasWhitespaceBefore();
  } else if (Style.isJson()) {
    if (Right.is(tok::colon) && Left.is(tok::string_literal))
      return Style.SpaceBeforeJsonColon;
  } 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_FatArrow) || Right.is(TT_FatArrow))
      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;

    // No space before null forgiving '!'.
    if (Right.is(TT_NonNullAssertion))
      return false;

    // No space between consecutive commas '[,,]'.
    if (Left.is(tok::comma) && Right.is(tok::comma))
      return false;

    // 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.SpaceBeforeParensOptions.AfterControlStatements ||
               spaceRequiredBeforeParens(Right);
      }
    }

    // space between method modifier and opening parenthesis of a tuple return
    // type
    if ((Left.isAccessSpecifierKeyword() ||
         Left.isOneOf(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.isJavaScript()) {
    if (Left.is(TT_FatArrow))
      return true;
    // for await ( ...
    if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && BeforeLeft &&
        BeforeLeft->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_FatArrow))
        return true;
    }
    if ((Left.is(TT_TemplateString) && Left.TokenText.ends_with("${")) ||
        (Right.is(TT_TemplateString) && Right.TokenText.starts_with("}"))) {
      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 (BeforeLeft && BeforeLeft->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) && BeforeLeft &&
          (BeforeLeft->is(tok::identifier) ||
           BeforeLeft->isOneOf(tok::r_square, tok::r_brace)))) &&
        (!BeforeLeft || BeforeLeft->isNot(tok::period))) {
      return true;
    }
    if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && BeforeLeft &&
        BeforeLeft->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) && BeforeLeft &&
        BeforeLeft->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_NonNullAssertion))
      return false;
    if (Left.is(TT_NonNullAssertion) &&
        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(TT_CaseLabelArrow) || Right.is(TT_CaseLabelArrow))
      return true;
    if (Left.is(tok::r_square) && Right.is(tok::l_brace))
      return true;
    // spaces inside square brackets.
    if (Left.is(tok::l_square) || Right.is(tok::r_square))
      return Style.SpacesInSquareBrackets;

    if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren)) {
      return Style.SpaceBeforeParensOptions.AfterControlStatements ||
             spaceRequiredBeforeParens(Right);
    }
    if ((Left.isAccessSpecifierKeyword() ||
         Left.isOneOf(tok::kw_static, Keywords.kw_final, Keywords.kw_abstract,
                      Keywords.kw_native)) &&
        Right.is(TT_TemplateOpener)) {
      return true;
    }
  } else if (IsVerilog) {
    // An escaped identifier ends with whitespace.
    if (Left.is(tok::identifier) && Left.TokenText[0] == '\\')
      return true;
    // Add space between things in a primitive's state table unless in a
    // transition like `(0?)`.
    if ((Left.is(TT_VerilogTableItem) &&
         !Right.isOneOf(tok::r_paren, tok::semi)) ||
        (Right.is(TT_VerilogTableItem) && Left.isNot(tok::l_paren))) {
      const FormatToken *Next = Right.getNextNonComment();
      return !(Next && Next->is(tok::r_paren));
    }
    // Don't add space within a delay like `#0`.
    if (Left.isNot(TT_BinaryOperator) &&
        Left.isOneOf(Keywords.kw_verilogHash, Keywords.kw_verilogHashHash)) {
      return false;
    }
    // Add space after a delay.
    if (Right.isNot(tok::semi) &&
        (Left.endsSequence(tok::numeric_constant, Keywords.kw_verilogHash) ||
         Left.endsSequence(tok::numeric_constant,
                           Keywords.kw_verilogHashHash) ||
         (Left.is(tok::r_paren) && Left.MatchingParen &&
          Left.MatchingParen->endsSequence(tok::l_paren, tok::at)))) {
      return true;
    }
    // Don't add embedded spaces in a number literal like `16'h1?ax` or an array
    // literal like `'{}`.
    if (Left.is(Keywords.kw_apostrophe) ||
        (Left.is(TT_VerilogNumberBase) && Right.is(tok::numeric_constant))) {
      return false;
    }
    // Add spaces around the implication operator `->`.
    if (Left.is(tok::arrow) || Right.is(tok::arrow))
      return true;
    // Don't add spaces between two at signs. Like in a coverage event.
    // Don't add spaces between at and a sensitivity list like
    // `@(posedge clk)`.
    if (Left.is(tok::at) && Right.isOneOf(tok::l_paren, tok::star, tok::at))
      return false;
    // Add space between the type name and dimension like `logic [1:0]`.
    if (Right.is(tok::l_square) &&
        Left.isOneOf(TT_VerilogDimensionedTypeName, Keywords.kw_function)) {
      return true;
    }
    // In a tagged union expression, there should be a space after the tag.
    if (Right.isOneOf(tok::period, Keywords.kw_apostrophe) &&
        Keywords.isVerilogIdentifier(Left) && Left.getPreviousNonComment() &&
        Left.getPreviousNonComment()->is(Keywords.kw_tagged)) {
      return true;
    }
    // Don't add spaces between a casting type and the quote or repetition count
    // and the brace. The case of tagged union expressions is handled by the
    // previous rule.
    if ((Right.is(Keywords.kw_apostrophe) ||
         (Right.is(BK_BracedInit) && Right.is(tok::l_brace))) &&
        !(Left.isOneOf(Keywords.kw_assign, Keywords.kw_unique) ||
          Keywords.isVerilogWordOperator(Left)) &&
        (Left.isOneOf(tok::r_square, tok::r_paren, tok::r_brace,
                      tok::numeric_constant) ||
         Keywords.isWordLike(Left))) {
      return false;
    }
    // Don't add spaces in imports like `import foo::*;`.
    if ((Right.is(tok::star) && Left.is(tok::coloncolon)) ||
        (Left.is(tok::star) && Right.is(tok::semi))) {
      return false;
    }
    // Add space in attribute like `(* ASYNC_REG = "TRUE" *)`.
    if (Left.endsSequence(tok::star, tok::l_paren) && Right.is(tok::identifier))
      return true;
    // Add space before drive strength like in `wire (strong1, pull0)`.
    if (Right.is(tok::l_paren) && Right.is(TT_VerilogStrength))
      return true;
    // Don't add space in a streaming concatenation like `{>>{j}}`.
    if ((Left.is(tok::l_brace) &&
         Right.isOneOf(tok::lessless, tok::greatergreater)) ||
        (Left.endsSequence(tok::lessless, tok::l_brace) ||
         Left.endsSequence(tok::greatergreater, tok::l_brace))) {
      return false;
    }
  } else if (Style.isTableGen()) {
    // Avoid to connect [ and {. [{ is start token of multiline string.
    if (Left.is(tok::l_square) && Right.is(tok::l_brace))
      return true;
    if (Left.is(tok::r_brace) && Right.is(tok::r_square))
      return true;
    // Do not insert around colon in DAGArg and cond operator.
    if (Right.isOneOf(TT_TableGenDAGArgListColon,
                      TT_TableGenDAGArgListColonToAlign) ||
        Left.isOneOf(TT_TableGenDAGArgListColon,
                     TT_TableGenDAGArgListColonToAlign)) {
      return false;
    }
    if (Right.is(TT_TableGenCondOperatorColon))
      return false;
    if (Left.isOneOf(TT_TableGenDAGArgOperatorID,
                     TT_TableGenDAGArgOperatorToBreak) &&
        Right.isNot(TT_TableGenDAGArgCloser)) {
      return true;
    }
    // Do not insert bang operators and consequent openers.
    if (Right.isOneOf(tok::l_paren, tok::less) &&
        Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {
      return false;
    }
    // Trailing paste requires space before '{' or ':', the case in name values.
    // Not before ';', the case in normal values.
    if (Left.is(TT_TableGenTrailingPasteOperator) &&
        Right.isOneOf(tok::l_brace, tok::colon)) {
      return true;
    }
    // Otherwise paste operator does not prefer space around.
    if (Left.is(tok::hash) || Right.is(tok::hash))
      return false;
    // Sure not to connect after defining keywords.
    if (Keywords.isTableGenDefinition(Left))
      return true;
  }

  if (Left.is(TT_ImplicitStringLiteral))
    return Right.hasWhitespaceBefore();
  if (Line.Type == LT_ObjCMethodDecl) {
    if (Left.is(TT_ObjCMethodSpecifier))
      return true;
    if (Left.is(tok::r_paren) && Left.isNot(TT_AttributeRParen) &&
        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 (Left.is(tok::comma) && Right.isNot(TT_OverloadedOperatorLParen) &&
      // In an unexpanded macro call we only find the parentheses and commas
      // in a line; the commas and closing parenthesis do not require a space.
      (Left.Children.empty() || !Left.MacroParent)) {
    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 (Right.is(TT_CaseLabelColon))
      return Style.SpaceBeforeCaseColon;
    if (Right.is(TT_GotoLabelColon))
      return false;
    // `private:` and `public:`.
    if (!Right.getNextNonComment())
      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_GenericSelectionColon))
      return false;
    if (Right.is(TT_BitFieldColon)) {
      return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
             Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
    }
    return true;
  }
  // Do not merge "- -" into "--".
  if ((Left.isOneOf(tok::minus, tok::minusminus) &&
       Right.isOneOf(tok::minus, tok::minusminus)) ||
      (Left.isOneOf(tok::plus, tok::plusplus) &&
       Right.isOneOf(tok::plus, tok::plusplus))) {
    return true;
  }
  if (Left.is(TT_UnaryOperator)) {
    // 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);
  }

  // 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);
  }

  auto ShouldAddSpacesInAngles = [this, &Right]() {
    if (this->Style.SpacesInAngles == FormatStyle::SIAS_Always)
      return true;
    if (this->Style.SpacesInAngles == FormatStyle::SIAS_Leave)
      return Right.hasWhitespaceBefore();
    return false;
  };

  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) ||
            ShouldAddSpacesInAngles());
  }
  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.hasWhitespaceBefore();
  }
  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) ||
             ShouldAddSpacesInAngles())) ||
           !(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
                          tok::kw___super, TT_TemplateOpener,
                          TT_TemplateCloser)) ||
           (Left.is(tok::l_paren) && Style.SpacesInParensOptions.Other);
  }
  if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
    return ShouldAddSpacesInAngles();
  if (Left.is(tok::r_paren) && Left.isNot(TT_TypeDeclarationParen) &&
      Right.is(TT_PointerOrReference) && Right.isOneOf(tok::amp, tok::ampamp)) {
    return true;
  }
  // Space before TT_StructuredBindingLSquare.
  if (Right.is(TT_StructuredBindingLSquare)) {
    return !Left.isOneOf(tok::amp, tok::ampamp) ||
           getTokenReferenceAlignment(Left) != 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 getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
  }
  if ((Right.is(TT_BinaryOperator) && Left.isNot(tok::l_paren)) ||
      (Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
       Right.isNot(tok::r_paren))) {
    return true;
  }
  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.Type == LT_ImportStatement) {
    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 a 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 isAllmanLambdaBrace(const FormatToken &Tok) {
  return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&
         !Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral);
}

bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
                                     const FormatToken &Right) const {
  const FormatToken &Left = *Right.Previous;
  if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0 &&
      (!Style.RemoveEmptyLinesInUnwrappedLines || &Right == Line.First)) {
    return true;
  }

  if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl &&
      Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen &&
      Left.ParameterCount > 0) {
    return true;
  }

  // Ignores the first parameter as this will be handled separately by
  // BreakFunctionDefinitionParameters or AlignAfterOpenBracket.
  if (Style.BinPackParameters == FormatStyle::BPPS_AlwaysOnePerLine &&
      Line.MightBeFunctionDecl && !Left.opensScope() &&
      startsNextParameter(Right, Style)) {
    return true;
  }

  const auto *BeforeLeft = Left.Previous;
  const auto *AfterRight = Right.Next;

  if (Style.isCSharp()) {
    if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) &&
        Style.BraceWrapping.AfterFunction) {
      return true;
    }
    if (Right.is(TT_CSharpNamedArgumentColon) ||
        Left.is(TT_CSharpNamedArgumentColon)) {
      return false;
    }
    if (Right.is(TT_CSharpGenericTypeConstraint))
      return true;
    if (AfterRight && AfterRight->is(TT_FatArrow) &&
        (Right.is(tok::numeric_constant) ||
         (Right.is(tok::identifier) && Right.TokenText == "_"))) {
      return true;
    }

    // Break after C# [...] and before public/protected/private/internal.
    if (Left.is(TT_AttributeSquare) && Left.is(tok::r_square) &&
        (Right.isAccessSpecifier(/*ColonRequired=*/false) ||
         Right.is(Keywords.kw_internal))) {
      return true;
    }
    // Break between ] and [ but only when there are really 2 attributes.
    if (Left.is(TT_AttributeSquare) && Right.is(TT_AttributeSquare) &&
        Left.is(tok::r_square) && Right.is(tok::l_square)) {
      return true;
    }
  } else if (Style.isJavaScript()) {
    // FIXME: This might apply to other languages and token kinds.
    if (Right.is(tok::string_literal) && Left.is(tok::plus) && BeforeLeft &&
        BeforeLeft->is(tok::string_literal)) {
      return true;
    }
    if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 &&
        BeforeLeft && BeforeLeft->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) && BeforeLeft &&
        BeforeLeft->is(TT_FatArrow)) {
      // 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) && AfterRight &&
        AfterRight->is(tok::string_literal)) {
      return true;
    }
  } else if (Style.isVerilog()) {
    // Break between assignments.
    if (Left.is(TT_VerilogAssignComma))
      return true;
    // Break between ports of different types.
    if (Left.is(TT_VerilogTypeComma))
      return true;
    // Break between ports in a module instantiation and after the parameter
    // list.
    if (Style.VerilogBreakBetweenInstancePorts &&
        (Left.is(TT_VerilogInstancePortComma) ||
         (Left.is(tok::r_paren) && Keywords.isVerilogIdentifier(Right) &&
          Left.MatchingParen &&
          Left.MatchingParen->is(TT_VerilogInstancePortLParen)))) {
      return true;
    }
    // Break after labels. In Verilog labels don't have the 'case' keyword, so
    // it is hard to identify them in UnwrappedLineParser.
    if (!Keywords.isVerilogBegin(Right) && Keywords.isVerilogEndOfLabel(Left))
      return true;
  } else if (Style.BreakAdjacentStringLiterals &&
             (IsCpp || Style.isProto() ||
              Style.Language == FormatStyle::LK_TableGen)) {
    if (Left.isStringLiteral() && Right.isStringLiteral())
      return true;
  }

  // Basic JSON newline processing.
  if (Style.isJson()) {
    // Always break after a JSON record opener.
    // {
    // }
    if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace))
      return true;
    // Always break after a JSON array opener based on BreakArrays.
    if ((Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) &&
         Right.isNot(tok::r_square)) ||
        Left.is(tok::comma)) {
      if (Right.is(tok::l_brace))
        return true;
      // scan to the right if an we see an object or an array inside
      // then break.
      for (const auto *Tok = &Right; Tok; Tok = Tok->Next) {
        if (Tok->isOneOf(tok::l_brace, tok::l_square))
          return true;
        if (Tok->isOneOf(tok::r_brace, tok::r_square))
          break;
      }
      return Style.BreakArrays;
    }
  } else if (Style.isTableGen()) {
    // Break the comma in side cond operators.
    // !cond(case1:1,
    //       case2:0);
    if (Left.is(TT_TableGenCondOperatorComma))
      return true;
    if (Left.is(TT_TableGenDAGArgOperatorToBreak) &&
        Right.isNot(TT_TableGenDAGArgCloser)) {
      return true;
    }
    if (Left.is(TT_TableGenDAGArgListCommaToBreak))
      return true;
    if (Right.is(TT_TableGenDAGArgCloser) && Right.MatchingParen &&
        Right.MatchingParen->is(TT_TableGenDAGArgOpenerToBreak) &&
        &Left != Right.MatchingParen->Next) {
      // Check to avoid empty DAGArg such as (ins).
      return Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll;
    }
  }

  if (Line.startsWith(tok::kw_asm) && Right.is(TT_InlineASMColon) &&
      Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always) {
    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.isJavaScript() && 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.isJavaScript() &&
                 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 (Left.IsUnterminatedLiteral)
    return true;

  if (BeforeLeft && BeforeLeft->is(tok::lessless) &&
      Left.is(tok::string_literal) && Right.is(tok::lessless) && AfterRight &&
      AfterRight->is(tok::string_literal)) {
    return Right.NewlinesBefore > 0;
  }

  if (Right.is(TT_RequiresClause)) {
    switch (Style.RequiresClausePosition) {
    case FormatStyle::RCPS_OwnLine:
    case FormatStyle::RCPS_OwnLineWithBrace:
    case FormatStyle::RCPS_WithFollowing:
      return true;
    default:
      break;
    }
  }
  // Can break after template<> declaration
  if (Left.ClosesTemplateDeclaration && Left.MatchingParen &&
      Left.MatchingParen->NestingLevel == 0) {
    // Put concepts on the next line e.g.
    // template<typename T>
    // concept ...
    if (Right.is(tok::kw_concept))
      return Style.BreakBeforeConceptDeclarations == FormatStyle::BBCDS_Always;
    return Style.BreakTemplateDeclarations == FormatStyle::BTDS_Yes ||
           (Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave &&
            Right.NewlinesBefore > 0);
  }
  if (Left.ClosesRequiresClause) {
    switch (Style.RequiresClausePosition) {
    case FormatStyle::RCPS_OwnLine:
    case FormatStyle::RCPS_WithPreceding:
      return Right.isNot(tok::semi);
    case FormatStyle::RCPS_OwnLineWithBrace:
      return !Right.isOneOf(tok::semi, tok::l_brace);
    default:
      break;
    }
  }
  if (Style.PackConstructorInitializers == FormatStyle::PCIS_Never) {
    if (Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon &&
        (Left.is(TT_CtorInitializerComma) ||
         Right.is(TT_CtorInitializerColon))) {
      return true;
    }

    if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&
        Left.isOneOf(TT_CtorInitializerColon, TT_CtorInitializerComma)) {
      return true;
    }
  }
  if (Style.PackConstructorInitializers < FormatStyle::PCIS_CurrentLine &&
      Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
      Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon)) {
    return true;
  }
  if (Style.PackConstructorInitializers == FormatStyle::PCIS_NextLineOnly) {
    if ((Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon ||
         Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) &&
        Right.is(TT_CtorInitializerColon)) {
      return true;
    }

    if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&
        Left.is(TT_CtorInitializerColon)) {
      return true;
    }
  }
  // Break only if we have multiple inheritance.
  if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&
      Right.is(TT_InheritanceComma)) {
    return true;
  }
  if (Style.BreakInheritanceList == FormatStyle::BILS_AfterComma &&
      Left.is(TT_InheritanceComma)) {
    return true;
  }
  if (Right.is(tok::string_literal) && Right.TokenText.starts_with("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 ((Left.is(tok::l_brace) ||
       (Left.is(tok::less) && BeforeLeft && BeforeLeft->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;

  if (isAllmanBrace(Left) || isAllmanBrace(Right)) {
    auto *FirstNonComment = Line.getFirstNonComment();
    bool AccessSpecifier =
        FirstNonComment && (FirstNonComment->is(Keywords.kw_internal) ||
                            FirstNonComment->isAccessSpecifierKeyword());

    if (Style.BraceWrapping.AfterEnum) {
      if (Line.startsWith(tok::kw_enum) ||
          Line.startsWith(tok::kw_typedef, tok::kw_enum)) {
        return true;
      }
      // Ensure BraceWrapping for `public enum A {`.
      if (AccessSpecifier && FirstNonComment->Next &&
          FirstNonComment->Next->is(tok::kw_enum)) {
        return true;
      }
    }

    // Ensure BraceWrapping for `public interface A {`.
    if (Style.BraceWrapping.AfterClass &&
        ((AccessSpecifier && FirstNonComment->Next &&
          FirstNonComment->Next->is(Keywords.kw_interface)) ||
         Line.startsWith(Keywords.kw_interface))) {
      return true;
    }

    // Don't attempt to interpret struct return types as structs.
    if (Right.isNot(TT_FunctionLBrace)) {
      return (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;
  }

  // Ensure wrapping after __attribute__((XX)) and @interface etc.
  if (Left.isOneOf(TT_AttributeRParen, TT_AttributeMacro) &&
      Right.is(TT_ObjCDecl)) {
    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;
    }
  }

  if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) &&
      (Left.isPointerOrReference() || Left.is(TT_TemplateCloser))) {
    return true;
  }

  // Put multiple Java annotation on a new line.
  if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
      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.isProto() && Right.is(TT_SelectorName) &&
      Right.isNot(tok::r_square) && AfterRight) {
    // Keep `@submessage` together in:
    // @submessage { key: value }
    if (Left.is(tok::at))
      return false;
    // Look for the scope opener after selector in cases like:
    // selector { ...
    // selector: { ...
    // selector: @base { ...
    const auto *LBrace = AfterRight;
    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;
  }

  return false;
}

bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
                                    const FormatToken &Right) const {
  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);
    // Keep nullable operators attached to their identifiers.
    if (Right.is(TT_CSharpNullable))
      return false;
  } 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.isJavaScript()) {
    const FormatToken *NonComment = Right.getPreviousNonComment();
    if (NonComment &&
        (NonComment->isAccessSpecifierKeyword() ||
         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, Keywords.kw_readonly, Keywords.kw_override,
             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 (NonComment && NonComment->is(tok::identifier) &&
        NonComment->TokenText == "asserts") {
      return false;
    }
    if (Left.is(TT_FatArrow) && 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->isNot(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_NonNullAssertion))
      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/main/doc/spec-ARCHIVED.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;
  } else if (Style.isTableGen()) {
    // Avoid to break after "def", "class", "let" and so on.
    if (Keywords.isTableGenDefinition(Left))
      return false;
    // Avoid to break after '(' in the cases that is in bang operators.
    if (Right.is(tok::l_paren)) {
      return !Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator,
                           TT_TemplateCloser);
    }
    // Avoid to break between the value and its suffix part.
    if (Left.is(TT_TableGenValueSuffix))
      return false;
    // Avoid to break around paste operator.
    if (Left.is(tok::hash) || Right.is(tok::hash))
      return false;
    if (Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator))
      return false;
  }

  // We can break before an r_brace if there was a break after the matching
  // l_brace, which is tracked by BreakBeforeClosingBrace, or if we are in a
  // block-indented initialization list.
  if (Right.is(tok::r_brace)) {
    return Right.MatchingParen && (Right.MatchingParen->is(BK_Block) ||
                                   (Right.isBlockIndentedInitRBrace(Style)));
  }

  // We only break before r_paren if we're in a block indented context.
  if (Right.is(tok::r_paren)) {
    if (Style.AlignAfterOpenBracket != FormatStyle::BAS_BlockIndent ||
        !Right.MatchingParen) {
      return false;
    }
    auto Next = Right.Next;
    if (Next && Next->is(tok::r_paren))
      Next = Next->Next;
    if (Next && Next->is(tok::l_paren))
      return false;
    const FormatToken *Previous = Right.MatchingParen->Previous;
    return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf()));
  }

  if (Left.isOneOf(tok::r_paren, TT_TrailingAnnotation) &&
      Right.is(TT_TrailingAnnotation) &&
      Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) {
    return false;
  }

  if (Right.is(TT_TemplateCloser))
    return Style.BreakBeforeTemplateCloser;

  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.isNot(tok::l_paren);
  if (Right.is(TT_PointerOrReference)) {
    return Line.IsMultiVariableDeclStmt ||
           (getTokenPointerOrReferenceAlignment(Right) ==
                FormatStyle::PAS_Right &&
            (!Right.Next || Right.Next->isNot(TT_FunctionDeclarationName)));
  }
  if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
                    TT_ClassHeadName, 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) && Right.NewlinesBefore > 0 &&
            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.isNot(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.isProto()) {
      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 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 (Right.is(tok::kw_concept))
    return Style.BreakBeforeConceptDeclarations != FormatStyle::BBCDS_Never;
  if (Right.is(TT_RequiresClause))
    return true;
  if (Left.ClosesTemplateDeclaration) {
    return Style.BreakTemplateDeclarations != FormatStyle::BTDS_Leave ||
           Right.NewlinesBefore > 0;
  }
  if (Left.is(TT_FunctionAnnotationRParen))
    return true;
  if (Left.ClosesRequiresClause)
    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.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.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(TT_AttributeLParen) ||
      (Left.is(tok::l_paren) && Left.is(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_square) && Right.MatchingParen &&
      Right.MatchingParen->is(TT_LambdaLSquare)) {
    return false;
  }

  // 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.isAttribute())
    return true;

  if (Right.is(tok::l_square) && Right.is(TT_AttributeSquare))
    return Left.isNot(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 &&
           (!Right.isTrailingComment() || Right.NewlinesBefore > 0);
  }
  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(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 && Right.is(TT_LambdaLBrace)) {
    if (isAllmanLambdaBrace(Left))
      return !isItAnEmptyLambdaAllowed(Left, ShortLambdaOption);
    if (isAllmanLambdaBrace(Right))
      return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption);
  }

  if (Right.is(tok::kw_noexcept) && Right.is(TT_TrailingAnnotation)) {
    switch (Style.AllowBreakBeforeNoexceptSpecifier) {
    case FormatStyle::BBNSS_Never:
      return false;
    case FormatStyle::BBNSS_Always:
      return true;
    case FormatStyle::BBNSS_OnlyWithParen:
      return Right.Next && Right.Next->is(tok::l_paren);
    }
  }

  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) ||
         (Left.is(tok::r_paren) &&
          Right.isOneOf(tok::identifier, tok::kw_const)) ||
         (Left.is(tok::l_paren) && Right.isNot(tok::r_paren)) ||
         (Left.is(TT_TemplateOpener) && Right.isNot(TT_TemplateCloser));
}

void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
  llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel
               << ", T=" << Line.Type << ", C=" << Line.IsContinuation
               << "):\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 (prec::Level LParen : Tok->FakeLParens)
      llvm::errs() << LParen << "/";
    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";
}

FormatStyle::PointerAlignmentStyle
TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {
  assert(Reference.isOneOf(tok::amp, tok::ampamp));
  switch (Style.ReferenceAlignment) {
  case FormatStyle::RAS_Pointer:
    return Style.PointerAlignment;
  case FormatStyle::RAS_Left:
    return FormatStyle::PAS_Left;
  case FormatStyle::RAS_Right:
    return FormatStyle::PAS_Right;
  case FormatStyle::RAS_Middle:
    return FormatStyle::PAS_Middle;
  }
  assert(0); //"Unhandled value of ReferenceAlignment"
  return Style.PointerAlignment;
}

FormatStyle::PointerAlignmentStyle
TokenAnnotator::getTokenPointerOrReferenceAlignment(
    const FormatToken &PointerOrReference) const {
  if (PointerOrReference.isOneOf(tok::amp, tok::ampamp)) {
    switch (Style.ReferenceAlignment) {
    case FormatStyle::RAS_Pointer:
      return Style.PointerAlignment;
    case FormatStyle::RAS_Left:
      return FormatStyle::PAS_Left;
    case FormatStyle::RAS_Right:
      return FormatStyle::PAS_Right;
    case FormatStyle::RAS_Middle:
      return FormatStyle::PAS_Middle;
    }
  }
  assert(PointerOrReference.is(tok::star));
  return Style.PointerAlignment;
}

} // namespace format
} // namespace clang
