//===--- 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.isTextProto() ||
         (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.isTextProto()) {
    // 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) {
    return Style.isCpp() &&
           Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope;
  }

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

  // 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.
  auto DisallowLineBreaks = [&] {
    if (!Style.isCpp() ||
        Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope) {
      return false;
    }

    // For example, `/*Newline=*/false`.
    if (Previous.is(TT_BlockComment) && Current.SpacesRequiredBefore == 0)
      return false;

    if (Current.isOneOf(tok::comment, tok::l_paren, TT_LambdaLSquare))
      return false;

    const auto *Prev = Current.getPreviousNonComment();
    if (!Prev || Prev->isNot(tok::l_paren))
      return false;

    if (Prev->BlockParameterCount == 0)
      return false;

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

    // A lambda followed by another arg.
    if (!Prev->Role)
      return false;

    const auto *Comma = Prev->Role->lastComma();
    if (!Comma)
      return false;

    const auto *Next = Comma->getNextNonComment();
    return Next && !Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret);
  };

  if (DisallowLineBreaks())
    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.isJava())
    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.isJava() &&
      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 (Style.BraceWrapping.BeforeLambdaBody &&
      Style.BraceWrapping.IndentBraces && Current.is(TT_LambdaLBrace)) {
    const auto From = Style.LambdaBodyIndentation == FormatStyle::LBI_Signature
                          ? CurrentState.Indent
                          : State.FirstIndent;
    return From + 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) &&
         !Current.endsSequence(TT_StartOfName, TT_AttributeMacro,
                               TT_PointerOrReference)) ||
        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.isJava() && 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) {
    const auto Indent = Style.IndentWidth * Style.BraceWrapping.IndentBraces;
    State.Stack.back().NestedBlockIndent = State.FirstIndent + Indent;
  }
  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);
  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.isJava() || 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
