//===--- ContinuationIndenter.cpp - Format C++ code -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements the continuation indenter.
///
//===----------------------------------------------------------------------===//

#include "ContinuationIndenter.h"
#include "BreakableToken.h"
#include "FormatInternal.h"
#include "FormatToken.h"
#include "WhitespaceManager.h"
#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Format/Format.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Debug.h"
#include <optional>

#define DEBUG_TYPE "format-indenter"

namespace clang {
namespace format {

// Returns true if a TT_SelectorName should be indented when wrapped,
// false otherwise.
static bool shouldIndentWrappedSelectorName(const FormatStyle &Style,
                                            LineType LineType) {
  return Style.IndentWrappedFunctionNames || LineType == LT_ObjCMethodDecl;
}

// Returns true if a binary operator following \p Tok should be unindented when
// the style permits it.
static bool shouldUnindentNextOperator(const FormatToken &Tok) {
  const FormatToken *Previous = Tok.getPreviousNonComment();
  return Previous && (Previous->getPrecedence() == prec::Assignment ||
                      Previous->isOneOf(tok::kw_return, TT_RequiresClause));
}

// Returns the length of everything up to the first possible line break after
// the ), ], } or > matching \c Tok.
static unsigned getLengthToMatchingParen(const FormatToken &Tok,
                                         ArrayRef<ParenState> Stack) {
  // Normally whether or not a break before T is possible is calculated and
  // stored in T.CanBreakBefore. Braces, array initializers and text proto
  // messages like `key: < ... >` are an exception: a break is possible
  // before a closing brace R if a break was inserted after the corresponding
  // opening brace. The information about whether or not a break is needed
  // before a closing brace R is stored in the ParenState field
  // S.BreakBeforeClosingBrace where S is the state that R closes.
  //
  // In order to decide whether there can be a break before encountered right
  // braces, this implementation iterates over the sequence of tokens and over
  // the paren stack in lockstep, keeping track of the stack level which visited
  // right braces correspond to in MatchingStackIndex.
  //
  // For example, consider:
  // L. <- line number
  // 1. {
  // 2. {1},
  // 3. {2},
  // 4. {{3}}}
  //     ^ where we call this method with this token.
  // The paren stack at this point contains 3 brace levels:
  //  0. { at line 1, BreakBeforeClosingBrace: true
  //  1. first { at line 4, BreakBeforeClosingBrace: false
  //  2. second { at line 4, BreakBeforeClosingBrace: false,
  //  where there might be fake parens levels in-between these levels.
  // The algorithm will start at the first } on line 4, which is the matching
  // brace of the initial left brace and at level 2 of the stack. Then,
  // examining BreakBeforeClosingBrace: false at level 2, it will continue to
  // the second } on line 4, and will traverse the stack downwards until it
  // finds the matching { on level 1. Then, examining BreakBeforeClosingBrace:
  // false at level 1, it will continue to the third } on line 4 and will
  // traverse the stack downwards until it finds the matching { on level 0.
  // Then, examining BreakBeforeClosingBrace: true at level 0, the algorithm
  // will stop and will use the second } on line 4 to determine the length to
  // return, as in this example the range will include the tokens: {3}}
  //
  // The algorithm will only traverse the stack if it encounters braces, array
  // initializer squares or text proto angle brackets.
  if (!Tok.MatchingParen)
    return 0;
  FormatToken *End = Tok.MatchingParen;
  // Maintains a stack level corresponding to the current End token.
  int MatchingStackIndex = Stack.size() - 1;
  // Traverses the stack downwards, looking for the level to which LBrace
  // corresponds. Returns either a pointer to the matching level or nullptr if
  // LParen is not found in the initial portion of the stack up to
  // MatchingStackIndex.
  auto FindParenState = [&](const FormatToken *LBrace) -> const ParenState * {
    while (MatchingStackIndex >= 0 && Stack[MatchingStackIndex].Tok != LBrace)
      --MatchingStackIndex;
    return MatchingStackIndex >= 0 ? &Stack[MatchingStackIndex] : nullptr;
  };
  for (; End->Next; End = End->Next) {
    if (End->Next->CanBreakBefore)
      break;
    if (!End->Next->closesScope())
      continue;
    if (End->Next->MatchingParen &&
        End->Next->MatchingParen->isOneOf(
            tok::l_brace, TT_ArrayInitializerLSquare, tok::less)) {
      const ParenState *State = FindParenState(End->Next->MatchingParen);
      if (State && State->BreakBeforeClosingBrace)
        break;
    }
  }
  return End->TotalLength - Tok.TotalLength + 1;
}

static unsigned getLengthToNextOperator(const FormatToken &Tok) {
  if (!Tok.NextOperator)
    return 0;
  return Tok.NextOperator->TotalLength - Tok.TotalLength;
}

// Returns \c true if \c Tok is the "." or "->" of a call and starts the next
// segment of a builder type call.
static bool startsSegmentOfBuilderTypeCall(const FormatToken &Tok) {
  return Tok.isMemberAccess() && Tok.Previous && Tok.Previous->closesScope();
}

// Returns \c true if \c Token in an alignable binary operator
static bool isAlignableBinaryOperator(const FormatToken &Token) {
  // No need to align binary operators that only have two operands.
  bool HasTwoOperands = Token.OperatorIndex == 0 && !Token.NextOperator;
  return Token.is(TT_BinaryOperator) && !HasTwoOperands &&
         Token.getPrecedence() > prec::Conditional &&
         Token.getPrecedence() < prec::PointerToMember;
}

// Returns \c true if \c Current starts the next operand in a binary operation.
static bool startsNextOperand(const FormatToken &Current) {
  assert(Current.Previous);
  const auto &Previous = *Current.Previous;
  return isAlignableBinaryOperator(Previous) && !Current.isTrailingComment();
}

// Returns \c true if \c Current is a binary operation that must break.
static bool mustBreakBinaryOperation(const FormatToken &Current,
                                     const FormatStyle &Style) {
  return Style.BreakBinaryOperations != FormatStyle::BBO_Never &&
         Current.CanBreakBefore &&
         (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None
              ? startsNextOperand
              : isAlignableBinaryOperator)(Current);
}

static bool opensProtoMessageField(const FormatToken &LessTok,
                                   const FormatStyle &Style) {
  if (LessTok.isNot(tok::less))
    return false;
  return Style.Language == FormatStyle::LK_TextProto ||
         (Style.Language == FormatStyle::LK_Proto &&
          (LessTok.NestingLevel > 0 ||
           (LessTok.Previous && LessTok.Previous->is(tok::equal))));
}

// Returns the delimiter of a raw string literal, or std::nullopt if TokenText
// is not the text of a raw string literal. The delimiter could be the empty
// string.  For example, the delimiter of R"deli(cont)deli" is deli.
static std::optional<StringRef> getRawStringDelimiter(StringRef TokenText) {
  if (TokenText.size() < 5 // The smallest raw string possible is 'R"()"'.
      || !TokenText.starts_with("R\"") || !TokenText.ends_with("\"")) {
    return std::nullopt;
  }

  // A raw string starts with 'R"<delimiter>(' and delimiter is ascii and has
  // size at most 16 by the standard, so the first '(' must be among the first
  // 19 bytes.
  size_t LParenPos = TokenText.substr(0, 19).find_first_of('(');
  if (LParenPos == StringRef::npos)
    return std::nullopt;
  StringRef Delimiter = TokenText.substr(2, LParenPos - 2);

  // Check that the string ends in ')Delimiter"'.
  size_t RParenPos = TokenText.size() - Delimiter.size() - 2;
  if (TokenText[RParenPos] != ')')
    return std::nullopt;
  if (!TokenText.substr(RParenPos + 1).starts_with(Delimiter))
    return std::nullopt;
  return Delimiter;
}

// Returns the canonical delimiter for \p Language, or the empty string if no
// canonical delimiter is specified.
static StringRef
getCanonicalRawStringDelimiter(const FormatStyle &Style,
                               FormatStyle::LanguageKind Language) {
  for (const auto &Format : Style.RawStringFormats)
    if (Format.Language == Language)
      return StringRef(Format.CanonicalDelimiter);
  return "";
}

RawStringFormatStyleManager::RawStringFormatStyleManager(
    const FormatStyle &CodeStyle) {
  for (const auto &RawStringFormat : CodeStyle.RawStringFormats) {
    std::optional<FormatStyle> LanguageStyle =
        CodeStyle.GetLanguageStyle(RawStringFormat.Language);
    if (!LanguageStyle) {
      FormatStyle PredefinedStyle;
      if (!getPredefinedStyle(RawStringFormat.BasedOnStyle,
                              RawStringFormat.Language, &PredefinedStyle)) {
        PredefinedStyle = getLLVMStyle();
        PredefinedStyle.Language = RawStringFormat.Language;
      }
      LanguageStyle = PredefinedStyle;
    }
    LanguageStyle->ColumnLimit = CodeStyle.ColumnLimit;
    for (StringRef Delimiter : RawStringFormat.Delimiters)
      DelimiterStyle.insert({Delimiter, *LanguageStyle});
    for (StringRef EnclosingFunction : RawStringFormat.EnclosingFunctions)
      EnclosingFunctionStyle.insert({EnclosingFunction, *LanguageStyle});
  }
}

std::optional<FormatStyle>
RawStringFormatStyleManager::getDelimiterStyle(StringRef Delimiter) const {
  auto It = DelimiterStyle.find(Delimiter);
  if (It == DelimiterStyle.end())
    return std::nullopt;
  return It->second;
}

std::optional<FormatStyle>
RawStringFormatStyleManager::getEnclosingFunctionStyle(
    StringRef EnclosingFunction) const {
  auto It = EnclosingFunctionStyle.find(EnclosingFunction);
  if (It == EnclosingFunctionStyle.end())
    return std::nullopt;
  return It->second;
}

ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
                                           const AdditionalKeywords &Keywords,
                                           const SourceManager &SourceMgr,
                                           WhitespaceManager &Whitespaces,
                                           encoding::Encoding Encoding,
                                           bool BinPackInconclusiveFunctions)
    : Style(Style), Keywords(Keywords), SourceMgr(SourceMgr),
      Whitespaces(Whitespaces), Encoding(Encoding),
      BinPackInconclusiveFunctions(BinPackInconclusiveFunctions),
      CommentPragmasRegex(Style.CommentPragmas), RawStringFormats(Style) {}

LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,
                                                unsigned FirstStartColumn,
                                                const AnnotatedLine *Line,
                                                bool DryRun) {
  LineState State;
  State.FirstIndent = FirstIndent;
  if (FirstStartColumn && Line->First->NewlinesBefore == 0)
    State.Column = FirstStartColumn;
  else
    State.Column = FirstIndent;
  // With preprocessor directive indentation, the line starts on column 0
  // since it's indented after the hash, but FirstIndent is set to the
  // preprocessor indent.
  if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash &&
      (Line->Type == LT_PreprocessorDirective ||
       Line->Type == LT_ImportStatement)) {
    State.Column = 0;
  }
  State.Line = Line;
  State.NextToken = Line->First;
  State.Stack.push_back(ParenState(/*Tok=*/nullptr, FirstIndent, FirstIndent,
                                   /*AvoidBinPacking=*/false,
                                   /*NoLineBreak=*/false));
  State.NoContinuation = false;
  State.StartOfStringLiteral = 0;
  State.NoLineBreak = false;
  State.StartOfLineLevel = 0;
  State.LowestLevelOnLine = 0;
  State.IgnoreStackForComparison = false;

  if (Style.Language == FormatStyle::LK_TextProto) {
    // We need this in order to deal with the bin packing of text fields at
    // global scope.
    auto &CurrentState = State.Stack.back();
    CurrentState.AvoidBinPacking = true;
    CurrentState.BreakBeforeParameter = true;
    CurrentState.AlignColons = false;
  }

  // The first token has already been indented and thus consumed.
  moveStateToNextToken(State, DryRun, /*Newline=*/false);
  return State;
}

bool ContinuationIndenter::canBreak(const LineState &State) {
  const FormatToken &Current = *State.NextToken;
  const FormatToken &Previous = *Current.Previous;
  const auto &CurrentState = State.Stack.back();
  assert(&Previous == Current.Previous);
  if (!Current.CanBreakBefore && !(CurrentState.BreakBeforeClosingBrace &&
                                   Current.closesBlockOrBlockTypeList(Style))) {
    return false;
  }
  // The opening "{" of a braced list has to be on the same line as the first
  // element if it is nested in another braced init list or function call.
  if (!Current.MustBreakBefore && Previous.is(tok::l_brace) &&
      Previous.isNot(TT_DictLiteral) && Previous.is(BK_BracedInit) &&
      Previous.Previous &&
      Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma)) {
    return false;
  }
  // This prevents breaks like:
  //   ...
  //   SomeParameter, OtherParameter).DoSomething(
  //   ...
  // As they hide "DoSomething" and are generally bad for readability.
  if (Previous.opensScope() && Previous.isNot(tok::l_brace) &&
      State.LowestLevelOnLine < State.StartOfLineLevel &&
      State.LowestLevelOnLine < Current.NestingLevel) {
    return false;
  }
  if (Current.isMemberAccess() && CurrentState.ContainsUnwrappedBuilder)
    return false;

  // Don't create a 'hanging' indent if there are multiple blocks in a single
  // statement and we are aligning lambda blocks to their signatures.
  if (Previous.is(tok::l_brace) && State.Stack.size() > 1 &&
      State.Stack[State.Stack.size() - 2].NestedBlockInlined &&
      State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks &&
      Style.LambdaBodyIndentation == FormatStyle::LBI_Signature) {
    return false;
  }

  // Don't break after very short return types (e.g. "void") as that is often
  // unexpected.
  if (Current.is(TT_FunctionDeclarationName)) {
    if (Style.BreakAfterReturnType == FormatStyle::RTBS_None &&
        State.Column < 6) {
      return false;
    }

    if (Style.BreakAfterReturnType == FormatStyle::RTBS_ExceptShortType) {
      assert(State.Column >= State.FirstIndent);
      if (State.Column - State.FirstIndent < 6)
        return false;
    }
  }

  // Don't allow breaking before a closing brace of a block-indented braced list
  // initializer if there isn't already a break.
  if (Current.is(tok::r_brace) && Current.MatchingParen &&
      Current.isBlockIndentedInitRBrace(Style)) {
    return CurrentState.BreakBeforeClosingBrace;
  }

  // Allow breaking before the right parens with block indentation if there was
  // a break after the left parens, which is tracked by BreakBeforeClosingParen.
  if (Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent &&
      Current.is(tok::r_paren)) {
    return CurrentState.BreakBeforeClosingParen;
  }

  if (Style.BreakBeforeTemplateCloser && Current.is(TT_TemplateCloser))
    return CurrentState.BreakBeforeClosingAngle;

  // If binary operators are moved to the next line (including commas for some
  // styles of constructor initializers), that's always ok.
  if (!Current.isOneOf(TT_BinaryOperator, tok::comma) &&
      // Allow breaking opening brace of lambdas (when passed as function
      // arguments) to a new line when BeforeLambdaBody brace wrapping is
      // enabled.
      (!Style.BraceWrapping.BeforeLambdaBody ||
       Current.isNot(TT_LambdaLBrace)) &&
      CurrentState.NoLineBreakInOperand) {
    return false;
  }

  if (Previous.is(tok::l_square) && Previous.is(TT_ObjCMethodExpr))
    return false;

  if (Current.is(TT_ConditionalExpr) && Previous.is(tok::r_paren) &&
      Previous.MatchingParen && Previous.MatchingParen->Previous &&
      Previous.MatchingParen->Previous->MatchingParen &&
      Previous.MatchingParen->Previous->MatchingParen->is(TT_LambdaLBrace)) {
    // We have a lambda within a conditional expression, allow breaking here.
    assert(Previous.MatchingParen->Previous->is(tok::r_brace));
    return true;
  }

  return !State.NoLineBreak && !CurrentState.NoLineBreak;
}

bool ContinuationIndenter::mustBreak(const LineState &State) {
  const FormatToken &Current = *State.NextToken;
  const FormatToken &Previous = *Current.Previous;
  const auto &CurrentState = State.Stack.back();
  if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore &&
      Current.is(TT_LambdaLBrace) && Previous.isNot(TT_LineComment)) {
    auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack);
    return LambdaBodyLength > getColumnLimit(State);
  }
  if (Current.MustBreakBefore ||
      (Current.is(TT_InlineASMColon) &&
       (Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always ||
        (Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_OnlyMultiline &&
         Style.ColumnLimit > 0)))) {
    return true;
  }
  if (CurrentState.BreakBeforeClosingBrace &&
      (Current.closesBlockOrBlockTypeList(Style) ||
       (Current.is(tok::r_brace) &&
        Current.isBlockIndentedInitRBrace(Style)))) {
    return true;
  }
  if (CurrentState.BreakBeforeClosingParen && Current.is(tok::r_paren))
    return true;
  if (CurrentState.BreakBeforeClosingAngle && Current.is(TT_TemplateCloser))
    return true;
  if (Style.Language == FormatStyle::LK_ObjC &&
      Style.ObjCBreakBeforeNestedBlockParam &&
      Current.ObjCSelectorNameParts > 1 &&
      Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)) {
    return true;
  }
  // Avoid producing inconsistent states by requiring breaks where they are not
  // permitted for C# generic type constraints.
  if (CurrentState.IsCSharpGenericTypeConstraint &&
      Previous.isNot(TT_CSharpGenericTypeConstraintComma)) {
    return false;
  }
  if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) ||
       (Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) &&
        State.Line->First->isNot(TT_AttributeSquare) && Style.isCpp() &&
        // FIXME: This is a temporary workaround for the case where clang-format
        // sets BreakBeforeParameter to avoid bin packing and this creates a
        // completely unnecessary line break after a template type that isn't
        // line-wrapped.
        (Previous.NestingLevel == 1 ||
         Style.BinPackParameters == FormatStyle::BPPS_BinPack)) ||
       (Style.BreakBeforeTernaryOperators && Current.is(TT_ConditionalExpr) &&
        Previous.isNot(tok::question)) ||
       (!Style.BreakBeforeTernaryOperators &&
        Previous.is(TT_ConditionalExpr))) &&
      CurrentState.BreakBeforeParameter && !Current.isTrailingComment() &&
      !Current.isOneOf(tok::r_paren, tok::r_brace)) {
    return true;
  }
  if (CurrentState.IsChainedConditional &&
      ((Style.BreakBeforeTernaryOperators && Current.is(TT_ConditionalExpr) &&
        Current.is(tok::colon)) ||
       (!Style.BreakBeforeTernaryOperators && Previous.is(TT_ConditionalExpr) &&
        Previous.is(tok::colon)))) {
    return true;
  }
  if (((Previous.is(TT_DictLiteral) && Previous.is(tok::l_brace)) ||
       (Previous.is(TT_ArrayInitializerLSquare) &&
        Previous.ParameterCount > 1) ||
       opensProtoMessageField(Previous, Style)) &&
      Style.ColumnLimit > 0 &&
      getLengthToMatchingParen(Previous, State.Stack) + State.Column - 1 >
          getColumnLimit(State)) {
    return true;
  }

  const FormatToken &BreakConstructorInitializersToken =
      Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon
          ? Previous
          : Current;
  if (BreakConstructorInitializersToken.is(TT_CtorInitializerColon) &&
      (State.Column + State.Line->Last->TotalLength - Previous.TotalLength >
           getColumnLimit(State) ||
       CurrentState.BreakBeforeParameter) &&
      ((!Current.isTrailingComment() && Style.ColumnLimit > 0) ||
       Current.NewlinesBefore > 0)) {
    return true;
  }

  if (Current.is(TT_ObjCMethodExpr) && Previous.isNot(TT_SelectorName) &&
      State.Line->startsWith(TT_ObjCMethodSpecifier)) {
    return true;
  }
  if (Current.is(TT_SelectorName) && Previous.isNot(tok::at) &&
      CurrentState.ObjCSelectorNameFound && CurrentState.BreakBeforeParameter &&
      (Style.ObjCBreakBeforeNestedBlockParam ||
       !Current.startsSequence(TT_SelectorName, tok::colon, tok::caret))) {
    return true;
  }

  unsigned NewLineColumn = getNewLineColumn(State);
  if (Current.isMemberAccess() && Style.ColumnLimit != 0 &&
      State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit &&
      (State.Column > NewLineColumn ||
       Current.NestingLevel < State.StartOfLineLevel)) {
    return true;
  }

  if (startsSegmentOfBuilderTypeCall(Current) &&
      (CurrentState.CallContinuation != 0 ||
       CurrentState.BreakBeforeParameter) &&
      // JavaScript is treated different here as there is a frequent pattern:
      //   SomeFunction(function() {
      //     ...
      //   }.bind(...));
      // FIXME: We should find a more generic solution to this problem.
      !(State.Column <= NewLineColumn && Style.isJavaScript()) &&
      !(Previous.closesScopeAfterBlock() && State.Column <= NewLineColumn)) {
    return true;
  }

  // If the template declaration spans multiple lines, force wrap before the
  // function/class declaration.
  if (Previous.ClosesTemplateDeclaration && CurrentState.BreakBeforeParameter &&
      Current.CanBreakBefore) {
    return true;
  }

  if (State.Line->First->isNot(tok::kw_enum) && State.Column <= NewLineColumn)
    return false;

  if (Style.AlwaysBreakBeforeMultilineStrings &&
      (NewLineColumn == State.FirstIndent + Style.ContinuationIndentWidth ||
       Previous.is(tok::comma) || Current.NestingLevel < 2) &&
      !Previous.isOneOf(tok::kw_return, tok::lessless, tok::at,
                        Keywords.kw_dollar) &&
      !Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
      nextIsMultilineString(State)) {
    return true;
  }

  // Using CanBreakBefore here and below takes care of the decision whether the
  // current style uses wrapping before or after operators for the given
  // operator.
  if (Previous.is(TT_BinaryOperator) && Current.CanBreakBefore) {
    const auto PreviousPrecedence = Previous.getPrecedence();
    if (PreviousPrecedence != prec::Assignment &&
        CurrentState.BreakBeforeParameter && !Current.isTrailingComment()) {
      const bool LHSIsBinaryExpr =
          Previous.Previous && Previous.Previous->EndsBinaryExpression;
      if (LHSIsBinaryExpr)
        return true;
      // If we need to break somewhere inside the LHS of a binary expression, we
      // should also break after the operator. Otherwise, the formatting would
      // hide the operator precedence, e.g. in:
      //   if (aaaaaaaaaaaaaa ==
      //           bbbbbbbbbbbbbb && c) {..
      // For comparisons, we only apply this rule, if the LHS is a binary
      // expression itself as otherwise, the line breaks seem superfluous.
      // We need special cases for ">>" which we have split into two ">" while
      // lexing in order to make template parsing easier.
      const bool IsComparison =
          (PreviousPrecedence == prec::Relational ||
           PreviousPrecedence == prec::Equality ||
           PreviousPrecedence == prec::Spaceship) &&
          Previous.Previous &&
          Previous.Previous->isNot(TT_BinaryOperator); // For >>.
      if (!IsComparison)
        return true;
    }
  } else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore &&
             CurrentState.BreakBeforeParameter) {
    return true;
  }

  // Same as above, but for the first "<<" operator.
  if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator) &&
      CurrentState.BreakBeforeParameter && CurrentState.FirstLessLess == 0) {
    return true;
  }

  if (Current.NestingLevel == 0 && !Current.isTrailingComment()) {
    // Always break after "template <...>"(*) and leading annotations. This is
    // only for cases where the entire line does not fit on a single line as a
    // different LineFormatter would be used otherwise.
    // *: Except when another option interferes with that, like concepts.
    if (Previous.ClosesTemplateDeclaration) {
      if (Current.is(tok::kw_concept)) {
        switch (Style.BreakBeforeConceptDeclarations) {
        case FormatStyle::BBCDS_Allowed:
          break;
        case FormatStyle::BBCDS_Always:
          return true;
        case FormatStyle::BBCDS_Never:
          return false;
        }
      }
      if (Current.is(TT_RequiresClause)) {
        switch (Style.RequiresClausePosition) {
        case FormatStyle::RCPS_SingleLine:
        case FormatStyle::RCPS_WithPreceding:
          return false;
        default:
          return true;
        }
      }
      return Style.BreakTemplateDeclarations != FormatStyle::BTDS_No &&
             (Style.BreakTemplateDeclarations != FormatStyle::BTDS_Leave ||
              Current.NewlinesBefore > 0);
    }
    if (Previous.is(TT_FunctionAnnotationRParen) &&
        State.Line->Type != LT_PreprocessorDirective) {
      return true;
    }
    if (Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) &&
        Current.isNot(TT_LeadingJavaAnnotation)) {
      return true;
    }
  }

  if (Style.isJavaScript() && Previous.is(tok::r_paren) &&
      Previous.is(TT_JavaAnnotation)) {
    // Break after the closing parenthesis of TypeScript decorators before
    // functions, getters and setters.
    static const llvm::StringSet<> BreakBeforeDecoratedTokens = {"get", "set",
                                                                 "function"};
    if (BreakBeforeDecoratedTokens.contains(Current.TokenText))
      return true;
  }

  if (Current.is(TT_FunctionDeclarationName) &&
      !State.Line->ReturnTypeWrapped &&
      // Don't break before a C# function when no break after return type.
      (!Style.isCSharp() ||
       Style.BreakAfterReturnType > FormatStyle::RTBS_ExceptShortType) &&
      // Don't always break between a JavaScript `function` and the function
      // name.
      !Style.isJavaScript() && Previous.isNot(tok::kw_template) &&
      CurrentState.BreakBeforeParameter) {
    for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous)
      if (Tok->FirstAfterPPLine || Tok->is(TT_LineComment))
        return false;

    return true;
  }

  // The following could be precomputed as they do not depend on the state.
  // However, as they should take effect only if the UnwrappedLine does not fit
  // into the ColumnLimit, they are checked here in the ContinuationIndenter.
  if (Style.ColumnLimit != 0 && Previous.is(BK_Block) &&
      Previous.is(tok::l_brace) &&
      !Current.isOneOf(tok::r_brace, tok::comment)) {
    return true;
  }

  if (Current.is(tok::lessless) &&
      ((Previous.is(tok::identifier) && Previous.TokenText == "endl") ||
       (Previous.Tok.isLiteral() && (Previous.TokenText.ends_with("\\n\"") ||
                                     Previous.TokenText == "\'\\n\'")))) {
    return true;
  }

  if (Previous.is(TT_BlockComment) && Previous.IsMultiline)
    return true;

  if (State.NoContinuation)
    return true;

  return false;
}

unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline,
                                               bool DryRun,
                                               unsigned ExtraSpaces) {
  const FormatToken &Current = *State.NextToken;
  assert(State.NextToken->Previous);
  const FormatToken &Previous = *State.NextToken->Previous;

  assert(!State.Stack.empty());
  State.NoContinuation = false;

  if (Current.is(TT_ImplicitStringLiteral) &&
      (!Previous.Tok.getIdentifierInfo() ||
       Previous.Tok.getIdentifierInfo()->getPPKeywordID() ==
           tok::pp_not_keyword)) {
    unsigned EndColumn =
        SourceMgr.getSpellingColumnNumber(Current.WhitespaceRange.getEnd());
    if (Current.LastNewlineOffset != 0) {
      // If there is a newline within this token, the final column will solely
      // determined by the current end column.
      State.Column = EndColumn;
    } else {
      unsigned StartColumn =
          SourceMgr.getSpellingColumnNumber(Current.WhitespaceRange.getBegin());
      assert(EndColumn >= StartColumn);
      State.Column += EndColumn - StartColumn;
    }
    moveStateToNextToken(State, DryRun, /*Newline=*/false);
    return 0;
  }

  unsigned Penalty = 0;
  if (Newline)
    Penalty = addTokenOnNewLine(State, DryRun);
  else
    addTokenOnCurrentLine(State, DryRun, ExtraSpaces);

  return moveStateToNextToken(State, DryRun, Newline) + Penalty;
}

void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
                                                 unsigned ExtraSpaces) {
  FormatToken &Current = *State.NextToken;
  assert(State.NextToken->Previous);
  const FormatToken &Previous = *State.NextToken->Previous;
  auto &CurrentState = State.Stack.back();

  bool DisallowLineBreaksOnThisLine =
      Style.LambdaBodyIndentation == FormatStyle::LBI_Signature &&
      // Deal with lambda arguments in C++. The aim here is to ensure that we
      // don't over-indent lambda function bodies when lambdas are passed as
      // arguments to function calls. We do this by ensuring that either all
      // arguments (including any lambdas) go on the same line as the function
      // call, or we break before the first argument.
      Style.isCpp() && [&] {
        // For example, `/*Newline=*/false`.
        if (Previous.is(TT_BlockComment) && Current.SpacesRequiredBefore == 0)
          return false;
        const auto *PrevNonComment = Current.getPreviousNonComment();
        if (!PrevNonComment || PrevNonComment->isNot(tok::l_paren))
          return false;
        if (Current.isOneOf(tok::comment, tok::l_paren, TT_LambdaLSquare))
          return false;
        auto BlockParameterCount = PrevNonComment->BlockParameterCount;
        if (BlockParameterCount == 0)
          return false;

        // Multiple lambdas in the same function call.
        if (BlockParameterCount > 1)
          return true;

        // A lambda followed by another arg.
        if (!PrevNonComment->Role)
          return false;
        auto Comma = PrevNonComment->Role->lastComma();
        if (!Comma)
          return false;
        auto Next = Comma->getNextNonComment();
        return Next &&
               !Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret);
      }();

  if (DisallowLineBreaksOnThisLine)
    State.NoLineBreak = true;

  if (Current.is(tok::equal) &&
      (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&
      CurrentState.VariablePos == 0 &&
      (!Previous.Previous ||
       Previous.Previous->isNot(TT_DesignatedInitializerPeriod))) {
    CurrentState.VariablePos = State.Column;
    // Move over * and & if they are bound to the variable name.
    const FormatToken *Tok = &Previous;
    while (Tok && CurrentState.VariablePos >= Tok->ColumnWidth) {
      CurrentState.VariablePos -= Tok->ColumnWidth;
      if (Tok->SpacesRequiredBefore != 0)
        break;
      Tok = Tok->Previous;
    }
    if (Previous.PartOfMultiVariableDeclStmt)
      CurrentState.LastSpace = CurrentState.VariablePos;
  }

  unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces;

  // Indent preprocessor directives after the hash if required.
  int PPColumnCorrection = 0;
  if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash &&
      Previous.is(tok::hash) && State.FirstIndent > 0 &&
      &Previous == State.Line->First &&
      (State.Line->Type == LT_PreprocessorDirective ||
       State.Line->Type == LT_ImportStatement)) {
    Spaces += State.FirstIndent;

    // For preprocessor indent with tabs, State.Column will be 1 because of the
    // hash. This causes second-level indents onward to have an extra space
    // after the tabs. We avoid this misalignment by subtracting 1 from the
    // column value passed to replaceWhitespace().
    if (Style.UseTab != FormatStyle::UT_Never)
      PPColumnCorrection = -1;
  }

  if (!DryRun) {
    Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, Spaces,
                                  State.Column + Spaces + PPColumnCorrection,
                                  /*IsAligned=*/false, State.Line->InMacroBody);
  }

  // If "BreakBeforeInheritanceComma" mode, don't break within the inheritance
  // declaration unless there is multiple inheritance.
  if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&
      Current.is(TT_InheritanceColon)) {
    CurrentState.NoLineBreak = true;
  }
  if (Style.BreakInheritanceList == FormatStyle::BILS_AfterColon &&
      Previous.is(TT_InheritanceColon)) {
    CurrentState.NoLineBreak = true;
  }

  if (Current.is(TT_SelectorName) && !CurrentState.ObjCSelectorNameFound) {
    unsigned MinIndent = std::max(
        State.FirstIndent + Style.ContinuationIndentWidth, CurrentState.Indent);
    unsigned FirstColonPos = State.Column + Spaces + Current.ColumnWidth;
    if (Current.LongestObjCSelectorName == 0)
      CurrentState.AlignColons = false;
    else if (MinIndent + Current.LongestObjCSelectorName > FirstColonPos)
      CurrentState.ColonPos = MinIndent + Current.LongestObjCSelectorName;
    else
      CurrentState.ColonPos = FirstColonPos;
  }

  // In "AlwaysBreak" or "BlockIndent" mode, enforce wrapping directly after the
  // parenthesis by disallowing any further line breaks if there is no line
  // break after the opening parenthesis. Don't break if it doesn't conserve
  // columns.
  auto IsOpeningBracket = [&](const FormatToken &Tok) {
    auto IsStartOfBracedList = [&]() {
      return Tok.is(tok::l_brace) && Tok.isNot(BK_Block) &&
             Style.Cpp11BracedListStyle;
    };
    if (!Tok.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) &&
        !IsStartOfBracedList()) {
      return false;
    }
    if (!Tok.Previous)
      return true;
    if (Tok.Previous->isIf())
      return Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak;
    return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while,
                                  tok::kw_switch) &&
           !(Style.isJavaScript() && Tok.Previous->is(Keywords.kw_await));
  };
  auto IsFunctionCallParen = [](const FormatToken &Tok) {
    return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous &&
           Tok.Previous->is(tok::identifier);
  };
  auto IsInTemplateString = [this](const FormatToken &Tok) {
    if (!Style.isJavaScript())
      return false;
    for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) {
      if (Prev->is(TT_TemplateString) && Prev->opensScope())
        return true;
      if (Prev->opensScope() ||
          (Prev->is(TT_TemplateString) && Prev->closesScope())) {
        break;
      }
    }
    return false;
  };
  // Identifies simple (no expression) one-argument function calls.
  auto StartsSimpleOneArgList = [&](const FormatToken &TokAfterLParen) {
    assert(TokAfterLParen.isNot(tok::comment) || TokAfterLParen.Next);
    const auto &Tok =
        TokAfterLParen.is(tok::comment) ? *TokAfterLParen.Next : TokAfterLParen;
    if (!Tok.FakeLParens.empty() && Tok.FakeLParens.back() > prec::Unknown)
      return false;
    // Nested calls that involve `new` expressions also look like simple
    // function calls, eg:
    // - foo(new Bar())
    // - foo(::new Bar())
    if (Tok.is(tok::kw_new) || Tok.startsSequence(tok::coloncolon, tok::kw_new))
      return true;
    if (Tok.is(TT_UnaryOperator) ||
        (Style.isJavaScript() &&
         Tok.isOneOf(tok::ellipsis, Keywords.kw_await))) {
      return true;
    }
    const auto *Previous = Tok.Previous;
    if (!Previous || (!Previous->isOneOf(TT_FunctionDeclarationLParen,
                                         TT_LambdaDefinitionLParen) &&
                      !IsFunctionCallParen(*Previous))) {
      return true;
    }
    if (IsOpeningBracket(Tok) || IsInTemplateString(Tok))
      return true;
    const auto *Next = Tok.Next;
    return !Next || Next->isMemberAccess() ||
           Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next);
  };
  if ((Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak ||
       Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) &&
      IsOpeningBracket(Previous) && State.Column > getNewLineColumn(State) &&
      // Don't do this for simple (no expressions) one-argument function calls
      // as that feels like needlessly wasting whitespace, e.g.:
      //
      //   caaaaaaaaaaaall(
      //       caaaaaaaaaaaall(
      //           caaaaaaaaaaaall(
      //               caaaaaaaaaaaaaaaaaaaaaaall(aaaaaaaaaaaaaa, aaaaaaaaa))));
      //  or
      //  caaaaaaaaaaaaaaaaaaaaal(
      //       new SomethingElseeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee());
      !StartsSimpleOneArgList(Current)) {
    CurrentState.NoLineBreak = true;
  }

  if (Previous.is(TT_TemplateString) && Previous.opensScope())
    CurrentState.NoLineBreak = true;

  // Align following lines within parentheses / brackets if configured.
  // Note: This doesn't apply to macro expansion lines, which are MACRO( , , )
  // with args as children of the '(' and ',' tokens. It does not make sense to
  // align the commas with the opening paren.
  if (Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign &&
      !CurrentState.IsCSharpGenericTypeConstraint && Previous.opensScope() &&
      Previous.isNot(TT_ObjCMethodExpr) && Previous.isNot(TT_RequiresClause) &&
      Previous.isNot(TT_TableGenDAGArgOpener) &&
      Previous.isNot(TT_TableGenDAGArgOpenerToBreak) &&
      !(Current.MacroParent && Previous.MacroParent) &&
      (Current.isNot(TT_LineComment) ||
       Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen)) &&
      !IsInTemplateString(Current)) {
    CurrentState.Indent = State.Column + Spaces;
    CurrentState.IsAligned = true;
  }
  if (CurrentState.AvoidBinPacking && startsNextParameter(Current, Style))
    CurrentState.NoLineBreak = true;
  if (mustBreakBinaryOperation(Current, Style))
    CurrentState.NoLineBreak = true;

  if (startsSegmentOfBuilderTypeCall(Current) &&
      State.Column > getNewLineColumn(State)) {
    CurrentState.ContainsUnwrappedBuilder = true;
  }

  if (Current.is(TT_LambdaArrow) && Style.Language == FormatStyle::LK_Java)
    CurrentState.NoLineBreak = true;
  if (Current.isMemberAccess() && Previous.is(tok::r_paren) &&
      (Previous.MatchingParen &&
       (Previous.TotalLength - Previous.MatchingParen->TotalLength > 10))) {
    // If there is a function call with long parameters, break before trailing
    // calls. This prevents things like:
    //   EXPECT_CALL(SomeLongParameter).Times(
    //       2);
    // We don't want to do this for short parameters as they can just be
    // indexes.
    CurrentState.NoLineBreak = true;
  }

  // Don't allow the RHS of an operator to be split over multiple lines unless
  // there is a line-break right after the operator.
  // Exclude relational operators, as there, it is always more desirable to
  // have the LHS 'left' of the RHS.
  const FormatToken *P = Current.getPreviousNonComment();
  if (Current.isNot(tok::comment) && P &&
      (P->isOneOf(TT_BinaryOperator, tok::comma) ||
       (P->is(TT_ConditionalExpr) && P->is(tok::colon))) &&
      !P->isOneOf(TT_OverloadedOperator, TT_CtorInitializerComma) &&
      P->getPrecedence() != prec::Assignment &&
      P->getPrecedence() != prec::Relational &&
      P->getPrecedence() != prec::Spaceship) {
    bool BreakBeforeOperator =
        P->MustBreakBefore || P->is(tok::lessless) ||
        (P->is(TT_BinaryOperator) &&
         Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None) ||
        (P->is(TT_ConditionalExpr) && Style.BreakBeforeTernaryOperators);
    // Don't do this if there are only two operands. In these cases, there is
    // always a nice vertical separation between them and the extra line break
    // does not help.
    bool HasTwoOperands = P->OperatorIndex == 0 && !P->NextOperator &&
                          P->isNot(TT_ConditionalExpr);
    if ((!BreakBeforeOperator &&
         !(HasTwoOperands &&
           Style.AlignOperands != FormatStyle::OAS_DontAlign)) ||
        (!CurrentState.LastOperatorWrapped && BreakBeforeOperator)) {
      CurrentState.NoLineBreakInOperand = true;
    }
  }

  State.Column += Spaces;
  if (Current.isNot(tok::comment) && Previous.is(tok::l_paren) &&
      Previous.Previous &&
      (Previous.Previous->is(tok::kw_for) || Previous.Previous->isIf())) {
    // Treat the condition inside an if as if it was a second function
    // parameter, i.e. let nested calls have a continuation indent.
    CurrentState.LastSpace = State.Column;
    CurrentState.NestedBlockIndent = State.Column;
  } else if (!Current.isOneOf(tok::comment, tok::caret) &&
             ((Previous.is(tok::comma) &&
               Previous.isNot(TT_OverloadedOperator)) ||
              (Previous.is(tok::colon) && Previous.is(TT_ObjCMethodExpr)))) {
    CurrentState.LastSpace = State.Column;
  } else if (Previous.is(TT_CtorInitializerColon) &&
             (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
             Style.BreakConstructorInitializers ==
                 FormatStyle::BCIS_AfterColon) {
    CurrentState.Indent = State.Column;
    CurrentState.LastSpace = State.Column;
  } else if (Previous.isOneOf(TT_ConditionalExpr, TT_CtorInitializerColon)) {
    CurrentState.LastSpace = State.Column;
  } else if (Previous.is(TT_BinaryOperator) &&
             ((Previous.getPrecedence() != prec::Assignment &&
               (Previous.isNot(tok::lessless) || Previous.OperatorIndex != 0 ||
                Previous.NextOperator)) ||
              Current.StartsBinaryExpression)) {
    // Indent relative to the RHS of the expression unless this is a simple
    // assignment without binary expression on the RHS.
    if (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None)
      CurrentState.LastSpace = State.Column;
  } else if (Previous.is(TT_InheritanceColon)) {
    CurrentState.Indent = State.Column;
    CurrentState.LastSpace = State.Column;
  } else if (Current.is(TT_CSharpGenericTypeConstraintColon)) {
    CurrentState.ColonPos = State.Column;
  } else if (Previous.opensScope()) {
    // If a function has a trailing call, indent all parameters from the
    // opening parenthesis. This avoids confusing indents like:
    //   OuterFunction(InnerFunctionCall( // break
    //       ParameterToInnerFunction))   // break
    //       .SecondInnerFunctionCall();
    if (Previous.MatchingParen) {
      const FormatToken *Next = Previous.MatchingParen->getNextNonComment();
      if (Next && Next->isMemberAccess() && State.Stack.size() > 1 &&
          State.Stack[State.Stack.size() - 2].CallContinuation == 0) {
        CurrentState.LastSpace = State.Column;
      }
    }
  }
}

unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
                                                 bool DryRun) {
  FormatToken &Current = *State.NextToken;
  assert(State.NextToken->Previous);
  const FormatToken &Previous = *State.NextToken->Previous;
  auto &CurrentState = State.Stack.back();

  // Extra penalty that needs to be added because of the way certain line
  // breaks are chosen.
  unsigned Penalty = 0;

  const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
  const FormatToken *NextNonComment = Previous.getNextNonComment();
  if (!NextNonComment)
    NextNonComment = &Current;
  // The first line break on any NestingLevel causes an extra penalty in order
  // prefer similar line breaks.
  if (!CurrentState.ContainsLineBreak)
    Penalty += 15;
  CurrentState.ContainsLineBreak = true;

  Penalty += State.NextToken->SplitPenalty;

  // Breaking before the first "<<" is generally not desirable if the LHS is
  // short. Also always add the penalty if the LHS is split over multiple lines
  // to avoid unnecessary line breaks that just work around this penalty.
  if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess == 0 &&
      (State.Column <= Style.ColumnLimit / 3 ||
       CurrentState.BreakBeforeParameter)) {
    Penalty += Style.PenaltyBreakFirstLessLess;
  }

  State.Column = getNewLineColumn(State);

  // Add Penalty proportional to amount of whitespace away from FirstColumn
  // This tends to penalize several lines that are far-right indented,
  // and prefers a line-break prior to such a block, e.g:
  //
  // Constructor() :
  //   member(value), looooooooooooooooong_member(
  //                      looooooooooong_call(param_1, param_2, param_3))
  // would then become
  // Constructor() :
  //   member(value),
  //   looooooooooooooooong_member(
  //       looooooooooong_call(param_1, param_2, param_3))
  if (State.Column > State.FirstIndent) {
    Penalty +=
        Style.PenaltyIndentedWhitespace * (State.Column - State.FirstIndent);
  }

  // Indent nested blocks relative to this column, unless in a very specific
  // JavaScript special case where:
  //
  //   var loooooong_name =
  //       function() {
  //     // code
  //   }
  //
  // is common and should be formatted like a free-standing function. The same
  // goes for wrapping before the lambda return type arrow.
  if (Current.isNot(TT_LambdaArrow) &&
      (!Style.isJavaScript() || Current.NestingLevel != 0 ||
       !PreviousNonComment || PreviousNonComment->isNot(tok::equal) ||
       !Current.isOneOf(Keywords.kw_async, Keywords.kw_function))) {
    CurrentState.NestedBlockIndent = State.Column;
  }

  if (NextNonComment->isMemberAccess()) {
    if (CurrentState.CallContinuation == 0)
      CurrentState.CallContinuation = State.Column;
  } else if (NextNonComment->is(TT_SelectorName)) {
    if (!CurrentState.ObjCSelectorNameFound) {
      if (NextNonComment->LongestObjCSelectorName == 0) {
        CurrentState.AlignColons = false;
      } else {
        CurrentState.ColonPos =
            (shouldIndentWrappedSelectorName(Style, State.Line->Type)
                 ? std::max(CurrentState.Indent,
                            State.FirstIndent + Style.ContinuationIndentWidth)
                 : CurrentState.Indent) +
            std::max(NextNonComment->LongestObjCSelectorName,
                     NextNonComment->ColumnWidth);
      }
    } else if (CurrentState.AlignColons &&
               CurrentState.ColonPos <= NextNonComment->ColumnWidth) {
      CurrentState.ColonPos = State.Column + NextNonComment->ColumnWidth;
    }
  } else if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
             PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
    // FIXME: This is hacky, find a better way. The problem is that in an ObjC
    // method expression, the block should be aligned to the line starting it,
    // e.g.:
    //   [aaaaaaaaaaaaaaa aaaaaaaaa: \\ break for some reason
    //                        ^(int *i) {
    //                            // ...
    //                        }];
    // Thus, we set LastSpace of the next higher NestingLevel, to which we move
    // when we consume all of the "}"'s FakeRParens at the "{".
    if (State.Stack.size() > 1) {
      State.Stack[State.Stack.size() - 2].LastSpace =
          std::max(CurrentState.LastSpace, CurrentState.Indent) +
          Style.ContinuationIndentWidth;
    }
  }

  if ((PreviousNonComment &&
       PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
       !CurrentState.AvoidBinPacking) ||
      Previous.is(TT_BinaryOperator)) {
    CurrentState.BreakBeforeParameter = false;
  }
  if (PreviousNonComment &&
      (PreviousNonComment->isOneOf(TT_TemplateCloser, TT_JavaAnnotation) ||
       PreviousNonComment->ClosesRequiresClause) &&
      Current.NestingLevel == 0) {
    CurrentState.BreakBeforeParameter = false;
  }
  if (NextNonComment->is(tok::question) ||
      (PreviousNonComment && PreviousNonComment->is(tok::question))) {
    CurrentState.BreakBeforeParameter = true;
  }
  if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore)
    CurrentState.BreakBeforeParameter = false;

  if (!DryRun) {
    unsigned MaxEmptyLinesToKeep = Style.MaxEmptyLinesToKeep + 1;
    if (Current.is(tok::r_brace) && Current.MatchingParen &&
        // Only strip trailing empty lines for l_braces that have children, i.e.
        // for function expressions (lambdas, arrows, etc).
        !Current.MatchingParen->Children.empty()) {
      // lambdas and arrow functions are expressions, thus their r_brace is not
      // on its own line, and thus not covered by UnwrappedLineFormatter's logic
      // about removing empty lines on closing blocks. Special case them here.
      MaxEmptyLinesToKeep = 1;
    }
    unsigned Newlines =
        std::max(1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
    bool ContinuePPDirective =
        State.Line->InPPDirective && State.Line->Type != LT_ImportStatement;
    Whitespaces.replaceWhitespace(Current, Newlines, State.Column, State.Column,
                                  CurrentState.IsAligned, ContinuePPDirective);
  }

  if (!Current.isTrailingComment())
    CurrentState.LastSpace = State.Column;
  if (Current.is(tok::lessless)) {
    // If we are breaking before a "<<", we always want to indent relative to
    // RHS. This is necessary only for "<<", as we special-case it and don't
    // always indent relative to the RHS.
    CurrentState.LastSpace += 3; // 3 -> width of "<< ".
  }

  State.StartOfLineLevel = Current.NestingLevel;
  State.LowestLevelOnLine = Current.NestingLevel;

  // Any break on this level means that the parent level has been broken
  // and we need to avoid bin packing there.
  bool NestedBlockSpecialCase =
      (!Style.isCpp() && Current.is(tok::r_brace) && State.Stack.size() > 1 &&
       State.Stack[State.Stack.size() - 2].NestedBlockInlined) ||
      (Style.Language == FormatStyle::LK_ObjC && Current.is(tok::r_brace) &&
       State.Stack.size() > 1 && !Style.ObjCBreakBeforeNestedBlockParam);
  // Do not force parameter break for statements with requires expressions.
  NestedBlockSpecialCase =
      NestedBlockSpecialCase ||
      (Current.MatchingParen &&
       Current.MatchingParen->is(TT_RequiresExpressionLBrace));
  if (!NestedBlockSpecialCase) {
    auto ParentLevelIt = std::next(State.Stack.rbegin());
    if (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope &&
        Current.MatchingParen && Current.MatchingParen->is(TT_LambdaLBrace)) {
      // If the first character on the new line is a lambda's closing brace, the
      // stack still contains that lambda's parenthesis. As such, we need to
      // recurse further down the stack than usual to find the parenthesis level
      // containing the lambda, which is where we want to set
      // BreakBeforeParameter.
      //
      // We specifically special case "OuterScope"-formatted lambdas here
      // because, when using that setting, breaking before the parameter
      // directly following the lambda is particularly unsightly. However, when
      // "OuterScope" is not set, the logic to find the parent parenthesis level
      // still appears to be sometimes incorrect. It has not been fixed yet
      // because it would lead to significant changes in existing behaviour.
      //
      // TODO: fix the non-"OuterScope" case too.
      auto FindCurrentLevel = [&](const auto &It) {
        return std::find_if(It, State.Stack.rend(), [](const auto &PState) {
          return PState.Tok != nullptr; // Ignore fake parens.
        });
      };
      auto MaybeIncrement = [&](const auto &It) {
        return It != State.Stack.rend() ? std::next(It) : It;
      };
      auto LambdaLevelIt = FindCurrentLevel(State.Stack.rbegin());
      auto LevelContainingLambdaIt =
          FindCurrentLevel(MaybeIncrement(LambdaLevelIt));
      ParentLevelIt = MaybeIncrement(LevelContainingLambdaIt);
    }
    for (auto I = ParentLevelIt, E = State.Stack.rend(); I != E; ++I)
      I->BreakBeforeParameter = true;
  }

  if (PreviousNonComment &&
      !PreviousNonComment->isOneOf(tok::comma, tok::colon, tok::semi) &&
      ((PreviousNonComment->isNot(TT_TemplateCloser) &&
        !PreviousNonComment->ClosesRequiresClause) ||
       Current.NestingLevel != 0) &&
      !PreviousNonComment->isOneOf(
          TT_BinaryOperator, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
          TT_LeadingJavaAnnotation) &&
      Current.isNot(TT_BinaryOperator) && !PreviousNonComment->opensScope() &&
      // We don't want to enforce line breaks for subsequent arguments just
      // because we have been forced to break before a lambda body.
      (!Style.BraceWrapping.BeforeLambdaBody ||
       Current.isNot(TT_LambdaLBrace))) {
    CurrentState.BreakBeforeParameter = true;
  }

  // If we break after { or the [ of an array initializer, we should also break
  // before the corresponding } or ].
  if (PreviousNonComment &&
      (PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
       opensProtoMessageField(*PreviousNonComment, Style))) {
    CurrentState.BreakBeforeClosingBrace = true;
  }

  if (PreviousNonComment && PreviousNonComment->is(tok::l_paren)) {
    CurrentState.BreakBeforeClosingParen =
        Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent;
  }

  if (PreviousNonComment && PreviousNonComment->is(TT_TemplateOpener))
    CurrentState.BreakBeforeClosingAngle = Style.BreakBeforeTemplateCloser;

  if (CurrentState.AvoidBinPacking) {
    // If we are breaking after '(', '{', '<', or this is the break after a ':'
    // to start a member initializer list in a constructor, this should not
    // be considered bin packing unless the relevant AllowAll option is false or
    // this is a dict/object literal.
    bool PreviousIsBreakingCtorInitializerColon =
        PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
        Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon;
    bool AllowAllConstructorInitializersOnNextLine =
        Style.PackConstructorInitializers == FormatStyle::PCIS_NextLine ||
        Style.PackConstructorInitializers == FormatStyle::PCIS_NextLineOnly;
    if (!(Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
          PreviousIsBreakingCtorInitializerColon) ||
        (!Style.AllowAllParametersOfDeclarationOnNextLine &&
         State.Line->MustBeDeclaration) ||
        (!Style.AllowAllArgumentsOnNextLine &&
         !State.Line->MustBeDeclaration) ||
        (!AllowAllConstructorInitializersOnNextLine &&
         PreviousIsBreakingCtorInitializerColon) ||
        Previous.is(TT_DictLiteral)) {
      CurrentState.BreakBeforeParameter = true;
    }

    // If we are breaking after a ':' to start a member initializer list,
    // and we allow all arguments on the next line, we should not break
    // before the next parameter.
    if (PreviousIsBreakingCtorInitializerColon &&
        AllowAllConstructorInitializersOnNextLine) {
      CurrentState.BreakBeforeParameter = false;
    }
  }

  if (mustBreakBinaryOperation(Current, Style))
    CurrentState.BreakBeforeParameter = true;

  return Penalty;
}

unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
  if (!State.NextToken || !State.NextToken->Previous)
    return 0;

  FormatToken &Current = *State.NextToken;
  const auto &CurrentState = State.Stack.back();

  if (CurrentState.IsCSharpGenericTypeConstraint &&
      Current.isNot(TT_CSharpGenericTypeConstraint)) {
    return CurrentState.ColonPos + 2;
  }

  const FormatToken &Previous = *Current.Previous;
  // If we are continuing an expression, we want to use the continuation indent.
  unsigned ContinuationIndent =
      std::max(CurrentState.LastSpace, CurrentState.Indent) +
      Style.ContinuationIndentWidth;
  const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
  const FormatToken *NextNonComment = Previous.getNextNonComment();
  if (!NextNonComment)
    NextNonComment = &Current;

  // Java specific bits.
  if (Style.Language == FormatStyle::LK_Java &&
      Current.isOneOf(Keywords.kw_implements, Keywords.kw_extends)) {
    return std::max(CurrentState.LastSpace,
                    CurrentState.Indent + Style.ContinuationIndentWidth);
  }

  // Indentation of the statement following a Verilog case label is taken care
  // of in moveStateToNextToken.
  if (Style.isVerilog() && PreviousNonComment &&
      Keywords.isVerilogEndOfLabel(*PreviousNonComment)) {
    return State.FirstIndent;
  }

  if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
      State.Line->First->is(tok::kw_enum)) {
    return (Style.IndentWidth * State.Line->First->IndentLevel) +
           Style.IndentWidth;
  }

  if ((NextNonComment->is(tok::l_brace) && NextNonComment->is(BK_Block)) ||
      (Style.isVerilog() && Keywords.isVerilogBegin(*NextNonComment))) {
    if (Current.NestingLevel == 0 ||
        (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope &&
         State.NextToken->is(TT_LambdaLBrace))) {
      return State.FirstIndent;
    }
    return CurrentState.Indent;
  }
  if (Current.is(TT_LambdaArrow) &&
      Previous.isOneOf(tok::kw_noexcept, tok::kw_mutable, tok::kw_constexpr,
                       tok::kw_consteval, tok::kw_static, TT_AttributeSquare)) {
    return ContinuationIndent;
  }
  if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
       (Current.is(tok::greater) && (Style.isProto() || Style.isTableGen()))) &&
      State.Stack.size() > 1) {
    if (Current.closesBlockOrBlockTypeList(Style))
      return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
    if (Current.MatchingParen && Current.MatchingParen->is(BK_BracedInit))
      return State.Stack[State.Stack.size() - 2].LastSpace;
    return State.FirstIndent;
  }
  // Indent a closing parenthesis at the previous level if followed by a semi,
  // const, or opening brace. This allows indentations such as:
  //     foo(
  //       a,
  //     );
  //     int Foo::getter(
  //         //
  //     ) const {
  //       return foo;
  //     }
  //     function foo(
  //       a,
  //     ) {
  //       code(); //
  //     }
  if (Current.is(tok::r_paren) && State.Stack.size() > 1 &&
      (!Current.Next ||
       Current.Next->isOneOf(tok::semi, tok::kw_const, tok::l_brace))) {
    return State.Stack[State.Stack.size() - 2].LastSpace;
  }
  // When DAGArg closer exists top of line, it should be aligned in the similar
  // way as function call above.
  if (Style.isTableGen() && Current.is(TT_TableGenDAGArgCloser) &&
      State.Stack.size() > 1) {
    return State.Stack[State.Stack.size() - 2].LastSpace;
  }
  if (Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent &&
      (Current.is(tok::r_paren) ||
       (Current.is(tok::r_brace) && Current.MatchingParen &&
        Current.MatchingParen->is(BK_BracedInit))) &&
      State.Stack.size() > 1) {
    return State.Stack[State.Stack.size() - 2].LastSpace;
  }
  if (Style.BreakBeforeTemplateCloser && Current.is(TT_TemplateCloser) &&
      State.Stack.size() > 1) {
    return State.Stack[State.Stack.size() - 2].LastSpace;
  }
  if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
    return State.Stack[State.Stack.size() - 2].LastSpace;
  // Field labels in a nested type should be aligned to the brace. For example
  // in ProtoBuf:
  //   optional int32 b = 2 [(foo_options) = {aaaaaaaaaaaaaaaaaaa: 123,
  //                                          bbbbbbbbbbbbbbbbbbbbbbbb:"baz"}];
  // For Verilog, a quote following a brace is treated as an identifier.  And
  // Both braces and colons get annotated as TT_DictLiteral.  So we have to
  // check.
  if (Current.is(tok::identifier) && Current.Next &&
      (!Style.isVerilog() || Current.Next->is(tok::colon)) &&
      (Current.Next->is(TT_DictLiteral) ||
       (Style.isProto() && Current.Next->isOneOf(tok::less, tok::l_brace)))) {
    return CurrentState.Indent;
  }
  if (NextNonComment->is(TT_ObjCStringLiteral) &&
      State.StartOfStringLiteral != 0) {
    return State.StartOfStringLiteral - 1;
  }
  if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0)
    return State.StartOfStringLiteral;
  if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess != 0)
    return CurrentState.FirstLessLess;
  if (NextNonComment->isMemberAccess()) {
    if (CurrentState.CallContinuation == 0)
      return ContinuationIndent;
    return CurrentState.CallContinuation;
  }
  if (CurrentState.QuestionColumn != 0 &&
      ((NextNonComment->is(tok::colon) &&
        NextNonComment->is(TT_ConditionalExpr)) ||
       Previous.is(TT_ConditionalExpr))) {
    if (((NextNonComment->is(tok::colon) && NextNonComment->Next &&
          !NextNonComment->Next->FakeLParens.empty() &&
          NextNonComment->Next->FakeLParens.back() == prec::Conditional) ||
         (Previous.is(tok::colon) && !Current.FakeLParens.empty() &&
          Current.FakeLParens.back() == prec::Conditional)) &&
        !CurrentState.IsWrappedConditional) {
      // NOTE: we may tweak this slightly:
      //    * not remove the 'lead' ContinuationIndentWidth
      //    * always un-indent by the operator when
      //    BreakBeforeTernaryOperators=true
      unsigned Indent = CurrentState.Indent;
      if (Style.AlignOperands != FormatStyle::OAS_DontAlign)
        Indent -= Style.ContinuationIndentWidth;
      if (Style.BreakBeforeTernaryOperators && CurrentState.UnindentOperator)
        Indent -= 2;
      return Indent;
    }
    return CurrentState.QuestionColumn;
  }
  if (Previous.is(tok::comma) && CurrentState.VariablePos != 0)
    return CurrentState.VariablePos;
  if (Current.is(TT_RequiresClause)) {
    if (Style.IndentRequiresClause)
      return CurrentState.Indent + Style.IndentWidth;
    switch (Style.RequiresClausePosition) {
    case FormatStyle::RCPS_OwnLine:
    case FormatStyle::RCPS_WithFollowing:
    case FormatStyle::RCPS_OwnLineWithBrace:
      return CurrentState.Indent;
    default:
      break;
    }
  }
  if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
                              TT_InheritanceComma)) {
    return State.FirstIndent + Style.ConstructorInitializerIndentWidth;
  }
  if ((PreviousNonComment &&
       (PreviousNonComment->ClosesTemplateDeclaration ||
        PreviousNonComment->ClosesRequiresClause ||
        (PreviousNonComment->is(TT_AttributeMacro) &&
         Current.isNot(tok::l_paren)) ||
        PreviousNonComment->isOneOf(
            TT_AttributeRParen, TT_AttributeSquare, TT_FunctionAnnotationRParen,
            TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
      (!Style.IndentWrappedFunctionNames &&
       NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName))) {
    return std::max(CurrentState.LastSpace, CurrentState.Indent);
  }
  if (NextNonComment->is(TT_SelectorName)) {
    if (!CurrentState.ObjCSelectorNameFound) {
      unsigned MinIndent = CurrentState.Indent;
      if (shouldIndentWrappedSelectorName(Style, State.Line->Type)) {
        MinIndent = std::max(MinIndent,
                             State.FirstIndent + Style.ContinuationIndentWidth);
      }
      // If LongestObjCSelectorName is 0, we are indenting the first
      // part of an ObjC selector (or a selector component which is
      // not colon-aligned due to block formatting).
      //
      // Otherwise, we are indenting a subsequent part of an ObjC
      // selector which should be colon-aligned to the longest
      // component of the ObjC selector.
      //
      // In either case, we want to respect Style.IndentWrappedFunctionNames.
      return MinIndent +
             std::max(NextNonComment->LongestObjCSelectorName,
                      NextNonComment->ColumnWidth) -
             NextNonComment->ColumnWidth;
    }
    if (!CurrentState.AlignColons)
      return CurrentState.Indent;
    if (CurrentState.ColonPos > NextNonComment->ColumnWidth)
      return CurrentState.ColonPos - NextNonComment->ColumnWidth;
    return CurrentState.Indent;
  }
  if (NextNonComment->is(tok::colon) && NextNonComment->is(TT_ObjCMethodExpr))
    return CurrentState.ColonPos;
  if (NextNonComment->is(TT_ArraySubscriptLSquare)) {
    if (CurrentState.StartOfArraySubscripts != 0) {
      return CurrentState.StartOfArraySubscripts;
    } else if (Style.isCSharp()) { // C# allows `["key"] = value` inside object
                                   // initializers.
      return CurrentState.Indent;
    }
    return ContinuationIndent;
  }

  // OpenMP clauses want to get additional indentation when they are pushed onto
  // the next line.
  if (State.Line->InPragmaDirective) {
    FormatToken *PragmaType = State.Line->First->Next->Next;
    if (PragmaType && PragmaType->TokenText == "omp")
      return CurrentState.Indent + Style.ContinuationIndentWidth;
  }

  // This ensure that we correctly format ObjC methods calls without inputs,
  // i.e. where the last element isn't selector like: [callee method];
  if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 &&
      NextNonComment->Next && NextNonComment->Next->is(TT_ObjCMethodExpr)) {
    return CurrentState.Indent;
  }

  if (NextNonComment->isOneOf(TT_StartOfName, TT_PointerOrReference) ||
      Previous.isOneOf(tok::coloncolon, tok::equal, TT_JsTypeColon)) {
    return ContinuationIndent;
  }
  if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
      PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
    return ContinuationIndent;
  }
  if (NextNonComment->is(TT_CtorInitializerComma))
    return CurrentState.Indent;
  if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
      Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon) {
    return CurrentState.Indent;
  }
  if (PreviousNonComment && PreviousNonComment->is(TT_InheritanceColon) &&
      Style.BreakInheritanceList == FormatStyle::BILS_AfterColon) {
    return CurrentState.Indent;
  }
  if (Previous.is(tok::r_paren) &&
      Previous.isNot(TT_TableGenDAGArgOperatorToBreak) &&
      !Current.isBinaryOperator() &&
      !Current.isOneOf(tok::colon, tok::comment)) {
    return ContinuationIndent;
  }
  if (Current.is(TT_ProtoExtensionLSquare))
    return CurrentState.Indent;
  if (Current.isBinaryOperator() && CurrentState.UnindentOperator) {
    return CurrentState.Indent - Current.Tok.getLength() -
           Current.SpacesRequiredBefore;
  }
  if (Current.is(tok::comment) && NextNonComment->isBinaryOperator() &&
      CurrentState.UnindentOperator) {
    return CurrentState.Indent - NextNonComment->Tok.getLength() -
           NextNonComment->SpacesRequiredBefore;
  }
  if (CurrentState.Indent == State.FirstIndent && PreviousNonComment &&
      !PreviousNonComment->isOneOf(tok::r_brace, TT_CtorInitializerComma)) {
    // Ensure that we fall back to the continuation indent width instead of
    // just flushing continuations left.
    return CurrentState.Indent + Style.ContinuationIndentWidth;
  }
  return CurrentState.Indent;
}

static bool hasNestedBlockInlined(const FormatToken *Previous,
                                  const FormatToken &Current,
                                  const FormatStyle &Style) {
  if (Previous->isNot(tok::l_paren))
    return true;
  if (Previous->ParameterCount > 1)
    return true;

  // Also a nested block if contains a lambda inside function with 1 parameter.
  return Style.BraceWrapping.BeforeLambdaBody && Current.is(TT_LambdaLSquare);
}

unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
                                                    bool DryRun, bool Newline) {
  assert(State.Stack.size());
  const FormatToken &Current = *State.NextToken;
  auto &CurrentState = State.Stack.back();

  if (Current.is(TT_CSharpGenericTypeConstraint))
    CurrentState.IsCSharpGenericTypeConstraint = true;
  if (Current.isOneOf(tok::comma, TT_BinaryOperator))
    CurrentState.NoLineBreakInOperand = false;
  if (Current.isOneOf(TT_InheritanceColon, TT_CSharpGenericTypeConstraintColon))
    CurrentState.AvoidBinPacking = true;
  if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator)) {
    if (CurrentState.FirstLessLess == 0)
      CurrentState.FirstLessLess = State.Column;
    else
      CurrentState.LastOperatorWrapped = Newline;
  }
  if (Current.is(TT_BinaryOperator) && Current.isNot(tok::lessless))
    CurrentState.LastOperatorWrapped = Newline;
  if (Current.is(TT_ConditionalExpr) && Current.Previous &&
      Current.Previous->isNot(TT_ConditionalExpr)) {
    CurrentState.LastOperatorWrapped = Newline;
  }
  if (Current.is(TT_ArraySubscriptLSquare) &&
      CurrentState.StartOfArraySubscripts == 0) {
    CurrentState.StartOfArraySubscripts = State.Column;
  }

  auto IsWrappedConditional = [](const FormatToken &Tok) {
    if (!(Tok.is(TT_ConditionalExpr) && Tok.is(tok::question)))
      return false;
    if (Tok.MustBreakBefore)
      return true;

    const FormatToken *Next = Tok.getNextNonComment();
    return Next && Next->MustBreakBefore;
  };
  if (IsWrappedConditional(Current))
    CurrentState.IsWrappedConditional = true;
  if (Style.BreakBeforeTernaryOperators && Current.is(tok::question))
    CurrentState.QuestionColumn = State.Column;
  if (!Style.BreakBeforeTernaryOperators && Current.isNot(tok::colon)) {
    const FormatToken *Previous = Current.Previous;
    while (Previous && Previous->isTrailingComment())
      Previous = Previous->Previous;
    if (Previous && Previous->is(tok::question))
      CurrentState.QuestionColumn = State.Column;
  }
  if (!Current.opensScope() && !Current.closesScope() &&
      Current.isNot(TT_PointerOrReference)) {
    State.LowestLevelOnLine =
        std::min(State.LowestLevelOnLine, Current.NestingLevel);
  }
  if (Current.isMemberAccess())
    CurrentState.StartOfFunctionCall = !Current.NextOperator ? 0 : State.Column;
  if (Current.is(TT_SelectorName))
    CurrentState.ObjCSelectorNameFound = true;
  if (Current.is(TT_CtorInitializerColon) &&
      Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon) {
    // Indent 2 from the column, so:
    // SomeClass::SomeClass()
    //     : First(...), ...
    //       Next(...)
    //       ^ line up here.
    CurrentState.Indent = State.Column + (Style.BreakConstructorInitializers ==
                                                  FormatStyle::BCIS_BeforeComma
                                              ? 0
                                              : 2);
    CurrentState.NestedBlockIndent = CurrentState.Indent;
    if (Style.PackConstructorInitializers > FormatStyle::PCIS_BinPack) {
      CurrentState.AvoidBinPacking = true;
      CurrentState.BreakBeforeParameter =
          Style.ColumnLimit > 0 &&
          Style.PackConstructorInitializers != FormatStyle::PCIS_NextLine &&
          Style.PackConstructorInitializers != FormatStyle::PCIS_NextLineOnly;
    } else {
      CurrentState.BreakBeforeParameter = false;
    }
  }
  if (Current.is(TT_CtorInitializerColon) &&
      Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon) {
    CurrentState.Indent =
        State.FirstIndent + Style.ConstructorInitializerIndentWidth;
    CurrentState.NestedBlockIndent = CurrentState.Indent;
    if (Style.PackConstructorInitializers > FormatStyle::PCIS_BinPack)
      CurrentState.AvoidBinPacking = true;
    else
      CurrentState.BreakBeforeParameter = false;
  }
  if (Current.is(TT_InheritanceColon)) {
    CurrentState.Indent =
        State.FirstIndent + Style.ConstructorInitializerIndentWidth;
  }
  if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
    CurrentState.NestedBlockIndent = State.Column + Current.ColumnWidth + 1;
  if (Current.isOneOf(TT_LambdaLSquare, TT_LambdaArrow))
    CurrentState.LastSpace = State.Column;
  if (Current.is(TT_RequiresExpression) &&
      Style.RequiresExpressionIndentation == FormatStyle::REI_Keyword) {
    CurrentState.NestedBlockIndent = State.Column;
  }

  // Insert scopes created by fake parenthesis.
  const FormatToken *Previous = Current.getPreviousNonComment();

  // Add special behavior to support a format commonly used for JavaScript
  // closures:
  //   SomeFunction(function() {
  //     foo();
  //     bar();
  //   }, a, b, c);
  if (Current.isNot(tok::comment) && !Current.ClosesRequiresClause &&
      Previous && Previous->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) &&
      Previous->isNot(TT_DictLiteral) && State.Stack.size() > 1 &&
      !CurrentState.HasMultipleNestedBlocks) {
    if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
      for (ParenState &PState : llvm::drop_end(State.Stack))
        PState.NoLineBreak = true;
    State.Stack[State.Stack.size() - 2].NestedBlockInlined = false;
  }
  if (Previous && (Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr) ||
                   (Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) &&
                    !Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)))) {
    CurrentState.NestedBlockInlined =
        !Newline && hasNestedBlockInlined(Previous, Current, Style);
  }

  moveStatePastFakeLParens(State, Newline);
  moveStatePastScopeCloser(State);
  // Do not use CurrentState here, since the two functions before may change the
  // Stack.
  bool AllowBreak = !State.Stack.back().NoLineBreak &&
                    !State.Stack.back().NoLineBreakInOperand;
  moveStatePastScopeOpener(State, Newline);
  moveStatePastFakeRParens(State);

  if (Current.is(TT_ObjCStringLiteral) && State.StartOfStringLiteral == 0)
    State.StartOfStringLiteral = State.Column + 1;
  if (Current.is(TT_CSharpStringLiteral) && State.StartOfStringLiteral == 0) {
    State.StartOfStringLiteral = State.Column + 1;
  } else if (Current.is(TT_TableGenMultiLineString) &&
             State.StartOfStringLiteral == 0) {
    State.StartOfStringLiteral = State.Column + 1;
  } else if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
    State.StartOfStringLiteral = State.Column;
  } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
             !Current.isStringLiteral()) {
    State.StartOfStringLiteral = 0;
  }

  State.Column += Current.ColumnWidth;
  State.NextToken = State.NextToken->Next;
  // Verilog case labels are on the same unwrapped lines as the statements that
  // follow. TokenAnnotator identifies them and sets MustBreakBefore.
  // Indentation is taken care of here. A case label can only have 1 statement
  // in Verilog, so we don't have to worry about lines that follow.
  if (Style.isVerilog() && State.NextToken &&
      State.NextToken->MustBreakBefore &&
      Keywords.isVerilogEndOfLabel(Current)) {
    State.FirstIndent += Style.IndentWidth;
    CurrentState.Indent = State.FirstIndent;
  }

  unsigned Penalty =
      handleEndOfLine(Current, State, DryRun, AllowBreak, Newline);

  if (Current.Role)
    Current.Role->formatFromToken(State, this, DryRun);
  // If the previous has a special role, let it consume tokens as appropriate.
  // It is necessary to start at the previous token for the only implemented
  // role (comma separated list). That way, the decision whether or not to break
  // after the "{" is already done and both options are tried and evaluated.
  // FIXME: This is ugly, find a better way.
  if (Previous && Previous->Role)
    Penalty += Previous->Role->formatAfterToken(State, this, DryRun);

  return Penalty;
}

void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
                                                    bool Newline) {
  const FormatToken &Current = *State.NextToken;
  if (Current.FakeLParens.empty())
    return;

  const FormatToken *Previous = Current.getPreviousNonComment();

  // Don't add extra indentation for the first fake parenthesis after
  // 'return', assignments, opening <({[, or requires clauses. The indentation
  // for these cases is special cased.
  bool SkipFirstExtraIndent =
      Previous &&
      (Previous->opensScope() ||
       Previous->isOneOf(tok::semi, tok::kw_return, TT_RequiresClause) ||
       (Previous->getPrecedence() == prec::Assignment &&
        Style.AlignOperands != FormatStyle::OAS_DontAlign) ||
       Previous->is(TT_ObjCMethodExpr));
  for (const auto &PrecedenceLevel : llvm::reverse(Current.FakeLParens)) {
    const auto &CurrentState = State.Stack.back();
    ParenState NewParenState = CurrentState;
    NewParenState.Tok = nullptr;
    NewParenState.ContainsLineBreak = false;
    NewParenState.LastOperatorWrapped = true;
    NewParenState.IsChainedConditional = false;
    NewParenState.IsWrappedConditional = false;
    NewParenState.UnindentOperator = false;
    NewParenState.NoLineBreak =
        NewParenState.NoLineBreak || CurrentState.NoLineBreakInOperand;

    // Don't propagate AvoidBinPacking into subexpressions of arg/param lists.
    if (PrecedenceLevel > prec::Comma)
      NewParenState.AvoidBinPacking = false;

    // Indent from 'LastSpace' unless these are fake parentheses encapsulating
    // a builder type call after 'return' or, if the alignment after opening
    // brackets is disabled.
    if (!Current.isTrailingComment() &&
        (Style.AlignOperands != FormatStyle::OAS_DontAlign ||
         PrecedenceLevel < prec::Assignment) &&
        (!Previous || Previous->isNot(tok::kw_return) ||
         (Style.Language != FormatStyle::LK_Java && PrecedenceLevel > 0)) &&
        (Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign ||
         PrecedenceLevel > prec::Comma || Current.NestingLevel == 0) &&
        (!Style.isTableGen() ||
         (Previous && Previous->isOneOf(TT_TableGenDAGArgListComma,
                                        TT_TableGenDAGArgListCommaToBreak)))) {
      NewParenState.Indent = std::max(
          std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
    }

    // Special case for generic selection expressions, its comma-separated
    // expressions are not aligned to the opening paren like regular calls, but
    // rather continuation-indented relative to the _Generic keyword.
    if (Previous && Previous->endsSequence(tok::l_paren, tok::kw__Generic) &&
        State.Stack.size() > 1) {
      NewParenState.Indent = State.Stack[State.Stack.size() - 2].Indent +
                             Style.ContinuationIndentWidth;
    }

    if ((shouldUnindentNextOperator(Current) ||
         (Previous &&
          (PrecedenceLevel == prec::Conditional &&
           Previous->is(tok::question) && Previous->is(TT_ConditionalExpr)))) &&
        !Newline) {
      // If BreakBeforeBinaryOperators is set, un-indent a bit to account for
      // the operator and keep the operands aligned.
      if (Style.AlignOperands == FormatStyle::OAS_AlignAfterOperator)
        NewParenState.UnindentOperator = true;
      // Mark indentation as alignment if the expression is aligned.
      if (Style.AlignOperands != FormatStyle::OAS_DontAlign)
        NewParenState.IsAligned = true;
    }

    // Do not indent relative to the fake parentheses inserted for "." or "->".
    // This is a special case to make the following to statements consistent:
    //   OuterFunction(InnerFunctionCall( // break
    //       ParameterToInnerFunction));
    //   OuterFunction(SomeObject.InnerFunctionCall( // break
    //       ParameterToInnerFunction));
    if (PrecedenceLevel > prec::Unknown)
      NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
    if (PrecedenceLevel != prec::Conditional &&
        Current.isNot(TT_UnaryOperator) &&
        Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign) {
      NewParenState.StartOfFunctionCall = State.Column;
    }

    // Indent conditional expressions, unless they are chained "else-if"
    // conditionals. Never indent expression where the 'operator' is ',', ';' or
    // an assignment (i.e. *I <= prec::Assignment) as those have different
    // indentation rules. Indent other expression, unless the indentation needs
    // to be skipped.
    if (PrecedenceLevel == prec::Conditional && Previous &&
        Previous->is(tok::colon) && Previous->is(TT_ConditionalExpr) &&
        &PrecedenceLevel == &Current.FakeLParens.back() &&
        !CurrentState.IsWrappedConditional) {
      NewParenState.IsChainedConditional = true;
      NewParenState.UnindentOperator = State.Stack.back().UnindentOperator;
    } else if (PrecedenceLevel == prec::Conditional ||
               (!SkipFirstExtraIndent && PrecedenceLevel > prec::Assignment &&
                !Current.isTrailingComment())) {
      NewParenState.Indent += Style.ContinuationIndentWidth;
    }
    if ((Previous && !Previous->opensScope()) || PrecedenceLevel != prec::Comma)
      NewParenState.BreakBeforeParameter = false;
    State.Stack.push_back(NewParenState);
    SkipFirstExtraIndent = false;
  }
}

void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
  for (unsigned i = 0, e = State.NextToken->FakeRParens; i != e; ++i) {
    unsigned VariablePos = State.Stack.back().VariablePos;
    if (State.Stack.size() == 1) {
      // Do not pop the last element.
      break;
    }
    State.Stack.pop_back();
    State.Stack.back().VariablePos = VariablePos;
  }

  if (State.NextToken->ClosesRequiresClause && Style.IndentRequiresClause) {
    // Remove the indentation of the requires clauses (which is not in Indent,
    // but in LastSpace).
    State.Stack.back().LastSpace -= Style.IndentWidth;
  }
}

void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
                                                    bool Newline) {
  const FormatToken &Current = *State.NextToken;
  if (!Current.opensScope())
    return;

  const auto &CurrentState = State.Stack.back();

  // Don't allow '<' or '(' in C# generic type constraints to start new scopes.
  if (Current.isOneOf(tok::less, tok::l_paren) &&
      CurrentState.IsCSharpGenericTypeConstraint) {
    return;
  }

  if (Current.MatchingParen && Current.is(BK_Block)) {
    moveStateToNewBlock(State, Newline);
    return;
  }

  unsigned NewIndent;
  unsigned LastSpace = CurrentState.LastSpace;
  bool AvoidBinPacking;
  bool BreakBeforeParameter = false;
  unsigned NestedBlockIndent = std::max(CurrentState.StartOfFunctionCall,
                                        CurrentState.NestedBlockIndent);
  if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
      opensProtoMessageField(Current, Style)) {
    if (Current.opensBlockOrBlockTypeList(Style)) {
      NewIndent = Style.IndentWidth +
                  std::min(State.Column, CurrentState.NestedBlockIndent);
    } else if (Current.is(tok::l_brace)) {
      const auto Width = Style.BracedInitializerIndentWidth;
      NewIndent = CurrentState.LastSpace +
                  (Width < 0 ? Style.ContinuationIndentWidth : Width);
    } else {
      NewIndent = CurrentState.LastSpace + Style.ContinuationIndentWidth;
    }
    const FormatToken *NextNonComment = Current.getNextNonComment();
    bool EndsInComma = Current.MatchingParen &&
                       Current.MatchingParen->Previous &&
                       Current.MatchingParen->Previous->is(tok::comma);
    AvoidBinPacking = EndsInComma || Current.is(TT_DictLiteral) ||
                      Style.isProto() || !Style.BinPackArguments ||
                      (NextNonComment && NextNonComment->isOneOf(
                                             TT_DesignatedInitializerPeriod,
                                             TT_DesignatedInitializerLSquare));
    BreakBeforeParameter = EndsInComma;
    if (Current.ParameterCount > 1)
      NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
  } else {
    NewIndent =
        Style.ContinuationIndentWidth +
        std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall);

    if (Style.isTableGen() && Current.is(TT_TableGenDAGArgOpenerToBreak) &&
        Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakElements) {
      // For the case the next token is a TableGen DAGArg operator identifier
      // that is not marked to have a line break after it.
      // In this case the option DAS_BreakElements requires to align the
      // DAGArg elements to the operator.
      const FormatToken *Next = Current.Next;
      if (Next && Next->is(TT_TableGenDAGArgOperatorID))
        NewIndent = State.Column + Next->TokenText.size() + 2;
    }

    // Ensure that different different brackets force relative alignment, e.g.:
    // void SomeFunction(vector<  // break
    //                       int> v);
    // FIXME: We likely want to do this for more combinations of brackets.
    if (Current.is(tok::less) && Current.ParentBracket == tok::l_paren) {
      NewIndent = std::max(NewIndent, CurrentState.Indent);
      LastSpace = std::max(LastSpace, CurrentState.Indent);
    }

    bool EndsInComma =
        Current.MatchingParen &&
        Current.MatchingParen->getPreviousNonComment() &&
        Current.MatchingParen->getPreviousNonComment()->is(tok::comma);

    // If ObjCBinPackProtocolList is unspecified, fall back to BinPackParameters
    // for backwards compatibility.
    bool ObjCBinPackProtocolList =
        (Style.ObjCBinPackProtocolList == FormatStyle::BPS_Auto &&
         Style.BinPackParameters == FormatStyle::BPPS_BinPack) ||
        Style.ObjCBinPackProtocolList == FormatStyle::BPS_Always;

    bool BinPackDeclaration =
        (State.Line->Type != LT_ObjCDecl &&
         Style.BinPackParameters == FormatStyle::BPPS_BinPack) ||
        (State.Line->Type == LT_ObjCDecl && ObjCBinPackProtocolList);

    bool GenericSelection =
        Current.getPreviousNonComment() &&
        Current.getPreviousNonComment()->is(tok::kw__Generic);

    AvoidBinPacking =
        (CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection ||
        (Style.isJavaScript() && EndsInComma) ||
        (State.Line->MustBeDeclaration && !BinPackDeclaration) ||
        (!State.Line->MustBeDeclaration && !Style.BinPackArguments) ||
        (Style.ExperimentalAutoDetectBinPacking &&
         (Current.is(PPK_OnePerLine) ||
          (!BinPackInconclusiveFunctions && Current.is(PPK_Inconclusive))));

    if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen &&
        Style.ObjCBreakBeforeNestedBlockParam) {
      if (Style.ColumnLimit) {
        // If this '[' opens an ObjC call, determine whether all parameters fit
        // into one line and put one per line if they don't.
        if (getLengthToMatchingParen(Current, State.Stack) + State.Column >
            getColumnLimit(State)) {
          BreakBeforeParameter = true;
        }
      } else {
        // For ColumnLimit = 0, we have to figure out whether there is or has to
        // be a line break within this call.
        for (const FormatToken *Tok = &Current;
             Tok && Tok != Current.MatchingParen; Tok = Tok->Next) {
          if (Tok->MustBreakBefore ||
              (Tok->CanBreakBefore && Tok->NewlinesBefore > 0)) {
            BreakBeforeParameter = true;
            break;
          }
        }
      }
    }

    if (Style.isJavaScript() && EndsInComma)
      BreakBeforeParameter = true;
  }
  // Generally inherit NoLineBreak from the current scope to nested scope.
  // However, don't do this for non-empty nested blocks, dict literals and
  // array literals as these follow different indentation rules.
  bool NoLineBreak =
      Current.Children.empty() &&
      !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) &&
      (CurrentState.NoLineBreak || CurrentState.NoLineBreakInOperand ||
       (Current.is(TT_TemplateOpener) &&
        CurrentState.ContainsUnwrappedBuilder));
  State.Stack.push_back(
      ParenState(&Current, NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
  auto &NewState = State.Stack.back();
  NewState.NestedBlockIndent = NestedBlockIndent;
  NewState.BreakBeforeParameter = BreakBeforeParameter;
  NewState.HasMultipleNestedBlocks = (Current.BlockParameterCount > 1);

  if (Style.BraceWrapping.BeforeLambdaBody && Current.Next &&
      Current.is(tok::l_paren)) {
    // Search for any parameter that is a lambda.
    FormatToken const *next = Current.Next;
    while (next) {
      if (next->is(TT_LambdaLSquare)) {
        NewState.HasMultipleNestedBlocks = true;
        break;
      }
      next = next->Next;
    }
  }

  NewState.IsInsideObjCArrayLiteral = Current.is(TT_ArrayInitializerLSquare) &&
                                      Current.Previous &&
                                      Current.Previous->is(tok::at);
}

void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
  const FormatToken &Current = *State.NextToken;
  if (!Current.closesScope())
    return;

  // If we encounter a closing ), ], } or >, we can remove a level from our
  // stacks.
  if (State.Stack.size() > 1 &&
      (Current.isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
       (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
       State.NextToken->is(TT_TemplateCloser) ||
       State.NextToken->is(TT_TableGenListCloser) ||
       (Current.is(tok::greater) && Current.is(TT_DictLiteral)))) {
    State.Stack.pop_back();
  }

  auto &CurrentState = State.Stack.back();

  // Reevaluate whether ObjC message arguments fit into one line.
  // If a receiver spans multiple lines, e.g.:
  //   [[object block:^{
  //     return 42;
  //   }] a:42 b:42];
  // BreakBeforeParameter is calculated based on an incorrect assumption
  // (it is checked whether the whole expression fits into one line without
  // considering a line break inside a message receiver).
  // We check whether arguments fit after receiver scope closer (into the same
  // line).
  if (CurrentState.BreakBeforeParameter && Current.MatchingParen &&
      Current.MatchingParen->Previous) {
    const FormatToken &CurrentScopeOpener = *Current.MatchingParen->Previous;
    if (CurrentScopeOpener.is(TT_ObjCMethodExpr) &&
        CurrentScopeOpener.MatchingParen) {
      int NecessarySpaceInLine =
          getLengthToMatchingParen(CurrentScopeOpener, State.Stack) +
          CurrentScopeOpener.TotalLength - Current.TotalLength - 1;
      if (State.Column + Current.ColumnWidth + NecessarySpaceInLine <=
          Style.ColumnLimit) {
        CurrentState.BreakBeforeParameter = false;
      }
    }
  }

  if (Current.is(tok::r_square)) {
    // If this ends the array subscript expr, reset the corresponding value.
    const FormatToken *NextNonComment = Current.getNextNonComment();
    if (NextNonComment && NextNonComment->isNot(tok::l_square))
      CurrentState.StartOfArraySubscripts = 0;
  }
}

void ContinuationIndenter::moveStateToNewBlock(LineState &State, bool NewLine) {
  if (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope &&
      State.NextToken->is(TT_LambdaLBrace) &&
      !State.Line->MightBeFunctionDecl) {
    State.Stack.back().NestedBlockIndent = State.FirstIndent;
  }
  unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
  // ObjC block sometimes follow special indentation rules.
  unsigned NewIndent =
      NestedBlockIndent + (State.NextToken->is(TT_ObjCBlockLBrace)
                               ? Style.ObjCBlockIndentWidth
                               : Style.IndentWidth);

  // Even when wrapping before lambda body, the left brace can still be added to
  // the same line. This occurs when checking whether the whole lambda body can
  // go on a single line. In this case we have to make sure there are no line
  // breaks in the body, otherwise we could just end up with a regular lambda
  // body without the brace wrapped.
  bool NoLineBreak = Style.BraceWrapping.BeforeLambdaBody && !NewLine &&
                     State.NextToken->is(TT_LambdaLBrace);

  State.Stack.push_back(ParenState(State.NextToken, NewIndent,
                                   State.Stack.back().LastSpace,
                                   /*AvoidBinPacking=*/true, NoLineBreak));
  State.Stack.back().NestedBlockIndent = NestedBlockIndent;
  State.Stack.back().BreakBeforeParameter = true;
}

static unsigned getLastLineEndColumn(StringRef Text, unsigned StartColumn,
                                     unsigned TabWidth,
                                     encoding::Encoding Encoding) {
  size_t LastNewlinePos = Text.find_last_of("\n");
  if (LastNewlinePos == StringRef::npos) {
    return StartColumn +
           encoding::columnWidthWithTabs(Text, StartColumn, TabWidth, Encoding);
  } else {
    return encoding::columnWidthWithTabs(Text.substr(LastNewlinePos),
                                         /*StartColumn=*/0, TabWidth, Encoding);
  }
}

unsigned ContinuationIndenter::reformatRawStringLiteral(
    const FormatToken &Current, LineState &State,
    const FormatStyle &RawStringStyle, bool DryRun, bool Newline) {
  unsigned StartColumn = State.Column - Current.ColumnWidth;
  StringRef OldDelimiter = *getRawStringDelimiter(Current.TokenText);
  StringRef NewDelimiter =
      getCanonicalRawStringDelimiter(Style, RawStringStyle.Language);
  if (NewDelimiter.empty())
    NewDelimiter = OldDelimiter;
  // The text of a raw string is between the leading 'R"delimiter(' and the
  // trailing 'delimiter)"'.
  unsigned OldPrefixSize = 3 + OldDelimiter.size();
  unsigned OldSuffixSize = 2 + OldDelimiter.size();
  // We create a virtual text environment which expects a null-terminated
  // string, so we cannot use StringRef.
  std::string RawText = std::string(
      Current.TokenText.substr(OldPrefixSize).drop_back(OldSuffixSize));
  if (NewDelimiter != OldDelimiter) {
    // Don't update to the canonical delimiter 'deli' if ')deli"' occurs in the
    // raw string.
    std::string CanonicalDelimiterSuffix = (")" + NewDelimiter + "\"").str();
    if (StringRef(RawText).contains(CanonicalDelimiterSuffix))
      NewDelimiter = OldDelimiter;
  }

  unsigned NewPrefixSize = 3 + NewDelimiter.size();
  unsigned NewSuffixSize = 2 + NewDelimiter.size();

  // The first start column is the column the raw text starts after formatting.
  unsigned FirstStartColumn = StartColumn + NewPrefixSize;

  // The next start column is the intended indentation a line break inside
  // the raw string at level 0. It is determined by the following rules:
  //   - if the content starts on newline, it is one level more than the current
  //     indent, and
  //   - if the content does not start on a newline, it is the first start
  //     column.
  // These rules have the advantage that the formatted content both does not
  // violate the rectangle rule and visually flows within the surrounding
  // source.
  bool ContentStartsOnNewline = Current.TokenText[OldPrefixSize] == '\n';
  // If this token is the last parameter (checked by looking if it's followed by
  // `)` and is not on a newline, the base the indent off the line's nested
  // block indent. Otherwise, base the indent off the arguments indent, so we
  // can achieve:
  //
  // fffffffffff(1, 2, 3, R"pb(
  //     key1: 1  #
  //     key2: 2)pb");
  //
  // fffffffffff(1, 2, 3,
  //             R"pb(
  //               key1: 1  #
  //               key2: 2
  //             )pb");
  //
  // fffffffffff(1, 2, 3,
  //             R"pb(
  //               key1: 1  #
  //               key2: 2
  //             )pb",
  //             5);
  unsigned CurrentIndent =
      (!Newline && Current.Next && Current.Next->is(tok::r_paren))
          ? State.Stack.back().NestedBlockIndent
          : State.Stack.back().Indent;
  unsigned NextStartColumn = ContentStartsOnNewline
                                 ? CurrentIndent + Style.IndentWidth
                                 : FirstStartColumn;

  // The last start column is the column the raw string suffix starts if it is
  // put on a newline.
  // The last start column is the intended indentation of the raw string postfix
  // if it is put on a newline. It is determined by the following rules:
  //   - if the raw string prefix starts on a newline, it is the column where
  //     that raw string prefix starts, and
  //   - if the raw string prefix does not start on a newline, it is the current
  //     indent.
  unsigned LastStartColumn =
      Current.NewlinesBefore ? FirstStartColumn - NewPrefixSize : CurrentIndent;

  std::pair<tooling::Replacements, unsigned> Fixes = internal::reformat(
      RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
      FirstStartColumn, NextStartColumn, LastStartColumn, "<stdin>",
      /*Status=*/nullptr);

  auto NewCode = applyAllReplacements(RawText, Fixes.first);
  tooling::Replacements NoFixes;
  if (!NewCode)
    return addMultilineToken(Current, State);
  if (!DryRun) {
    if (NewDelimiter != OldDelimiter) {
      // In 'R"delimiter(...', the delimiter starts 2 characters after the start
      // of the token.
      SourceLocation PrefixDelimiterStart =
          Current.Tok.getLocation().getLocWithOffset(2);
      auto PrefixErr = Whitespaces.addReplacement(tooling::Replacement(
          SourceMgr, PrefixDelimiterStart, OldDelimiter.size(), NewDelimiter));
      if (PrefixErr) {
        llvm::errs()
            << "Failed to update the prefix delimiter of a raw string: "
            << llvm::toString(std::move(PrefixErr)) << "\n";
      }
      // In 'R"delimiter(...)delimiter"', the suffix delimiter starts at
      // position length - 1 - |delimiter|.
      SourceLocation SuffixDelimiterStart =
          Current.Tok.getLocation().getLocWithOffset(Current.TokenText.size() -
                                                     1 - OldDelimiter.size());
      auto SuffixErr = Whitespaces.addReplacement(tooling::Replacement(
          SourceMgr, SuffixDelimiterStart, OldDelimiter.size(), NewDelimiter));
      if (SuffixErr) {
        llvm::errs()
            << "Failed to update the suffix delimiter of a raw string: "
            << llvm::toString(std::move(SuffixErr)) << "\n";
      }
    }
    SourceLocation OriginLoc =
        Current.Tok.getLocation().getLocWithOffset(OldPrefixSize);
    for (const tooling::Replacement &Fix : Fixes.first) {
      auto Err = Whitespaces.addReplacement(tooling::Replacement(
          SourceMgr, OriginLoc.getLocWithOffset(Fix.getOffset()),
          Fix.getLength(), Fix.getReplacementText()));
      if (Err) {
        llvm::errs() << "Failed to reformat raw string: "
                     << llvm::toString(std::move(Err)) << "\n";
      }
    }
  }
  unsigned RawLastLineEndColumn = getLastLineEndColumn(
      *NewCode, FirstStartColumn, Style.TabWidth, Encoding);
  State.Column = RawLastLineEndColumn + NewSuffixSize;
  // Since we're updating the column to after the raw string literal here, we
  // have to manually add the penalty for the prefix R"delim( over the column
  // limit.
  unsigned PrefixExcessCharacters =
      StartColumn + NewPrefixSize > Style.ColumnLimit
          ? StartColumn + NewPrefixSize - Style.ColumnLimit
          : 0;
  bool IsMultiline =
      ContentStartsOnNewline || (NewCode->find('\n') != std::string::npos);
  if (IsMultiline) {
    // Break before further function parameters on all levels.
    for (ParenState &Paren : State.Stack)
      Paren.BreakBeforeParameter = true;
  }
  return Fixes.second + PrefixExcessCharacters * Style.PenaltyExcessCharacter;
}

unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current,
                                                 LineState &State) {
  // Break before further function parameters on all levels.
  for (ParenState &Paren : State.Stack)
    Paren.BreakBeforeParameter = true;

  unsigned ColumnsUsed = State.Column;
  // We can only affect layout of the first and the last line, so the penalty
  // for all other lines is constant, and we ignore it.
  State.Column = Current.LastLineColumnWidth;

  if (ColumnsUsed > getColumnLimit(State))
    return Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit(State));
  return 0;
}

unsigned ContinuationIndenter::handleEndOfLine(const FormatToken &Current,
                                               LineState &State, bool DryRun,
                                               bool AllowBreak, bool Newline) {
  unsigned Penalty = 0;
  // Compute the raw string style to use in case this is a raw string literal
  // that can be reformatted.
  auto RawStringStyle = getRawStringStyle(Current, State);
  if (RawStringStyle && !Current.Finalized) {
    Penalty = reformatRawStringLiteral(Current, State, *RawStringStyle, DryRun,
                                       Newline);
  } else if (Current.IsMultiline && Current.isNot(TT_BlockComment)) {
    // Don't break multi-line tokens other than block comments and raw string
    // literals. Instead, just update the state.
    Penalty = addMultilineToken(Current, State);
  } else if (State.Line->Type != LT_ImportStatement) {
    // We generally don't break import statements.
    LineState OriginalState = State;

    // Whether we force the reflowing algorithm to stay strictly within the
    // column limit.
    bool Strict = false;
    // Whether the first non-strict attempt at reflowing did intentionally
    // exceed the column limit.
    bool Exceeded = false;
    std::tie(Penalty, Exceeded) = breakProtrudingToken(
        Current, State, AllowBreak, /*DryRun=*/true, Strict);
    if (Exceeded) {
      // If non-strict reflowing exceeds the column limit, try whether strict
      // reflowing leads to an overall lower penalty.
      LineState StrictState = OriginalState;
      unsigned StrictPenalty =
          breakProtrudingToken(Current, StrictState, AllowBreak,
                               /*DryRun=*/true, /*Strict=*/true)
              .first;
      Strict = StrictPenalty <= Penalty;
      if (Strict) {
        Penalty = StrictPenalty;
        State = StrictState;
      }
    }
    if (!DryRun) {
      // If we're not in dry-run mode, apply the changes with the decision on
      // strictness made above.
      breakProtrudingToken(Current, OriginalState, AllowBreak, /*DryRun=*/false,
                           Strict);
    }
  }
  if (State.Column > getColumnLimit(State)) {
    unsigned ExcessCharacters = State.Column - getColumnLimit(State);
    Penalty += Style.PenaltyExcessCharacter * ExcessCharacters;
  }
  return Penalty;
}

// Returns the enclosing function name of a token, or the empty string if not
// found.
static StringRef getEnclosingFunctionName(const FormatToken &Current) {
  // Look for: 'function(' or 'function<templates>(' before Current.
  auto Tok = Current.getPreviousNonComment();
  if (!Tok || Tok->isNot(tok::l_paren))
    return "";
  Tok = Tok->getPreviousNonComment();
  if (!Tok)
    return "";
  if (Tok->is(TT_TemplateCloser)) {
    Tok = Tok->MatchingParen;
    if (Tok)
      Tok = Tok->getPreviousNonComment();
  }
  if (!Tok || Tok->isNot(tok::identifier))
    return "";
  return Tok->TokenText;
}

std::optional<FormatStyle>
ContinuationIndenter::getRawStringStyle(const FormatToken &Current,
                                        const LineState &State) {
  if (!Current.isStringLiteral())
    return std::nullopt;
  auto Delimiter = getRawStringDelimiter(Current.TokenText);
  if (!Delimiter)
    return std::nullopt;
  auto RawStringStyle = RawStringFormats.getDelimiterStyle(*Delimiter);
  if (!RawStringStyle && Delimiter->empty()) {
    RawStringStyle = RawStringFormats.getEnclosingFunctionStyle(
        getEnclosingFunctionName(Current));
  }
  if (!RawStringStyle)
    return std::nullopt;
  RawStringStyle->ColumnLimit = getColumnLimit(State);
  return RawStringStyle;
}

std::unique_ptr<BreakableToken>
ContinuationIndenter::createBreakableToken(const FormatToken &Current,
                                           LineState &State, bool AllowBreak) {
  unsigned StartColumn = State.Column - Current.ColumnWidth;
  if (Current.isStringLiteral()) {
    // Strings in JSON cannot be broken. Breaking strings in JavaScript is
    // disabled for now.
    if (Style.isJson() || Style.isJavaScript() || !Style.BreakStringLiterals ||
        !AllowBreak) {
      return nullptr;
    }

    // Don't break string literals inside preprocessor directives (except for
    // #define directives, as their contents are stored in separate lines and
    // are not affected by this check).
    // This way we avoid breaking code with line directives and unknown
    // preprocessor directives that contain long string literals.
    if (State.Line->Type == LT_PreprocessorDirective)
      return nullptr;
    // Exempts unterminated string literals from line breaking. The user will
    // likely want to terminate the string before any line breaking is done.
    if (Current.IsUnterminatedLiteral)
      return nullptr;
    // Don't break string literals inside Objective-C array literals (doing so
    // raises the warning -Wobjc-string-concatenation).
    if (State.Stack.back().IsInsideObjCArrayLiteral)
      return nullptr;

    // The "DPI"/"DPI-C" in SystemVerilog direct programming interface
    // imports/exports cannot be split, e.g.
    // `import "DPI" function foo();`
    // FIXME: make this use same infra as C++ import checks
    if (Style.isVerilog() && Current.Previous &&
        Current.Previous->isOneOf(tok::kw_export, Keywords.kw_import)) {
      return nullptr;
    }
    StringRef Text = Current.TokenText;

    // We need this to address the case where there is an unbreakable tail only
    // if certain other formatting decisions have been taken. The
    // UnbreakableTailLength of Current is an overapproximation in that case and
    // we need to be correct here.
    unsigned UnbreakableTailLength = (State.NextToken && canBreak(State))
                                         ? 0
                                         : Current.UnbreakableTailLength;

    if (Style.isVerilog() || Style.Language == FormatStyle::LK_Java ||
        Style.isJavaScript() || Style.isCSharp()) {
      BreakableStringLiteralUsingOperators::QuoteStyleType QuoteStyle;
      if (Style.isJavaScript() && Text.starts_with("'") &&
          Text.ends_with("'")) {
        QuoteStyle = BreakableStringLiteralUsingOperators::SingleQuotes;
      } else if (Style.isCSharp() && Text.starts_with("@\"") &&
                 Text.ends_with("\"")) {
        QuoteStyle = BreakableStringLiteralUsingOperators::AtDoubleQuotes;
      } else if (Text.starts_with("\"") && Text.ends_with("\"")) {
        QuoteStyle = BreakableStringLiteralUsingOperators::DoubleQuotes;
      } else {
        return nullptr;
      }
      return std::make_unique<BreakableStringLiteralUsingOperators>(
          Current, QuoteStyle,
          /*UnindentPlus=*/shouldUnindentNextOperator(Current), StartColumn,
          UnbreakableTailLength, State.Line->InPPDirective, Encoding, Style);
    }

    StringRef Prefix;
    StringRef Postfix;
    // FIXME: Handle whitespace between '_T', '(', '"..."', and ')'.
    // FIXME: Store Prefix and Suffix (or PrefixLength and SuffixLength to
    // reduce the overhead) for each FormatToken, which is a string, so that we
    // don't run multiple checks here on the hot path.
    if ((Text.ends_with(Postfix = "\"") &&
         (Text.starts_with(Prefix = "@\"") || Text.starts_with(Prefix = "\"") ||
          Text.starts_with(Prefix = "u\"") ||
          Text.starts_with(Prefix = "U\"") ||
          Text.starts_with(Prefix = "u8\"") ||
          Text.starts_with(Prefix = "L\""))) ||
        (Text.starts_with(Prefix = "_T(\"") &&
         Text.ends_with(Postfix = "\")"))) {
      return std::make_unique<BreakableStringLiteral>(
          Current, StartColumn, Prefix, Postfix, UnbreakableTailLength,
          State.Line->InPPDirective, Encoding, Style);
    }
  } else if (Current.is(TT_BlockComment)) {
    if (Style.ReflowComments == FormatStyle::RCS_Never ||
        // If a comment token switches formatting, like
        // /* clang-format on */, we don't want to break it further,
        // but we may still want to adjust its indentation.
        switchesFormatting(Current)) {
      return nullptr;
    }
    return std::make_unique<BreakableBlockComment>(
        Current, StartColumn, Current.OriginalColumn, !Current.Previous,
        State.Line->InPPDirective, Encoding, Style, Whitespaces.useCRLF());
  } else if (Current.is(TT_LineComment) &&
             (!Current.Previous ||
              Current.Previous->isNot(TT_ImplicitStringLiteral))) {
    bool RegularComments = [&]() {
      for (const FormatToken *T = &Current; T && T->is(TT_LineComment);
           T = T->Next) {
        if (!(T->TokenText.starts_with("//") || T->TokenText.starts_with("#")))
          return false;
      }
      return true;
    }();
    if (Style.ReflowComments == FormatStyle::RCS_Never ||
        CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
        switchesFormatting(Current) || !RegularComments) {
      return nullptr;
    }
    return std::make_unique<BreakableLineCommentSection>(
        Current, StartColumn, /*InPPDirective=*/false, Encoding, Style);
  }
  return nullptr;
}

std::pair<unsigned, bool>
ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
                                           LineState &State, bool AllowBreak,
                                           bool DryRun, bool Strict) {
  std::unique_ptr<const BreakableToken> Token =
      createBreakableToken(Current, State, AllowBreak);
  if (!Token)
    return {0, false};
  assert(Token->getLineCount() > 0);
  unsigned ColumnLimit = getColumnLimit(State);
  if (Current.is(TT_LineComment)) {
    // We don't insert backslashes when breaking line comments.
    ColumnLimit = Style.ColumnLimit;
  }
  if (ColumnLimit == 0) {
    // To make the rest of the function easier set the column limit to the
    // maximum, if there should be no limit.
    ColumnLimit = std::numeric_limits<decltype(ColumnLimit)>::max();
  }
  if (Current.UnbreakableTailLength >= ColumnLimit)
    return {0, false};
  // ColumnWidth was already accounted into State.Column before calling
  // breakProtrudingToken.
  unsigned StartColumn = State.Column - Current.ColumnWidth;
  unsigned NewBreakPenalty = Current.isStringLiteral()
                                 ? Style.PenaltyBreakString
                                 : Style.PenaltyBreakComment;
  // Stores whether we intentionally decide to let a line exceed the column
  // limit.
  bool Exceeded = false;
  // Stores whether we introduce a break anywhere in the token.
  bool BreakInserted = Token->introducesBreakBeforeToken();
  // Store whether we inserted a new line break at the end of the previous
  // logical line.
  bool NewBreakBefore = false;
  // We use a conservative reflowing strategy. Reflow starts after a line is
  // broken or the corresponding whitespace compressed. Reflow ends as soon as a
  // line that doesn't get reflown with the previous line is reached.
  bool Reflow = false;
  // Keep track of where we are in the token:
  // Where we are in the content of the current logical line.
  unsigned TailOffset = 0;
  // The column number we're currently at.
  unsigned ContentStartColumn =
      Token->getContentStartColumn(0, /*Break=*/false);
  // The number of columns left in the current logical line after TailOffset.
  unsigned RemainingTokenColumns =
      Token->getRemainingLength(0, TailOffset, ContentStartColumn);
  // Adapt the start of the token, for example indent.
  if (!DryRun)
    Token->adaptStartOfLine(0, Whitespaces);

  unsigned ContentIndent = 0;
  unsigned Penalty = 0;
  LLVM_DEBUG(llvm::dbgs() << "Breaking protruding token at column "
                          << StartColumn << ".\n");
  for (unsigned LineIndex = 0, EndIndex = Token->getLineCount();
       LineIndex != EndIndex; ++LineIndex) {
    LLVM_DEBUG(llvm::dbgs()
               << "  Line: " << LineIndex << " (Reflow: " << Reflow << ")\n");
    NewBreakBefore = false;
    // If we did reflow the previous line, we'll try reflowing again. Otherwise
    // we'll start reflowing if the current line is broken or whitespace is
    // compressed.
    bool TryReflow = Reflow;
    // Break the current token until we can fit the rest of the line.
    while (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
      LLVM_DEBUG(llvm::dbgs() << "    Over limit, need: "
                              << (ContentStartColumn + RemainingTokenColumns)
                              << ", space: " << ColumnLimit
                              << ", reflown prefix: " << ContentStartColumn
                              << ", offset in line: " << TailOffset << "\n");
      // If the current token doesn't fit, find the latest possible split in the
      // current line so that breaking at it will be under the column limit.
      // FIXME: Use the earliest possible split while reflowing to correctly
      // compress whitespace within a line.
      BreakableToken::Split Split =
          Token->getSplit(LineIndex, TailOffset, ColumnLimit,
                          ContentStartColumn, CommentPragmasRegex);
      if (Split.first == StringRef::npos) {
        // No break opportunity - update the penalty and continue with the next
        // logical line.
        if (LineIndex < EndIndex - 1) {
          // The last line's penalty is handled in addNextStateToQueue() or when
          // calling replaceWhitespaceAfterLastLine below.
          Penalty += Style.PenaltyExcessCharacter *
                     (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
        }
        LLVM_DEBUG(llvm::dbgs() << "    No break opportunity.\n");
        break;
      }
      assert(Split.first != 0);

      if (Token->supportsReflow()) {
        // Check whether the next natural split point after the current one can
        // still fit the line, either because we can compress away whitespace,
        // or because the penalty the excess characters introduce is lower than
        // the break penalty.
        // We only do this for tokens that support reflowing, and thus allow us
        // to change the whitespace arbitrarily (e.g. comments).
        // Other tokens, like string literals, can be broken on arbitrary
        // positions.

        // First, compute the columns from TailOffset to the next possible split
        // position.
        // For example:
        // ColumnLimit:     |
        // // Some text   that    breaks
        //    ^ tail offset
        //             ^-- split
        //    ^-------- to split columns
        //                    ^--- next split
        //    ^--------------- to next split columns
        unsigned ToSplitColumns = Token->getRangeLength(
            LineIndex, TailOffset, Split.first, ContentStartColumn);
        LLVM_DEBUG(llvm::dbgs() << "    ToSplit: " << ToSplitColumns << "\n");

        BreakableToken::Split NextSplit = Token->getSplit(
            LineIndex, TailOffset + Split.first + Split.second, ColumnLimit,
            ContentStartColumn + ToSplitColumns + 1, CommentPragmasRegex);
        // Compute the columns necessary to fit the next non-breakable sequence
        // into the current line.
        unsigned ToNextSplitColumns = 0;
        if (NextSplit.first == StringRef::npos) {
          ToNextSplitColumns = Token->getRemainingLength(LineIndex, TailOffset,
                                                         ContentStartColumn);
        } else {
          ToNextSplitColumns = Token->getRangeLength(
              LineIndex, TailOffset,
              Split.first + Split.second + NextSplit.first, ContentStartColumn);
        }
        // Compress the whitespace between the break and the start of the next
        // unbreakable sequence.
        ToNextSplitColumns =
            Token->getLengthAfterCompression(ToNextSplitColumns, Split);
        LLVM_DEBUG(llvm::dbgs()
                   << "    ContentStartColumn: " << ContentStartColumn << "\n");
        LLVM_DEBUG(llvm::dbgs()
                   << "    ToNextSplit: " << ToNextSplitColumns << "\n");
        // If the whitespace compression makes us fit, continue on the current
        // line.
        bool ContinueOnLine =
            ContentStartColumn + ToNextSplitColumns <= ColumnLimit;
        unsigned ExcessCharactersPenalty = 0;
        if (!ContinueOnLine && !Strict) {
          // Similarly, if the excess characters' penalty is lower than the
          // penalty of introducing a new break, continue on the current line.
          ExcessCharactersPenalty =
              (ContentStartColumn + ToNextSplitColumns - ColumnLimit) *
              Style.PenaltyExcessCharacter;
          LLVM_DEBUG(llvm::dbgs()
                     << "    Penalty excess: " << ExcessCharactersPenalty
                     << "\n            break : " << NewBreakPenalty << "\n");
          if (ExcessCharactersPenalty < NewBreakPenalty) {
            Exceeded = true;
            ContinueOnLine = true;
          }
        }
        if (ContinueOnLine) {
          LLVM_DEBUG(llvm::dbgs() << "    Continuing on line...\n");
          // The current line fits after compressing the whitespace - reflow
          // the next line into it if possible.
          TryReflow = true;
          if (!DryRun) {
            Token->compressWhitespace(LineIndex, TailOffset, Split,
                                      Whitespaces);
          }
          // When we continue on the same line, leave one space between content.
          ContentStartColumn += ToSplitColumns + 1;
          Penalty += ExcessCharactersPenalty;
          TailOffset += Split.first + Split.second;
          RemainingTokenColumns = Token->getRemainingLength(
              LineIndex, TailOffset, ContentStartColumn);
          continue;
        }
      }
      LLVM_DEBUG(llvm::dbgs() << "    Breaking...\n");
      // Update the ContentIndent only if the current line was not reflown with
      // the previous line, since in that case the previous line should still
      // determine the ContentIndent. Also never intent the last line.
      if (!Reflow)
        ContentIndent = Token->getContentIndent(LineIndex);
      LLVM_DEBUG(llvm::dbgs()
                 << "    ContentIndent: " << ContentIndent << "\n");
      ContentStartColumn = ContentIndent + Token->getContentStartColumn(
                                               LineIndex, /*Break=*/true);

      unsigned NewRemainingTokenColumns = Token->getRemainingLength(
          LineIndex, TailOffset + Split.first + Split.second,
          ContentStartColumn);
      if (NewRemainingTokenColumns == 0) {
        // No content to indent.
        ContentIndent = 0;
        ContentStartColumn =
            Token->getContentStartColumn(LineIndex, /*Break=*/true);
        NewRemainingTokenColumns = Token->getRemainingLength(
            LineIndex, TailOffset + Split.first + Split.second,
            ContentStartColumn);
      }

      // When breaking before a tab character, it may be moved by a few columns,
      // but will still be expanded to the next tab stop, so we don't save any
      // columns.
      if (NewRemainingTokenColumns >= RemainingTokenColumns) {
        // FIXME: Do we need to adjust the penalty?
        break;
      }

      LLVM_DEBUG(llvm::dbgs() << "    Breaking at: " << TailOffset + Split.first
                              << ", " << Split.second << "\n");
      if (!DryRun) {
        Token->insertBreak(LineIndex, TailOffset, Split, ContentIndent,
                           Whitespaces);
      }

      Penalty += NewBreakPenalty;
      TailOffset += Split.first + Split.second;
      RemainingTokenColumns = NewRemainingTokenColumns;
      BreakInserted = true;
      NewBreakBefore = true;
    }
    // In case there's another line, prepare the state for the start of the next
    // line.
    if (LineIndex + 1 != EndIndex) {
      unsigned NextLineIndex = LineIndex + 1;
      if (NewBreakBefore) {
        // After breaking a line, try to reflow the next line into the current
        // one once RemainingTokenColumns fits.
        TryReflow = true;
      }
      if (TryReflow) {
        // We decided that we want to try reflowing the next line into the
        // current one.
        // We will now adjust the state as if the reflow is successful (in
        // preparation for the next line), and see whether that works. If we
        // decide that we cannot reflow, we will later reset the state to the
        // start of the next line.
        Reflow = false;
        // As we did not continue breaking the line, RemainingTokenColumns is
        // known to fit after ContentStartColumn. Adapt ContentStartColumn to
        // the position at which we want to format the next line if we do
        // actually reflow.
        // When we reflow, we need to add a space between the end of the current
        // line and the next line's start column.
        ContentStartColumn += RemainingTokenColumns + 1;
        // Get the split that we need to reflow next logical line into the end
        // of the current one; the split will include any leading whitespace of
        // the next logical line.
        BreakableToken::Split SplitBeforeNext =
            Token->getReflowSplit(NextLineIndex, CommentPragmasRegex);
        LLVM_DEBUG(llvm::dbgs()
                   << "    Size of reflown text: " << ContentStartColumn
                   << "\n    Potential reflow split: ");
        if (SplitBeforeNext.first != StringRef::npos) {
          LLVM_DEBUG(llvm::dbgs() << SplitBeforeNext.first << ", "
                                  << SplitBeforeNext.second << "\n");
          TailOffset = SplitBeforeNext.first + SplitBeforeNext.second;
          // If the rest of the next line fits into the current line below the
          // column limit, we can safely reflow.
          RemainingTokenColumns = Token->getRemainingLength(
              NextLineIndex, TailOffset, ContentStartColumn);
          Reflow = true;
          if (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
            LLVM_DEBUG(llvm::dbgs()
                       << "    Over limit after reflow, need: "
                       << (ContentStartColumn + RemainingTokenColumns)
                       << ", space: " << ColumnLimit
                       << ", reflown prefix: " << ContentStartColumn
                       << ", offset in line: " << TailOffset << "\n");
            // If the whole next line does not fit, try to find a point in
            // the next line at which we can break so that attaching the part
            // of the next line to that break point onto the current line is
            // below the column limit.
            BreakableToken::Split Split =
                Token->getSplit(NextLineIndex, TailOffset, ColumnLimit,
                                ContentStartColumn, CommentPragmasRegex);
            if (Split.first == StringRef::npos) {
              LLVM_DEBUG(llvm::dbgs() << "    Did not find later break\n");
              Reflow = false;
            } else {
              // Check whether the first split point gets us below the column
              // limit. Note that we will execute this split below as part of
              // the normal token breaking and reflow logic within the line.
              unsigned ToSplitColumns = Token->getRangeLength(
                  NextLineIndex, TailOffset, Split.first, ContentStartColumn);
              if (ContentStartColumn + ToSplitColumns > ColumnLimit) {
                LLVM_DEBUG(llvm::dbgs() << "    Next split protrudes, need: "
                                        << (ContentStartColumn + ToSplitColumns)
                                        << ", space: " << ColumnLimit);
                unsigned ExcessCharactersPenalty =
                    (ContentStartColumn + ToSplitColumns - ColumnLimit) *
                    Style.PenaltyExcessCharacter;
                if (NewBreakPenalty < ExcessCharactersPenalty)
                  Reflow = false;
              }
            }
          }
        } else {
          LLVM_DEBUG(llvm::dbgs() << "not found.\n");
        }
      }
      if (!Reflow) {
        // If we didn't reflow into the next line, the only space to consider is
        // the next logical line. Reset our state to match the start of the next
        // line.
        TailOffset = 0;
        ContentStartColumn =
            Token->getContentStartColumn(NextLineIndex, /*Break=*/false);
        RemainingTokenColumns = Token->getRemainingLength(
            NextLineIndex, TailOffset, ContentStartColumn);
        // Adapt the start of the token, for example indent.
        if (!DryRun)
          Token->adaptStartOfLine(NextLineIndex, Whitespaces);
      } else {
        // If we found a reflow split and have added a new break before the next
        // line, we are going to remove the line break at the start of the next
        // logical line. For example, here we'll add a new line break after
        // 'text', and subsequently delete the line break between 'that' and
        // 'reflows'.
        //   // some text that
        //   // reflows
        // ->
        //   // some text
        //   // that reflows
        // When adding the line break, we also added the penalty for it, so we
        // need to subtract that penalty again when we remove the line break due
        // to reflowing.
        if (NewBreakBefore) {
          assert(Penalty >= NewBreakPenalty);
          Penalty -= NewBreakPenalty;
        }
        if (!DryRun)
          Token->reflow(NextLineIndex, Whitespaces);
      }
    }
  }

  BreakableToken::Split SplitAfterLastLine =
      Token->getSplitAfterLastLine(TailOffset);
  if (SplitAfterLastLine.first != StringRef::npos) {
    LLVM_DEBUG(llvm::dbgs() << "Replacing whitespace after last line.\n");

    // We add the last line's penalty here, since that line is going to be split
    // now.
    Penalty += Style.PenaltyExcessCharacter *
               (ContentStartColumn + RemainingTokenColumns - ColumnLimit);

    if (!DryRun) {
      Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
                                            Whitespaces);
    }
    ContentStartColumn =
        Token->getContentStartColumn(Token->getLineCount() - 1, /*Break=*/true);
    RemainingTokenColumns = Token->getRemainingLength(
        Token->getLineCount() - 1,
        TailOffset + SplitAfterLastLine.first + SplitAfterLastLine.second,
        ContentStartColumn);
  }

  State.Column = ContentStartColumn + RemainingTokenColumns -
                 Current.UnbreakableTailLength;

  if (BreakInserted) {
    if (!DryRun)
      Token->updateAfterBroken(Whitespaces);

    // If we break the token inside a parameter list, we need to break before
    // the next parameter on all levels, so that the next parameter is clearly
    // visible. Line comments already introduce a break.
    if (Current.isNot(TT_LineComment))
      for (ParenState &Paren : State.Stack)
        Paren.BreakBeforeParameter = true;

    if (Current.is(TT_BlockComment))
      State.NoContinuation = true;

    State.Stack.back().LastSpace = StartColumn;
  }

  Token->updateNextToken(State);

  return {Penalty, Exceeded};
}

unsigned ContinuationIndenter::getColumnLimit(const LineState &State) const {
  // In preprocessor directives reserve two chars for trailing " \".
  return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
}

bool ContinuationIndenter::nextIsMultilineString(const LineState &State) {
  const FormatToken &Current = *State.NextToken;
  if (!Current.isStringLiteral() || Current.is(TT_ImplicitStringLiteral))
    return false;
  // We never consider raw string literals "multiline" for the purpose of
  // AlwaysBreakBeforeMultilineStrings implementation as they are special-cased
  // (see TokenAnnotator::mustBreakBefore().
  if (Current.TokenText.starts_with("R\""))
    return false;
  if (Current.IsMultiline)
    return true;
  if (Current.getNextNonComment() &&
      Current.getNextNonComment()->isStringLiteral()) {
    return true; // Implicit concatenation.
  }
  if (Style.ColumnLimit != 0 && Style.BreakStringLiterals &&
      State.Column + Current.ColumnWidth + Current.UnbreakableTailLength >
          Style.ColumnLimit) {
    return true; // String will be split.
  }
  return false;
}

} // namespace format
} // namespace clang
