//===--- UnwrappedLineFormatter.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
//
//===----------------------------------------------------------------------===//

#include "UnwrappedLineFormatter.h"
#include "FormatToken.h"
#include "NamespaceEndCommentsFixer.h"
#include "WhitespaceManager.h"
#include "llvm/Support/Debug.h"
#include <queue>

#define DEBUG_TYPE "format-formatter"

namespace clang {
namespace format {

namespace {

bool startsExternCBlock(const AnnotatedLine &Line) {
  const FormatToken *Next = Line.First->getNextNonComment();
  const FormatToken *NextNext = Next ? Next->getNextNonComment() : nullptr;
  return Line.startsWith(tok::kw_extern) && Next && Next->isStringLiteral() &&
         NextNext && NextNext->is(tok::l_brace);
}

bool isRecordLBrace(const FormatToken &Tok) {
  return Tok.isOneOf(TT_ClassLBrace, TT_EnumLBrace, TT_RecordLBrace,
                     TT_StructLBrace, TT_UnionLBrace);
}

/// Tracks the indent level of \c AnnotatedLines across levels.
///
/// \c nextLine must be called for each \c AnnotatedLine, after which \c
/// getIndent() will return the indent for the last line \c nextLine was called
/// with.
/// If the line is not formatted (and thus the indent does not change), calling
/// \c adjustToUnmodifiedLine after the call to \c nextLine will cause
/// subsequent lines on the same level to be indented at the same level as the
/// given line.
class LevelIndentTracker {
public:
  LevelIndentTracker(const FormatStyle &Style,
                     const AdditionalKeywords &Keywords, unsigned StartLevel,
                     int AdditionalIndent)
      : Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) {
    for (unsigned i = 0; i != StartLevel; ++i)
      IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
  }

  /// Returns the indent for the current line.
  unsigned getIndent() const { return Indent; }

  /// Update the indent state given that \p Line is going to be formatted
  /// next.
  void nextLine(const AnnotatedLine &Line) {
    Offset = getIndentOffset(Line);
    // Update the indent level cache size so that we can rely on it
    // having the right size in adjustToUnmodifiedline.
    if (Line.Level >= IndentForLevel.size())
      IndentForLevel.resize(Line.Level + 1, -1);
    if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave &&
        (Line.InPPDirective || Line.Type == LT_CommentAbovePPDirective)) {
      Indent = Line.InMacroBody
                   ? (Line.Level - Line.PPLevel) * Style.IndentWidth +
                         AdditionalIndent
                   : Line.First->OriginalColumn;
    } else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
               (Line.InPPDirective ||
                (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
                 Line.Type == LT_CommentAbovePPDirective))) {
      unsigned PPIndentWidth =
          (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
      Indent = Line.InMacroBody
                   ? Line.PPLevel * PPIndentWidth +
                         (Line.Level - Line.PPLevel) * Style.IndentWidth
                   : Line.Level * PPIndentWidth;
      Indent += AdditionalIndent;
    } else {
      // When going to lower levels, forget previous higher levels so that we
      // recompute future higher levels. But don't forget them if we enter a PP
      // directive, since these do not terminate a C++ code block.
      if (!Line.InPPDirective) {
        assert(Line.Level <= IndentForLevel.size());
        IndentForLevel.resize(Line.Level + 1);
      }
      Indent = getIndent(Line.Level);
    }
    if (static_cast<int>(Indent) + Offset >= 0)
      Indent += Offset;
    if (Line.IsContinuation)
      Indent = Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth;
  }

  /// Update the level indent to adapt to the given \p Line.
  ///
  /// When a line is not formatted, we move the subsequent lines on the same
  /// level to the same indent.
  /// Note that \c nextLine must have been called before this method.
  void adjustToUnmodifiedLine(const AnnotatedLine &Line) {
    if (Line.InPPDirective || Line.IsContinuation)
      return;
    assert(Line.Level < IndentForLevel.size());
    if (Line.First->is(tok::comment) && IndentForLevel[Line.Level] != -1)
      return;
    unsigned LevelIndent = Line.First->OriginalColumn;
    if (static_cast<int>(LevelIndent) - Offset >= 0)
      LevelIndent -= Offset;
    IndentForLevel[Line.Level] = LevelIndent;
  }

private:
  /// Get the offset of the line relatively to the level.
  ///
  /// For example, 'public:' labels in classes are offset by 1 or 2
  /// characters to the left from their level.
  int getIndentOffset(const AnnotatedLine &Line) {
    if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
      return 0;
    const auto &RootToken = *Line.First;
    if (Line.Type == LT_AccessModifier ||
        RootToken.isAccessSpecifier(/*ColonRequired=*/false) ||
        RootToken.isObjCAccessSpecifier() ||
        (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
         RootToken.Next && RootToken.Next->is(tok::colon))) {
      // The AccessModifierOffset may be overridden by IndentAccessModifiers,
      // in which case we take a negative value of the IndentWidth to simulate
      // the upper indent level.
      return Style.IndentAccessModifiers ? -Style.IndentWidth
                                         : Style.AccessModifierOffset;
    }
    return 0;
  }

  /// Get the indent of \p Level from \p IndentForLevel.
  ///
  /// \p IndentForLevel must contain the indent for the level \c l
  /// at \p IndentForLevel[l], or a value < 0 if the indent for
  /// that level is unknown.
  unsigned getIndent(unsigned Level) const {
    assert(Level < IndentForLevel.size());
    if (IndentForLevel[Level] != -1)
      return IndentForLevel[Level];
    if (Level == 0)
      return 0;
    return getIndent(Level - 1) + Style.IndentWidth;
  }

  const FormatStyle &Style;
  const AdditionalKeywords &Keywords;
  const unsigned AdditionalIndent;

  /// The indent in characters for each level. It remembers the indent of
  /// previous lines (that are not PP directives) of equal or lower levels. This
  /// is used to align formatted lines to the indent of previous non-formatted
  /// lines. Think about the --lines parameter of clang-format.
  SmallVector<int> IndentForLevel;

  /// Offset of the current line relative to the indent level.
  ///
  /// For example, the 'public' keywords is often indented with a negative
  /// offset.
  int Offset = 0;

  /// The current line's indent.
  unsigned Indent = 0;
};

const FormatToken *
getMatchingNamespaceToken(const AnnotatedLine *Line,
                          const ArrayRef<AnnotatedLine *> &AnnotatedLines) {
  if (!Line->startsWith(tok::r_brace))
    return nullptr;
  size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex;
  if (StartLineIndex == UnwrappedLine::kInvalidIndex)
    return nullptr;
  assert(StartLineIndex < AnnotatedLines.size());
  return AnnotatedLines[StartLineIndex]->First->getNamespaceToken();
}

StringRef getNamespaceTokenText(const AnnotatedLine *Line) {
  const FormatToken *NamespaceToken = Line->First->getNamespaceToken();
  return NamespaceToken ? NamespaceToken->TokenText : StringRef();
}

StringRef
getMatchingNamespaceTokenText(const AnnotatedLine *Line,
                              const ArrayRef<AnnotatedLine *> &AnnotatedLines) {
  const FormatToken *NamespaceToken =
      getMatchingNamespaceToken(Line, AnnotatedLines);
  return NamespaceToken ? NamespaceToken->TokenText : StringRef();
}

class LineJoiner {
public:
  LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords,
             const SmallVectorImpl<AnnotatedLine *> &Lines)
      : Style(Style), Keywords(Keywords), End(Lines.end()), Next(Lines.begin()),
        AnnotatedLines(Lines) {}

  /// Returns the next line, merging multiple lines into one if possible.
  const AnnotatedLine *getNextMergedLine(bool DryRun,
                                         LevelIndentTracker &IndentTracker) {
    if (Next == End)
      return nullptr;
    const AnnotatedLine *Current = *Next;
    IndentTracker.nextLine(*Current);
    unsigned MergedLines = tryFitMultipleLinesInOne(IndentTracker, Next, End);
    if (MergedLines > 0 && Style.ColumnLimit == 0) {
      // Disallow line merging if there is a break at the start of one of the
      // input lines.
      for (unsigned i = 0; i < MergedLines; ++i)
        if (Next[i + 1]->First->NewlinesBefore > 0)
          MergedLines = 0;
    }
    if (!DryRun)
      for (unsigned i = 0; i < MergedLines; ++i)
        join(*Next[0], *Next[i + 1]);
    Next = Next + MergedLines + 1;
    return Current;
  }

private:
  /// Calculates how many lines can be merged into 1 starting at \p I.
  unsigned
  tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
                           ArrayRef<AnnotatedLine *>::const_iterator I,
                           ArrayRef<AnnotatedLine *>::const_iterator E) {
    // Can't join the last line with anything.
    if (I + 1 == E)
      return 0;
    // We can never merge stuff if there are trailing line comments.
    const AnnotatedLine *TheLine = *I;
    if (TheLine->Last->is(TT_LineComment))
      return 0;
    const auto &NextLine = *I[1];
    if (NextLine.Type == LT_Invalid || NextLine.First->MustBreakBefore)
      return 0;
    if (TheLine->InPPDirective &&
        (!NextLine.InPPDirective || NextLine.First->HasUnescapedNewline)) {
      return 0;
    }

    const auto Indent = IndentTracker.getIndent();
    if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)
      return 0;

    unsigned Limit =
        Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent;
    // If we already exceed the column limit, we set 'Limit' to 0. The different
    // tryMerge..() functions can then decide whether to still do merging.
    Limit = TheLine->Last->TotalLength > Limit
                ? 0
                : Limit - TheLine->Last->TotalLength;

    if (TheLine->Last->is(TT_FunctionLBrace) &&
        TheLine->First == TheLine->Last) {
      const bool EmptyFunctionBody = NextLine.First->is(tok::r_brace);
      if ((EmptyFunctionBody && !Style.BraceWrapping.SplitEmptyFunction) ||
          (!EmptyFunctionBody &&
           Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always)) {
        return tryMergeSimpleBlock(I, E, Limit);
      }
    }

    const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] : nullptr;
    // Handle empty record blocks where the brace has already been wrapped.
    if (PreviousLine && TheLine->Last->is(tok::l_brace) &&
        TheLine->First == TheLine->Last) {
      bool EmptyBlock = NextLine.First->is(tok::r_brace);

      const FormatToken *Tok = PreviousLine->First;
      if (Tok && Tok->is(tok::comment))
        Tok = Tok->getNextNonComment();

      if (Tok && Tok->getNamespaceToken()) {
        return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
                   ? tryMergeSimpleBlock(I, E, Limit)
                   : 0;
      }

      if (Tok && Tok->is(tok::kw_typedef))
        Tok = Tok->getNextNonComment();
      if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
                              tok::kw_extern, Keywords.kw_interface,
                              Keywords.kw_record)) {
        return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
                   ? tryMergeSimpleBlock(I, E, Limit)
                   : 0;
      }

      if (Tok && Tok->is(tok::kw_template) &&
          Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) {
        return 0;
      }
    }

    auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine,
                                      TheLine]() {
      if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All)
        return true;
      if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
          NextLine.First->is(tok::r_brace)) {
        return true;
      }

      if (Style.AllowShortFunctionsOnASingleLine &
          FormatStyle::SFS_InlineOnly) {
        // Just checking TheLine->Level != 0 is not enough, because it
        // provokes treating functions inside indented namespaces as short.
        if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
          return true;

        if (TheLine->Level != 0) {
          if (!PreviousLine)
            return false;

          // TODO: Use IndentTracker to avoid loop?
          // Find the last line with lower level.
          const AnnotatedLine *Line = nullptr;
          for (auto J = I - 1; J >= AnnotatedLines.begin(); --J) {
            assert(*J);
            if (((*J)->InPPDirective && !(*J)->InMacroBody) ||
                (*J)->isComment() || (*J)->Level > TheLine->Level) {
              continue;
            }
            if ((*J)->Level < TheLine->Level ||
                (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
                 (*J)->First->is(tok::l_brace))) {
              Line = *J;
              break;
            }
          }

          if (!Line)
            return false;

          // Check if the found line starts a record.
          const auto *LastNonComment = Line->getLastNonComment();
          // There must be another token (usually `{`), because we chose a
          // non-PPDirective and non-comment line that has a smaller level.
          assert(LastNonComment);
          return isRecordLBrace(*LastNonComment);
        }
      }

      return false;
    };

    bool MergeShortFunctions = ShouldMergeShortFunctions();

    const auto *FirstNonComment = TheLine->getFirstNonComment();
    if (!FirstNonComment)
      return 0;

    // FIXME: There are probably cases where we should use FirstNonComment
    // instead of TheLine->First.

    if (Style.AllowShortNamespacesOnASingleLine &&
        TheLine->First->is(tok::kw_namespace)) {
      const auto result = tryMergeNamespace(I, E, Limit);
      if (result > 0)
        return result;
    }

    if (Style.CompactNamespaces) {
      if (const auto *NSToken = TheLine->First->getNamespaceToken()) {
        int J = 1;
        assert(TheLine->MatchingClosingBlockLineIndex > 0);
        for (auto ClosingLineIndex = TheLine->MatchingClosingBlockLineIndex - 1;
             I + J != E && NSToken->TokenText == getNamespaceTokenText(I[J]) &&
             ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
             I[J]->Last->TotalLength < Limit;
             ++J, --ClosingLineIndex) {
          Limit -= I[J]->Last->TotalLength + 1;

          // Reduce indent level for bodies of namespaces which were compacted,
          // but only if their content was indented in the first place.
          auto *ClosingLine = AnnotatedLines.begin() + ClosingLineIndex + 1;
          const int OutdentBy = I[J]->Level - TheLine->Level;
          assert(OutdentBy >= 0);
          for (auto *CompactedLine = I + J; CompactedLine <= ClosingLine;
               ++CompactedLine) {
            if (!(*CompactedLine)->InPPDirective) {
              const int Level = (*CompactedLine)->Level;
              (*CompactedLine)->Level = std::max(Level - OutdentBy, 0);
            }
          }
        }
        return J - 1;
      }

      if (auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) {
        int i = 0;
        unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
        for (; I + 1 + i != E &&
               nsToken->TokenText ==
                   getMatchingNamespaceTokenText(I[i + 1], AnnotatedLines) &&
               openingLine == I[i + 1]->MatchingOpeningBlockLineIndex;
             i++, --openingLine) {
          // No space between consecutive braces.
          I[i + 1]->First->SpacesRequiredBefore =
              I[i]->Last->isNot(tok::r_brace);

          // Indent like the outer-most namespace.
          IndentTracker.nextLine(*I[i + 1]);
        }
        return i;
      }
    }

    const auto *LastNonComment = TheLine->getLastNonComment();
    assert(LastNonComment);
    // FIXME: There are probably cases where we should use LastNonComment
    // instead of TheLine->Last.

    // Try to merge a function block with left brace unwrapped.
    if (LastNonComment->is(TT_FunctionLBrace) &&
        TheLine->First != LastNonComment) {
      return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
    }

    // Try to merge a control statement block with left brace unwrapped.
    if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
        (FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
                                  TT_ForEachMacro) ||
         TheLine->startsWithExportBlock())) {
      return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never
                 ? tryMergeSimpleBlock(I, E, Limit)
                 : 0;
    }
    // Try to merge a control statement block with left brace wrapped.
    if (NextLine.First->is(TT_ControlStatementLBrace)) {
      // If possible, merge the next line's wrapped left brace with the
      // current line. Otherwise, leave it on the next line, as this is a
      // multi-line control statement.
      return Style.BraceWrapping.AfterControlStatement ==
                     FormatStyle::BWACS_Always
                 ? tryMergeSimpleBlock(I, E, Limit)
                 : 0;
    }
    if (PreviousLine && TheLine->First->is(tok::l_brace)) {
      switch (PreviousLine->First->Tok.getKind()) {
      case tok::at:
        // Don't merge block with left brace wrapped after ObjC special blocks.
        if (PreviousLine->First->Next &&
            PreviousLine->First->Next->isOneOf(tok::objc_autoreleasepool,
                                               tok::objc_synchronized)) {
          return 0;
        }
        break;

      case tok::kw_case:
      case tok::kw_default:
        // Don't merge block with left brace wrapped after case labels.
        return 0;

      default:
        break;
      }
    }

    // Don't merge an empty template class or struct if SplitEmptyRecords
    // is defined.
    if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord &&
        TheLine->Last->is(tok::l_brace) && PreviousLine->Last) {
      const FormatToken *Previous = PreviousLine->Last;
      if (Previous) {
        if (Previous->is(tok::comment))
          Previous = Previous->getPreviousNonComment();
        if (Previous) {
          if (Previous->is(tok::greater) && !PreviousLine->InPPDirective)
            return 0;
          if (Previous->is(tok::identifier)) {
            const FormatToken *PreviousPrevious =
                Previous->getPreviousNonComment();
            if (PreviousPrevious &&
                PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct)) {
              return 0;
            }
          }
        }
      }
    }

    if (TheLine->First->is(TT_SwitchExpressionLabel)) {
      return Style.AllowShortCaseExpressionOnASingleLine
                 ? tryMergeShortCaseLabels(I, E, Limit)
                 : 0;
    }

    if (TheLine->Last->is(tok::l_brace)) {
      bool ShouldMerge = false;
      // Try to merge records.
      if (TheLine->Last->is(TT_EnumLBrace)) {
        ShouldMerge = Style.AllowShortEnumsOnASingleLine;
      } else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
        ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
      } else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace,
                                        TT_RecordLBrace)) {
        // NOTE: We use AfterClass (whereas AfterStruct exists) for both classes
        // and structs, but it seems that wrapping is still handled correctly
        // elsewhere.
        ShouldMerge = !Style.BraceWrapping.AfterClass ||
                      (NextLine.First->is(tok::r_brace) &&
                       !Style.BraceWrapping.SplitEmptyRecord);
      } else if (TheLine->InPPDirective ||
                 TheLine->First->isNoneOf(tok::kw_class, tok::kw_enum,
                                          tok::kw_struct, Keywords.kw_record)) {
        // Try to merge a block with left brace unwrapped that wasn't yet
        // covered.
        ShouldMerge = !Style.BraceWrapping.AfterFunction ||
                      (NextLine.First->is(tok::r_brace) &&
                       !Style.BraceWrapping.SplitEmptyFunction);
      }
      return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit) : 0;
    }

    // Try to merge a function block with left brace wrapped.
    if (NextLine.First->is(TT_FunctionLBrace) &&
        Style.BraceWrapping.AfterFunction) {
      if (NextLine.Last->is(TT_LineComment))
        return 0;

      // Check for Limit <= 2 to account for the " {".
      if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
        return 0;
      Limit -= 2;

      unsigned MergedLines = 0;
      if (MergeShortFunctions ||
          (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
           NextLine.First == NextLine.Last && I + 2 != E &&
           I[2]->First->is(tok::r_brace))) {
        MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
        // If we managed to merge the block, count the function header, which is
        // on a separate line.
        if (MergedLines > 0)
          ++MergedLines;
      }
      return MergedLines;
    }
    auto IsElseLine = [&TheLine]() -> bool {
      const FormatToken *First = TheLine->First;
      if (First->is(tok::kw_else))
        return true;

      return First->is(tok::r_brace) && First->Next &&
             First->Next->is(tok::kw_else);
    };
    if (TheLine->First->is(tok::kw_if) ||
        (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine ==
                          FormatStyle::SIS_AllIfsAndElse))) {
      return Style.AllowShortIfStatementsOnASingleLine
                 ? tryMergeSimpleControlStatement(I, E, Limit)
                 : 0;
    }
    if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do,
                                TT_ForEachMacro)) {
      return Style.AllowShortLoopsOnASingleLine
                 ? tryMergeSimpleControlStatement(I, E, Limit)
                 : 0;
    }
    if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) {
      return Style.AllowShortCaseLabelsOnASingleLine
                 ? tryMergeShortCaseLabels(I, E, Limit)
                 : 0;
    }
    if (TheLine->InPPDirective &&
        (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
      return tryMergeSimplePPDirective(I, E, Limit);
    }
    return 0;
  }

  unsigned
  tryMergeSimplePPDirective(ArrayRef<AnnotatedLine *>::const_iterator I,
                            ArrayRef<AnnotatedLine *>::const_iterator E,
                            unsigned Limit) {
    if (Limit == 0)
      return 0;
    if (I + 2 != E && I[2]->InPPDirective && !I[2]->First->HasUnescapedNewline)
      return 0;
    if (1 + I[1]->Last->TotalLength > Limit)
      return 0;
    return 1;
  }

  unsigned tryMergeNamespace(ArrayRef<AnnotatedLine *>::const_iterator I,
                             ArrayRef<AnnotatedLine *>::const_iterator E,
                             unsigned Limit) {
    if (Limit == 0)
      return 0;

    // The merging code is relative to the opening namespace brace, which could
    // be either on the first or second line due to the brace wrapping rules.
    const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace;
    const auto *BraceOpenLine = I + OpenBraceWrapped;

    assert(*BraceOpenLine);
    if (BraceOpenLine[0]->Last->isNot(TT_NamespaceLBrace))
      return 0;

    if (std::distance(BraceOpenLine, E) <= 2)
      return 0;

    if (BraceOpenLine[0]->Last->is(tok::comment))
      return 0;

    assert(BraceOpenLine[1]);
    const auto &L1 = *BraceOpenLine[1];
    if (L1.InPPDirective != (*I)->InPPDirective ||
        (L1.InPPDirective && L1.First->HasUnescapedNewline)) {
      return 0;
    }

    assert(BraceOpenLine[2]);
    const auto &L2 = *BraceOpenLine[2];
    if (L2.Type == LT_Invalid)
      return 0;

    Limit = limitConsideringMacros(I + 1, E, Limit);

    const auto LinesToBeMerged = OpenBraceWrapped + 2;
    if (!nextNLinesFitInto(I, I + LinesToBeMerged, Limit))
      return 0;

    // Check if it's a namespace inside a namespace, and call recursively if so.
    // '3' is the sizes of the whitespace and closing brace for " _inner_ }".
    if (L1.First->is(tok::kw_namespace)) {
      if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)
        return 0;

      assert(Limit >= L1.Last->TotalLength + 3);
      const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
      const auto MergedLines =
          tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit);
      if (MergedLines == 0)
        return 0;
      const auto N = MergedLines + LinesToBeMerged;
      // Check if there is even a line after the inner result.
      if (auto Distance = std::distance(I, E);
          static_cast<decltype(N)>(Distance) <= N) {
        return 0;
      }
      // Check that the line after the inner result starts with a closing brace
      // which we are permitted to merge into one line.
      if (I[N]->First->is(TT_NamespaceRBrace) &&
          !I[N]->First->MustBreakBefore &&
          BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) &&
          nextNLinesFitInto(I, I + N + 1, Limit)) {
        return N;
      }
      return 0;
    }

    // There's no inner namespace, so we are considering to merge at most one
    // line.

    // The line which is in the namespace should end with semicolon.
    if (L1.Last->isNot(tok::semi))
      return 0;

    // Last, check that the third line starts with a closing brace.
    if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore)
      return 0;

    // If so, merge all lines.
    return LinesToBeMerged;
  }

  unsigned
  tryMergeSimpleControlStatement(ArrayRef<AnnotatedLine *>::const_iterator I,
                                 ArrayRef<AnnotatedLine *>::const_iterator E,
                                 unsigned Limit) {
    if (Limit == 0)
      return 0;
    if (Style.BraceWrapping.AfterControlStatement ==
            FormatStyle::BWACS_Always &&
        I[1]->First->is(tok::l_brace) &&
        Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
      return 0;
    }
    if (I[1]->InPPDirective != (*I)->InPPDirective ||
        (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) {
      return 0;
    }
    Limit = limitConsideringMacros(I + 1, E, Limit);
    AnnotatedLine &Line = **I;
    if (Line.First->isNoneOf(tok::kw_do, tok::kw_else) &&
        Line.Last->isNoneOf(tok::kw_else, tok::r_paren)) {
      return 0;
    }
    // Only merge `do while` if `do` is the only statement on the line.
    if (Line.First->is(tok::kw_do) && Line.Last->isNot(tok::kw_do))
      return 0;
    if (1 + I[1]->Last->TotalLength > Limit)
      return 0;
    // Don't merge with loops, ifs, a single semicolon or a line comment.
    if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,
                             TT_ForEachMacro, TT_LineComment)) {
      return 0;
    }
    // Only inline simple if's (no nested if or else), unless specified
    if (Style.AllowShortIfStatementsOnASingleLine ==
        FormatStyle::SIS_WithoutElse) {
      if (I + 2 != E && Line.startsWith(tok::kw_if) &&
          I[2]->First->is(tok::kw_else)) {
        return 0;
      }
    }
    return 1;
  }

  unsigned tryMergeShortCaseLabels(ArrayRef<AnnotatedLine *>::const_iterator I,
                                   ArrayRef<AnnotatedLine *>::const_iterator E,
                                   unsigned Limit) {
    if (Limit == 0 || I + 1 == E ||
        I[1]->First->isOneOf(tok::kw_case, tok::kw_default)) {
      return 0;
    }
    if (I[0]->Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))
      return 0;
    unsigned NumStmts = 0;
    unsigned Length = 0;
    bool EndsWithComment = false;
    bool InPPDirective = I[0]->InPPDirective;
    bool InMacroBody = I[0]->InMacroBody;
    const unsigned Level = I[0]->Level;
    for (; NumStmts < 3; ++NumStmts) {
      if (I + 1 + NumStmts == E)
        break;
      const AnnotatedLine *Line = I[1 + NumStmts];
      if (Line->InPPDirective != InPPDirective)
        break;
      if (Line->InMacroBody != InMacroBody)
        break;
      if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
        break;
      if (Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
                               tok::kw_while) ||
          EndsWithComment) {
        return 0;
      }
      if (Line->First->is(tok::comment)) {
        if (Level != Line->Level)
          return 0;
        const auto *J = I + 2 + NumStmts;
        for (; J != E; ++J) {
          Line = *J;
          if (Line->InPPDirective != InPPDirective)
            break;
          if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
            break;
          if (Line->First->isNot(tok::comment) || Level != Line->Level)
            return 0;
        }
        break;
      }
      if (Line->Last->is(tok::comment))
        EndsWithComment = true;
      Length += I[1 + NumStmts]->Last->TotalLength + 1; // 1 for the space.
    }
    if (NumStmts == 0 || NumStmts == 3 || Length > Limit)
      return 0;
    return NumStmts;
  }

  unsigned tryMergeSimpleBlock(ArrayRef<AnnotatedLine *>::const_iterator I,
                               ArrayRef<AnnotatedLine *>::const_iterator E,
                               unsigned Limit) {
    // Don't merge with a preprocessor directive.
    if (I[1]->Type == LT_PreprocessorDirective)
      return 0;

    AnnotatedLine &Line = **I;

    // Don't merge ObjC @ keywords and methods.
    // FIXME: If an option to allow short exception handling clauses on a single
    // line is added, change this to not return for @try and friends.
    if (!Style.isJava() && Line.First->isOneOf(tok::at, tok::minus, tok::plus))
      return 0;

    // Check that the current line allows merging. This depends on whether we
    // are in a control flow statements as well as several style flags.
    if (Line.First->is(tok::kw_case) ||
        (Line.First->Next && Line.First->Next->is(tok::kw_else))) {
      return 0;
    }
    // default: in switch statement
    if (Line.First->is(tok::kw_default)) {
      const FormatToken *Tok = Line.First->getNextNonComment();
      if (Tok && Tok->is(tok::colon))
        return 0;
    }

    auto IsCtrlStmt = [](const auto &Line) {
      return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
                                 tok::kw_do, tok::kw_for, TT_ForEachMacro);
    };

    const bool IsSplitBlock =
        Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never ||
        (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty &&
         I[1]->First->isNot(tok::r_brace));

    if (IsCtrlStmt(Line) ||
        Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
                            tok::kw___finally, tok::r_brace,
                            Keywords.kw___except) ||
        Line.startsWithExportBlock()) {
      if (IsSplitBlock)
        return 0;
      // Don't merge when we can't except the case when
      // the control statement block is empty
      if (!Style.AllowShortIfStatementsOnASingleLine &&
          Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
          !Style.BraceWrapping.AfterControlStatement &&
          I[1]->First->isNot(tok::r_brace)) {
        return 0;
      }
      if (!Style.AllowShortIfStatementsOnASingleLine &&
          Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
          Style.BraceWrapping.AfterControlStatement ==
              FormatStyle::BWACS_Always &&
          I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
        return 0;
      }
      if (!Style.AllowShortLoopsOnASingleLine &&
          Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
                              TT_ForEachMacro) &&
          !Style.BraceWrapping.AfterControlStatement &&
          I[1]->First->isNot(tok::r_brace)) {
        return 0;
      }
      if (!Style.AllowShortLoopsOnASingleLine &&
          Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
                              TT_ForEachMacro) &&
          Style.BraceWrapping.AfterControlStatement ==
              FormatStyle::BWACS_Always &&
          I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
        return 0;
      }
      // FIXME: Consider an option to allow short exception handling clauses on
      // a single line.
      // FIXME: This isn't covered by tests.
      // FIXME: For catch, __except, __finally the first token on the line
      // is '}', so this isn't correct here.
      if (Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
                              Keywords.kw___except, tok::kw___finally)) {
        return 0;
      }
    }

    if (Line.endsWith(tok::l_brace)) {
      if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never &&
          Line.First->is(TT_BlockLBrace)) {
        return 0;
      }

      if (IsSplitBlock && Line.First == Line.Last &&
          I > AnnotatedLines.begin() &&
          (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {
        return 0;
      }
      FormatToken *Tok = I[1]->First;
      auto ShouldMerge = [Tok]() {
        if (Tok->isNot(tok::r_brace) || Tok->MustBreakBefore)
          return false;
        const FormatToken *Next = Tok->getNextNonComment();
        return !Next || Next->is(tok::semi);
      };

      if (ShouldMerge()) {
        // We merge empty blocks even if the line exceeds the column limit.
        Tok->SpacesRequiredBefore =
            Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never ||
            Line.Last->is(tok::comment);
        Tok->CanBreakBefore = true;
        return 1;
      } else if (Limit != 0 && !Line.startsWithNamespace() &&
                 !startsExternCBlock(Line)) {
        // We don't merge short records.
        if (isRecordLBrace(*Line.Last))
          return 0;

        // Check that we still have three lines and they fit into the limit.
        if (I + 2 == E || I[2]->Type == LT_Invalid)
          return 0;
        Limit = limitConsideringMacros(I + 2, E, Limit);

        if (!nextTwoLinesFitInto(I, Limit))
          return 0;

        // Second, check that the next line does not contain any braces - if it
        // does, readability declines when putting it into a single line.
        if (I[1]->Last->is(TT_LineComment))
          return 0;
        do {
          if (Tok->is(tok::l_brace) && Tok->isNot(BK_BracedInit))
            return 0;
          Tok = Tok->Next;
        } while (Tok);

        // Last, check that the third line starts with a closing brace.
        Tok = I[2]->First;
        if (Tok->isNot(tok::r_brace))
          return 0;

        // Don't merge "if (a) { .. } else {".
        if (Tok->Next && Tok->Next->is(tok::kw_else))
          return 0;

        // Don't merge a trailing multi-line control statement block like:
        // } else if (foo &&
        //            bar)
        // { <-- current Line
        //   baz();
        // }
        if (Line.First == Line.Last &&
            Line.First->is(TT_ControlStatementLBrace) &&
            Style.BraceWrapping.AfterControlStatement ==
                FormatStyle::BWACS_MultiLine) {
          return 0;
        }

        return 2;
      }
    } else if (I[1]->First->is(tok::l_brace)) {
      if (I[1]->Last->is(TT_LineComment))
        return 0;

      // Check for Limit <= 2 to account for the " {".
      if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))
        return 0;
      Limit -= 2;
      unsigned MergedLines = 0;
      if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never ||
          (I[1]->First == I[1]->Last && I + 2 != E &&
           I[2]->First->is(tok::r_brace))) {
        MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
        // If we managed to merge the block, count the statement header, which
        // is on a separate line.
        if (MergedLines > 0)
          ++MergedLines;
      }
      return MergedLines;
    }
    return 0;
  }

  /// Returns the modified column limit for \p I if it is inside a macro and
  /// needs a trailing '\'.
  unsigned limitConsideringMacros(ArrayRef<AnnotatedLine *>::const_iterator I,
                                  ArrayRef<AnnotatedLine *>::const_iterator E,
                                  unsigned Limit) {
    if (I[0]->InPPDirective && I + 1 != E &&
        !I[1]->First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {
      return Limit < 2 ? 0 : Limit - 2;
    }
    return Limit;
  }

  bool nextTwoLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I,
                           unsigned Limit) {
    if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore)
      return false;
    return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
  }

  bool nextNLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I,
                         ArrayRef<AnnotatedLine *>::const_iterator E,
                         unsigned Limit) {
    unsigned JoinedLength = 0;
    for (const auto *J = I + 1; J != E; ++J) {
      if ((*J)->First->MustBreakBefore)
        return false;

      JoinedLength += 1 + (*J)->Last->TotalLength;
      if (JoinedLength > Limit)
        return false;
    }
    return true;
  }

  bool containsMustBreak(const AnnotatedLine *Line) {
    assert(Line->First);
    // Ignore the first token, because in this situation, it applies more to the
    // last token of the previous line.
    for (const FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next)
      if (Tok->MustBreakBefore)
        return true;
    return false;
  }

  void join(AnnotatedLine &A, const AnnotatedLine &B) {
    assert(!A.Last->Next);
    assert(!B.First->Previous);
    if (B.Affected || B.LeadingEmptyLinesAffected) {
      assert(B.Affected || A.Last->Children.empty());
      A.Affected = true;
    }
    A.Last->Next = B.First;
    B.First->Previous = A.Last;
    B.First->CanBreakBefore = true;
    unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
    for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {
      Tok->TotalLength += LengthA;
      A.Last = Tok;
    }
  }

  const FormatStyle &Style;
  const AdditionalKeywords &Keywords;
  const ArrayRef<AnnotatedLine *>::const_iterator End;

  ArrayRef<AnnotatedLine *>::const_iterator Next;
  const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
};

static void markFinalized(FormatToken *Tok) {
  if (Tok->is(tok::hash) && !Tok->Previous && Tok->Next &&
      Tok->Next->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef,
                         tok::pp_elif, tok::pp_elifdef, tok::pp_elifndef,
                         tok::pp_else, tok::pp_endif)) {
    Tok = Tok->Next;
  }
  for (; Tok; Tok = Tok->Next) {
    if (Tok->MacroCtx && Tok->MacroCtx->Role == MR_ExpandedArg) {
      // In the first pass we format all macro arguments in the expanded token
      // stream. Instead of finalizing the macro arguments, we mark that they
      // will be modified as unexpanded arguments (as part of the macro call
      // formatting) in the next pass.
      Tok->MacroCtx->Role = MR_UnexpandedArg;
      // Reset whether spaces or a line break are required before this token, as
      // that is context dependent, and that context may change when formatting
      // the macro call.  For example, given M(x) -> 2 * x, and the macro call
      // M(var), the token 'var' will have SpacesRequiredBefore = 1 after being
      // formatted as part of the expanded macro, but SpacesRequiredBefore = 0
      // for its position within the macro call.
      Tok->SpacesRequiredBefore = 0;
      if (!Tok->MustBreakBeforeFinalized)
        Tok->MustBreakBefore = 0;
    } else {
      Tok->Finalized = true;
    }
  }
}

#ifndef NDEBUG
static void printLineState(const LineState &State) {
  llvm::dbgs() << "State: ";
  for (const ParenState &P : State.Stack) {
    llvm::dbgs() << (P.Tok ? P.Tok->TokenText : "F") << "|" << P.Indent.Total
                 << "|" << P.LastSpace << "|" << P.NestedBlockIndent << " ";
  }
  llvm::dbgs() << State.NextToken->TokenText << "\n";
}
#endif

/// Base class for classes that format one \c AnnotatedLine.
class LineFormatter {
public:
  LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
                const FormatStyle &Style,
                UnwrappedLineFormatter *BlockFormatter)
      : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
        BlockFormatter(BlockFormatter) {}
  virtual ~LineFormatter() {}

  /// Formats an \c AnnotatedLine and returns the penalty.
  ///
  /// If \p DryRun is \c false, directly applies the changes.
  virtual unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
                              unsigned FirstStartColumn, bool DryRun) = 0;

protected:
  /// If the \p State's next token is an r_brace closing a nested block,
  /// format the nested block before it.
  ///
  /// Returns \c true if all children could be placed successfully and adapts
  /// \p Penalty as well as \p State. If \p DryRun is false, also directly
  /// creates changes using \c Whitespaces.
  ///
  /// The crucial idea here is that children always get formatted upon
  /// encountering the closing brace right after the nested block. Now, if we
  /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is
  /// \c false), the entire block has to be kept on the same line (which is only
  /// possible if it fits on the line, only contains a single statement, etc.
  ///
  /// If \p NewLine is true, we format the nested block on separate lines, i.e.
  /// break after the "{", format all lines with correct indentation and the put
  /// the closing "}" on yet another new line.
  ///
  /// This enables us to keep the simple structure of the
  /// \c UnwrappedLineFormatter, where we only have two options for each token:
  /// break or don't break.
  bool formatChildren(LineState &State, bool NewLine, bool DryRun,
                      unsigned &Penalty) {
    const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
    bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(BK_Block);
    FormatToken &Previous = *State.NextToken->Previous;
    if (Previous.Children.empty() || (!HasLBrace && !LBrace->MacroParent)) {
      // The previous token does not open a block. Nothing to do. We don't
      // assert so that we can simply call this function for all tokens.
      return true;
    }

    if (NewLine || Previous.MacroParent) {
      const ParenState &P = State.Stack.back();

      int AdditionalIndent =
          P.Indent.Total - Previous.Children[0]->Level * Style.IndentWidth;
      Penalty +=
          BlockFormatter->format(Previous.Children, DryRun, AdditionalIndent,
                                 /*FixBadIndentation=*/true);
      return true;
    }

    if (Previous.Children[0]->First->MustBreakBefore)
      return false;

    // Cannot merge into one line if this line ends on a comment.
    if (Previous.is(tok::comment))
      return false;

    // Cannot merge multiple statements into a single line.
    if (Previous.Children.size() > 1)
      return false;

    const AnnotatedLine *Child = Previous.Children[0];
    // We can't put the closing "}" on a line with a trailing comment.
    if (Child->Last->isTrailingComment())
      return false;

    // If the child line exceeds the column limit, we wouldn't want to merge it.
    // We add +2 for the trailing " }".
    if (Style.ColumnLimit > 0 &&
        Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit) {
      return false;
    }

    if (!DryRun) {
      Whitespaces->replaceWhitespace(
          *Child->First, /*Newlines=*/0, /*Spaces=*/1,
          /*StartOfTokenColumn=*/State.Column, /*IsAligned=*/false,
          State.Line->InPPDirective);
    }
    Penalty +=
        formatLine(*Child, State.Column + 1, /*FirstStartColumn=*/0, DryRun);
    if (!DryRun)
      markFinalized(Child->First);

    State.Column += 1 + Child->Last->TotalLength;
    return true;
  }

  ContinuationIndenter *Indenter;

private:
  WhitespaceManager *Whitespaces;
  const FormatStyle &Style;
  UnwrappedLineFormatter *BlockFormatter;
};

/// Formatter that keeps the existing line breaks.
class NoColumnLimitLineFormatter : public LineFormatter {
public:
  NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
                             WhitespaceManager *Whitespaces,
                             const FormatStyle &Style,
                             UnwrappedLineFormatter *BlockFormatter)
      : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}

  /// Formats the line, simply keeping all of the input's line breaking
  /// decisions.
  unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
                      unsigned FirstStartColumn, bool DryRun) override {
    assert(!DryRun);
    LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
                                                &Line, /*DryRun=*/false);
    while (State.NextToken) {
      bool Newline =
          Indenter->mustBreak(State) ||
          (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
      unsigned Penalty = 0;
      formatChildren(State, Newline, /*DryRun=*/false, Penalty);
      Indenter->addTokenToState(State, Newline, /*DryRun=*/false);
    }
    return 0;
  }
};

/// Formatter that puts all tokens into a single line without breaks.
class NoLineBreakFormatter : public LineFormatter {
public:
  NoLineBreakFormatter(ContinuationIndenter *Indenter,
                       WhitespaceManager *Whitespaces, const FormatStyle &Style,
                       UnwrappedLineFormatter *BlockFormatter)
      : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}

  /// Puts all tokens into a single line.
  unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
                      unsigned FirstStartColumn, bool DryRun) override {
    unsigned Penalty = 0;
    LineState State =
        Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun);
    while (State.NextToken) {
      formatChildren(State, /*NewLine=*/false, DryRun, Penalty);
      Indenter->addTokenToState(
          State, /*Newline=*/State.NextToken->MustBreakBefore, DryRun);
    }
    return Penalty;
  }
};

/// Finds the best way to break lines.
class OptimizingLineFormatter : public LineFormatter {
public:
  OptimizingLineFormatter(ContinuationIndenter *Indenter,
                          WhitespaceManager *Whitespaces,
                          const FormatStyle &Style,
                          UnwrappedLineFormatter *BlockFormatter)
      : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}

  /// Formats the line by finding the best line breaks with line lengths
  /// below the column limit.
  unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
                      unsigned FirstStartColumn, bool DryRun) override {
    LineState State =
        Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun);

    // If the ObjC method declaration does not fit on a line, we should format
    // it with one arg per line.
    if (State.Line->Type == LT_ObjCMethodDecl)
      State.Stack.back().BreakBeforeParameter = true;

    // Find best solution in solution space.
    return analyzeSolutionSpace(State, DryRun);
  }

private:
  struct CompareLineStatePointers {
    bool operator()(LineState *obj1, LineState *obj2) const {
      return *obj1 < *obj2;
    }
  };

  /// A pair of <penalty, count> that is used to prioritize the BFS on.
  ///
  /// In case of equal penalties, we want to prefer states that were inserted
  /// first. During state generation we make sure that we insert states first
  /// that break the line as late as possible.
  typedef std::pair<unsigned, unsigned> OrderedPenalty;

  /// An edge in the solution space from \c Previous->State to \c State,
  /// inserting a newline dependent on the \c NewLine.
  struct StateNode {
    StateNode(const LineState &State, bool NewLine, StateNode *Previous)
        : State(State), NewLine(NewLine), Previous(Previous) {}
    LineState State;
    bool NewLine;
    StateNode *Previous;
  };

  /// An item in the prioritized BFS search queue. The \c StateNode's
  /// \c State has the given \c OrderedPenalty.
  typedef std::pair<OrderedPenalty, StateNode *> QueueItem;

  /// The BFS queue type.
  typedef std::priority_queue<QueueItem, SmallVector<QueueItem>,
                              std::greater<QueueItem>>
      QueueType;

  /// Analyze the entire solution space starting from \p InitialState.
  ///
  /// This implements a variant of Dijkstra's algorithm on the graph that spans
  /// the solution space (\c LineStates are the nodes). The algorithm tries to
  /// find the shortest path (the one with lowest penalty) from \p InitialState
  /// to a state where all tokens are placed. Returns the penalty.
  ///
  /// If \p DryRun is \c false, directly applies the changes.
  unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun) {
    std::set<LineState *, CompareLineStatePointers> Seen;

    // Increasing count of \c StateNode items we have created. This is used to
    // create a deterministic order independent of the container.
    unsigned Count = 0;
    QueueType Queue;

    // Insert start element into queue.
    StateNode *RootNode =
        new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);
    Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode));
    ++Count;

    unsigned Penalty = 0;

    // While not empty, take first element and follow edges.
    while (!Queue.empty()) {
      // Quit if we still haven't found a solution by now.
      if (Count > 25'000'000)
        return 0;

      Penalty = Queue.top().first.first;
      StateNode *Node = Queue.top().second;
      if (!Node->State.NextToken) {
        LLVM_DEBUG(llvm::dbgs()
                   << "\n---\nPenalty for line: " << Penalty << "\n");
        break;
      }
      Queue.pop();

      // Cut off the analysis of certain solutions if the analysis gets too
      // complex. See description of IgnoreStackForComparison.
      if (Count > 50'000)
        Node->State.IgnoreStackForComparison = true;

      if (!Seen.insert(&Node->State).second) {
        // State already examined with lower penalty.
        continue;
      }

      FormatDecision LastFormat = Node->State.NextToken->getDecision();
      if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
        addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);
      if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
        addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);
    }

    if (Queue.empty()) {
      // We were unable to find a solution, do nothing.
      // FIXME: Add diagnostic?
      LLVM_DEBUG(llvm::dbgs() << "Could not find a solution.\n");
      return 0;
    }

    // Reconstruct the solution.
    if (!DryRun)
      reconstructPath(InitialState, Queue.top().second);

    LLVM_DEBUG(llvm::dbgs()
               << "Total number of analyzed states: " << Count << "\n");
    LLVM_DEBUG(llvm::dbgs() << "---\n");

    return Penalty;
  }

  /// Add the following state to the analysis queue \c Queue.
  ///
  /// Assume the current state is \p PreviousNode and has been reached with a
  /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.
  void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,
                           bool NewLine, unsigned *Count, QueueType *Queue) {
    if (NewLine && !Indenter->canBreak(PreviousNode->State))
      return;
    if (!NewLine && Indenter->mustBreak(PreviousNode->State))
      return;

    StateNode *Node = new (Allocator.Allocate())
        StateNode(PreviousNode->State, NewLine, PreviousNode);
    if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))
      return;

    Penalty += Indenter->addTokenToState(Node->State, NewLine, true);

    Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
    ++(*Count);
  }

  /// Applies the best formatting by reconstructing the path in the
  /// solution space that leads to \c Best.
  void reconstructPath(LineState &State, StateNode *Best) {
    llvm::SmallVector<StateNode *> Path;
    // We do not need a break before the initial token.
    while (Best->Previous) {
      Path.push_back(Best);
      Best = Best->Previous;
    }
    for (const auto &Node : llvm::reverse(Path)) {
      unsigned Penalty = 0;
      formatChildren(State, Node->NewLine, /*DryRun=*/false, Penalty);
      Penalty += Indenter->addTokenToState(State, Node->NewLine, false);

      LLVM_DEBUG({
        printLineState(Node->Previous->State);
        if (Node->NewLine) {
          llvm::dbgs() << "Penalty for placing "
                       << Node->Previous->State.NextToken->Tok.getName()
                       << " on a new line: " << Penalty << "\n";
        }
      });
    }
  }

  llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
};

} // anonymous namespace

unsigned UnwrappedLineFormatter::format(
    const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
    int AdditionalIndent, bool FixBadIndentation, unsigned FirstStartColumn,
    unsigned NextStartColumn, unsigned LastStartColumn) {
  LineJoiner Joiner(Style, Keywords, Lines);

  // Try to look up already computed penalty in DryRun-mode.
  std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey(
      &Lines, AdditionalIndent);
  auto CacheIt = PenaltyCache.find(CacheKey);
  if (DryRun && CacheIt != PenaltyCache.end())
    return CacheIt->second;

  assert(!Lines.empty());
  unsigned Penalty = 0;
  LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
                                   AdditionalIndent);
  const AnnotatedLine *PrevPrevLine = nullptr;
  const AnnotatedLine *PreviousLine = nullptr;
  const AnnotatedLine *NextLine = nullptr;

  // The minimum level of consecutive lines that have been formatted.
  unsigned RangeMinLevel = UINT_MAX;

  bool FirstLine = true;
  for (const AnnotatedLine *Line =
           Joiner.getNextMergedLine(DryRun, IndentTracker);
       Line; PrevPrevLine = PreviousLine, PreviousLine = Line, Line = NextLine,
                           FirstLine = false) {
    assert(Line->First);
    const AnnotatedLine &TheLine = *Line;
    unsigned Indent = IndentTracker.getIndent();

    // We continue formatting unchanged lines to adjust their indent, e.g. if a
    // scope was added. However, we need to carefully stop doing this when we
    // exit the scope of affected lines to prevent indenting the entire
    // remaining file if it currently missing a closing brace.
    bool PreviousRBrace =
        PreviousLine && PreviousLine->startsWith(tok::r_brace);
    bool ContinueFormatting =
        TheLine.Level > RangeMinLevel ||
        (TheLine.Level == RangeMinLevel && !PreviousRBrace &&
         !TheLine.startsWith(TT_NamespaceRBrace));

    bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
                          Indent != TheLine.First->OriginalColumn;
    bool ShouldFormat = TheLine.Affected || FixIndentation;
    // We cannot format this line; if the reason is that the line had a
    // parsing error, remember that.
    if (ShouldFormat && TheLine.Type == LT_Invalid && Status) {
      Status->FormatComplete = false;
      Status->Line =
          SourceMgr.getSpellingLineNumber(TheLine.First->Tok.getLocation());
    }

    if (ShouldFormat && TheLine.Type != LT_Invalid) {
      if (!DryRun) {
        bool LastLine = TheLine.First->is(tok::eof);
        formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines, Indent,
                         LastLine ? LastStartColumn : NextStartColumn + Indent);
      }

      NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
      unsigned ColumnLimit = getColumnLimit(TheLine.InPPDirective, NextLine);
      bool FitsIntoOneLine =
          !TheLine.ContainsMacroCall &&
          (TheLine.Last->TotalLength + Indent <= ColumnLimit ||
           (TheLine.Type == LT_ImportStatement &&
            (!Style.isJavaScript() || !Style.JavaScriptWrapImports)) ||
           (Style.isCSharp() &&
            TheLine.InPPDirective)); // don't split #regions in C#
      if (Style.ColumnLimit == 0) {
        NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this)
            .formatLine(TheLine, NextStartColumn + Indent,
                        FirstLine ? FirstStartColumn : 0, DryRun);
      } else if (FitsIntoOneLine) {
        Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style, this)
                       .formatLine(TheLine, NextStartColumn + Indent,
                                   FirstLine ? FirstStartColumn : 0, DryRun);
      } else {
        Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this)
                       .formatLine(TheLine, NextStartColumn + Indent,
                                   FirstLine ? FirstStartColumn : 0, DryRun);
      }
      RangeMinLevel = std::min(RangeMinLevel, TheLine.Level);
    } else {
      // If no token in the current line is affected, we still need to format
      // affected children.
      if (TheLine.ChildrenAffected) {
        for (const FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next)
          if (!Tok->Children.empty())
            format(Tok->Children, DryRun);
      }

      // Adapt following lines on the current indent level to the same level
      // unless the current \c AnnotatedLine is not at the beginning of a line.
      bool StartsNewLine =
          TheLine.First->NewlinesBefore > 0 || TheLine.First->IsFirst;
      if (StartsNewLine)
        IndentTracker.adjustToUnmodifiedLine(TheLine);
      if (!DryRun) {
        bool ReformatLeadingWhitespace =
            StartsNewLine && ((PreviousLine && PreviousLine->Affected) ||
                              TheLine.LeadingEmptyLinesAffected);
        // Format the first token.
        if (ReformatLeadingWhitespace) {
          formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
                           TheLine.First->OriginalColumn,
                           TheLine.First->OriginalColumn);
        } else {
          Whitespaces->addUntouchableToken(*TheLine.First,
                                           TheLine.InPPDirective);
        }

        // Notify the WhitespaceManager about the unchanged whitespace.
        for (FormatToken *Tok = TheLine.First->Next; Tok; Tok = Tok->Next)
          Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
      }
      NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
      RangeMinLevel = UINT_MAX;
    }
    if (!DryRun)
      markFinalized(TheLine.First);
  }
  PenaltyCache[CacheKey] = Penalty;
  return Penalty;
}

static auto computeNewlines(const AnnotatedLine &Line,
                            const AnnotatedLine *PreviousLine,
                            const AnnotatedLine *PrevPrevLine,
                            const SmallVectorImpl<AnnotatedLine *> &Lines,
                            const FormatStyle &Style) {
  const auto &RootToken = *Line.First;
  auto Newlines =
      std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
  // Remove empty lines before "}" where applicable.
  if (RootToken.is(tok::r_brace) &&
      (!RootToken.Next ||
       (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&
      // Do not remove empty lines before namespace closing "}".
      !getNamespaceToken(&Line, Lines)) {
    Newlines = std::min(Newlines, 1u);
  }
  // Remove empty lines at the start of nested blocks (lambdas/arrow functions)
  if (!PreviousLine && Line.Level > 0)
    Newlines = std::min(Newlines, 1u);
  if (Newlines == 0 && !RootToken.IsFirst)
    Newlines = 1;
  if (RootToken.IsFirst &&
      (!Style.KeepEmptyLines.AtStartOfFile || !RootToken.HasUnescapedNewline)) {
    Newlines = 0;
  }

  // Remove empty lines after "{".
  if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine &&
      PreviousLine->Last->is(tok::l_brace) &&
      !PreviousLine->startsWithNamespace() &&
      !(PrevPrevLine && PrevPrevLine->startsWithNamespace() &&
        PreviousLine->startsWith(tok::l_brace)) &&
      !startsExternCBlock(*PreviousLine)) {
    Newlines = 1;
  }

  if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) {
    // Modify empty lines after TT_NamespaceLBrace.
    if (PreviousLine && PreviousLine->endsWith(TT_NamespaceLBrace)) {
      if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
        Newlines = 1;
      else if (!Line.startsWithNamespace())
        Newlines = std::max(Newlines, 2u);
    }
    // Modify empty lines before TT_NamespaceRBrace.
    if (Line.startsWith(TT_NamespaceRBrace)) {
      if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
        Newlines = 1;
      else if (!PreviousLine->startsWith(TT_NamespaceRBrace))
        Newlines = std::max(Newlines, 2u);
    }
  }

  // Insert or remove empty line before access specifiers.
  if (PreviousLine && RootToken.isAccessSpecifier()) {
    switch (Style.EmptyLineBeforeAccessModifier) {
    case FormatStyle::ELBAMS_Never:
      if (Newlines > 1)
        Newlines = 1;
      break;
    case FormatStyle::ELBAMS_Leave:
      Newlines = std::max(RootToken.NewlinesBefore, 1u);
      break;
    case FormatStyle::ELBAMS_LogicalBlock:
      if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) && Newlines <= 1)
        Newlines = 2;
      if (PreviousLine->First->isAccessSpecifier())
        Newlines = 1; // Previous is an access modifier remove all new lines.
      break;
    case FormatStyle::ELBAMS_Always: {
      const FormatToken *previousToken;
      if (PreviousLine->Last->is(tok::comment))
        previousToken = PreviousLine->Last->getPreviousNonComment();
      else
        previousToken = PreviousLine->Last;
      if ((!previousToken || previousToken->isNot(tok::l_brace)) &&
          Newlines <= 1) {
        Newlines = 2;
      }
    } break;
    }
  }

  // Insert or remove empty line after access specifiers.
  if (PreviousLine && PreviousLine->First->isAccessSpecifier() &&
      (!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline)) {
    // EmptyLineBeforeAccessModifier is handling the case when two access
    // modifiers follow each other.
    if (!RootToken.isAccessSpecifier()) {
      switch (Style.EmptyLineAfterAccessModifier) {
      case FormatStyle::ELAAMS_Never:
        Newlines = 1;
        break;
      case FormatStyle::ELAAMS_Leave:
        Newlines = std::max(Newlines, 1u);
        break;
      case FormatStyle::ELAAMS_Always:
        if (RootToken.is(tok::r_brace)) // Do not add at end of class.
          Newlines = 1u;
        else
          Newlines = std::max(Newlines, 2u);
        break;
      }
    }
  }

  return Newlines;
}

void UnwrappedLineFormatter::formatFirstToken(
    const AnnotatedLine &Line, const AnnotatedLine *PreviousLine,
    const AnnotatedLine *PrevPrevLine,
    const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent,
    unsigned NewlineIndent) {
  FormatToken &RootToken = *Line.First;
  if (RootToken.is(tok::eof)) {
    unsigned Newlines = std::min(
        RootToken.NewlinesBefore,
        Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);
    unsigned TokenIndent = Newlines ? NewlineIndent : 0;
    Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent,
                                   TokenIndent);
    return;
  }

  if (RootToken.Newlines < 0) {
    RootToken.Newlines =
        computeNewlines(Line, PreviousLine, PrevPrevLine, Lines, Style);
    assert(RootToken.Newlines >= 0);
  }

  if (RootToken.Newlines > 0)
    Indent = NewlineIndent;

  // Preprocessor directives get indented before the hash only if specified. In
  // Javascript import statements are indented like normal statements.
  if (!Style.isJavaScript() &&
      Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash &&
      (Line.Type == LT_PreprocessorDirective ||
       Line.Type == LT_ImportStatement)) {
    Indent = 0;
  }

  Whitespaces->replaceWhitespace(RootToken, RootToken.Newlines, Indent, Indent,
                                 /*IsAligned=*/false,
                                 Line.InPPDirective &&
                                     !RootToken.HasUnescapedNewline);
}

unsigned
UnwrappedLineFormatter::getColumnLimit(bool InPPDirective,
                                       const AnnotatedLine *NextLine) const {
  // In preprocessor directives reserve two chars for trailing " \" if the
  // next line continues the preprocessor directive.
  bool ContinuesPPDirective =
      InPPDirective &&
      // If there is no next line, this is likely a child line and the parent
      // continues the preprocessor directive.
      (!NextLine ||
       (NextLine->InPPDirective &&
        // If there is an unescaped newline between this line and the next, the
        // next line starts a new preprocessor directive.
        !NextLine->First->HasUnescapedNewline));
  return Style.ColumnLimit - (ContinuesPPDirective ? 2 : 0);
}

} // namespace format
} // namespace clang
