//===--- UnwrappedLineParser.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 contains the implementation of the UnwrappedLineParser,
/// which turns a stream of tokens into UnwrappedLines.
///
//===----------------------------------------------------------------------===//

#include "UnwrappedLineParser.h"
#include "FormatToken.h"
#include "FormatTokenSource.h"
#include "Macros.h"
#include "TokenAnnotator.h"
#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_os_ostream.h"
#include "llvm/Support/raw_ostream.h"

#include <utility>

#define DEBUG_TYPE "format-parser"

namespace clang {
namespace format {

namespace {

void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line,
               StringRef Prefix = "", bool PrintText = false) {
  OS << Prefix << "Line(" << Line.Level << ", FSC=" << Line.FirstStartColumn
     << ")" << (Line.InPPDirective ? " MACRO" : "") << ": ";
  bool NewLine = false;
  for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
                                                    E = Line.Tokens.end();
       I != E; ++I) {
    if (NewLine) {
      OS << Prefix;
      NewLine = false;
    }
    OS << I->Tok->Tok.getName() << "["
       << "T=" << (unsigned)I->Tok->getType()
       << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText
       << "\"] ";
    for (const auto *CI = I->Children.begin(), *CE = I->Children.end();
         CI != CE; ++CI) {
      OS << "\n";
      printLine(OS, *CI, (Prefix + "  ").str());
      NewLine = true;
    }
  }
  if (!NewLine)
    OS << "\n";
}

[[maybe_unused]] static void printDebugInfo(const UnwrappedLine &Line) {
  printLine(llvm::dbgs(), Line);
}

class ScopedDeclarationState {
public:
  ScopedDeclarationState(UnwrappedLine &Line, llvm::BitVector &Stack,
                         bool MustBeDeclaration)
      : Line(Line), Stack(Stack) {
    Line.MustBeDeclaration = MustBeDeclaration;
    Stack.push_back(MustBeDeclaration);
  }
  ~ScopedDeclarationState() {
    Stack.pop_back();
    if (!Stack.empty())
      Line.MustBeDeclaration = Stack.back();
    else
      Line.MustBeDeclaration = true;
  }

private:
  UnwrappedLine &Line;
  llvm::BitVector &Stack;
};

} // end anonymous namespace

std::ostream &operator<<(std::ostream &Stream, const UnwrappedLine &Line) {
  llvm::raw_os_ostream OS(Stream);
  printLine(OS, Line);
  return Stream;
}

class ScopedLineState {
public:
  ScopedLineState(UnwrappedLineParser &Parser,
                  bool SwitchToPreprocessorLines = false)
      : Parser(Parser), OriginalLines(Parser.CurrentLines) {
    if (SwitchToPreprocessorLines)
      Parser.CurrentLines = &Parser.PreprocessorDirectives;
    else if (!Parser.Line->Tokens.empty())
      Parser.CurrentLines = &Parser.Line->Tokens.back().Children;
    PreBlockLine = std::move(Parser.Line);
    Parser.Line = std::make_unique<UnwrappedLine>();
    Parser.Line->Level = PreBlockLine->Level;
    Parser.Line->PPLevel = PreBlockLine->PPLevel;
    Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
    Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
    Parser.Line->UnbracedBodyLevel = PreBlockLine->UnbracedBodyLevel;
  }

  ~ScopedLineState() {
    if (!Parser.Line->Tokens.empty())
      Parser.addUnwrappedLine();
    assert(Parser.Line->Tokens.empty());
    Parser.Line = std::move(PreBlockLine);
    if (Parser.CurrentLines == &Parser.PreprocessorDirectives)
      Parser.AtEndOfPPLine = true;
    Parser.CurrentLines = OriginalLines;
  }

private:
  UnwrappedLineParser &Parser;

  std::unique_ptr<UnwrappedLine> PreBlockLine;
  SmallVectorImpl<UnwrappedLine> *OriginalLines;
};

class CompoundStatementIndenter {
public:
  CompoundStatementIndenter(UnwrappedLineParser *Parser,
                            const FormatStyle &Style, unsigned &LineLevel)
      : CompoundStatementIndenter(Parser, LineLevel,
                                  Style.BraceWrapping.AfterControlStatement ==
                                      FormatStyle::BWACS_Always,
                                  Style.BraceWrapping.IndentBraces) {}
  CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel,
                            bool WrapBrace, bool IndentBrace)
      : LineLevel(LineLevel), OldLineLevel(LineLevel) {
    if (WrapBrace)
      Parser->addUnwrappedLine();
    if (IndentBrace)
      ++LineLevel;
  }
  ~CompoundStatementIndenter() { LineLevel = OldLineLevel; }

private:
  unsigned &LineLevel;
  unsigned OldLineLevel;
};

UnwrappedLineParser::UnwrappedLineParser(
    SourceManager &SourceMgr, const FormatStyle &Style,
    const AdditionalKeywords &Keywords, unsigned FirstStartColumn,
    ArrayRef<FormatToken *> Tokens, UnwrappedLineConsumer &Callback,
    llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
    IdentifierTable &IdentTable)
    : Line(new UnwrappedLine), AtEndOfPPLine(false), CurrentLines(&Lines),
      Style(Style), IsCpp(Style.isCpp()),
      LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords),
      CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
      Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
      IncludeGuard(getIncludeGuardState(Style.IndentPPDirectives)),
      IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn),
      Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {}

void UnwrappedLineParser::reset() {
  PPBranchLevel = -1;
  IncludeGuard = getIncludeGuardState(Style.IndentPPDirectives);
  IncludeGuardToken = nullptr;
  Line.reset(new UnwrappedLine);
  CommentsBeforeNextToken.clear();
  FormatTok = nullptr;
  AtEndOfPPLine = false;
  IsDecltypeAutoFunction = false;
  PreprocessorDirectives.clear();
  CurrentLines = &Lines;
  DeclarationScopeStack.clear();
  NestedTooDeep.clear();
  NestedLambdas.clear();
  PPStack.clear();
  Line->FirstStartColumn = FirstStartColumn;

  if (!Unexpanded.empty())
    for (FormatToken *Token : AllTokens)
      Token->MacroCtx.reset();
  CurrentExpandedLines.clear();
  ExpandedLines.clear();
  Unexpanded.clear();
  InExpansion = false;
  Reconstruct.reset();
}

void UnwrappedLineParser::parse() {
  IndexedTokenSource TokenSource(AllTokens);
  Line->FirstStartColumn = FirstStartColumn;
  do {
    LLVM_DEBUG(llvm::dbgs() << "----\n");
    reset();
    Tokens = &TokenSource;
    TokenSource.reset();

    readToken();
    parseFile();

    // If we found an include guard then all preprocessor directives (other than
    // the guard) are over-indented by one.
    if (IncludeGuard == IG_Found) {
      for (auto &Line : Lines)
        if (Line.InPPDirective && Line.Level > 0)
          --Line.Level;
    }

    // Create line with eof token.
    assert(eof());
    pushToken(FormatTok);
    addUnwrappedLine();

    // In a first run, format everything with the lines containing macro calls
    // replaced by the expansion.
    if (!ExpandedLines.empty()) {
      LLVM_DEBUG(llvm::dbgs() << "Expanded lines:\n");
      for (const auto &Line : Lines) {
        if (!Line.Tokens.empty()) {
          auto it = ExpandedLines.find(Line.Tokens.begin()->Tok);
          if (it != ExpandedLines.end()) {
            for (const auto &Expanded : it->second) {
              LLVM_DEBUG(printDebugInfo(Expanded));
              Callback.consumeUnwrappedLine(Expanded);
            }
            continue;
          }
        }
        LLVM_DEBUG(printDebugInfo(Line));
        Callback.consumeUnwrappedLine(Line);
      }
      Callback.finishRun();
    }

    LLVM_DEBUG(llvm::dbgs() << "Unwrapped lines:\n");
    for (const UnwrappedLine &Line : Lines) {
      LLVM_DEBUG(printDebugInfo(Line));
      Callback.consumeUnwrappedLine(Line);
    }
    Callback.finishRun();
    Lines.clear();
    while (!PPLevelBranchIndex.empty() &&
           PPLevelBranchIndex.back() + 1 >= PPLevelBranchCount.back()) {
      PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1);
      PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1);
    }
    if (!PPLevelBranchIndex.empty()) {
      ++PPLevelBranchIndex.back();
      assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size());
      assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());
    }
  } while (!PPLevelBranchIndex.empty());
}

void UnwrappedLineParser::parseFile() {
  // The top-level context in a file always has declarations, except for pre-
  // processor directives and JavaScript files.
  bool MustBeDeclaration = !Line->InPPDirective && !Style.isJavaScript();
  ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
                                          MustBeDeclaration);
  if (Style.isTextProto() || (Style.isJson() && FormatTok->IsFirst))
    parseBracedList();
  else
    parseLevel();
  // Make sure to format the remaining tokens.
  //
  // LK_TextProto is special since its top-level is parsed as the body of a
  // braced list, which does not necessarily have natural line separators such
  // as a semicolon. Comments after the last entry that have been determined to
  // not belong to that line, as in:
  //   key: value
  //   // endfile comment
  // do not have a chance to be put on a line of their own until this point.
  // Here we add this newline before end-of-file comments.
  if (Style.isTextProto() && !CommentsBeforeNextToken.empty())
    addUnwrappedLine();
  flushComments(true);
  addUnwrappedLine();
}

void UnwrappedLineParser::parseCSharpGenericTypeConstraint() {
  do {
    switch (FormatTok->Tok.getKind()) {
    case tok::l_brace:
    case tok::semi:
      return;
    default:
      if (FormatTok->is(Keywords.kw_where)) {
        addUnwrappedLine();
        nextToken();
        parseCSharpGenericTypeConstraint();
        break;
      }
      nextToken();
      break;
    }
  } while (!eof());
}

void UnwrappedLineParser::parseCSharpAttribute() {
  int UnpairedSquareBrackets = 1;
  do {
    switch (FormatTok->Tok.getKind()) {
    case tok::r_square:
      nextToken();
      --UnpairedSquareBrackets;
      if (UnpairedSquareBrackets == 0) {
        addUnwrappedLine();
        return;
      }
      break;
    case tok::l_square:
      ++UnpairedSquareBrackets;
      nextToken();
      break;
    default:
      nextToken();
      break;
    }
  } while (!eof());
}

bool UnwrappedLineParser::precededByCommentOrPPDirective() const {
  if (!Lines.empty() && Lines.back().InPPDirective)
    return true;

  const FormatToken *Previous = Tokens->getPreviousToken();
  return Previous && Previous->is(tok::comment) &&
         (Previous->IsMultiline || Previous->NewlinesBefore > 0);
}

/// Parses a level, that is ???.
/// \param OpeningBrace Opening brace (\p nullptr if absent) of that level.
/// \param IfKind The \p if statement kind in the level.
/// \param IfLeftBrace The left brace of the \p if block in the level.
/// \returns true if a simple block of if/else/for/while, or false otherwise.
/// (A simple block has a single statement.)
bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
                                     IfStmtKind *IfKind,
                                     FormatToken **IfLeftBrace) {
  const bool InRequiresExpression =
      OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);
  const bool IsPrecededByCommentOrPPDirective =
      !Style.RemoveBracesLLVM || precededByCommentOrPPDirective();
  FormatToken *IfLBrace = nullptr;
  bool HasDoWhile = false;
  bool HasLabel = false;
  unsigned StatementCount = 0;
  bool SwitchLabelEncountered = false;

  do {
    if (FormatTok->isAttribute()) {
      nextToken();
      if (FormatTok->is(tok::l_paren))
        parseParens();
      continue;
    }
    tok::TokenKind Kind = FormatTok->Tok.getKind();
    if (FormatTok->is(TT_MacroBlockBegin))
      Kind = tok::l_brace;
    else if (FormatTok->is(TT_MacroBlockEnd))
      Kind = tok::r_brace;

    auto ParseDefault = [this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,
                         &HasLabel, &StatementCount] {
      parseStructuralElement(OpeningBrace, IfKind, &IfLBrace,
                             HasDoWhile ? nullptr : &HasDoWhile,
                             HasLabel ? nullptr : &HasLabel);
      ++StatementCount;
      assert(StatementCount > 0 && "StatementCount overflow!");
    };

    switch (Kind) {
    case tok::comment:
      nextToken();
      addUnwrappedLine();
      break;
    case tok::l_brace:
      if (InRequiresExpression) {
        FormatTok->setFinalizedType(TT_CompoundRequirementLBrace);
      } else if (FormatTok->Previous &&
                 FormatTok->Previous->ClosesRequiresClause) {
        // We need the 'default' case here to correctly parse a function
        // l_brace.
        ParseDefault();
        continue;
      }
      if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) {
        if (tryToParseBracedList())
          continue;
        FormatTok->setFinalizedType(TT_BlockLBrace);
      }
      parseBlock();
      ++StatementCount;
      assert(StatementCount > 0 && "StatementCount overflow!");
      addUnwrappedLine();
      break;
    case tok::r_brace:
      if (OpeningBrace) {
        if (!Style.RemoveBracesLLVM || Line->InPPDirective ||
            OpeningBrace->isNoneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {
          return false;
        }
        if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel ||
            HasDoWhile || IsPrecededByCommentOrPPDirective ||
            precededByCommentOrPPDirective()) {
          return false;
        }
        const FormatToken *Next = Tokens->peekNextToken();
        if (Next->is(tok::comment) && Next->NewlinesBefore == 0)
          return false;
        if (IfLeftBrace)
          *IfLeftBrace = IfLBrace;
        return true;
      }
      nextToken();
      addUnwrappedLine();
      break;
    case tok::kw_default: {
      unsigned StoredPosition = Tokens->getPosition();
      auto *Next = Tokens->getNextNonComment();
      FormatTok = Tokens->setPosition(StoredPosition);
      if (Next->isNoneOf(tok::colon, tok::arrow)) {
        // default not followed by `:` or `->` is not a case label; treat it
        // like an identifier.
        parseStructuralElement();
        break;
      }
      // Else, if it is 'default:', fall through to the case handling.
      [[fallthrough]];
    }
    case tok::kw_case:
      if (Style.Language == FormatStyle::LK_Proto || Style.isVerilog() ||
          (Style.isJavaScript() && Line->MustBeDeclaration)) {
        // Proto: there are no switch/case statements
        // Verilog: Case labels don't have this word. We handle case
        // labels including default in TokenAnnotator.
        // JavaScript: A 'case: string' style field declaration.
        ParseDefault();
        break;
      }
      if (!SwitchLabelEncountered &&
          (Style.IndentCaseLabels ||
           (OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) ||
           (Line->InPPDirective && Line->Level == 1))) {
        ++Line->Level;
      }
      SwitchLabelEncountered = true;
      parseStructuralElement();
      break;
    case tok::l_square:
      if (Style.isCSharp()) {
        nextToken();
        parseCSharpAttribute();
        break;
      }
      if (handleCppAttributes())
        break;
      [[fallthrough]];
    default:
      ParseDefault();
      break;
    }
  } while (!eof());

  return false;
}

void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
  // We'll parse forward through the tokens until we hit
  // a closing brace or eof - note that getNextToken() will
  // parse macros, so this will magically work inside macro
  // definitions, too.
  unsigned StoredPosition = Tokens->getPosition();
  FormatToken *Tok = FormatTok;
  const FormatToken *PrevTok = Tok->Previous;
  // Keep a stack of positions of lbrace tokens. We will
  // update information about whether an lbrace starts a
  // braced init list or a different block during the loop.
  struct StackEntry {
    FormatToken *Tok;
    const FormatToken *PrevTok;
  };
  SmallVector<StackEntry, 8> LBraceStack;
  assert(Tok->is(tok::l_brace));

  do {
    auto *NextTok = Tokens->getNextNonComment();

    if (!Line->InMacroBody && !Style.isTableGen()) {
      // Skip PPDirective lines (except macro definitions) and comments.
      while (NextTok->is(tok::hash)) {
        NextTok = Tokens->getNextToken();
        if (NextTok->isOneOf(tok::pp_not_keyword, tok::pp_define))
          break;
        do {
          NextTok = Tokens->getNextToken();
        } while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof));

        while (NextTok->is(tok::comment))
          NextTok = Tokens->getNextToken();
      }
    }

    switch (Tok->Tok.getKind()) {
    case tok::l_brace:
      if (Style.isJavaScript() && PrevTok) {
        if (PrevTok->isOneOf(tok::colon, tok::less)) {
          // A ':' indicates this code is in a type, or a braced list
          // following a label in an object literal ({a: {b: 1}}).
          // A '<' could be an object used in a comparison, but that is nonsense
          // code (can never return true), so more likely it is a generic type
          // argument (`X<{a: string; b: number}>`).
          // The code below could be confused by semicolons between the
          // individual members in a type member list, which would normally
          // trigger BK_Block. In both cases, this must be parsed as an inline
          // braced init.
          Tok->setBlockKind(BK_BracedInit);
        } else if (PrevTok->is(tok::r_paren)) {
          // `) { }` can only occur in function or method declarations in JS.
          Tok->setBlockKind(BK_Block);
        }
      } else if (Style.isJava() && PrevTok && PrevTok->is(tok::arrow)) {
        Tok->setBlockKind(BK_Block);
      } else {
        Tok->setBlockKind(BK_Unknown);
      }
      LBraceStack.push_back({Tok, PrevTok});
      break;
    case tok::r_brace:
      if (LBraceStack.empty())
        break;
      if (auto *LBrace = LBraceStack.back().Tok; LBrace->is(BK_Unknown)) {
        bool ProbablyBracedList = false;
        if (Style.Language == FormatStyle::LK_Proto) {
          ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
        } else if (LBrace->isNot(TT_EnumLBrace)) {
          // Using OriginalColumn to distinguish between ObjC methods and
          // binary operators is a bit hacky.
          bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
                                  NextTok->OriginalColumn == 0;

          // Try to detect a braced list. Note that regardless how we mark inner
          // braces here, we will overwrite the BlockKind later if we parse a
          // braced list (where all blocks inside are by default braced lists),
          // or when we explicitly detect blocks (for example while parsing
          // lambdas).

          // If we already marked the opening brace as braced list, the closing
          // must also be part of it.
          ProbablyBracedList = LBrace->is(TT_BracedListLBrace);

          ProbablyBracedList = ProbablyBracedList ||
                               (Style.isJavaScript() &&
                                NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
                                                 Keywords.kw_as));
          ProbablyBracedList =
              ProbablyBracedList ||
              (IsCpp && (PrevTok->Tok.isLiteral() ||
                         NextTok->isOneOf(tok::l_paren, tok::arrow)));

          // If there is a comma, or right paren after the closing brace, we
          // assume this is a braced initializer list.
          // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a
          // braced list in JS.
          ProbablyBracedList =
              ProbablyBracedList ||
              NextTok->isOneOf(tok::comma, tok::period, tok::colon,
                               tok::r_paren, tok::r_square, tok::ellipsis);

          // Distinguish between braced list in a constructor initializer list
          // followed by constructor body, or just adjacent blocks.
          ProbablyBracedList =
              ProbablyBracedList ||
              (NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok &&
               LBraceStack.back().PrevTok->isOneOf(tok::identifier,
                                                   tok::greater));

          ProbablyBracedList =
              ProbablyBracedList ||
              (NextTok->is(tok::identifier) &&
               PrevTok->isNoneOf(tok::semi, tok::r_brace, tok::l_brace));

          ProbablyBracedList = ProbablyBracedList ||
                               (NextTok->is(tok::semi) &&
                                (!ExpectClassBody || LBraceStack.size() != 1));

          ProbablyBracedList =
              ProbablyBracedList ||
              (NextTok->isBinaryOperator() && !NextIsObjCMethod);

          if (!Style.isCSharp() && NextTok->is(tok::l_square)) {
            // We can have an array subscript after a braced init
            // list, but C++11 attributes are expected after blocks.
            NextTok = Tokens->getNextToken();
            ProbablyBracedList = NextTok->isNot(tok::l_square);
          }

          // Cpp macro definition body that is a nonempty braced list or block:
          if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&
              !FormatTok->Previous && NextTok->is(tok::eof) &&
              // A statement can end with only `;` (simple statement), a block
              // closing brace (compound statement), or `:` (label statement).
              // If PrevTok is a block opening brace, Tok ends an empty block.
              PrevTok->isNoneOf(tok::semi, BK_Block, tok::colon)) {
            ProbablyBracedList = true;
          }
        }
        const auto BlockKind = ProbablyBracedList ? BK_BracedInit : BK_Block;
        Tok->setBlockKind(BlockKind);
        LBrace->setBlockKind(BlockKind);
      }
      LBraceStack.pop_back();
      break;
    case tok::identifier:
      if (Tok->isNot(TT_StatementMacro))
        break;
      [[fallthrough]];
    case tok::at:
    case tok::semi:
    case tok::kw_if:
    case tok::kw_while:
    case tok::kw_for:
    case tok::kw_switch:
    case tok::kw_try:
    case tok::kw___try:
      if (!LBraceStack.empty() && LBraceStack.back().Tok->is(BK_Unknown))
        LBraceStack.back().Tok->setBlockKind(BK_Block);
      break;
    default:
      break;
    }

    PrevTok = Tok;
    Tok = NextTok;
  } while (Tok->isNot(tok::eof) && !LBraceStack.empty());

  // Assume other blocks for all unclosed opening braces.
  for (const auto &Entry : LBraceStack)
    if (Entry.Tok->is(BK_Unknown))
      Entry.Tok->setBlockKind(BK_Block);

  FormatTok = Tokens->setPosition(StoredPosition);
}

// Sets the token type of the directly previous right brace.
void UnwrappedLineParser::setPreviousRBraceType(TokenType Type) {
  if (auto Prev = FormatTok->getPreviousNonComment();
      Prev && Prev->is(tok::r_brace)) {
    Prev->setFinalizedType(Type);
  }
}

template <class T>
static inline void hash_combine(std::size_t &seed, const T &v) {
  std::hash<T> hasher;
  seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}

size_t UnwrappedLineParser::computePPHash() const {
  size_t h = 0;
  for (const auto &i : PPStack) {
    hash_combine(h, size_t(i.Kind));
    hash_combine(h, i.Line);
  }
  return h;
}

// Checks whether \p ParsedLine might fit on a single line. If \p OpeningBrace
// is not null, subtracts its length (plus the preceding space) when computing
// the length of \p ParsedLine. We must clone the tokens of \p ParsedLine before
// running the token annotator on it so that we can restore them afterward.
bool UnwrappedLineParser::mightFitOnOneLine(
    UnwrappedLine &ParsedLine, const FormatToken *OpeningBrace) const {
  const auto ColumnLimit = Style.ColumnLimit;
  if (ColumnLimit == 0)
    return true;

  auto &Tokens = ParsedLine.Tokens;
  assert(!Tokens.empty());

  const auto *LastToken = Tokens.back().Tok;
  assert(LastToken);

  SmallVector<UnwrappedLineNode> SavedTokens(Tokens.size());

  int Index = 0;
  for (const auto &Token : Tokens) {
    assert(Token.Tok);
    auto &SavedToken = SavedTokens[Index++];
    SavedToken.Tok = new FormatToken;
    SavedToken.Tok->copyFrom(*Token.Tok);
    SavedToken.Children = std::move(Token.Children);
  }

  AnnotatedLine Line(ParsedLine);
  assert(Line.Last == LastToken);

  TokenAnnotator Annotator(Style, Keywords);
  Annotator.annotate(Line);
  Annotator.calculateFormattingInformation(Line);

  auto Length = LastToken->TotalLength;
  if (OpeningBrace) {
    assert(OpeningBrace != Tokens.front().Tok);
    if (auto Prev = OpeningBrace->Previous;
        Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {
      Length -= ColumnLimit;
    }
    Length -= OpeningBrace->TokenText.size() + 1;
  }

  if (const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {
    assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));
    Length -= FirstToken->TokenText.size() + 1;
  }

  Index = 0;
  for (auto &Token : Tokens) {
    const auto &SavedToken = SavedTokens[Index++];
    Token.Tok->copyFrom(*SavedToken.Tok);
    Token.Children = std::move(SavedToken.Children);
    delete SavedToken.Tok;
  }

  // If these change PPLevel needs to be used for get correct indentation.
  assert(!Line.InMacroBody);
  assert(!Line.InPPDirective);
  return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
}

FormatToken *UnwrappedLineParser::parseBlock(bool MustBeDeclaration,
                                             unsigned AddLevels, bool MunchSemi,
                                             bool KeepBraces,
                                             IfStmtKind *IfKind,
                                             bool UnindentWhitesmithsBraces) {
  auto HandleVerilogBlockLabel = [this]() {
    // ":" name
    if (Style.isVerilog() && FormatTok->is(tok::colon)) {
      nextToken();
      if (Keywords.isVerilogIdentifier(*FormatTok))
        nextToken();
    }
  };

  // Whether this is a Verilog-specific block that has a special header like a
  // module.
  const bool VerilogHierarchy =
      Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok);
  assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||
          (Style.isVerilog() &&
           (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&
         "'{' or macro block token expected");
  FormatToken *Tok = FormatTok;
  const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);
  auto Index = CurrentLines->size();
  const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
  FormatTok->setBlockKind(BK_Block);

  const bool IsWhitesmiths =
      Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;

  // For Whitesmiths mode, jump to the next level prior to skipping over the
  // braces.
  if (!VerilogHierarchy && AddLevels > 0 && IsWhitesmiths)
    ++Line->Level;

  size_t PPStartHash = computePPHash();

  const unsigned InitialLevel = Line->Level;
  if (VerilogHierarchy) {
    AddLevels += parseVerilogHierarchyHeader();
  } else {
    nextToken(/*LevelDifference=*/AddLevels);
    HandleVerilogBlockLabel();
  }

  // Bail out if there are too many levels. Otherwise, the stack might overflow.
  if (Line->Level > 300)
    return nullptr;

  if (MacroBlock && FormatTok->is(tok::l_paren))
    parseParens();

  size_t NbPreprocessorDirectives =
      !parsingPPDirective() ? PreprocessorDirectives.size() : 0;
  addUnwrappedLine();
  size_t OpeningLineIndex =
      CurrentLines->empty()
          ? (UnwrappedLine::kInvalidIndex)
          : (CurrentLines->size() - 1 - NbPreprocessorDirectives);

  // Whitesmiths is weird here. The brace needs to be indented for the namespace
  // block, but the block itself may not be indented depending on the style
  // settings. This allows the format to back up one level in those cases.
  if (UnindentWhitesmithsBraces)
    --Line->Level;

  ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
                                          MustBeDeclaration);

  // Whitesmiths logic has already added a level by this point, so avoid
  // adding it twice.
  if (AddLevels > 0u)
    Line->Level += AddLevels - (IsWhitesmiths ? 1 : 0);

  FormatToken *IfLBrace = nullptr;
  const bool SimpleBlock = parseLevel(Tok, IfKind, &IfLBrace);

  if (eof())
    return IfLBrace;

  if (MacroBlock ? FormatTok->isNot(TT_MacroBlockEnd)
                 : FormatTok->isNot(tok::r_brace)) {
    Line->Level = InitialLevel;
    FormatTok->setBlockKind(BK_Block);
    return IfLBrace;
  }

  if (FormatTok->is(tok::r_brace)) {
    FormatTok->setBlockKind(BK_Block);
    if (Tok->is(TT_NamespaceLBrace))
      FormatTok->setFinalizedType(TT_NamespaceRBrace);
  }

  const bool IsFunctionRBrace =
      FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);

  auto RemoveBraces = [=]() mutable {
    if (!SimpleBlock)
      return false;
    assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));
    assert(FormatTok->is(tok::r_brace));
    const bool WrappedOpeningBrace = !Tok->Previous;
    if (WrappedOpeningBrace && FollowedByComment)
      return false;
    const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;
    if (KeepBraces && !HasRequiredIfBraces)
      return false;
    if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {
      const FormatToken *Previous = Tokens->getPreviousToken();
      assert(Previous);
      if (Previous->is(tok::r_brace) && !Previous->Optional)
        return false;
    }
    assert(!CurrentLines->empty());
    auto &LastLine = CurrentLines->back();
    if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))
      return false;
    if (Tok->is(TT_ElseLBrace))
      return true;
    if (WrappedOpeningBrace) {
      assert(Index > 0);
      --Index; // The line above the wrapped l_brace.
      Tok = nullptr;
    }
    return mightFitOnOneLine((*CurrentLines)[Index], Tok);
  };
  if (RemoveBraces()) {
    Tok->MatchingParen = FormatTok;
    FormatTok->MatchingParen = Tok;
  }

  size_t PPEndHash = computePPHash();

  // Munch the closing brace.
  nextToken(/*LevelDifference=*/-AddLevels);

  // When this is a function block and there is an unnecessary semicolon
  // afterwards then mark it as optional (so the RemoveSemi pass can get rid of
  // it later).
  if (Style.RemoveSemicolon && IsFunctionRBrace) {
    while (FormatTok->is(tok::semi)) {
      FormatTok->Optional = true;
      nextToken();
    }
  }

  HandleVerilogBlockLabel();

  if (MacroBlock && FormatTok->is(tok::l_paren))
    parseParens();

  Line->Level = InitialLevel;

  if (FormatTok->is(tok::kw_noexcept)) {
    // A noexcept in a requires expression.
    nextToken();
  }

  if (FormatTok->is(tok::arrow)) {
    // Following the } or noexcept we can find a trailing return type arrow
    // as part of an implicit conversion constraint.
    nextToken();
    parseStructuralElement();
  }

  if (MunchSemi && FormatTok->is(tok::semi))
    nextToken();

  if (PPStartHash == PPEndHash) {
    Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
    if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
      // Update the opening line to add the forward reference as well
      (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
          CurrentLines->size() - 1;
    }
  }

  return IfLBrace;
}

static bool isGoogScope(const UnwrappedLine &Line) {
  // FIXME: Closure-library specific stuff should not be hard-coded but be
  // configurable.
  if (Line.Tokens.size() < 4)
    return false;
  auto I = Line.Tokens.begin();
  if (I->Tok->TokenText != "goog")
    return false;
  ++I;
  if (I->Tok->isNot(tok::period))
    return false;
  ++I;
  if (I->Tok->TokenText != "scope")
    return false;
  ++I;
  return I->Tok->is(tok::l_paren);
}

static bool isIIFE(const UnwrappedLine &Line,
                   const AdditionalKeywords &Keywords) {
  // Look for the start of an immediately invoked anonymous function.
  // https://en.wikipedia.org/wiki/Immediately-invoked_function_expression
  // This is commonly done in JavaScript to create a new, anonymous scope.
  // Example: (function() { ... })()
  if (Line.Tokens.size() < 3)
    return false;
  auto I = Line.Tokens.begin();
  if (I->Tok->isNot(tok::l_paren))
    return false;
  ++I;
  if (I->Tok->isNot(Keywords.kw_function))
    return false;
  ++I;
  return I->Tok->is(tok::l_paren);
}

static bool ShouldBreakBeforeBrace(const FormatStyle &Style,
                                   const FormatToken &InitialToken,
                                   bool IsEmptyBlock,
                                   bool IsJavaRecord = false) {
  if (IsJavaRecord)
    return Style.BraceWrapping.AfterClass;

  tok::TokenKind Kind = InitialToken.Tok.getKind();
  if (InitialToken.is(TT_NamespaceMacro))
    Kind = tok::kw_namespace;

  const bool WrapRecordAllowed =
      !IsEmptyBlock ||
      Style.AllowShortRecordOnASingleLine < FormatStyle::SRS_Empty ||
      Style.BraceWrapping.SplitEmptyRecord;

  switch (Kind) {
  case tok::kw_namespace:
    return Style.BraceWrapping.AfterNamespace;
  case tok::kw_class:
    return Style.BraceWrapping.AfterClass && WrapRecordAllowed;
  case tok::kw_union:
    return Style.BraceWrapping.AfterUnion && WrapRecordAllowed;
  case tok::kw_struct:
    return Style.BraceWrapping.AfterStruct && WrapRecordAllowed;
  case tok::kw_enum:
    return Style.BraceWrapping.AfterEnum;
  default:
    return false;
  }
}

void UnwrappedLineParser::parseChildBlock() {
  assert(FormatTok->is(tok::l_brace));
  FormatTok->setBlockKind(BK_Block);
  const FormatToken *OpeningBrace = FormatTok;
  nextToken();
  {
    bool SkipIndent = (Style.isJavaScript() &&
                       (isGoogScope(*Line) || isIIFE(*Line, Keywords)));
    ScopedLineState LineState(*this);
    ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
                                            /*MustBeDeclaration=*/false);
    Line->Level += SkipIndent ? 0 : 1;
    parseLevel(OpeningBrace);
    flushComments(isOnNewLine(*FormatTok));
    Line->Level -= SkipIndent ? 0 : 1;
  }
  nextToken();
}

void UnwrappedLineParser::parsePPDirective() {
  assert(FormatTok->is(tok::hash) && "'#' expected");
  ScopedMacroState MacroState(*Line, Tokens, FormatTok);

  nextToken();

  if (!FormatTok->Tok.getIdentifierInfo()) {
    parsePPUnknown();
    return;
  }

  switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
  case tok::pp_define:
    parsePPDefine();
    return;
  case tok::pp_if:
    parsePPIf(/*IfDef=*/false);
    break;
  case tok::pp_ifdef:
  case tok::pp_ifndef:
    parsePPIf(/*IfDef=*/true);
    break;
  case tok::pp_else:
  case tok::pp_elifdef:
  case tok::pp_elifndef:
  case tok::pp_elif:
    parsePPElse();
    break;
  case tok::pp_endif:
    parsePPEndIf();
    break;
  case tok::pp_pragma:
    parsePPPragma();
    break;
  case tok::pp_error:
  case tok::pp_warning:
    nextToken();
    if (!eof() && Style.isCpp())
      FormatTok->setFinalizedType(TT_AfterPPDirective);
    [[fallthrough]];
  default:
    parsePPUnknown();
    break;
  }
}

void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) {
  size_t Line = CurrentLines->size();
  if (CurrentLines == &PreprocessorDirectives)
    Line += Lines.size();

  if (Unreachable ||
      (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable)) {
    PPStack.push_back({PP_Unreachable, Line});
  } else {
    PPStack.push_back({PP_Conditional, Line});
  }
}

void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {
  ++PPBranchLevel;
  assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size());
  if (PPBranchLevel == (int)PPLevelBranchIndex.size()) {
    PPLevelBranchIndex.push_back(0);
    PPLevelBranchCount.push_back(0);
  }
  PPChainBranchIndex.push(Unreachable ? -1 : 0);
  bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;
  conditionalCompilationCondition(Unreachable || Skip);
}

void UnwrappedLineParser::conditionalCompilationAlternative() {
  if (!PPStack.empty())
    PPStack.pop_back();
  assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
  if (!PPChainBranchIndex.empty())
    ++PPChainBranchIndex.top();
  conditionalCompilationCondition(
      PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&
      PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top());
}

void UnwrappedLineParser::conditionalCompilationEnd() {
  assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
  if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {
    if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel])
      PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1;
  }
  // Guard against #endif's without #if.
  if (PPBranchLevel > -1)
    --PPBranchLevel;
  if (!PPChainBranchIndex.empty())
    PPChainBranchIndex.pop();
  if (!PPStack.empty())
    PPStack.pop_back();
}

void UnwrappedLineParser::parsePPIf(bool IfDef) {
  bool IfNDef = FormatTok->is(tok::pp_ifndef);
  nextToken();
  bool Unreachable = false;
  if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText == "0"))
    Unreachable = true;
  if (IfDef && !IfNDef && FormatTok->TokenText == "SWIG")
    Unreachable = true;
  conditionalCompilationStart(Unreachable);
  FormatToken *IfCondition = FormatTok;
  // If there's a #ifndef on the first line, and the only lines before it are
  // comments, it could be an include guard.
  bool MaybeIncludeGuard = IfNDef;
  if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
    for (auto &Line : Lines) {
      if (Line.Tokens.front().Tok->isNot(tok::comment)) {
        MaybeIncludeGuard = false;
        IncludeGuard = IG_Rejected;
        break;
      }
    }
  }
  --PPBranchLevel;
  parsePPUnknown();
  ++PPBranchLevel;
  if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
    IncludeGuard = IG_IfNdefed;
    IncludeGuardToken = IfCondition;
  }
}

void UnwrappedLineParser::parsePPElse() {
  // If a potential include guard has an #else, it's not an include guard.
  if (IncludeGuard == IG_Defined && PPBranchLevel == 0)
    IncludeGuard = IG_Rejected;
  // Don't crash when there is an #else without an #if.
  assert(PPBranchLevel >= -1);
  if (PPBranchLevel == -1)
    conditionalCompilationStart(/*Unreachable=*/true);
  conditionalCompilationAlternative();
  --PPBranchLevel;
  parsePPUnknown();
  ++PPBranchLevel;
}

void UnwrappedLineParser::parsePPEndIf() {
  conditionalCompilationEnd();
  parsePPUnknown();
}

void UnwrappedLineParser::parsePPDefine() {
  nextToken();

  if (!FormatTok->Tok.getIdentifierInfo()) {
    IncludeGuard = IG_Rejected;
    IncludeGuardToken = nullptr;
    parsePPUnknown();
    return;
  }

  bool MaybeIncludeGuard = false;
  if (IncludeGuard == IG_IfNdefed &&
      IncludeGuardToken->TokenText == FormatTok->TokenText) {
    IncludeGuard = IG_Defined;
    IncludeGuardToken = nullptr;
    for (auto &Line : Lines) {
      if (Line.Tokens.front().Tok->isNoneOf(tok::comment, tok::hash)) {
        IncludeGuard = IG_Rejected;
        break;
      }
    }
    MaybeIncludeGuard = IncludeGuard == IG_Defined;
  }

  // In the context of a define, even keywords should be treated as normal
  // identifiers. Setting the kind to identifier is not enough, because we need
  // to treat additional keywords like __except as well, which are already
  // identifiers. Setting the identifier info to null interferes with include
  // guard processing above, and changes preprocessing nesting.
  FormatTok->Tok.setKind(tok::identifier);
  FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define);
  nextToken();

  // IncludeGuard can't have a non-empty macro definition.
  if (MaybeIncludeGuard && !eof())
    IncludeGuard = IG_Rejected;

  if (FormatTok->is(tok::l_paren) && !FormatTok->hasWhitespaceBefore())
    parseParens();
  if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
    Line->Level += PPBranchLevel + 1;
  addUnwrappedLine();
  ++Line->Level;

  Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);
  assert((int)Line->PPLevel >= 0);

  if (eof())
    return;

  Line->InMacroBody = true;

  if (!Style.SkipMacroDefinitionBody) {
    // Errors during a preprocessor directive can only affect the layout of the
    // preprocessor directive, and thus we ignore them. An alternative approach
    // would be to use the same approach we use on the file level (no
    // re-indentation if there was a structural error) within the macro
    // definition.
    parseFile();
    return;
  }

  for (auto *Comment : CommentsBeforeNextToken)
    Comment->Finalized = true;

  do {
    FormatTok->Finalized = true;
    FormatTok = Tokens->getNextToken();
  } while (!eof());

  addUnwrappedLine();
}

void UnwrappedLineParser::parsePPPragma() {
  Line->InPragmaDirective = true;
  parsePPUnknown();
}

void UnwrappedLineParser::parsePPUnknown() {
  while (!eof())
    nextToken();
  if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
    Line->Level += PPBranchLevel + 1;
  addUnwrappedLine();
}

// Here we exclude certain tokens that are not usually the first token in an
// unwrapped line. This is used in attempt to distinguish macro calls without
// trailing semicolons from other constructs split to several lines.
static bool tokenCanStartNewLine(const FormatToken &Tok) {
  // Semicolon can be a null-statement, l_square can be a start of a macro or
  // a C++11 attribute, but this doesn't seem to be common.
  return Tok.isNoneOf(tok::semi, tok::l_brace,
                      // Tokens that can only be used as binary operators and a
                      // part of overloaded operator names.
                      tok::period, tok::periodstar, tok::arrow, tok::arrowstar,
                      tok::less, tok::greater, tok::slash, tok::percent,
                      tok::lessless, tok::greatergreater, tok::equal,
                      tok::plusequal, tok::minusequal, tok::starequal,
                      tok::slashequal, tok::percentequal, tok::ampequal,
                      tok::pipeequal, tok::caretequal, tok::greatergreaterequal,
                      tok::lesslessequal,
                      // Colon is used in labels, base class lists, initializer
                      // lists, range-based for loops, ternary operator, but
                      // should never be the first token in an unwrapped line.
                      tok::colon,
                      // 'noexcept' is a trailing annotation.
                      tok::kw_noexcept);
}

static bool mustBeJSIdent(const AdditionalKeywords &Keywords,
                          const FormatToken *FormatTok) {
  // FIXME: This returns true for C/C++ keywords like 'struct'.
  return FormatTok->is(tok::identifier) &&
         (!FormatTok->Tok.getIdentifierInfo() ||
          FormatTok->isNoneOf(
              Keywords.kw_in, Keywords.kw_of, Keywords.kw_as, Keywords.kw_async,
              Keywords.kw_await, Keywords.kw_yield, Keywords.kw_finally,
              Keywords.kw_function, Keywords.kw_import, Keywords.kw_is,
              Keywords.kw_let, Keywords.kw_var, tok::kw_const,
              Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements,
              Keywords.kw_instanceof, Keywords.kw_interface,
              Keywords.kw_override, Keywords.kw_throws, Keywords.kw_from));
}

static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
                                 const FormatToken *FormatTok) {
  return FormatTok->Tok.isLiteral() ||
         FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||
         mustBeJSIdent(Keywords, FormatTok);
}

// isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement
// when encountered after a value (see mustBeJSIdentOrValue).
static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords,
                           const FormatToken *FormatTok) {
  return FormatTok->isOneOf(
      tok::kw_return, Keywords.kw_yield,
      // conditionals
      tok::kw_if, tok::kw_else,
      // loops
      tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
      // switch/case
      tok::kw_switch, tok::kw_case,
      // exceptions
      tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.kw_finally,
      // declaration
      tok::kw_const, tok::kw_class, Keywords.kw_var, Keywords.kw_let,
      Keywords.kw_async, Keywords.kw_function,
      // import/export
      Keywords.kw_import, tok::kw_export);
}

// Checks whether a token is a type in K&R C (aka C78).
static bool isC78Type(const FormatToken &Tok) {
  return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,
                     tok::kw_unsigned, tok::kw_float, tok::kw_double,
                     tok::identifier);
}

// This function checks whether a token starts the first parameter declaration
// in a K&R C (aka C78) function definition, e.g.:
//   int f(a, b)
//   short a, b;
//   {
//      return a + b;
//   }
static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next,
                               const FormatToken *FuncName) {
  assert(Tok);
  assert(Next);
  assert(FuncName);

  if (FuncName->isNot(tok::identifier))
    return false;

  const FormatToken *Prev = FuncName->Previous;
  if (!Prev || (Prev->isNot(tok::star) && !isC78Type(*Prev)))
    return false;

  if (!isC78Type(*Tok) &&
      Tok->isNoneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {
    return false;
  }

  if (Next->isNot(tok::star) && !Next->Tok.getIdentifierInfo())
    return false;

  Tok = Tok->Previous;
  if (!Tok || Tok->isNot(tok::r_paren))
    return false;

  Tok = Tok->Previous;
  if (!Tok || Tok->isNot(tok::identifier))
    return false;

  return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma);
}

bool UnwrappedLineParser::parseModuleDecl() {
  assert(IsCpp);
  assert(FormatTok->is(Keywords.kw_module));

  if (Style.Language == FormatStyle::LK_C ||
      Style.Standard < FormatStyle::LS_Cpp20) {
    return false;
  }

  nextToken();
  if (FormatTok->isNot(tok::identifier))
    return false;

  for (nextToken(); FormatTok->isNoneOf(tok::semi, tok::eof); nextToken())
    if (FormatTok->is(tok::colon))
      FormatTok->setFinalizedType(TT_ModulePartitionColon);

  nextToken();
  Line->IsModuleOrImportDecl = true;
  addUnwrappedLine();
  return true;
}

bool UnwrappedLineParser::parseImportDecl() {
  assert(IsCpp);
  assert(FormatTok->is(Keywords.kw_import) && "'import' expected");

  if (Style.Language == FormatStyle::LK_C ||
      Style.Standard < FormatStyle::LS_Cpp20) {
    return false;
  }

  nextToken();
  if (FormatTok->is(tok::colon)) {
    FormatTok->setFinalizedType(TT_ModulePartitionColon);
    nextToken();
  }
  if (FormatTok->isNoneOf(tok::identifier, tok::less, tok::string_literal))
    return false;

  for (; FormatTok->isNoneOf(tok::semi, tok::eof); nextToken()) {
    // Handle import <foo/bar.h> as we would an include statement.
    if (FormatTok->is(tok::less)) {
      for (nextToken(); FormatTok->isNoneOf(tok::greater, tok::semi, tok::eof);
           nextToken()) {
        // Mark tokens as implicit string literals, so that import <A/Foo> will
        // neither be broken nor have a space added.
        FormatTok->setFinalizedType(TT_ImplicitStringLiteral);
      }
    }
  }

  nextToken();
  Line->IsModuleOrImportDecl = true;
  addUnwrappedLine();
  return true;
}

// readTokenWithJavaScriptASI reads the next token and terminates the current
// line if JavaScript Automatic Semicolon Insertion must
// happen between the current token and the next token.
//
// This method is conservative - it cannot cover all edge cases of JavaScript,
// but only aims to correctly handle certain well known cases. It *must not*
// return true in speculative cases.
void UnwrappedLineParser::readTokenWithJavaScriptASI() {
  FormatToken *Previous = FormatTok;
  readToken();
  FormatToken *Next = FormatTok;

  bool IsOnSameLine =
      CommentsBeforeNextToken.empty()
          ? Next->NewlinesBefore == 0
          : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
  if (IsOnSameLine)
    return;

  bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);
  bool PreviousStartsTemplateExpr =
      Previous->is(TT_TemplateString) && Previous->TokenText.ends_with("${");
  if (PreviousMustBeValue || Previous->is(tok::r_paren)) {
    // If the line contains an '@' sign, the previous token might be an
    // annotation, which can precede another identifier/value.
    bool HasAt = llvm::any_of(Line->Tokens, [](UnwrappedLineNode &LineNode) {
      return LineNode.Tok->is(tok::at);
    });
    if (HasAt)
      return;
  }
  if (Next->is(tok::exclaim) && PreviousMustBeValue)
    return addUnwrappedLine();
  bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);
  bool NextEndsTemplateExpr =
      Next->is(TT_TemplateString) && Next->TokenText.starts_with("}");
  if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
      (PreviousMustBeValue ||
       Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
                         tok::minusminus))) {
    return addUnwrappedLine();
  }
  if ((PreviousMustBeValue || Previous->is(tok::r_paren)) &&
      isJSDeclOrStmt(Keywords, Next)) {
    return addUnwrappedLine();
  }
}

void UnwrappedLineParser::parseStructuralElement(
    const FormatToken *OpeningBrace, IfStmtKind *IfKind,
    FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) {
  if (Style.isTableGen() && FormatTok->is(tok::pp_include)) {
    nextToken();
    if (FormatTok->is(tok::string_literal))
      nextToken();
    addUnwrappedLine();
    return;
  }

  if (IsCpp) {
    while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
    }
  } else if (Style.isVerilog()) {
    // Skip attributes.
    while (FormatTok->is(tok::l_paren) &&
           Tokens->peekNextToken()->is(tok::star)) {
      parseParens();
    }
    skipVerilogQualifiers();
    // Skip things that can exist before keywords like 'if' and 'case'.
    if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,
                           Keywords.kw_unique0)) {
      nextToken();
    }

    if (Keywords.isVerilogStructuredProcedure(*FormatTok)) {
      parseForOrWhileLoop(/*HasParens=*/false);
      return;
    }
    if (FormatTok->isOneOf(Keywords.kw_foreach, Keywords.kw_repeat)) {
      parseForOrWhileLoop();
      return;
    }
    if (FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
                           Keywords.kw_assume, Keywords.kw_cover)) {
      parseIfThenElse(IfKind, /*KeepBraces=*/false, /*IsVerilogAssert=*/true);
      return;
    }
  }

  // Tokens that only make sense at the beginning of a line.
  if (FormatTok->isAccessSpecifierKeyword()) {
    if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
      nextToken();
    else
      parseAccessSpecifier();
    return;
  }
  switch (FormatTok->Tok.getKind()) {
  case tok::kw_asm: {
    // Track whether to skip formatting inline asm by finalizing the tokens
    // in the block. Formatting is skipped inside of braces by default.
    // A style option could be added to also skip formatting inside parens.
    bool DoNotFormat = false;
    tok::TokenKind OpenType;
    tok::TokenKind CloseType;
    nextToken();
    while (FormatTok &&
           FormatTok->isOneOf(tok::kw_volatile, tok::kw_inline, tok::kw_goto)) {
      nextToken();
    }
    if (!FormatTok)
      break;
    if (FormatTok->is(tok::l_brace)) {
      FormatTok->setFinalizedType(TT_InlineASMBrace);
      OpenType = tok::l_brace;
      CloseType = tok::r_brace;
      DoNotFormat = true;
    } else if (FormatTok->is(tok::l_paren)) {
      OpenType = tok::l_paren;
      CloseType = tok::r_paren;
      FormatTok->setFinalizedType(TT_InlineASMParen);
    } else {
      break;
    }
    if (DoNotFormat) {
      FormatToken *OpenTok = FormatTok;
      int NestLevel = 0;
      nextToken();
      while (FormatTok && !eof()) {
        if (FormatTok->is(OpenType)) {
          ++NestLevel;
        } else if (FormatTok->is(CloseType)) {
          --NestLevel;
          if (NestLevel < 1) {
            FormatTok->setFinalizedType(OpenTok->getType());
            nextToken();
            addUnwrappedLine();
            break;
          }
        }
        FormatTok->Finalized = true;
        nextToken();
      }
    }
    break;
  }
  case tok::kw_namespace:
    parseNamespace();
    return;
  case tok::kw_if: {
    if (Style.isJavaScript() && Line->MustBeDeclaration) {
      // field/method declaration.
      break;
    }
    FormatToken *Tok = parseIfThenElse(IfKind);
    if (IfLeftBrace)
      *IfLeftBrace = Tok;
    return;
  }
  case tok::kw_for:
  case tok::kw_while:
    if (Style.isJavaScript() && Line->MustBeDeclaration) {
      // field/method declaration.
      break;
    }
    parseForOrWhileLoop();
    return;
  case tok::kw_do:
    if (Style.isJavaScript() && Line->MustBeDeclaration) {
      // field/method declaration.
      break;
    }
    parseDoWhile();
    if (HasDoWhile)
      *HasDoWhile = true;
    return;
  case tok::kw_switch:
    if (Style.isJavaScript() && Line->MustBeDeclaration) {
      // 'switch: string' field declaration.
      break;
    }
    parseSwitch(/*IsExpr=*/false);
    return;
  case tok::kw_default: {
    // In Verilog default along with other labels are handled in the next loop.
    if (Style.isVerilog())
      break;
    if (Style.isJavaScript() && Line->MustBeDeclaration) {
      // 'default: string' field declaration.
      break;
    }
    auto *Default = FormatTok;
    nextToken();
    if (FormatTok->is(tok::colon)) {
      FormatTok->setFinalizedType(TT_CaseLabelColon);
      parseLabel();
      return;
    }
    if (FormatTok->is(tok::arrow)) {
      FormatTok->setFinalizedType(TT_CaseLabelArrow);
      Default->setFinalizedType(TT_SwitchExpressionLabel);
      parseLabel();
      return;
    }
    // e.g. "default void f() {}" in a Java interface.
    break;
  }
  case tok::kw_case:
    // Proto: there are no switch/case statements.
    if (Style.Language == FormatStyle::LK_Proto) {
      nextToken();
      return;
    }
    if (Style.isVerilog()) {
      parseBlock();
      addUnwrappedLine();
      return;
    }
    if (Style.isJavaScript() && Line->MustBeDeclaration) {
      // 'case: string' field declaration.
      nextToken();
      break;
    }
    parseCaseLabel();
    return;
  case tok::kw_goto:
    nextToken();
    if (FormatTok->is(tok::kw_case))
      nextToken();
    break;
  case tok::kw_try:
  case tok::kw___try:
    if (Style.isJavaScript() && Line->MustBeDeclaration) {
      // field/method declaration.
      break;
    }
    parseTryCatch();
    return;
  case tok::kw_extern:
    if (Style.isVerilog()) {
      // In Verilog an extern module declaration looks like a start of module.
      // But there is no body and endmodule. So we handle it separately.
      parseVerilogExtern();
      return;
    }
    nextToken();
    if (FormatTok->is(tok::string_literal)) {
      nextToken();
      if (FormatTok->is(tok::l_brace)) {
        if (Style.BraceWrapping.AfterExternBlock)
          addUnwrappedLine();
        // Either we indent or for backwards compatibility we follow the
        // AfterExternBlock style.
        unsigned AddLevels =
            (Style.IndentExternBlock == FormatStyle::IEBS_Indent) ||
                    (Style.BraceWrapping.AfterExternBlock &&
                     Style.IndentExternBlock ==
                         FormatStyle::IEBS_AfterExternBlock)
                ? 1u
                : 0u;
        parseBlock(/*MustBeDeclaration=*/true, AddLevels);
        addUnwrappedLine();
        return;
      }
    }
    break;
  case tok::kw_export:
    if (IsCpp) {
      nextToken();
      if (FormatTok->is(tok::kw_namespace)) {
        parseNamespace();
        return;
      }
      if (FormatTok->is(tok::l_brace)) {
        parseCppExportBlock();
        return;
      }
      if (FormatTok->is(Keywords.kw_module) && parseModuleDecl())
        return;
      if (FormatTok->is(Keywords.kw_import) && parseImportDecl())
        return;
      break;
    }
    if (Style.isJavaScript()) {
      parseJavaScriptEs6ImportExport();
      return;
    }
    if (Style.isVerilog()) {
      parseVerilogExtern();
      return;
    }
    break;
  case tok::kw_inline:
    nextToken();
    if (FormatTok->is(tok::kw_namespace)) {
      parseNamespace();
      return;
    }
    break;
  case tok::identifier:
    if (FormatTok->is(TT_ForEachMacro)) {
      parseForOrWhileLoop();
      return;
    }
    if (FormatTok->is(TT_MacroBlockBegin)) {
      parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
                 /*MunchSemi=*/false);
      return;
    }
    if (FormatTok->is(Keywords.kw_import)) {
      if (IsCpp && parseImportDecl())
        return;
      if (Style.isJavaScript()) {
        parseJavaScriptEs6ImportExport();
        return;
      }
      if (Style.Language == FormatStyle::LK_Proto) {
        nextToken();
        if (FormatTok->is(tok::kw_public))
          nextToken();
        if (FormatTok->isNot(tok::string_literal))
          return;
        nextToken();
        if (FormatTok->is(tok::semi))
          nextToken();
        addUnwrappedLine();
        return;
      }
      if (Style.isVerilog()) {
        parseVerilogExtern();
        return;
      }
    }
    if (IsCpp) {
      if (FormatTok->is(Keywords.kw_module) && parseModuleDecl())
        return;
      if (FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
                             Keywords.kw_slots, Keywords.kw_qslots)) {
        nextToken();
        if (FormatTok->is(tok::colon)) {
          nextToken();
          addUnwrappedLine();
          return;
        }
      }
      if (FormatTok->is(TT_StatementMacro)) {
        parseStatementMacro();
        return;
      }
      if (FormatTok->is(TT_NamespaceMacro)) {
        parseNamespace();
        return;
      }
    }
    // In Verilog labels can be any expression, so we don't do them here.
    // JS doesn't have macros, and within classes colons indicate fields, not
    // labels.
    // TableGen doesn't have labels.
    if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() &&
        Tokens->peekNextToken()->is(tok::colon) && !Line->MustBeDeclaration) {
      nextToken();
      if (!Line->InMacroBody || CurrentLines->size() > 1)
        Line->Tokens.begin()->Tok->MustBreakBefore = true;
      FormatTok->setFinalizedType(TT_GotoLabelColon);
      parseLabel(/*IsGotoLabel=*/true);
      if (HasLabel)
        *HasLabel = true;
      return;
    }
    if (Style.isJava() && FormatTok->is(Keywords.kw_record)) {
      parseRecord(/*ParseAsExpr=*/false, /*IsJavaRecord=*/true);
      addUnwrappedLine();
      return;
    }
    // In all other cases, parse the declaration.
    break;
  default:
    break;
  }

  bool SeenEqual = false;
  for (const bool InRequiresExpression =
           OpeningBrace && OpeningBrace->isOneOf(TT_RequiresExpressionLBrace,
                                                 TT_CompoundRequirementLBrace);
       !eof();) {
    const FormatToken *Previous = FormatTok->Previous;
    switch (FormatTok->Tok.getKind()) {
    case tok::at:
      nextToken();
      if (FormatTok->is(tok::l_brace)) {
        nextToken();
        parseBracedList();
        break;
      }
      if (Style.isJava() && FormatTok->is(Keywords.kw_interface)) {
        nextToken();
        break;
      }
      switch (bool IsAutoRelease = false; FormatTok->Tok.getObjCKeywordID()) {
      case tok::objc_public:
      case tok::objc_protected:
      case tok::objc_package:
      case tok::objc_private:
        return parseAccessSpecifier();
      case tok::objc_interface:
      case tok::objc_implementation:
        return parseObjCInterfaceOrImplementation();
      case tok::objc_protocol:
        if (parseObjCProtocol())
          return;
        break;
      case tok::objc_end:
        return; // Handled by the caller.
      case tok::objc_optional:
      case tok::objc_required:
        nextToken();
        addUnwrappedLine();
        return;
      case tok::objc_autoreleasepool:
        IsAutoRelease = true;
        [[fallthrough]];
      case tok::objc_synchronized:
        nextToken();
        if (!IsAutoRelease && FormatTok->is(tok::l_paren)) {
          // Skip synchronization object
          parseParens();
        }
        if (FormatTok->is(tok::l_brace)) {
          if (Style.BraceWrapping.AfterControlStatement ==
              FormatStyle::BWACS_Always) {
            addUnwrappedLine();
          }
          parseBlock();
        }
        addUnwrappedLine();
        return;
      case tok::objc_try:
        // This branch isn't strictly necessary (the kw_try case below would
        // do this too after the tok::at is parsed above).  But be explicit.
        parseTryCatch();
        return;
      default:
        break;
      }
      break;
    case tok::kw_requires: {
      if (IsCpp) {
        bool ParsedClause = parseRequires(SeenEqual);
        if (ParsedClause)
          return;
      } else {
        nextToken();
      }
      break;
    }
    case tok::kw_enum:
      // Ignore if this is part of "template <enum ..." or "... -> enum" or
      // "template <..., enum ...>".
      if (Previous && Previous->isOneOf(tok::less, tok::arrow, tok::comma)) {
        nextToken();
        break;
      }

      // parseEnum falls through and does not yet add an unwrapped line as an
      // enum definition can start a structural element.
      if (!parseEnum())
        break;
      // This only applies to C++ and Verilog.
      if (!IsCpp && !Style.isVerilog()) {
        addUnwrappedLine();
        return;
      }
      break;
    case tok::kw_typedef:
      nextToken();
      if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
                             Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,
                             Keywords.kw_CF_CLOSED_ENUM,
                             Keywords.kw_NS_CLOSED_ENUM)) {
        parseEnum();
      }
      break;
    case tok::kw_class:
      if (Style.isVerilog()) {
        parseBlock();
        addUnwrappedLine();
        return;
      }
      if (Style.isTableGen()) {
        // Do nothing special. In this case the l_brace becomes FunctionLBrace.
        // This is same as def and so on.
        nextToken();
        break;
      }
      [[fallthrough]];
    case tok::kw_struct:
    case tok::kw_union:
      if (parseStructLike())
        return;
      break;
    case tok::kw_decltype:
      nextToken();
      if (FormatTok->is(tok::l_paren)) {
        parseParens();
        if (FormatTok->Previous &&
            FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto,
                                              tok::l_paren)) {
          Line->SeenDecltypeAuto = true;
        }
      }
      break;
    case tok::period:
      nextToken();
      // In Java, classes have an implicit static member "class".
      if (Style.isJava() && FormatTok && FormatTok->is(tok::kw_class))
        nextToken();
      if (Style.isJavaScript() && FormatTok &&
          FormatTok->Tok.getIdentifierInfo()) {
        // JavaScript only has pseudo keywords, all keywords are allowed to
        // appear in "IdentifierName" positions. See http://es5.github.io/#x7.6
        nextToken();
      }
      break;
    case tok::semi:
      nextToken();
      addUnwrappedLine();
      return;
    case tok::r_brace:
      addUnwrappedLine();
      return;
    case tok::string_literal:
      if (Style.isVerilog() && FormatTok->is(TT_VerilogProtected)) {
        FormatTok->Finalized = true;
        nextToken();
        addUnwrappedLine();
        return;
      }
      nextToken();
      break;
    case tok::l_paren: {
      parseParens();
      // Break the unwrapped line if a K&R C function definition has a parameter
      // declaration.
      if (OpeningBrace || !IsCpp || !Previous || eof())
        break;
      if (isC78ParameterDecl(FormatTok,
                             Tokens->peekNextToken(/*SkipComment=*/true),
                             Previous)) {
        addUnwrappedLine();
        return;
      }
      break;
    }
    case tok::kw_operator:
      nextToken();
      if (FormatTok->isBinaryOperator())
        nextToken();
      break;
    case tok::caret: {
      const auto *Prev = FormatTok->getPreviousNonComment();
      nextToken();
      if (Prev && Prev->is(tok::identifier))
        break;
      // Block return type.
      if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) {
        nextToken();
        // Return types: pointers are ok too.
        while (FormatTok->is(tok::star))
          nextToken();
      }
      // Block argument list.
      if (FormatTok->is(tok::l_paren))
        parseParens();
      // Block body.
      if (FormatTok->is(tok::l_brace))
        parseChildBlock();
      break;
    }
    case tok::l_brace:
      if (InRequiresExpression)
        FormatTok->setFinalizedType(TT_BracedListLBrace);
      if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
        IsDecltypeAutoFunction = Line->SeenDecltypeAuto;
        // A block outside of parentheses must be the last part of a
        // structural element.
        // FIXME: Figure out cases where this is not true, and add projections
        // for them (the one we know is missing are lambdas).
        if (Style.isJava() &&
            Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {
          // If necessary, we could set the type to something different than
          // TT_FunctionLBrace.
          if (Style.BraceWrapping.AfterControlStatement ==
              FormatStyle::BWACS_Always) {
            addUnwrappedLine();
          }
        } else if (Style.BraceWrapping.AfterFunction) {
          addUnwrappedLine();
        }
        if (!Previous || Previous->isNot(TT_TypeDeclarationParen))
          FormatTok->setFinalizedType(TT_FunctionLBrace);
        parseBlock();
        IsDecltypeAutoFunction = false;
        addUnwrappedLine();
        return;
      }
      // Otherwise this was a braced init list, and the structural
      // element continues.
      break;
    case tok::kw_try:
      if (Style.isJavaScript() && Line->MustBeDeclaration) {
        // field/method declaration.
        nextToken();
        break;
      }
      // We arrive here when parsing function-try blocks.
      if (Style.BraceWrapping.AfterFunction)
        addUnwrappedLine();
      parseTryCatch();
      return;
    case tok::identifier: {
      if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) &&
          Line->MustBeDeclaration) {
        addUnwrappedLine();
        parseCSharpGenericTypeConstraint();
        break;
      }
      if (FormatTok->is(TT_MacroBlockEnd)) {
        addUnwrappedLine();
        return;
      }

      // Function declarations (as opposed to function expressions) are parsed
      // on their own unwrapped line by continuing this loop. Function
      // expressions (functions that are not on their own line) must not create
      // a new unwrapped line, so they are special cased below.
      size_t TokenCount = Line->Tokens.size();
      if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) &&
          (TokenCount > 1 ||
           (TokenCount == 1 &&
            Line->Tokens.front().Tok->isNot(Keywords.kw_async)))) {
        tryToParseJSFunction();
        break;
      }
      if ((Style.isJavaScript() || Style.isJava()) &&
          FormatTok->is(Keywords.kw_interface)) {
        if (Style.isJavaScript()) {
          // In JavaScript/TypeScript, "interface" can be used as a standalone
          // identifier, e.g. in `var interface = 1;`. If "interface" is
          // followed by another identifier, it is very like to be an actual
          // interface declaration.
          unsigned StoredPosition = Tokens->getPosition();
          FormatToken *Next = Tokens->getNextToken();
          FormatTok = Tokens->setPosition(StoredPosition);
          if (!mustBeJSIdent(Keywords, Next)) {
            nextToken();
            break;
          }
        }
        parseRecord();
        addUnwrappedLine();
        return;
      }

      if (Style.isVerilog()) {
        if (FormatTok->is(Keywords.kw_table)) {
          parseVerilogTable();
          return;
        }
        if (Keywords.isVerilogBegin(*FormatTok) ||
            Keywords.isVerilogHierarchy(*FormatTok)) {
          parseBlock();
          addUnwrappedLine();
          return;
        }
      }

      if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
        if (parseStructLike())
          return;
        break;
      }

      if (IsCpp && FormatTok->is(TT_StatementMacro)) {
        parseStatementMacro();
        return;
      }

      // See if the following token should start a new unwrapped line.
      StringRef Text = FormatTok->TokenText;

      FormatToken *PreviousToken = FormatTok;
      nextToken();

      // JS doesn't have macros, and within classes colons indicate fields, not
      // labels.
      if (Style.isJavaScript())
        break;

      auto OneTokenSoFar = [&]() {
        auto I = Line->Tokens.begin(), E = Line->Tokens.end();
        while (I != E && I->Tok->is(tok::comment))
          ++I;
        if (Style.isVerilog())
          while (I != E && I->Tok->is(tok::hash))
            ++I;
        return I != E && (++I == E);
      };
      if (OneTokenSoFar()) {
        // Recognize function-like macro usages without trailing semicolon as
        // well as free-standing macros like Q_OBJECT.
        bool FunctionLike = FormatTok->is(tok::l_paren);
        if (FunctionLike)
          parseParens();

        bool FollowedByNewline =
            CommentsBeforeNextToken.empty()
                ? FormatTok->NewlinesBefore > 0
                : CommentsBeforeNextToken.front()->NewlinesBefore > 0;

        if (FollowedByNewline &&
            (Text.size() >= 5 ||
             (FunctionLike && FormatTok->isNot(tok::l_paren))) &&
            tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) {
          if (PreviousToken->isNot(TT_UntouchableMacroFunc))
            PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
          addUnwrappedLine();
          return;
        }
      }
      break;
    }
    case tok::equal:
      if ((Style.isJavaScript() || Style.isCSharp()) &&
          FormatTok->is(TT_FatArrow)) {
        tryToParseChildBlock();
        break;
      }

      SeenEqual = true;
      nextToken();
      if (FormatTok->is(tok::l_brace)) {
        // C# needs this change to ensure that array initialisers and object
        // initialisers are indented the same way. In TypeScript, the brace
        // can also be an object type definition.
        if (!Style.isJavaScript())
          FormatTok->setBlockKind(BK_BracedInit);
        // TableGen's defset statement has syntax of the form,
        // `defset <type> <name> = { <statement>... }`
        if (Style.isTableGen() &&
            Line->Tokens.begin()->Tok->is(Keywords.kw_defset)) {
          FormatTok->setFinalizedType(TT_FunctionLBrace);
          parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
                     /*MunchSemi=*/false);
          addUnwrappedLine();
          break;
        }
        nextToken();
        parseBracedList();
      } else if (Style.Language == FormatStyle::LK_Proto &&
                 FormatTok->is(tok::less)) {
        nextToken();
        parseBracedList(/*IsAngleBracket=*/true);
      }
      break;
    case tok::l_square:
      parseSquare();
      break;
    case tok::kw_new:
      if (Style.isCSharp() &&
          (Tokens->peekNextToken()->isAccessSpecifierKeyword() ||
           (Previous && Previous->isAccessSpecifierKeyword()))) {
        nextToken();
      } else {
        parseNew();
      }
      break;
    case tok::kw_switch:
      if (Style.isJava())
        parseSwitch(/*IsExpr=*/true);
      else
        nextToken();
      break;
    case tok::kw_case:
      // Proto: there are no switch/case statements.
      if (Style.Language == FormatStyle::LK_Proto) {
        nextToken();
        return;
      }
      // In Verilog switch is called case.
      if (Style.isVerilog()) {
        parseBlock();
        addUnwrappedLine();
        return;
      }
      if (Style.isJavaScript() && Line->MustBeDeclaration) {
        // 'case: string' field declaration.
        nextToken();
        break;
      }
      parseCaseLabel();
      break;
    case tok::kw_default:
      nextToken();
      if (Style.isVerilog()) {
        if (FormatTok->is(tok::colon)) {
          // The label will be handled in the next iteration.
          break;
        }
        if (FormatTok->is(Keywords.kw_clocking)) {
          // A default clocking block.
          parseBlock();
          addUnwrappedLine();
          return;
        }
        parseVerilogCaseLabel();
        return;
      }
      break;
    case tok::colon:
      nextToken();
      if (Style.isVerilog()) {
        parseVerilogCaseLabel();
        return;
      }
      break;
    case tok::greater:
      nextToken();
      if (FormatTok->is(tok::l_brace))
        FormatTok->Previous->setFinalizedType(TT_TemplateCloser);
      break;
    default:
      nextToken();
      break;
    }
  }
}

bool UnwrappedLineParser::tryToParsePropertyAccessor() {
  assert(FormatTok->is(tok::l_brace));
  if (!Style.isCSharp())
    return false;
  // See if it's a property accessor.
  if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier))
    return false;

  // See if we are inside a property accessor.
  //
  // Record the current tokenPosition so that we can advance and
  // reset the current token. `Next` is not set yet so we need
  // another way to advance along the token stream.
  unsigned int StoredPosition = Tokens->getPosition();
  FormatToken *Tok = Tokens->getNextToken();

  // A trivial property accessor is of the form:
  // { [ACCESS_SPECIFIER] [get]; [ACCESS_SPECIFIER] [set|init] }
  // Track these as they do not require line breaks to be introduced.
  bool HasSpecialAccessor = false;
  bool IsTrivialPropertyAccessor = true;
  bool HasAttribute = false;
  while (!eof()) {
    if (const bool IsAccessorKeyword =
            Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set);
        IsAccessorKeyword || Tok->isAccessSpecifierKeyword() ||
        Tok->isOneOf(tok::l_square, tok::semi, Keywords.kw_internal)) {
      if (IsAccessorKeyword)
        HasSpecialAccessor = true;
      else if (Tok->is(tok::l_square))
        HasAttribute = true;
      Tok = Tokens->getNextToken();
      continue;
    }
    if (Tok->isNot(tok::r_brace))
      IsTrivialPropertyAccessor = false;
    break;
  }

  if (!HasSpecialAccessor || HasAttribute) {
    Tokens->setPosition(StoredPosition);
    return false;
  }

  // Try to parse the property accessor:
  // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
  Tokens->setPosition(StoredPosition);
  if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction)
    addUnwrappedLine();
  nextToken();
  do {
    switch (FormatTok->Tok.getKind()) {
    case tok::r_brace:
      nextToken();
      if (FormatTok->is(tok::equal)) {
        while (!eof() && FormatTok->isNot(tok::semi))
          nextToken();
        nextToken();
      }
      addUnwrappedLine();
      return true;
    case tok::l_brace:
      ++Line->Level;
      parseBlock(/*MustBeDeclaration=*/true);
      addUnwrappedLine();
      --Line->Level;
      break;
    case tok::equal:
      if (FormatTok->is(TT_FatArrow)) {
        ++Line->Level;
        do {
          nextToken();
        } while (!eof() && FormatTok->isNot(tok::semi));
        nextToken();
        addUnwrappedLine();
        --Line->Level;
        break;
      }
      nextToken();
      break;
    default:
      if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init,
                             Keywords.kw_set) &&
          !IsTrivialPropertyAccessor) {
        // Non-trivial get/set needs to be on its own line.
        addUnwrappedLine();
      }
      nextToken();
    }
  } while (!eof());

  // Unreachable for well-formed code (paired '{' and '}').
  return true;
}

bool UnwrappedLineParser::tryToParseLambda() {
  assert(FormatTok->is(tok::l_square));
  if (!IsCpp) {
    nextToken();
    return false;
  }
  FormatToken &LSquare = *FormatTok;
  if (!tryToParseLambdaIntroducer())
    return false;

  FormatToken *Arrow = nullptr;
  bool InTemplateParameterList = false;

  while (FormatTok->isNot(tok::l_brace)) {
    if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) {
      nextToken();
      continue;
    }
    switch (FormatTok->Tok.getKind()) {
    case tok::l_brace:
      break;
    case tok::l_paren:
      parseParens(/*AmpAmpTokenType=*/TT_PointerOrReference);
      break;
    case tok::l_square:
      parseSquare();
      break;
    case tok::less:
      assert(FormatTok->Previous);
      if (FormatTok->Previous->is(tok::r_square))
        InTemplateParameterList = true;
      nextToken();
      break;
    case tok::kw_auto:
    case tok::kw_class:
    case tok::kw_struct:
    case tok::kw_union:
    case tok::kw_template:
    case tok::kw_typename:
    case tok::amp:
    case tok::star:
    case tok::kw_const:
    case tok::kw_constexpr:
    case tok::kw_consteval:
    case tok::comma:
    case tok::greater:
    case tok::identifier:
    case tok::numeric_constant:
    case tok::coloncolon:
    case tok::kw_mutable:
    case tok::kw_noexcept:
    case tok::kw_static:
      nextToken();
      break;
    // Specialization of a template with an integer parameter can contain
    // arithmetic, logical, comparison and ternary operators.
    //
    // FIXME: This also accepts sequences of operators that are not in the scope
    // of a template argument list.
    //
    // In a C++ lambda a template type can only occur after an arrow. We use
    // this as an heuristic to distinguish between Objective-C expressions
    // followed by an `a->b` expression, such as:
    // ([obj func:arg] + a->b)
    // Otherwise the code below would parse as a lambda.
    case tok::plus:
    case tok::minus:
    case tok::exclaim:
    case tok::tilde:
    case tok::slash:
    case tok::percent:
    case tok::lessless:
    case tok::pipe:
    case tok::pipepipe:
    case tok::ampamp:
    case tok::caret:
    case tok::equalequal:
    case tok::exclaimequal:
    case tok::greaterequal:
    case tok::lessequal:
    case tok::question:
    case tok::colon:
    case tok::ellipsis:
    case tok::kw_true:
    case tok::kw_false:
      if (Arrow || InTemplateParameterList) {
        nextToken();
        break;
      }
      return true;
    case tok::arrow:
      Arrow = FormatTok;
      nextToken();
      break;
    case tok::kw_requires:
      parseRequiresClause();
      break;
    case tok::equal:
      if (!InTemplateParameterList)
        return true;
      nextToken();
      break;
    default:
      return true;
    }
  }

  FormatTok->setFinalizedType(TT_LambdaLBrace);
  LSquare.setFinalizedType(TT_LambdaLSquare);

  if (Arrow)
    Arrow->setFinalizedType(TT_LambdaArrow);

  NestedLambdas.push_back(Line->SeenDecltypeAuto);
  parseChildBlock();
  assert(!NestedLambdas.empty());
  NestedLambdas.pop_back();

  return true;
}

bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
  const FormatToken *Previous = FormatTok->Previous;
  const FormatToken *LeftSquare = FormatTok;
  nextToken();
  if (Previous) {
    const auto *PrevPrev = Previous->getPreviousNonComment();
    if (Previous->is(tok::star) && PrevPrev && PrevPrev->isTypeName(LangOpts))
      return false;
    if (Previous->closesScope()) {
      // Not a potential C-style cast.
      if (Previous->isNot(tok::r_paren))
        return false;
      // Lambdas can be cast to function types only, e.g. `std::function<int()>`
      // and `int (*)()`.
      if (!PrevPrev || PrevPrev->isNoneOf(tok::greater, tok::r_paren))
        return false;
    }
    if (Previous && Previous->Tok.getIdentifierInfo() &&
        Previous->isNoneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
                           tok::kw_co_return)) {
      return false;
    }
  }
  if (LeftSquare->isCppStructuredBinding(IsCpp))
    return false;
  if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind()))
    return false;
  if (FormatTok->is(tok::r_square)) {
    const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true);
    if (Next->is(tok::greater))
      return false;
  }
  parseSquare(/*LambdaIntroducer=*/true);
  return true;
}

void UnwrappedLineParser::tryToParseJSFunction() {
  assert(FormatTok->is(Keywords.kw_function));
  if (FormatTok->is(Keywords.kw_async))
    nextToken();
  // Consume "function".
  nextToken();

  // Consume * (generator function). Treat it like C++'s overloaded operators.
  if (FormatTok->is(tok::star)) {
    FormatTok->setFinalizedType(TT_OverloadedOperator);
    nextToken();
  }

  // Consume function name.
  if (FormatTok->is(tok::identifier))
    nextToken();

  if (FormatTok->isNot(tok::l_paren))
    return;

  // Parse formal parameter list.
  parseParens();

  if (FormatTok->is(tok::colon)) {
    // Parse a type definition.
    nextToken();

    // Eat the type declaration. For braced inline object types, balance braces,
    // otherwise just parse until finding an l_brace for the function body.
    if (FormatTok->is(tok::l_brace))
      tryToParseBracedList();
    else
      while (FormatTok->isNoneOf(tok::l_brace, tok::semi) && !eof())
        nextToken();
  }

  if (FormatTok->is(tok::semi))
    return;

  parseChildBlock();
}

bool UnwrappedLineParser::tryToParseBracedList() {
  if (FormatTok->is(BK_Unknown))
    calculateBraceTypes();
  assert(FormatTok->isNot(BK_Unknown));
  if (FormatTok->is(BK_Block))
    return false;
  nextToken();
  parseBracedList();
  return true;
}

bool UnwrappedLineParser::tryToParseChildBlock() {
  assert(Style.isJavaScript() || Style.isCSharp());
  assert(FormatTok->is(TT_FatArrow));
  // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType TT_FatArrow.
  // They always start an expression or a child block if followed by a curly
  // brace.
  nextToken();
  if (FormatTok->isNot(tok::l_brace))
    return false;
  parseChildBlock();
  return true;
}

bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {
  assert(!IsAngleBracket || !IsEnum);
  bool HasError = false;

  // FIXME: Once we have an expression parser in the UnwrappedLineParser,
  // replace this by using parseAssignmentExpression() inside.
  do {
    if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&
        tryToParseChildBlock()) {
      continue;
    }
    if (Style.isJavaScript()) {
      if (FormatTok->is(Keywords.kw_function)) {
        tryToParseJSFunction();
        continue;
      }
      if (FormatTok->is(tok::l_brace)) {
        // Could be a method inside of a braced list `{a() { return 1; }}`.
        if (tryToParseBracedList())
          continue;
        parseChildBlock();
      }
    }
    if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {
      if (IsEnum) {
        FormatTok->setBlockKind(BK_Block);
        if (!Style.AllowShortEnumsOnASingleLine)
          addUnwrappedLine();
      }
      nextToken();
      return !HasError;
    }
    switch (FormatTok->Tok.getKind()) {
    case tok::l_square:
      if (Style.isCSharp())
        parseSquare();
      else
        tryToParseLambda();
      break;
    case tok::l_paren:
      parseParens();
      // JavaScript can just have free standing methods and getters/setters in
      // object literals. Detect them by a "{" following ")".
      if (Style.isJavaScript()) {
        if (FormatTok->is(tok::l_brace))
          parseChildBlock();
        break;
      }
      break;
    case tok::l_brace:
      // Assume there are no blocks inside a braced init list apart
      // from the ones we explicitly parse out (like lambdas).
      FormatTok->setBlockKind(BK_BracedInit);
      if (!IsAngleBracket) {
        auto *Prev = FormatTok->Previous;
        if (Prev && Prev->is(tok::greater))
          Prev->setFinalizedType(TT_TemplateCloser);
      }
      nextToken();
      parseBracedList();
      break;
    case tok::less:
      nextToken();
      if (IsAngleBracket)
        parseBracedList(/*IsAngleBracket=*/true);
      break;
    case tok::semi:
      // JavaScript (or more precisely TypeScript) can have semicolons in braced
      // lists (in so-called TypeMemberLists). Thus, the semicolon cannot be
      // used for error recovery if we have otherwise determined that this is
      // a braced list.
      if (Style.isJavaScript()) {
        nextToken();
        break;
      }
      HasError = true;
      if (!IsEnum)
        return false;
      nextToken();
      break;
    case tok::comma:
      nextToken();
      if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
        addUnwrappedLine();
      break;
    case tok::kw_requires:
      parseRequiresExpression();
      break;
    default:
      nextToken();
      break;
    }
  } while (!eof());
  return false;
}

/// Parses a pair of parentheses (and everything between them).
/// \param StarAndAmpTokenType If different than TT_Unknown sets this type for
/// all (double) ampersands and stars. This applies for all nested scopes as
/// well.
///
/// Returns whether there is a `=` token between the parentheses.
bool UnwrappedLineParser::parseParens(TokenType StarAndAmpTokenType,
                                      bool InMacroCall) {
  assert(FormatTok->is(tok::l_paren) && "'(' expected.");
  auto *LParen = FormatTok;
  auto *Prev = FormatTok->Previous;
  bool SeenComma = false;
  bool SeenEqual = false;
  bool MightBeFoldExpr = false;
  nextToken();
  const bool MightBeStmtExpr = FormatTok->is(tok::l_brace);
  if (!InMacroCall && Prev && Prev->is(TT_FunctionLikeMacro))
    InMacroCall = true;
  do {
    switch (FormatTok->Tok.getKind()) {
    case tok::l_paren:
      if (parseParens(StarAndAmpTokenType, InMacroCall))
        SeenEqual = true;
      if (Style.isJava() && FormatTok->is(tok::l_brace))
        parseChildBlock();
      break;
    case tok::r_paren: {
      auto *RParen = FormatTok;
      nextToken();
      if (Prev) {
        auto OptionalParens = [&] {
          if (Style.RemoveParentheses == FormatStyle::RPS_Leave ||
              MightBeStmtExpr || MightBeFoldExpr || SeenComma || InMacroCall ||
              Line->InMacroBody || RParen->getPreviousNonComment() == LParen) {
            return false;
          }
          const bool DoubleParens =
              Prev->is(tok::l_paren) && FormatTok->is(tok::r_paren);
          if (DoubleParens) {
            const auto *PrevPrev = Prev->getPreviousNonComment();
            const bool Excluded =
                PrevPrev &&
                (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
                 (SeenEqual &&
                  (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) ||
                   PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if))));
            if (!Excluded)
              return true;
          } else {
            const bool CommaSeparated =
                Prev->isOneOf(tok::l_paren, tok::comma) &&
                FormatTok->isOneOf(tok::comma, tok::r_paren);
            if (CommaSeparated &&
                // LParen is not preceded by ellipsis, comma.
                !Prev->endsSequence(tok::comma, tok::ellipsis) &&
                // RParen is not followed by comma, ellipsis.
                !(FormatTok->is(tok::comma) &&
                  Tokens->peekNextToken()->is(tok::ellipsis))) {
              return true;
            }
            const bool ReturnParens =
                Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&
                ((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
                 (!NestedLambdas.empty() && !NestedLambdas.back())) &&
                Prev->isOneOf(tok::kw_return, tok::kw_co_return) &&
                FormatTok->is(tok::semi);
            if (ReturnParens)
              return true;
          }
          return false;
        };
        if (OptionalParens()) {
          LParen->Optional = true;
          RParen->Optional = true;
        } else if (Prev->is(TT_TypenameMacro)) {
          LParen->setFinalizedType(TT_TypeDeclarationParen);
          RParen->setFinalizedType(TT_TypeDeclarationParen);
        } else if (Prev->is(tok::greater) && RParen->Previous == LParen) {
          Prev->setFinalizedType(TT_TemplateCloser);
        } else if (FormatTok->is(tok::l_brace) && Prev->is(tok::amp) &&
                   !Prev->Previous) {
          FormatTok->setBlockKind(BK_BracedInit);
        }
      }
      return SeenEqual;
    }
    case tok::r_brace:
      // A "}" inside parenthesis is an error if there wasn't a matching "{".
      return SeenEqual;
    case tok::l_square:
      tryToParseLambda();
      break;
    case tok::l_brace:
      if (!tryToParseBracedList())
        parseChildBlock();
      break;
    case tok::at:
      nextToken();
      if (FormatTok->is(tok::l_brace)) {
        nextToken();
        parseBracedList();
      }
      break;
    case tok::comma:
      SeenComma = true;
      nextToken();
      break;
    case tok::ellipsis:
      MightBeFoldExpr = true;
      nextToken();
      break;
    case tok::equal:
      SeenEqual = true;
      if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
        tryToParseChildBlock();
      else
        nextToken();
      break;
    case tok::kw_class:
      if (Style.isJavaScript())
        parseRecord(/*ParseAsExpr=*/true);
      else
        nextToken();
      break;
    case tok::identifier:
      if (Style.isJavaScript() && (FormatTok->is(Keywords.kw_function)))
        tryToParseJSFunction();
      else
        nextToken();
      break;
    case tok::kw_switch:
      if (Style.isJava())
        parseSwitch(/*IsExpr=*/true);
      else
        nextToken();
      break;
    case tok::kw_requires:
      parseRequiresExpression();
      break;
    case tok::star:
    case tok::amp:
    case tok::ampamp:
      if (StarAndAmpTokenType != TT_Unknown)
        FormatTok->setFinalizedType(StarAndAmpTokenType);
      [[fallthrough]];
    default:
      nextToken();
      break;
    }
  } while (!eof());
  return SeenEqual;
}

void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {
  if (!LambdaIntroducer) {
    assert(FormatTok->is(tok::l_square) && "'[' expected.");
    if (tryToParseLambda())
      return;
  }
  do {
    switch (FormatTok->Tok.getKind()) {
    case tok::l_paren:
      parseParens();
      break;
    case tok::r_square:
      nextToken();
      return;
    case tok::r_brace:
      // A "}" inside parenthesis is an error if there wasn't a matching "{".
      return;
    case tok::l_square:
      parseSquare();
      break;
    case tok::l_brace: {
      if (!tryToParseBracedList())
        parseChildBlock();
      break;
    }
    case tok::at:
    case tok::colon:
      nextToken();
      if (FormatTok->is(tok::l_brace)) {
        nextToken();
        parseBracedList();
      }
      break;
    default:
      nextToken();
      break;
    }
  } while (!eof());
}

void UnwrappedLineParser::keepAncestorBraces() {
  if (!Style.RemoveBracesLLVM)
    return;

  const int MaxNestingLevels = 2;
  const int Size = NestedTooDeep.size();
  if (Size >= MaxNestingLevels)
    NestedTooDeep[Size - MaxNestingLevels] = true;
  NestedTooDeep.push_back(false);
}

static FormatToken *getLastNonComment(const UnwrappedLine &Line) {
  for (const auto &Token : llvm::reverse(Line.Tokens))
    if (Token.Tok->isNot(tok::comment))
      return Token.Tok;

  return nullptr;
}

void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) {
  FormatToken *Tok = nullptr;

  if (Style.InsertBraces && !Line->InPPDirective && !Line->Tokens.empty() &&
      PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {
    Tok = Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Never
              ? getLastNonComment(*Line)
              : Line->Tokens.back().Tok;
    assert(Tok);
    if (Tok->BraceCount < 0) {
      assert(Tok->BraceCount == -1);
      Tok = nullptr;
    } else {
      Tok->BraceCount = -1;
    }
  }

  addUnwrappedLine();
  ++Line->Level;
  ++Line->UnbracedBodyLevel;
  parseStructuralElement();
  --Line->UnbracedBodyLevel;

  if (Tok) {
    assert(!Line->InPPDirective);
    Tok = nullptr;
    for (const auto &L : llvm::reverse(*CurrentLines)) {
      if (!L.InPPDirective && getLastNonComment(L)) {
        Tok = L.Tokens.back().Tok;
        break;
      }
    }
    assert(Tok);
    ++Tok->BraceCount;
  }

  if (CheckEOF && eof())
    addUnwrappedLine();

  --Line->Level;
}

static void markOptionalBraces(FormatToken *LeftBrace) {
  if (!LeftBrace)
    return;

  assert(LeftBrace->is(tok::l_brace));

  FormatToken *RightBrace = LeftBrace->MatchingParen;
  if (!RightBrace) {
    assert(!LeftBrace->Optional);
    return;
  }

  assert(RightBrace->is(tok::r_brace));
  assert(RightBrace->MatchingParen == LeftBrace);
  assert(LeftBrace->Optional == RightBrace->Optional);

  LeftBrace->Optional = true;
  RightBrace->Optional = true;
}

void UnwrappedLineParser::handleAttributes() {
  // Handle AttributeMacro, e.g. `if (x) UNLIKELY`.
  if (FormatTok->isAttribute())
    nextToken();
  else if (FormatTok->is(tok::l_square))
    handleCppAttributes();
}

bool UnwrappedLineParser::handleCppAttributes() {
  // Handle [[likely]] / [[unlikely]] attributes.
  assert(FormatTok->is(tok::l_square));
  if (!tryToParseSimpleAttribute())
    return false;
  parseSquare();
  return true;
}

/// Returns whether \c Tok begins a block.
bool UnwrappedLineParser::isBlockBegin(const FormatToken &Tok) const {
  // FIXME: rename the function or make
  // Tok.isOneOf(tok::l_brace, TT_MacroBlockBegin) work.
  return Style.isVerilog() ? Keywords.isVerilogBegin(Tok)
                           : Tok.is(tok::l_brace);
}

FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
                                                  bool KeepBraces,
                                                  bool IsVerilogAssert) {
  assert((FormatTok->is(tok::kw_if) ||
          (Style.isVerilog() &&
           FormatTok->isOneOf(tok::kw_restrict, Keywords.kw_assert,
                              Keywords.kw_assume, Keywords.kw_cover))) &&
         "'if' expected");
  nextToken();

  if (IsVerilogAssert) {
    // Handle `assert #0` and `assert final`.
    if (FormatTok->is(Keywords.kw_verilogHash)) {
      nextToken();
      if (FormatTok->is(tok::numeric_constant))
        nextToken();
    } else if (FormatTok->isOneOf(Keywords.kw_final, Keywords.kw_property,
                                  Keywords.kw_sequence)) {
      nextToken();
    }
  }

  // TableGen's if statement has the form of `if <cond> then { ... }`.
  if (Style.isTableGen()) {
    while (!eof() && FormatTok->isNot(Keywords.kw_then)) {
      // Simply skip until then. This range only contains a value.
      nextToken();
    }
  }

  // Handle `if !consteval`.
  if (FormatTok->is(tok::exclaim))
    nextToken();

  bool KeepIfBraces = true;
  if (FormatTok->is(tok::kw_consteval)) {
    nextToken();
  } else {
    KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces;
    if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))
      nextToken();
    if (FormatTok->is(tok::l_paren)) {
      FormatTok->setFinalizedType(TT_ConditionLParen);
      parseParens();
    }
  }
  handleAttributes();
  // The then action is optional in Verilog assert statements.
  if (IsVerilogAssert && FormatTok->is(tok::semi)) {
    nextToken();
    addUnwrappedLine();
    return nullptr;
  }

  bool NeedsUnwrappedLine = false;
  keepAncestorBraces();

  FormatToken *IfLeftBrace = nullptr;
  IfStmtKind IfBlockKind = IfStmtKind::NotIf;

  if (isBlockBegin(*FormatTok)) {
    FormatTok->setFinalizedType(TT_ControlStatementLBrace);
    IfLeftBrace = FormatTok;
    CompoundStatementIndenter Indenter(this, Style, Line->Level);
    parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
               /*MunchSemi=*/true, KeepIfBraces, &IfBlockKind);
    setPreviousRBraceType(TT_ControlStatementRBrace);
    if (Style.BraceWrapping.BeforeElse)
      addUnwrappedLine();
    else
      NeedsUnwrappedLine = true;
  } else if (IsVerilogAssert && FormatTok->is(tok::kw_else)) {
    addUnwrappedLine();
  } else {
    parseUnbracedBody();
  }

  if (Style.RemoveBracesLLVM) {
    assert(!NestedTooDeep.empty());
    KeepIfBraces = KeepIfBraces ||
                   (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
                   NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
                   IfBlockKind == IfStmtKind::IfElseIf;
  }

  bool KeepElseBraces = KeepIfBraces;
  FormatToken *ElseLeftBrace = nullptr;
  IfStmtKind Kind = IfStmtKind::IfOnly;

  if (FormatTok->is(tok::kw_else)) {
    if (Style.RemoveBracesLLVM) {
      NestedTooDeep.back() = false;
      Kind = IfStmtKind::IfElse;
    }
    nextToken();
    handleAttributes();
    if (isBlockBegin(*FormatTok)) {
      const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);
      FormatTok->setFinalizedType(TT_ElseLBrace);
      ElseLeftBrace = FormatTok;
      CompoundStatementIndenter Indenter(this, Style, Line->Level);
      IfStmtKind ElseBlockKind = IfStmtKind::NotIf;
      FormatToken *IfLBrace =
          parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
                     /*MunchSemi=*/true, KeepElseBraces, &ElseBlockKind);
      setPreviousRBraceType(TT_ElseRBrace);
      if (FormatTok->is(tok::kw_else)) {
        KeepElseBraces = KeepElseBraces ||
                         ElseBlockKind == IfStmtKind::IfOnly ||
                         ElseBlockKind == IfStmtKind::IfElseIf;
      } else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
        KeepElseBraces = true;
        assert(ElseLeftBrace->MatchingParen);
        markOptionalBraces(ElseLeftBrace);
      }
      addUnwrappedLine();
    } else if (!IsVerilogAssert && FormatTok->is(tok::kw_if)) {
      const FormatToken *Previous = Tokens->getPreviousToken();
      assert(Previous);
      const bool IsPrecededByComment = Previous->is(tok::comment);
      if (IsPrecededByComment) {
        addUnwrappedLine();
        ++Line->Level;
      }
      bool TooDeep = true;
      if (Style.RemoveBracesLLVM) {
        Kind = IfStmtKind::IfElseIf;
        TooDeep = NestedTooDeep.pop_back_val();
      }
      ElseLeftBrace = parseIfThenElse(/*IfKind=*/nullptr, KeepIfBraces);
      if (Style.RemoveBracesLLVM)
        NestedTooDeep.push_back(TooDeep);
      if (IsPrecededByComment)
        --Line->Level;
    } else {
      parseUnbracedBody(/*CheckEOF=*/true);
    }
  } else {
    KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;
    if (NeedsUnwrappedLine)
      addUnwrappedLine();
  }

  if (!Style.RemoveBracesLLVM)
    return nullptr;

  assert(!NestedTooDeep.empty());
  KeepElseBraces = KeepElseBraces ||
                   (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||
                   NestedTooDeep.back();

  NestedTooDeep.pop_back();

  if (!KeepIfBraces && !KeepElseBraces) {
    markOptionalBraces(IfLeftBrace);
    markOptionalBraces(ElseLeftBrace);
  } else if (IfLeftBrace) {
    FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
    if (IfRightBrace) {
      assert(IfRightBrace->MatchingParen == IfLeftBrace);
      assert(!IfLeftBrace->Optional);
      assert(!IfRightBrace->Optional);
      IfLeftBrace->MatchingParen = nullptr;
      IfRightBrace->MatchingParen = nullptr;
    }
  }

  if (IfKind)
    *IfKind = Kind;

  return IfLeftBrace;
}

void UnwrappedLineParser::parseTryCatch() {
  assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");
  nextToken();
  bool NeedsUnwrappedLine = false;
  bool HasCtorInitializer = false;
  if (FormatTok->is(tok::colon)) {
    auto *Colon = FormatTok;
    // We are in a function try block, what comes is an initializer list.
    nextToken();
    if (FormatTok->is(tok::identifier)) {
      HasCtorInitializer = true;
      Colon->setFinalizedType(TT_CtorInitializerColon);
    }

    // In case identifiers were removed by clang-tidy, what might follow is
    // multiple commas in sequence - before the first identifier.
    while (FormatTok->is(tok::comma))
      nextToken();

    while (FormatTok->is(tok::identifier)) {
      nextToken();
      if (FormatTok->is(tok::l_paren)) {
        parseParens();
      } else if (FormatTok->is(tok::l_brace)) {
        nextToken();
        parseBracedList();
      }

      // In case identifiers were removed by clang-tidy, what might follow is
      // multiple commas in sequence - after the first identifier.
      while (FormatTok->is(tok::comma))
        nextToken();
    }
  }
  // Parse try with resource.
  if (Style.isJava() && FormatTok->is(tok::l_paren))
    parseParens();

  keepAncestorBraces();

  if (FormatTok->is(tok::l_brace)) {
    if (HasCtorInitializer)
      FormatTok->setFinalizedType(TT_FunctionLBrace);
    CompoundStatementIndenter Indenter(this, Style, Line->Level);
    parseBlock();
    if (Style.BraceWrapping.BeforeCatch)
      addUnwrappedLine();
    else
      NeedsUnwrappedLine = true;
  } else if (FormatTok->isNot(tok::kw_catch)) {
    // The C++ standard requires a compound-statement after a try.
    // If there's none, we try to assume there's a structuralElement
    // and try to continue.
    addUnwrappedLine();
    ++Line->Level;
    parseStructuralElement();
    --Line->Level;
  }
  for (bool SeenCatch = false;;) {
    if (FormatTok->is(tok::at))
      nextToken();
    if (FormatTok->isNoneOf(tok::kw_catch, Keywords.kw___except,
                            tok::kw___finally, tok::objc_catch,
                            tok::objc_finally) &&
        !((Style.isJava() || Style.isJavaScript()) &&
          FormatTok->is(Keywords.kw_finally))) {
      break;
    }
    if (FormatTok->is(tok::kw_catch))
      SeenCatch = true;
    nextToken();
    while (FormatTok->isNot(tok::l_brace)) {
      if (FormatTok->is(tok::l_paren)) {
        parseParens();
        continue;
      }
      if (FormatTok->isOneOf(tok::semi, tok::r_brace) || eof()) {
        if (Style.RemoveBracesLLVM)
          NestedTooDeep.pop_back();
        return;
      }
      nextToken();
    }
    if (SeenCatch) {
      FormatTok->setFinalizedType(TT_ControlStatementLBrace);
      SeenCatch = false;
    }
    NeedsUnwrappedLine = false;
    Line->MustBeDeclaration = false;
    CompoundStatementIndenter Indenter(this, Style, Line->Level);
    parseBlock();
    if (Style.BraceWrapping.BeforeCatch)
      addUnwrappedLine();
    else
      NeedsUnwrappedLine = true;
  }

  if (Style.RemoveBracesLLVM)
    NestedTooDeep.pop_back();

  if (NeedsUnwrappedLine)
    addUnwrappedLine();
}

void UnwrappedLineParser::parseNamespaceOrExportBlock(unsigned AddLevels) {
  bool ManageWhitesmithsBraces =
      AddLevels == 0u && Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;

  // If we're in Whitesmiths mode, indent the brace if we're not indenting
  // the whole block.
  if (ManageWhitesmithsBraces)
    ++Line->Level;

  // Munch the semicolon after the block. This is more common than one would
  // think. Putting the semicolon into its own line is very ugly.
  parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true,
             /*KeepBraces=*/true, /*IfKind=*/nullptr, ManageWhitesmithsBraces);

  addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);

  if (ManageWhitesmithsBraces)
    --Line->Level;
}

void UnwrappedLineParser::parseNamespace() {
  assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&
         "'namespace' expected");

  const FormatToken &InitialToken = *FormatTok;
  nextToken();
  if (InitialToken.is(TT_NamespaceMacro)) {
    parseParens();
  } else {
    while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
                              tok::l_square, tok::period, tok::l_paren) ||
           (Style.isCSharp() && FormatTok->is(tok::kw_union))) {
      if (FormatTok->is(tok::l_square))
        parseSquare();
      else if (FormatTok->is(tok::l_paren))
        parseParens();
      else
        nextToken();
    }
  }
  if (FormatTok->is(tok::l_brace)) {
    FormatTok->setFinalizedType(TT_NamespaceLBrace);

    if (ShouldBreakBeforeBrace(Style, InitialToken,
                               Tokens->peekNextToken()->is(tok::r_brace))) {
      addUnwrappedLine();
    }

    unsigned AddLevels =
        Style.NamespaceIndentation == FormatStyle::NI_All ||
                (Style.NamespaceIndentation == FormatStyle::NI_Inner &&
                 DeclarationScopeStack.size() > 1)
            ? 1u
            : 0u;
    parseNamespaceOrExportBlock(AddLevels);
  }
  // FIXME: Add error handling.
}

void UnwrappedLineParser::parseCppExportBlock() {
  parseNamespaceOrExportBlock(/*AddLevels=*/Style.IndentExportBlock ? 1 : 0);
}

void UnwrappedLineParser::parseNew() {
  assert(FormatTok->is(tok::kw_new) && "'new' expected");
  nextToken();

  if (Style.isCSharp()) {
    do {
      // Handle constructor invocation, e.g. `new(field: value)`.
      if (FormatTok->is(tok::l_paren))
        parseParens();

      // Handle array initialization syntax, e.g. `new[] {10, 20, 30}`.
      if (FormatTok->is(tok::l_brace))
        parseBracedList();

      if (FormatTok->isOneOf(tok::semi, tok::comma))
        return;

      nextToken();
    } while (!eof());
  }

  if (!Style.isJava())
    return;

  // In Java, we can parse everything up to the parens, which aren't optional.
  do {
    // There should not be a ;, { or } before the new's open paren.
    if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
      return;

    // Consume the parens.
    if (FormatTok->is(tok::l_paren)) {
      parseParens();

      // If there is a class body of an anonymous class, consume that as child.
      if (FormatTok->is(tok::l_brace))
        parseChildBlock();
      return;
    }
    nextToken();
  } while (!eof());
}

void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) {
  keepAncestorBraces();

  if (isBlockBegin(*FormatTok)) {
    FormatTok->setFinalizedType(TT_ControlStatementLBrace);
    FormatToken *LeftBrace = FormatTok;
    CompoundStatementIndenter Indenter(this, Style, Line->Level);
    parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
               /*MunchSemi=*/true, KeepBraces);
    setPreviousRBraceType(TT_ControlStatementRBrace);
    if (!KeepBraces) {
      assert(!NestedTooDeep.empty());
      if (!NestedTooDeep.back())
        markOptionalBraces(LeftBrace);
    }
    if (WrapRightBrace)
      addUnwrappedLine();
  } else {
    parseUnbracedBody();
  }

  if (!KeepBraces)
    NestedTooDeep.pop_back();
}

void UnwrappedLineParser::parseForOrWhileLoop(bool HasParens) {
  assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) ||
          (Style.isVerilog() &&
           FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb,
                              Keywords.kw_always_ff, Keywords.kw_always_latch,
                              Keywords.kw_final, Keywords.kw_initial,
                              Keywords.kw_foreach, Keywords.kw_forever,
                              Keywords.kw_repeat))) &&
         "'for', 'while' or foreach macro expected");
  const bool KeepBraces = !Style.RemoveBracesLLVM ||
                          FormatTok->isNoneOf(tok::kw_for, tok::kw_while);

  nextToken();
  // JS' for await ( ...
  if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
    nextToken();
  if (IsCpp && FormatTok->is(tok::kw_co_await))
    nextToken();
  if (HasParens && FormatTok->is(tok::l_paren)) {
    // The type is only set for Verilog basically because we were afraid to
    // change the existing behavior for loops. See the discussion on D121756 for
    // details.
    if (Style.isVerilog())
      FormatTok->setFinalizedType(TT_ConditionLParen);
    parseParens();
  }

  if (Style.isVerilog()) {
    // Event control.
    parseVerilogSensitivityList();
  } else if (Style.AllowShortLoopsOnASingleLine && FormatTok->is(tok::semi) &&
             Tokens->getPreviousToken()->is(tok::r_paren)) {
    nextToken();
    addUnwrappedLine();
    return;
  }

  handleAttributes();
  parseLoopBody(KeepBraces, /*WrapRightBrace=*/true);
}

void UnwrappedLineParser::parseDoWhile() {
  assert(FormatTok->is(tok::kw_do) && "'do' expected");
  nextToken();

  parseLoopBody(/*KeepBraces=*/true, Style.BraceWrapping.BeforeWhile);

  // FIXME: Add error handling.
  if (FormatTok->isNot(tok::kw_while)) {
    addUnwrappedLine();
    return;
  }

  FormatTok->setFinalizedType(TT_DoWhile);

  // If in Whitesmiths mode, the line with the while() needs to be indented
  // to the same level as the block.
  if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths)
    ++Line->Level;

  nextToken();
  parseStructuralElement();
}

void UnwrappedLineParser::parseLabel(bool IsGotoLabel) {
  nextToken();

  const auto IndentGotoLabel = Style.IndentGotoLabels;
  const auto OldLineLevel = Line->Level;
  auto &Level = Line->Level;

  if (IsGotoLabel && IndentGotoLabel == FormatStyle::IGLS_NoIndent)
    Level = 0;

  if (!IsGotoLabel || IndentGotoLabel == FormatStyle::IGLS_OuterIndent) {
    if (OldLineLevel > 1 || (!Line->InPPDirective && OldLineLevel > 0))
      --Level;
  }

  if (!IsGotoLabel && !Style.IndentCaseBlocks &&
      CommentsBeforeNextToken.empty() && FormatTok->is(tok::l_brace)) {
    CompoundStatementIndenter Indenter(this, Level,
                                       Style.BraceWrapping.AfterCaseLabel,
                                       Style.BraceWrapping.IndentBraces);
    parseBlock();
    if (FormatTok->is(tok::kw_break)) {
      if (Style.BraceWrapping.AfterControlStatement ==
          FormatStyle::BWACS_Always) {
        addUnwrappedLine();
        if (!Style.IndentCaseBlocks &&
            Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
          ++Level;
        }
      }
      parseStructuralElement();
    }
    addUnwrappedLine();
  } else {
    if (FormatTok->is(tok::semi))
      nextToken();
    addUnwrappedLine();
  }

  Level = OldLineLevel;

  if (FormatTok->isNot(tok::l_brace)) {
    parseStructuralElement();
    addUnwrappedLine();
  }
}

void UnwrappedLineParser::parseCaseLabel() {
  assert(FormatTok->is(tok::kw_case) && "'case' expected");
  auto *Case = FormatTok;

  // FIXME: fix handling of complex expressions here.
  do {
    nextToken();
    if (FormatTok->is(tok::colon)) {
      FormatTok->setFinalizedType(TT_CaseLabelColon);
      break;
    }
    if (Style.isJava() && FormatTok->is(tok::arrow)) {
      FormatTok->setFinalizedType(TT_CaseLabelArrow);
      Case->setFinalizedType(TT_SwitchExpressionLabel);
      break;
    }
  } while (!eof());
  parseLabel();
}

void UnwrappedLineParser::parseSwitch(bool IsExpr) {
  assert(FormatTok->is(tok::kw_switch) && "'switch' expected");
  nextToken();
  if (FormatTok->is(tok::l_paren))
    parseParens();

  keepAncestorBraces();

  if (FormatTok->is(tok::l_brace)) {
    CompoundStatementIndenter Indenter(this, Style, Line->Level);
    FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace
                                       : TT_ControlStatementLBrace);
    if (IsExpr)
      parseChildBlock();
    else
      parseBlock();
    setPreviousRBraceType(TT_ControlStatementRBrace);
    if (!IsExpr)
      addUnwrappedLine();
  } else {
    addUnwrappedLine();
    ++Line->Level;
    parseStructuralElement();
    --Line->Level;
  }

  if (Style.RemoveBracesLLVM)
    NestedTooDeep.pop_back();
}

void UnwrappedLineParser::parseAccessSpecifier() {
  nextToken();
  // Understand Qt's slots.
  if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
    nextToken();
  // Otherwise, we don't know what it is, and we'd better keep the next token.
  if (FormatTok->is(tok::colon))
    nextToken();
  addUnwrappedLine();
}

/// Parses a requires, decides if it is a clause or an expression.
/// \pre The current token has to be the requires keyword.
/// \returns true if it parsed a clause.
bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
  assert(FormatTok->is(tok::kw_requires) && "'requires' expected");

  // We try to guess if it is a requires clause, or a requires expression. For
  // that we first check the next token.
  switch (Tokens->peekNextToken(/*SkipComment=*/true)->Tok.getKind()) {
  case tok::l_brace:
    // This can only be an expression, never a clause.
    parseRequiresExpression();
    return false;
  case tok::l_paren:
    // Clauses and expression can start with a paren, it's unclear what we have.
    break;
  default:
    // All other tokens can only be a clause.
    parseRequiresClause();
    return true;
  }

  // Looking forward we would have to decide if there are function declaration
  // like arguments to the requires expression:
  // requires (T t) {
  // Or there is a constraint expression for the requires clause:
  // requires (C<T> && ...

  // But first let's look behind.
  auto *PreviousNonComment = FormatTok->getPreviousNonComment();

  if (!PreviousNonComment ||
      PreviousNonComment->is(TT_RequiresExpressionLBrace)) {
    // If there is no token, or an expression left brace, we are a requires
    // clause within a requires expression.
    parseRequiresClause();
    return true;
  }

  switch (PreviousNonComment->Tok.getKind()) {
  case tok::greater:
  case tok::r_paren:
  case tok::kw_noexcept:
  case tok::kw_const:
  case tok::star:
  case tok::amp:
    // This is a requires clause.
    parseRequiresClause();
    return true;
  case tok::ampamp: {
    // This can be either:
    // if (... && requires (T t) ...)
    // Or
    // void member(...) && requires (C<T> ...
    // We check the one token before that for a const:
    // void member(...) const && requires (C<T> ...
    auto PrevPrev = PreviousNonComment->getPreviousNonComment();
    if ((PrevPrev && PrevPrev->is(tok::kw_const)) || !SeenEqual) {
      parseRequiresClause();
      return true;
    }
    break;
  }
  default:
    if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {
      // This is a requires clause.
      parseRequiresClause();
      return true;
    }
    // It's an expression.
    parseRequiresExpression();
    return false;
  }

  // Now we look forward and try to check if the paren content is a parameter
  // list. The parameters can be cv-qualified and contain references or
  // pointers.
  // So we want basically to check for TYPE NAME, but TYPE can contain all kinds
  // of stuff: typename, const, *, &, &&, ::, identifiers.

  unsigned StoredPosition = Tokens->getPosition();
  FormatToken *NextToken = Tokens->getNextToken();
  int Lookahead = 0;
  auto PeekNext = [&Lookahead, &NextToken, this] {
    ++Lookahead;
    NextToken = Tokens->getNextToken();
  };

  bool FoundType = false;
  bool LastWasColonColon = false;
  int OpenAngles = 0;

  for (; Lookahead < 50; PeekNext()) {
    switch (NextToken->Tok.getKind()) {
    case tok::kw_volatile:
    case tok::kw_const:
    case tok::comma:
      if (OpenAngles == 0) {
        FormatTok = Tokens->setPosition(StoredPosition);
        parseRequiresExpression();
        return false;
      }
      break;
    case tok::eof:
      // Break out of the loop.
      Lookahead = 50;
      break;
    case tok::coloncolon:
      LastWasColonColon = true;
      break;
    case tok::kw_decltype:
    case tok::identifier:
      if (FoundType && !LastWasColonColon && OpenAngles == 0) {
        FormatTok = Tokens->setPosition(StoredPosition);
        parseRequiresExpression();
        return false;
      }
      FoundType = true;
      LastWasColonColon = false;
      break;
    case tok::less:
      ++OpenAngles;
      break;
    case tok::greater:
      --OpenAngles;
      break;
    default:
      if (NextToken->isTypeName(LangOpts)) {
        FormatTok = Tokens->setPosition(StoredPosition);
        parseRequiresExpression();
        return false;
      }
      break;
    }
  }
  // This seems to be a complicated expression, just assume it's a clause.
  FormatTok = Tokens->setPosition(StoredPosition);
  parseRequiresClause();
  return true;
}

/// Parses a requires clause.
/// \sa parseRequiresExpression
///
/// Returns if it either has finished parsing the clause, or it detects, that
/// the clause is incorrect.
void UnwrappedLineParser::parseRequiresClause() {
  assert(FormatTok->is(tok::kw_requires) && "'requires' expected");

  // If there is no previous token, we are within a requires expression,
  // otherwise we will always have the template or function declaration in front
  // of it.
  bool InRequiresExpression =
      !FormatTok->Previous ||
      FormatTok->Previous->is(TT_RequiresExpressionLBrace);

  FormatTok->setFinalizedType(InRequiresExpression
                                  ? TT_RequiresClauseInARequiresExpression
                                  : TT_RequiresClause);
  nextToken();

  // NOTE: parseConstraintExpression is only ever called from this function.
  // It could be inlined into here.
  parseConstraintExpression();

  if (!InRequiresExpression && FormatTok->Previous)
    FormatTok->Previous->ClosesRequiresClause = true;
}

/// Parses a requires expression.
/// \sa parseRequiresClause
///
/// Returns if it either has finished parsing the expression, or it detects,
/// that the expression is incorrect.
void UnwrappedLineParser::parseRequiresExpression() {
  assert(FormatTok->is(tok::kw_requires) && "'requires' expected");

  FormatTok->setFinalizedType(TT_RequiresExpression);
  nextToken();

  if (FormatTok->is(tok::l_paren)) {
    FormatTok->setFinalizedType(TT_RequiresExpressionLParen);
    parseParens();
  }

  if (FormatTok->is(tok::l_brace)) {
    FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);
    parseChildBlock();
  }
}

/// Parses a constraint expression.
///
/// This is the body of a requires clause. It returns, when the parsing is
/// complete, or the expression is incorrect.
void UnwrappedLineParser::parseConstraintExpression() {
  // The special handling for lambdas is needed since tryToParseLambda() eats a
  // token and if a requires expression is the last part of a requires clause
  // and followed by an attribute like [[nodiscard]] the ClosesRequiresClause is
  // not set on the correct token. Thus we need to be aware if we even expect a
  // lambda to be possible.
  // template <typename T> requires requires { ... } [[nodiscard]] ...;
  bool LambdaNextTimeAllowed = true;

  // Within lambda declarations, it is permitted to put a requires clause after
  // its template parameter list, which would place the requires clause right
  // before the parentheses of the parameters of the lambda declaration. Thus,
  // we track if we expect to see grouping parentheses at all.
  // Without this check, `requires foo<T> (T t)` in the below example would be
  // seen as the whole requires clause, accidentally eating the parameters of
  // the lambda.
  // [&]<typename T> requires foo<T> (T t) { ... };
  bool TopLevelParensAllowed = true;

  do {
    bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed, false);

    switch (FormatTok->Tok.getKind()) {
    case tok::kw_requires:
      parseRequiresExpression();
      break;

    case tok::l_paren:
      if (!TopLevelParensAllowed)
        return;
      parseParens(/*AmpAmpTokenType=*/TT_BinaryOperator);
      TopLevelParensAllowed = false;
      break;

    case tok::l_square:
      if (!LambdaThisTimeAllowed || !tryToParseLambda())
        return;
      break;

    case tok::kw_const:
    case tok::semi:
    case tok::kw_class:
    case tok::kw_struct:
    case tok::kw_union:
      return;

    case tok::l_brace:
      // Potential function body.
      return;

    case tok::ampamp:
    case tok::pipepipe:
      FormatTok->setFinalizedType(TT_BinaryOperator);
      nextToken();
      LambdaNextTimeAllowed = true;
      TopLevelParensAllowed = true;
      break;

    case tok::comma:
    case tok::comment:
      LambdaNextTimeAllowed = LambdaThisTimeAllowed;
      nextToken();
      break;

    case tok::kw_sizeof:
    case tok::greater:
    case tok::greaterequal:
    case tok::greatergreater:
    case tok::less:
    case tok::lessequal:
    case tok::lessless:
    case tok::equalequal:
    case tok::exclaim:
    case tok::exclaimequal:
    case tok::plus:
    case tok::minus:
    case tok::star:
    case tok::slash:
      LambdaNextTimeAllowed = true;
      TopLevelParensAllowed = true;
      // Just eat them.
      nextToken();
      break;

    case tok::numeric_constant:
    case tok::coloncolon:
    case tok::kw_true:
    case tok::kw_false:
      TopLevelParensAllowed = false;
      // Just eat them.
      nextToken();
      break;

    case tok::kw_static_cast:
    case tok::kw_const_cast:
    case tok::kw_reinterpret_cast:
    case tok::kw_dynamic_cast:
      nextToken();
      if (FormatTok->isNot(tok::less))
        return;

      nextToken();
      parseBracedList(/*IsAngleBracket=*/true);
      break;

    default:
      if (!FormatTok->Tok.getIdentifierInfo()) {
        // Identifiers are part of the default case, we check for more then
        // tok::identifier to handle builtin type traits.
        return;
      }

      // We need to differentiate identifiers for a template deduction guide,
      // variables, or function return types (the constraint expression has
      // ended before that), and basically all other cases. But it's easier to
      // check the other way around.
      assert(FormatTok->Previous);
      switch (FormatTok->Previous->Tok.getKind()) {
      case tok::coloncolon:  // Nested identifier.
      case tok::ampamp:      // Start of a function or variable for the
      case tok::pipepipe:    // constraint expression. (binary)
      case tok::exclaim:     // The same as above, but unary.
      case tok::kw_requires: // Initial identifier of a requires clause.
      case tok::equal:       // Initial identifier of a concept declaration.
      case tok::kw_template: // A dependent template.
        break;
      default:
        return;
      }

      // Read identifier with optional template declaration.
      nextToken();
      if (FormatTok->is(tok::less)) {
        nextToken();
        parseBracedList(/*IsAngleBracket=*/true);
      }
      TopLevelParensAllowed = false;
      break;
    }
  } while (!eof());
}

bool UnwrappedLineParser::parseEnum() {
  const FormatToken &InitialToken = *FormatTok;

  // Won't be 'enum' for NS_ENUMs.
  if (FormatTok->is(tok::kw_enum))
    nextToken();

  // In TypeScript, "enum" can also be used as property name, e.g. in interface
  // declarations. An "enum" keyword followed by a colon would be a syntax
  // error and thus assume it is just an identifier.
  if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))
    return false;

  // In protobuf, "enum" can be used as a field name.
  if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal))
    return false;

  if (IsCpp) {
    // Eat up enum class ...
    if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
      nextToken();
    while (FormatTok->is(tok::l_square))
      if (!handleCppAttributes())
        return false;
  }

  while (FormatTok->Tok.getIdentifierInfo() ||
         FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
                            tok::greater, tok::comma, tok::question,
                            tok::l_square)) {
    if (FormatTok->is(tok::colon))
      FormatTok->setFinalizedType(TT_EnumUnderlyingTypeColon);
    if (Style.isVerilog()) {
      FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);
      nextToken();
      // In Verilog the base type can have dimensions.
      while (FormatTok->is(tok::l_square))
        parseSquare();
    } else {
      nextToken();
    }
    // We can have macros or attributes in between 'enum' and the enum name.
    if (FormatTok->is(tok::l_paren))
      parseParens();
    if (FormatTok->is(tok::identifier)) {
      nextToken();
      // If there are two identifiers in a row, this is likely an elaborate
      // return type. In Java, this can be "implements", etc.
      if (IsCpp && FormatTok->is(tok::identifier))
        return false;
    }
  }

  // Just a declaration or something is wrong.
  if (FormatTok->isNot(tok::l_brace))
    return true;
  FormatTok->setFinalizedType(TT_EnumLBrace);
  FormatTok->setBlockKind(BK_Block);

  if (Style.isJava()) {
    // Java enums are different.
    parseJavaEnumBody();
    return true;
  }
  if (Style.Language == FormatStyle::LK_Proto) {
    parseBlock(/*MustBeDeclaration=*/true);
    return true;
  }

  const bool ManageWhitesmithsBraces =
      Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;

  if (!Style.AllowShortEnumsOnASingleLine &&
      ShouldBreakBeforeBrace(Style, InitialToken,
                             Tokens->peekNextToken()->is(tok::r_brace))) {
    addUnwrappedLine();

    // If we're in Whitesmiths mode, indent the brace if we're not indenting
    // the whole block.
    if (ManageWhitesmithsBraces)
      ++Line->Level;
  }
  // Parse enum body.
  nextToken();
  if (!Style.AllowShortEnumsOnASingleLine) {
    addUnwrappedLine();
    if (!ManageWhitesmithsBraces)
      ++Line->Level;
  }
  const auto OpeningLineIndex = CurrentLines->empty()
                                    ? UnwrappedLine::kInvalidIndex
                                    : CurrentLines->size() - 1;
  bool HasError = !parseBracedList(/*IsAngleBracket=*/false, /*IsEnum=*/true);
  if (!Style.AllowShortEnumsOnASingleLine && !ManageWhitesmithsBraces)
    --Line->Level;
  if (HasError) {
    if (FormatTok->is(tok::semi))
      nextToken();
    addUnwrappedLine();
  }
  setPreviousRBraceType(TT_EnumRBrace);
  if (ManageWhitesmithsBraces)
    Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
  return true;

  // There is no addUnwrappedLine() here so that we fall through to parsing a
  // structural element afterwards. Thus, in "enum A {} n, m;",
  // "} n, m;" will end up in one unwrapped line.
}

bool UnwrappedLineParser::parseStructLike() {
  // parseRecord falls through and does not yet add an unwrapped line as a
  // record declaration or definition can start a structural element.
  parseRecord();
  // This does not apply to Java, JavaScript and C#.
  if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) {
    if (FormatTok->is(tok::semi))
      nextToken();
    addUnwrappedLine();
    return true;
  }
  return false;
}

namespace {
// A class used to set and restore the Token position when peeking
// ahead in the token source.
class ScopedTokenPosition {
  unsigned StoredPosition;
  FormatTokenSource *Tokens;

public:
  ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {
    assert(Tokens && "Tokens expected to not be null");
    StoredPosition = Tokens->getPosition();
  }

  ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }
};
} // namespace

// Look to see if we have [[ by looking ahead, if
// its not then rewind to the original position.
bool UnwrappedLineParser::tryToParseSimpleAttribute() {
  ScopedTokenPosition AutoPosition(Tokens);
  FormatToken *Tok = Tokens->getNextToken();
  // We already read the first [ check for the second.
  if (Tok->isNot(tok::l_square))
    return false;
  // Double check that the attribute is just something
  // fairly simple.
  while (Tok->isNot(tok::eof)) {
    if (Tok->is(tok::r_square))
      break;
    Tok = Tokens->getNextToken();
  }
  if (Tok->is(tok::eof))
    return false;
  Tok = Tokens->getNextToken();
  if (Tok->isNot(tok::r_square))
    return false;
  Tok = Tokens->getNextToken();
  if (Tok->is(tok::semi))
    return false;
  return true;
}

void UnwrappedLineParser::parseJavaEnumBody() {
  assert(FormatTok->is(tok::l_brace));
  const FormatToken *OpeningBrace = FormatTok;

  // Determine whether the enum is simple, i.e. does not have a semicolon or
  // constants with class bodies. Simple enums can be formatted like braced
  // lists, contracted to a single line, etc.
  unsigned StoredPosition = Tokens->getPosition();
  bool IsSimple = true;
  FormatToken *Tok = Tokens->getNextToken();
  while (Tok->isNot(tok::eof)) {
    if (Tok->is(tok::r_brace))
      break;
    if (Tok->isOneOf(tok::l_brace, tok::semi)) {
      IsSimple = false;
      break;
    }
    // FIXME: This will also mark enums with braces in the arguments to enum
    // constants as "not simple". This is probably fine in practice, though.
    Tok = Tokens->getNextToken();
  }
  FormatTok = Tokens->setPosition(StoredPosition);

  if (IsSimple) {
    nextToken();
    parseBracedList();
    addUnwrappedLine();
    return;
  }

  // Parse the body of a more complex enum.
  // First add a line for everything up to the "{".
  nextToken();
  addUnwrappedLine();
  ++Line->Level;

  // Parse the enum constants.
  while (!eof()) {
    if (FormatTok->is(tok::l_brace)) {
      // Parse the constant's class body.
      parseBlock(/*MustBeDeclaration=*/true, /*AddLevels=*/1u,
                 /*MunchSemi=*/false);
    } else if (FormatTok->is(tok::l_paren)) {
      parseParens();
    } else if (FormatTok->is(tok::comma)) {
      nextToken();
      addUnwrappedLine();
    } else if (FormatTok->is(tok::semi)) {
      nextToken();
      addUnwrappedLine();
      break;
    } else if (FormatTok->is(tok::r_brace)) {
      addUnwrappedLine();
      break;
    } else {
      nextToken();
    }
  }

  // Parse the class body after the enum's ";" if any.
  parseLevel(OpeningBrace);
  nextToken();
  --Line->Level;
  addUnwrappedLine();
}

void UnwrappedLineParser::parseRecord(bool ParseAsExpr, bool IsJavaRecord) {
  assert(!IsJavaRecord || FormatTok->is(Keywords.kw_record));
  const FormatToken &InitialToken = *FormatTok;
  nextToken();

  FormatToken *ClassName =
      IsJavaRecord && FormatTok->is(tok::identifier) ? FormatTok : nullptr;
  bool IsDerived = false;
  auto IsNonMacroIdentifier = [](const FormatToken *Tok) {
    return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper();
  };
  // JavaScript/TypeScript supports anonymous classes like:
  // a = class extends foo { }
  bool JSPastExtendsOrImplements = false;
  // The actual identifier can be a nested name specifier, and in macros
  // it is often token-pasted.
  // An [[attribute]] can be before the identifier.
  while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
                            tok::kw_alignas, tok::l_square) ||
         FormatTok->isAttribute() ||
         ((Style.isJava() || Style.isJavaScript()) &&
          FormatTok->isOneOf(tok::period, tok::comma))) {
    if (Style.isJavaScript() &&
        FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
      JSPastExtendsOrImplements = true;
      // JavaScript/TypeScript supports inline object types in
      // extends/implements positions:
      //     class Foo implements {bar: number} { }
      nextToken();
      if (FormatTok->is(tok::l_brace)) {
        tryToParseBracedList();
        continue;
      }
    }
    if (FormatTok->is(tok::l_square) && handleCppAttributes())
      continue;
    auto *Previous = FormatTok;
    nextToken();
    switch (FormatTok->Tok.getKind()) {
    case tok::l_paren:
      // We can have macros in between 'class' and the class name.
      if (IsJavaRecord || !IsNonMacroIdentifier(Previous) ||
          // e.g. `struct macro(a) S { int i; };`
          Previous->Previous == &InitialToken) {
        parseParens();
      }
      break;
    case tok::coloncolon:
    case tok::hashhash:
      break;
    default:
      if (JSPastExtendsOrImplements || ClassName ||
          Previous->isNot(tok::identifier) || Previous->is(TT_AttributeMacro)) {
        break;
      }
      if (const auto Text = Previous->TokenText;
          Text.size() == 1 || Text != Text.upper()) {
        ClassName = Previous;
      }
    }
  }

  auto IsListInitialization = [&] {
    if (!ClassName || IsDerived || JSPastExtendsOrImplements)
      return false;
    assert(FormatTok->is(tok::l_brace));
    const auto *Prev = FormatTok->getPreviousNonComment();
    assert(Prev);
    return Prev != ClassName && Prev->is(tok::identifier) &&
           Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
  };

  if (FormatTok->isOneOf(tok::colon, tok::less)) {
    int AngleNestingLevel = 0;
    do {
      if (FormatTok->is(tok::less))
        ++AngleNestingLevel;
      else if (FormatTok->is(tok::greater))
        --AngleNestingLevel;

      if (AngleNestingLevel == 0) {
        if (FormatTok->is(tok::colon)) {
          IsDerived = true;
        } else if (!IsDerived && FormatTok->is(tok::identifier) &&
                   FormatTok->Previous->is(tok::coloncolon)) {
          ClassName = FormatTok;
        } else if (FormatTok->is(tok::l_paren) &&
                   IsNonMacroIdentifier(FormatTok->Previous)) {
          break;
        }
      }
      if (FormatTok->is(tok::l_brace)) {
        if (AngleNestingLevel == 0 && IsListInitialization())
          return;
        calculateBraceTypes(/*ExpectClassBody=*/true);
        if (!tryToParseBracedList())
          break;
      }
      if (FormatTok->is(tok::l_square)) {
        FormatToken *Previous = FormatTok->Previous;
        if (!Previous || (Previous->isNot(tok::r_paren) &&
                          !Previous->isTypeOrIdentifier(LangOpts))) {
          // Don't try parsing a lambda if we had a closing parenthesis before,
          // it was probably a pointer to an array: int (*)[].
          if (!tryToParseLambda())
            continue;
        } else {
          parseSquare();
          continue;
        }
      }
      if (FormatTok->is(tok::semi))
        return;
      if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) {
        addUnwrappedLine();
        nextToken();
        parseCSharpGenericTypeConstraint();
        break;
      }
      nextToken();
    } while (!eof());
  }

  auto GetBraceTypes =
      [](const FormatToken &RecordTok) -> std::pair<TokenType, TokenType> {
    switch (RecordTok.Tok.getKind()) {
    case tok::kw_class:
      return {TT_ClassLBrace, TT_ClassRBrace};
    case tok::kw_struct:
      return {TT_StructLBrace, TT_StructRBrace};
    case tok::kw_union:
      return {TT_UnionLBrace, TT_UnionRBrace};
    default:
      // Useful for e.g. interface.
      return {TT_RecordLBrace, TT_RecordRBrace};
    }
  };
  if (FormatTok->is(tok::l_brace)) {
    if (IsListInitialization())
      return;
    if (ClassName)
      ClassName->setFinalizedType(TT_ClassHeadName);
    auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
    FormatTok->setFinalizedType(OpenBraceType);
    if (ParseAsExpr) {
      parseChildBlock();
    } else {
      if (ShouldBreakBeforeBrace(Style, InitialToken,
                                 Tokens->peekNextToken()->is(tok::r_brace),
                                 IsJavaRecord)) {
        addUnwrappedLine();
      }

      unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u;
      parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/false);
    }
    setPreviousRBraceType(ClosingBraceType);
  }
  // There is no addUnwrappedLine() here so that we fall through to parsing a
  // structural element afterwards. Thus, in "class A {} n, m;",
  // "} n, m;" will end up in one unwrapped line.
}

void UnwrappedLineParser::parseObjCMethod() {
  assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&
         "'(' or identifier expected.");
  do {
    if (FormatTok->is(tok::semi)) {
      nextToken();
      addUnwrappedLine();
      return;
    } else if (FormatTok->is(tok::l_brace)) {
      if (Style.BraceWrapping.AfterFunction)
        addUnwrappedLine();
      parseBlock();
      addUnwrappedLine();
      return;
    } else {
      nextToken();
    }
  } while (!eof());
}

void UnwrappedLineParser::parseObjCProtocolList() {
  assert(FormatTok->is(tok::less) && "'<' expected.");
  do {
    nextToken();
    // Early exit in case someone forgot a close angle.
    if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
      return;
  } while (!eof() && FormatTok->isNot(tok::greater));
  nextToken(); // Skip '>'.
}

void UnwrappedLineParser::parseObjCUntilAtEnd() {
  do {
    if (FormatTok->is(tok::objc_end)) {
      nextToken();
      addUnwrappedLine();
      break;
    }
    if (FormatTok->is(tok::l_brace)) {
      parseBlock();
      // In ObjC interfaces, nothing should be following the "}".
      addUnwrappedLine();
    } else if (FormatTok->is(tok::r_brace)) {
      // Ignore stray "}". parseStructuralElement doesn't consume them.
      nextToken();
      addUnwrappedLine();
    } else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
      nextToken();
      if (FormatTok->isOneOf(tok::l_paren, tok::identifier))
        parseObjCMethod();
    } else {
      parseStructuralElement();
    }
  } while (!eof());
}

void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
  assert(FormatTok->isOneOf(tok::objc_interface, tok::objc_implementation));
  nextToken();
  nextToken(); // interface name

  // @interface can be followed by a lightweight generic
  // specialization list, then either a base class or a category.
  if (FormatTok->is(tok::less))
    parseObjCLightweightGenerics();
  if (FormatTok->is(tok::colon)) {
    nextToken();
    nextToken(); // base class name
    // The base class can also have lightweight generics applied to it.
    if (FormatTok->is(tok::less))
      parseObjCLightweightGenerics();
  } else if (FormatTok->is(tok::l_paren)) {
    // Skip category, if present.
    parseParens();
  }

  if (FormatTok->is(tok::less))
    parseObjCProtocolList();

  if (FormatTok->is(tok::l_brace)) {
    if (Style.BraceWrapping.AfterObjCDeclaration)
      addUnwrappedLine();
    parseBlock(/*MustBeDeclaration=*/true);
  }

  // With instance variables, this puts '}' on its own line.  Without instance
  // variables, this ends the @interface line.
  addUnwrappedLine();

  parseObjCUntilAtEnd();
}

void UnwrappedLineParser::parseObjCLightweightGenerics() {
  assert(FormatTok->is(tok::less));
  // Unlike protocol lists, generic parameterizations support
  // nested angles:
  //
  // @interface Foo<ValueType : id <NSCopying, NSSecureCoding>> :
  //     NSObject <NSCopying, NSSecureCoding>
  //
  // so we need to count how many open angles we have left.
  unsigned NumOpenAngles = 1;
  do {
    nextToken();
    // Early exit in case someone forgot a close angle.
    if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::objc_end))
      break;
    if (FormatTok->is(tok::less)) {
      ++NumOpenAngles;
    } else if (FormatTok->is(tok::greater)) {
      assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative");
      --NumOpenAngles;
    }
  } while (!eof() && NumOpenAngles != 0);
  nextToken(); // Skip '>'.
}

// Returns true for the declaration/definition form of @protocol,
// false for the expression form.
bool UnwrappedLineParser::parseObjCProtocol() {
  assert(FormatTok->is(tok::objc_protocol));
  nextToken();

  if (FormatTok->is(tok::l_paren)) {
    // The expression form of @protocol, e.g. "Protocol* p = @protocol(foo);".
    return false;
  }

  // The definition/declaration form,
  // @protocol Foo
  // - (int)someMethod;
  // @end

  nextToken(); // protocol name

  if (FormatTok->is(tok::less))
    parseObjCProtocolList();

  // Check for protocol declaration.
  if (FormatTok->is(tok::semi)) {
    nextToken();
    addUnwrappedLine();
    return true;
  }

  addUnwrappedLine();
  parseObjCUntilAtEnd();
  return true;
}

void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
  bool IsImport = FormatTok->is(Keywords.kw_import);
  assert(IsImport || FormatTok->is(tok::kw_export));
  nextToken();

  // Consume the "default" in "export default class/function".
  if (FormatTok->is(tok::kw_default))
    nextToken();

  // Consume "async function", "function" and "default function", so that these
  // get parsed as free-standing JS functions, i.e. do not require a trailing
  // semicolon.
  if (FormatTok->is(Keywords.kw_async))
    nextToken();
  if (FormatTok->is(Keywords.kw_function)) {
    nextToken();
    return;
  }

  // For imports, `export *`, `export {...}`, consume the rest of the line up
  // to the terminating `;`. For everything else, just return and continue
  // parsing the structural element, i.e. the declaration or expression for
  // `export default`.
  if (!IsImport && FormatTok->isNoneOf(tok::l_brace, tok::star) &&
      !FormatTok->isStringLiteral() &&
      !(FormatTok->is(Keywords.kw_type) &&
        Tokens->peekNextToken()->isOneOf(tok::l_brace, tok::star))) {
    return;
  }

  while (!eof()) {
    if (FormatTok->is(tok::semi))
      return;
    if (Line->Tokens.empty()) {
      // Common issue: Automatic Semicolon Insertion wrapped the line, so the
      // import statement should terminate.
      return;
    }
    if (FormatTok->is(tok::l_brace)) {
      FormatTok->setBlockKind(BK_Block);
      nextToken();
      parseBracedList();
    } else {
      nextToken();
    }
  }
}

void UnwrappedLineParser::parseStatementMacro() {
  nextToken();
  if (FormatTok->is(tok::l_paren))
    parseParens();
  if (FormatTok->is(tok::semi))
    nextToken();
  addUnwrappedLine();
}

void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
  // consume things like a::`b.c[d:e] or a::*
  while (true) {
    if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,
                           tok::coloncolon, tok::hash) ||
        Keywords.isVerilogIdentifier(*FormatTok)) {
      nextToken();
    } else if (FormatTok->is(tok::l_square)) {
      parseSquare();
    } else {
      break;
    }
  }
}

void UnwrappedLineParser::parseVerilogSensitivityList() {
  if (FormatTok->isNot(tok::at))
    return;
  nextToken();
  // A block event expression has 2 at signs.
  if (FormatTok->is(tok::at))
    nextToken();
  switch (FormatTok->Tok.getKind()) {
  case tok::star:
    nextToken();
    break;
  case tok::l_paren:
    parseParens();
    break;
  default:
    parseVerilogHierarchyIdentifier();
    break;
  }
}

unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
  unsigned AddLevels = 0;

  if (FormatTok->is(Keywords.kw_clocking)) {
    nextToken();
    if (Keywords.isVerilogIdentifier(*FormatTok))
      nextToken();
    parseVerilogSensitivityList();
    if (FormatTok->is(tok::semi))
      nextToken();
  } else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
                                Keywords.kw_casez, Keywords.kw_randcase,
                                Keywords.kw_randsequence)) {
    if (Style.IndentCaseLabels)
      AddLevels++;
    nextToken();
    if (FormatTok->is(tok::l_paren)) {
      FormatTok->setFinalizedType(TT_ConditionLParen);
      parseParens();
    }
    if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))
      nextToken();
    // The case header has no semicolon.
  } else {
    // "module" etc.
    nextToken();
    // all the words like the name of the module and specifiers like
    // "automatic" and the width of function return type
    while (true) {
      if (FormatTok->is(tok::l_square)) {
        auto Prev = FormatTok->getPreviousNonComment();
        if (Prev && Keywords.isVerilogIdentifier(*Prev))
          Prev->setFinalizedType(TT_VerilogDimensionedTypeName);
        parseSquare();
      } else if (Keywords.isVerilogIdentifier(*FormatTok) ||
                 FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon,
                                    Keywords.kw_automatic, tok::kw_static)) {
        nextToken();
      } else {
        break;
      }
    }

    auto NewLine = [this]() {
      addUnwrappedLine();
      Line->IsContinuation = true;
    };

    // package imports
    while (FormatTok->is(Keywords.kw_import)) {
      NewLine();
      nextToken();
      parseVerilogHierarchyIdentifier();
      if (FormatTok->is(tok::semi))
        nextToken();
    }

    // parameters and ports
    if (FormatTok->is(Keywords.kw_verilogHash)) {
      NewLine();
      nextToken();
      if (FormatTok->is(tok::l_paren)) {
        FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
        parseParens();
      }
    }
    if (FormatTok->is(tok::l_paren)) {
      NewLine();
      FormatTok->setFinalizedType(TT_VerilogMultiLineListLParen);
      parseParens();
    }

    // extends and implements
    if (FormatTok->is(Keywords.kw_extends)) {
      NewLine();
      nextToken();
      parseVerilogHierarchyIdentifier();
      if (FormatTok->is(tok::l_paren))
        parseParens();
    }
    if (FormatTok->is(Keywords.kw_implements)) {
      NewLine();
      do {
        nextToken();
        parseVerilogHierarchyIdentifier();
      } while (FormatTok->is(tok::comma));
    }

    // Coverage event for cover groups.
    if (FormatTok->is(tok::at)) {
      NewLine();
      parseVerilogSensitivityList();
    }

    if (FormatTok->is(tok::semi))
      nextToken(/*LevelDifference=*/1);
    addUnwrappedLine();
  }

  return AddLevels;
}

void UnwrappedLineParser::parseVerilogTable() {
  assert(FormatTok->is(Keywords.kw_table));
  nextToken(/*LevelDifference=*/1);
  addUnwrappedLine();

  auto InitialLevel = Line->Level++;
  while (!eof() && !Keywords.isVerilogEnd(*FormatTok)) {
    FormatToken *Tok = FormatTok;
    nextToken();
    if (Tok->is(tok::semi))
      addUnwrappedLine();
    else if (Tok->isOneOf(tok::star, tok::colon, tok::question, tok::minus))
      Tok->setFinalizedType(TT_VerilogTableItem);
  }
  Line->Level = InitialLevel;
  nextToken(/*LevelDifference=*/-1);
  addUnwrappedLine();
}

void UnwrappedLineParser::parseVerilogCaseLabel() {
  // The label will get unindented in AnnotatingParser. If there are no leading
  // spaces, indent the rest here so that things inside the block will be
  // indented relative to things outside. We don't use parseLabel because we
  // don't know whether this colon is a label or a ternary expression at this
  // point.
  auto OrigLevel = Line->Level;
  auto FirstLine = CurrentLines->size();
  if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1))
    ++Line->Level;
  else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))
    --Line->Level;
  parseStructuralElement();
  // Restore the indentation in both the new line and the line that has the
  // label.
  if (CurrentLines->size() > FirstLine)
    (*CurrentLines)[FirstLine].Level = OrigLevel;
  Line->Level = OrigLevel;
}

void UnwrappedLineParser::parseVerilogExtern() {
  assert(
      FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import));
  nextToken();
  // "DPI-C"
  if (FormatTok->is(tok::string_literal))
    nextToken();
  skipVerilogQualifiers();
  if (Keywords.isVerilogIdentifier(*FormatTok))
    nextToken();
  if (FormatTok->is(tok::equal))
    nextToken();
  if (Keywords.isVerilogHierarchy(*FormatTok))
    parseVerilogHierarchyHeader();
}

void UnwrappedLineParser::skipVerilogQualifiers() {
  while (FormatTok->isOneOf(tok::kw_protected, tok::kw_virtual, tok::kw_static,
                            Keywords.kw_rand, Keywords.kw_context,
                            Keywords.kw_pure, Keywords.kw_randc,
                            Keywords.kw_local)) {
    nextToken();
  }
}

bool UnwrappedLineParser::containsExpansion(const UnwrappedLine &Line) const {
  for (const auto &N : Line.Tokens) {
    if (N.Tok->MacroCtx)
      return true;
    for (const UnwrappedLine &Child : N.Children)
      if (containsExpansion(Child))
        return true;
  }
  return false;
}

void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
  if (Line->Tokens.empty())
    return;
  LLVM_DEBUG({
    if (!parsingPPDirective()) {
      llvm::dbgs() << "Adding unwrapped line:\n";
      printDebugInfo(*Line);
    }
  });

  // If this line closes a block when in Whitesmiths mode, remember that
  // information so that the level can be decreased after the line is added.
  // This has to happen after the addition of the line since the line itself
  // needs to be indented.
  bool ClosesWhitesmithsBlock =
      Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
      Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;

  // If the current line was expanded from a macro call, we use it to
  // reconstruct an unwrapped line from the structure of the expanded unwrapped
  // line and the unexpanded token stream.
  if (!parsingPPDirective() && !InExpansion && containsExpansion(*Line)) {
    if (!Reconstruct)
      Reconstruct.emplace(Line->Level, Unexpanded);
    Reconstruct->addLine(*Line);

    // While the reconstructed unexpanded lines are stored in the normal
    // flow of lines, the expanded lines are stored on the side to be analyzed
    // in an extra step.
    CurrentExpandedLines.push_back(std::move(*Line));

    if (Reconstruct->finished()) {
      UnwrappedLine Reconstructed = std::move(*Reconstruct).takeResult();
      assert(!Reconstructed.Tokens.empty() &&
             "Reconstructed must at least contain the macro identifier.");
      assert(!parsingPPDirective());
      LLVM_DEBUG({
        llvm::dbgs() << "Adding unexpanded line:\n";
        printDebugInfo(Reconstructed);
      });
      ExpandedLines[Reconstructed.Tokens.begin()->Tok] = CurrentExpandedLines;
      Lines.push_back(std::move(Reconstructed));
      CurrentExpandedLines.clear();
      Reconstruct.reset();
    }
  } else {
    // At the top level we only get here when no unexpansion is going on, or
    // when conditional formatting led to unfinished macro reconstructions.
    assert(!Reconstruct || (CurrentLines != &Lines) || !PPStack.empty());
    CurrentLines->push_back(std::move(*Line));
  }
  Line->Tokens.clear();
  Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
  Line->FirstStartColumn = 0;
  Line->IsContinuation = false;
  Line->SeenDecltypeAuto = false;
  Line->IsModuleOrImportDecl = false;

  if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
    --Line->Level;
  if (!parsingPPDirective() && !PreprocessorDirectives.empty()) {
    CurrentLines->append(
        std::make_move_iterator(PreprocessorDirectives.begin()),
        std::make_move_iterator(PreprocessorDirectives.end()));
    PreprocessorDirectives.clear();
  }
  // Disconnect the current token from the last token on the previous line.
  FormatTok->Previous = nullptr;
}

bool UnwrappedLineParser::eof() const { return FormatTok->is(tok::eof); }

bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
  return (Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
         FormatTok.NewlinesBefore > 0;
}

// Checks if \p FormatTok is a line comment that continues the line comment
// section on \p Line.
static bool
continuesLineCommentSection(const FormatToken &FormatTok,
                            const UnwrappedLine &Line, const FormatStyle &Style,
                            const llvm::Regex &CommentPragmasRegex) {
  if (Line.Tokens.empty() || Style.ReflowComments != FormatStyle::RCS_Always)
    return false;

  StringRef IndentContent = FormatTok.TokenText;
  if (FormatTok.TokenText.starts_with("//") ||
      FormatTok.TokenText.starts_with("/*")) {
    IndentContent = FormatTok.TokenText.substr(2);
  }
  if (CommentPragmasRegex.match(IndentContent))
    return false;

  // If Line starts with a line comment, then FormatTok continues the comment
  // section if its original column is greater or equal to the original start
  // column of the line.
  //
  // Define the min column token of a line as follows: if a line ends in '{' or
  // contains a '{' followed by a line comment, then the min column token is
  // that '{'. Otherwise, the min column token of the line is the first token of
  // the line.
  //
  // If Line starts with a token other than a line comment, then FormatTok
  // continues the comment section if its original column is greater than the
  // original start column of the min column token of the line.
  //
  // For example, the second line comment continues the first in these cases:
  //
  // // first line
  // // second line
  //
  // and:
  //
  // // first line
  //  // second line
  //
  // and:
  //
  // int i; // first line
  //  // second line
  //
  // and:
  //
  // do { // first line
  //      // second line
  //   int i;
  // } while (true);
  //
  // and:
  //
  // enum {
  //   a, // first line
  //    // second line
  //   b
  // };
  //
  // The second line comment doesn't continue the first in these cases:
  //
  //   // first line
  //  // second line
  //
  // and:
  //
  // int i; // first line
  // // second line
  //
  // and:
  //
  // do { // first line
  //   // second line
  //   int i;
  // } while (true);
  //
  // and:
  //
  // enum {
  //   a, // first line
  //   // second line
  // };
  const FormatToken *MinColumnToken = Line.Tokens.front().Tok;

  // Scan for '{//'. If found, use the column of '{' as a min column for line
  // comment section continuation.
  const FormatToken *PreviousToken = nullptr;
  for (const UnwrappedLineNode &Node : Line.Tokens) {
    if (PreviousToken && PreviousToken->is(tok::l_brace) &&
        isLineComment(*Node.Tok)) {
      MinColumnToken = PreviousToken;
      break;
    }
    PreviousToken = Node.Tok;

    // Grab the last newline preceding a token in this unwrapped line.
    if (Node.Tok->NewlinesBefore > 0)
      MinColumnToken = Node.Tok;
  }
  if (PreviousToken && PreviousToken->is(tok::l_brace))
    MinColumnToken = PreviousToken;

  return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok,
                              MinColumnToken);
}

void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
  bool JustComments = Line->Tokens.empty();
  for (FormatToken *Tok : CommentsBeforeNextToken) {
    // Line comments that belong to the same line comment section are put on the
    // same line since later we might want to reflow content between them.
    // Additional fine-grained breaking of line comment sections is controlled
    // by the class BreakableLineCommentSection in case it is desirable to keep
    // several line comment sections in the same unwrapped line.
    //
    // FIXME: Consider putting separate line comment sections as children to the
    // unwrapped line instead.
    Tok->ContinuesLineCommentSection =
        continuesLineCommentSection(*Tok, *Line, Style, CommentPragmasRegex);
    if (isOnNewLine(*Tok) && JustComments && !Tok->ContinuesLineCommentSection)
      addUnwrappedLine();
    pushToken(Tok);
  }
  if (NewlineBeforeNext && JustComments)
    addUnwrappedLine();
  CommentsBeforeNextToken.clear();
}

void UnwrappedLineParser::nextToken(int LevelDifference) {
  if (eof())
    return;
  flushComments(isOnNewLine(*FormatTok));
  pushToken(FormatTok);
  FormatToken *Previous = FormatTok;
  if (!Style.isJavaScript())
    readToken(LevelDifference);
  else
    readTokenWithJavaScriptASI();
  FormatTok->Previous = Previous;
  if (Style.isVerilog()) {
    // Blocks in Verilog can have `begin` and `end` instead of braces.  For
    // keywords like `begin`, we can't treat them the same as left braces
    // because some contexts require one of them.  For example structs use
    // braces and if blocks use keywords, and a left brace can occur in an if
    // statement, but it is not a block.  For keywords like `end`, we simply
    // treat them the same as right braces.
    if (Keywords.isVerilogEnd(*FormatTok))
      FormatTok->Tok.setKind(tok::r_brace);
  }
}

void UnwrappedLineParser::distributeComments(
    const ArrayRef<FormatToken *> &Comments, const FormatToken *NextTok) {
  // Whether or not a line comment token continues a line is controlled by
  // the method continuesLineCommentSection, with the following caveat:
  //
  // Define a trail of Comments to be a nonempty proper postfix of Comments such
  // that each comment line from the trail is aligned with the next token, if
  // the next token exists. If a trail exists, the beginning of the maximal
  // trail is marked as a start of a new comment section.
  //
  // For example in this code:
  //
  // int a; // line about a
  //   // line 1 about b
  //   // line 2 about b
  //   int b;
  //
  // the two lines about b form a maximal trail, so there are two sections, the
  // first one consisting of the single comment "// line about a" and the
  // second one consisting of the next two comments.
  if (Comments.empty())
    return;
  bool ShouldPushCommentsInCurrentLine = true;
  bool HasTrailAlignedWithNextToken = false;
  unsigned StartOfTrailAlignedWithNextToken = 0;
  if (NextTok) {
    // We are skipping the first element intentionally.
    for (unsigned i = Comments.size() - 1; i > 0; --i) {
      if (Comments[i]->OriginalColumn == NextTok->OriginalColumn) {
        HasTrailAlignedWithNextToken = true;
        StartOfTrailAlignedWithNextToken = i;
      }
    }
  }
  for (unsigned i = 0, e = Comments.size(); i < e; ++i) {
    FormatToken *FormatTok = Comments[i];
    if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
      FormatTok->ContinuesLineCommentSection = false;
    } else {
      FormatTok->ContinuesLineCommentSection = continuesLineCommentSection(
          *FormatTok, *Line, Style, CommentPragmasRegex);
    }
    if (!FormatTok->ContinuesLineCommentSection &&
        (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
      ShouldPushCommentsInCurrentLine = false;
    }
    if (ShouldPushCommentsInCurrentLine)
      pushToken(FormatTok);
    else
      CommentsBeforeNextToken.push_back(FormatTok);
  }
}

void UnwrappedLineParser::readToken(int LevelDifference) {
  SmallVector<FormatToken *, 1> Comments;
  bool PreviousWasComment = false;
  bool FirstNonCommentOnLine = false;
  do {
    FormatTok = Tokens->getNextToken();
    assert(FormatTok);
    while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,
                              TT_ConflictAlternative)) {
      if (FormatTok->is(TT_ConflictStart))
        conditionalCompilationStart(/*Unreachable=*/false);
      else if (FormatTok->is(TT_ConflictAlternative))
        conditionalCompilationAlternative();
      else if (FormatTok->is(TT_ConflictEnd))
        conditionalCompilationEnd();
      FormatTok = Tokens->getNextToken();
      FormatTok->MustBreakBefore = true;
      FormatTok->MustBreakBeforeFinalized = true;
    }

    auto IsFirstNonCommentOnLine = [](bool FirstNonCommentOnLine,
                                      const FormatToken &Tok,
                                      bool PreviousWasComment) {
      auto IsFirstOnLine = [](const FormatToken &Tok) {
        return Tok.HasUnescapedNewline || Tok.IsFirst;
      };

      // Consider preprocessor directives preceded by block comments as first
      // on line.
      if (PreviousWasComment)
        return FirstNonCommentOnLine || IsFirstOnLine(Tok);
      return IsFirstOnLine(Tok);
    };

    FirstNonCommentOnLine = IsFirstNonCommentOnLine(
        FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
    PreviousWasComment = FormatTok->is(tok::comment);

    while (!Line->InPPDirective && FormatTok->is(tok::hash) &&
           FirstNonCommentOnLine) {
      // In Verilog, the backtick is used for macro invocations. In TableGen,
      // the single hash is used for the paste operator.
      const auto *Next = Tokens->peekNextToken();
      if ((Style.isVerilog() && !Keywords.isVerilogPPDirective(*Next)) ||
          (Style.isTableGen() &&
           Next->isNoneOf(tok::kw_else, tok::pp_define, tok::pp_ifdef,
                          tok::pp_ifndef, tok::pp_endif))) {
        break;
      }
      distributeComments(Comments, FormatTok);
      Comments.clear();
      // If there is an unfinished unwrapped line, we flush the preprocessor
      // directives only after that unwrapped line was finished later.
      bool SwitchToPreprocessorLines = !Line->Tokens.empty();
      ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
      assert((LevelDifference >= 0 ||
              static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
             "LevelDifference makes Line->Level negative");
      Line->Level += LevelDifference;
      // Comments stored before the preprocessor directive need to be output
      // before the preprocessor directive, at the same level as the
      // preprocessor directive, as we consider them to apply to the directive.
      if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
          PPBranchLevel > 0) {
        Line->Level += PPBranchLevel;
      }
      assert(Line->Level >= Line->UnbracedBodyLevel);
      Line->Level -= Line->UnbracedBodyLevel;
      flushComments(isOnNewLine(*FormatTok));
      const bool IsEndIf = Tokens->peekNextToken()->is(tok::pp_endif);
      parsePPDirective();
      PreviousWasComment = FormatTok->is(tok::comment);
      FirstNonCommentOnLine = IsFirstNonCommentOnLine(
          FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
      // If the #endif of a potential include guard is the last thing in the
      // file, then we found an include guard.
      if (IsEndIf && IncludeGuard == IG_Defined && PPBranchLevel == -1 &&
          getIncludeGuardState(Style.IndentPPDirectives) == IG_Inited &&
          (eof() ||
           (PreviousWasComment &&
            Tokens->peekNextToken(/*SkipComment=*/true)->is(tok::eof)))) {
        IncludeGuard = IG_Found;
      }
    }

    if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
        !Line->InPPDirective) {
      continue;
    }

    if (FormatTok->is(tok::identifier) &&
        Macros.defined(FormatTok->TokenText) &&
        // FIXME: Allow expanding macros in preprocessor directives.
        !Line->InPPDirective) {
      FormatToken *ID = FormatTok;
      unsigned Position = Tokens->getPosition();

      // To correctly parse the code, we need to replace the tokens of the macro
      // call with its expansion.
      auto PreCall = std::move(Line);
      Line.reset(new UnwrappedLine);
      bool OldInExpansion = InExpansion;
      InExpansion = true;
      // We parse the macro call into a new line.
      auto Args = parseMacroCall();
      InExpansion = OldInExpansion;
      assert(Line->Tokens.front().Tok == ID);
      // And remember the unexpanded macro call tokens.
      auto UnexpandedLine = std::move(Line);
      // Reset to the old line.
      Line = std::move(PreCall);

      LLVM_DEBUG({
        llvm::dbgs() << "Macro call: " << ID->TokenText << "(";
        if (Args) {
          llvm::dbgs() << "(";
          for (const auto &Arg : Args.value())
            for (const auto &T : Arg)
              llvm::dbgs() << T->TokenText << " ";
          llvm::dbgs() << ")";
        }
        llvm::dbgs() << "\n";
      });
      if (Macros.objectLike(ID->TokenText) && Args &&
          !Macros.hasArity(ID->TokenText, Args->size())) {
        // The macro is either
        // - object-like, but we got argumnets, or
        // - overloaded to be both object-like and function-like, but none of
        //   the function-like arities match the number of arguments.
        // Thus, expand as object-like macro.
        LLVM_DEBUG(llvm::dbgs()
                   << "Macro \"" << ID->TokenText
                   << "\" not overloaded for arity " << Args->size()
                   << "or not function-like, using object-like overload.");
        Args.reset();
        UnexpandedLine->Tokens.resize(1);
        Tokens->setPosition(Position);
        nextToken();
        assert(!Args && Macros.objectLike(ID->TokenText));
      }
      if ((!Args && Macros.objectLike(ID->TokenText)) ||
          (Args && Macros.hasArity(ID->TokenText, Args->size()))) {
        // Next, we insert the expanded tokens in the token stream at the
        // current position, and continue parsing.
        Unexpanded[ID] = std::move(UnexpandedLine);
        SmallVector<FormatToken *, 8> Expansion =
            Macros.expand(ID, std::move(Args));
        if (!Expansion.empty())
          FormatTok = Tokens->insertTokens(Expansion);

        LLVM_DEBUG({
          llvm::dbgs() << "Expanded: ";
          for (const auto &T : Expansion)
            llvm::dbgs() << T->TokenText << " ";
          llvm::dbgs() << "\n";
        });
      } else {
        LLVM_DEBUG({
          llvm::dbgs() << "Did not expand macro \"" << ID->TokenText
                       << "\", because it was used ";
          if (Args)
            llvm::dbgs() << "with " << Args->size();
          else
            llvm::dbgs() << "without";
          llvm::dbgs() << " arguments, which doesn't match any definition.\n";
        });
        Tokens->setPosition(Position);
        FormatTok = ID;
      }
    }

    if (FormatTok->isNot(tok::comment)) {
      distributeComments(Comments, FormatTok);
      Comments.clear();
      return;
    }

    Comments.push_back(FormatTok);
  } while (!eof());

  distributeComments(Comments, nullptr);
  Comments.clear();
}

namespace {
template <typename Iterator>
void pushTokens(Iterator Begin, Iterator End,
                SmallVectorImpl<FormatToken *> &Into) {
  for (auto I = Begin; I != End; ++I) {
    Into.push_back(I->Tok);
    for (const auto &Child : I->Children)
      pushTokens(Child.Tokens.begin(), Child.Tokens.end(), Into);
  }
}
} // namespace

std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
UnwrappedLineParser::parseMacroCall() {
  std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>> Args;
  assert(Line->Tokens.empty());
  nextToken();
  if (FormatTok->isNot(tok::l_paren))
    return Args;
  unsigned Position = Tokens->getPosition();
  FormatToken *Tok = FormatTok;
  nextToken();
  Args.emplace();
  auto ArgStart = std::prev(Line->Tokens.end());

  int Parens = 0;
  do {
    switch (FormatTok->Tok.getKind()) {
    case tok::l_paren:
      ++Parens;
      nextToken();
      break;
    case tok::r_paren: {
      if (Parens > 0) {
        --Parens;
        nextToken();
        break;
      }
      Args->push_back({});
      pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back());
      nextToken();
      return Args;
    }
    case tok::comma: {
      if (Parens > 0) {
        nextToken();
        break;
      }
      Args->push_back({});
      pushTokens(std::next(ArgStart), Line->Tokens.end(), Args->back());
      nextToken();
      ArgStart = std::prev(Line->Tokens.end());
      break;
    }
    default:
      nextToken();
      break;
    }
  } while (!eof());
  Line->Tokens.resize(1);
  Tokens->setPosition(Position);
  FormatTok = Tok;
  return {};
}

void UnwrappedLineParser::pushToken(FormatToken *Tok) {
  Line->Tokens.push_back(UnwrappedLineNode(Tok));
  if (AtEndOfPPLine) {
    auto &Tok = *Line->Tokens.back().Tok;
    Tok.MustBreakBefore = true;
    Tok.MustBreakBeforeFinalized = true;
    Tok.FirstAfterPPLine = true;
    AtEndOfPPLine = false;
  }
}

} // end namespace format
} // end namespace clang
