diff options
Diffstat (limited to 'lib/Format/ContinuationIndenter.cpp')
| -rw-r--r-- | lib/Format/ContinuationIndenter.cpp | 759 | 
1 files changed, 495 insertions, 264 deletions
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 971acc2b7a3c1..014c30e346ad1 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -12,8 +12,6 @@  ///  //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "format-formatter" -  #include "BreakableToken.h"  #include "ContinuationIndenter.h"  #include "WhitespaceManager.h" @@ -23,13 +21,15 @@  #include "llvm/Support/Debug.h"  #include <string> +#define DEBUG_TYPE "format-formatter" +  namespace clang {  namespace format {  // Returns the length of everything up to the first possible line break after  // the ), ], } or > matching \c Tok.  static unsigned getLengthToMatchingParen(const FormatToken &Tok) { -  if (Tok.MatchingParen == NULL) +  if (!Tok.MatchingParen)      return 0;    FormatToken *End = Tok.MatchingParen;    while (End->Next && !End->Next->CanBreakBefore) { @@ -63,7 +63,8 @@ ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,                                             bool BinPackInconclusiveFunctions)      : Style(Style), SourceMgr(SourceMgr), Whitespaces(Whitespaces),        Encoding(Encoding), -      BinPackInconclusiveFunctions(BinPackInconclusiveFunctions) {} +      BinPackInconclusiveFunctions(BinPackInconclusiveFunctions), +      CommentPragmasRegex(Style.CommentPragmas) {}  LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,                                                  const AnnotatedLine *Line, @@ -77,10 +78,9 @@ LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,                                     /*AvoidBinPacking=*/false,                                     /*NoLineBreak=*/false));    State.LineContainsContinuedForLoopSection = false; -  State.ParenLevel = 0;    State.StartOfStringLiteral = 0; -  State.StartOfLineLevel = State.ParenLevel; -  State.LowestLevelOnLine = State.ParenLevel; +  State.StartOfLineLevel = 0; +  State.LowestLevelOnLine = 0;    State.IgnoreStackForComparison = false;    // The first token has already been indented and thus consumed. @@ -98,8 +98,8 @@ bool ContinuationIndenter::canBreak(const LineState &State) {    // 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.Type != TT_DictLiteral && -      Previous.BlockKind == BK_BracedInit && Previous.Previous && +      Previous.Type != TT_DictLiteral && Previous.BlockKind == BK_BracedInit && +      Previous.Previous &&        Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma))      return false;    // This prevents breaks like: @@ -107,10 +107,21 @@ bool ContinuationIndenter::canBreak(const LineState &State) {    //   SomeParameter, OtherParameter).DoSomething(    //   ...    // As they hide "DoSomething" and are generally bad for readability. -  if (Previous.opensScope() && State.LowestLevelOnLine < State.StartOfLineLevel) +  if (Previous.opensScope() && Previous.isNot(tok::l_brace) && +      State.LowestLevelOnLine < State.StartOfLineLevel && +      State.LowestLevelOnLine < Current.NestingLevel)      return false;    if (Current.isMemberAccess() && State.Stack.back().ContainsUnwrappedBuilder)      return false; + +  // Don't create a 'hanging' indent if there are multiple blocks in a single +  // statement. +  if (Style.Language == FormatStyle::LK_JavaScript && +      Previous.is(tok::l_brace) && State.Stack.size() > 1 && +      State.Stack[State.Stack.size() - 2].JSFunctionInlined && +      State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks) +    return false; +    return !State.Stack.back().NoLineBreak;  } @@ -136,13 +147,21 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {    if (Style.AlwaysBreakBeforeMultilineStrings &&        State.Column > State.Stack.back().Indent && // Breaking saves columns.        !Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) && -      Previous.Type != TT_InlineASMColon && NextIsMultilineString(State)) +      Previous.Type != TT_InlineASMColon && +      Previous.Type != TT_ConditionalExpr && nextIsMultilineString(State))      return true;    if (((Previous.Type == TT_DictLiteral && Previous.is(tok::l_brace)) ||         Previous.Type == TT_ArrayInitializerLSquare) && +      Style.ColumnLimit > 0 &&        getLengthToMatchingParen(Previous) + State.Column > getColumnLimit(State))      return true; +  if (Current.Type == TT_CtorInitializerColon && +      ((Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All) || +       Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0)) +    return true; +  if (State.Column < getNewLineColumn(State)) +    return false;    if (!Style.BreakBeforeBinaryOperators) {      // If we need to break somewhere inside the LHS of a binary expression, we      // should also break after the operator. Otherwise, the formatting would @@ -165,38 +184,45 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {      if (Previous.Type == TT_BinaryOperator &&          (!IsComparison || LHSIsBinaryExpr) &&          Current.Type != TT_BinaryOperator && // For >>. -        !Current.isTrailingComment() && -        !Previous.isOneOf(tok::lessless, tok::question) && +        !Current.isTrailingComment() && !Previous.is(tok::lessless) &&          Previous.getPrecedence() != prec::Assignment &&          State.Stack.back().BreakBeforeParameter)        return true;    }    // Same as above, but for the first "<<" operator. -  if (Current.is(tok::lessless) && State.Stack.back().BreakBeforeParameter && +  if (Current.is(tok::lessless) && Current.Type != TT_OverloadedOperator && +      State.Stack.back().BreakBeforeParameter &&        State.Stack.back().FirstLessLess == 0)      return true; -  // FIXME: Comparing LongestObjCSelectorName to 0 is a hacky way of finding -  // out whether it is the first parameter. Clean this up. -  if (Current.Type == TT_ObjCSelectorName && -      Current.LongestObjCSelectorName == 0 && +  if (Current.Type == TT_SelectorName && +      State.Stack.back().ObjCSelectorNameFound &&        State.Stack.back().BreakBeforeParameter)      return true; -  if ((Current.Type == TT_CtorInitializerColon || -       (Previous.ClosesTemplateDeclaration && State.ParenLevel == 0 && -        !Current.isTrailingComment()))) +  if (Previous.ClosesTemplateDeclaration && Current.NestingLevel == 0 && +      !Current.isTrailingComment())      return true; -  if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) && -      State.Line->MightBeFunctionDecl && -      State.Stack.back().BreakBeforeParameter && State.ParenLevel == 0) +  // If the return type spans multiple lines, wrap before the function name. +  if ((Current.Type == TT_FunctionDeclarationName || +       Current.is(tok::kw_operator)) && +      State.Stack.back().BreakBeforeParameter)      return true; +    if (startsSegmentOfBuilderTypeCall(Current) &&        (State.Stack.back().CallContinuation != 0 ||         (State.Stack.back().BreakBeforeParameter &&          State.Stack.back().ContainsUnwrappedBuilder)))      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.BlockKind == BK_Block && +      Previous.is(tok::l_brace) && !Current.isOneOf(tok::r_brace, tok::comment)) +    return true; +    return false;  } @@ -205,9 +231,9 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline,                                                 unsigned ExtraSpaces) {    const FormatToken &Current = *State.NextToken; -  if (State.Stack.size() == 0 || -      (Current.Type == TT_ImplicitStringLiteral && -       (Current.Previous->Tok.getIdentifierInfo() == NULL || +  assert(!State.Stack.empty()); +  if ((Current.Type == TT_ImplicitStringLiteral && +       (Current.Previous->Tok.getIdentifierInfo() == nullptr ||          Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() ==              tok::pp_not_keyword))) {      // FIXME: Is this correct? @@ -215,8 +241,8 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline,                                 State.NextToken->WhitespaceRange.getEnd()) -                             SourceMgr.getSpellingColumnNumber(                                 State.NextToken->WhitespaceRange.getBegin()); -    State.Column += WhitespaceLength + State.NextToken->ColumnWidth; -    State.NextToken = State.NextToken->Next; +    State.Column += WhitespaceLength; +    moveStateToNextToken(State, DryRun, /*Newline=*/false);      return 0;    } @@ -234,7 +260,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,    FormatToken &Current = *State.NextToken;    const FormatToken &Previous = *State.NextToken->Previous;    if (Current.is(tok::equal) && -      (State.Line->First->is(tok::kw_for) || State.ParenLevel == 0) && +      (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&        State.Stack.back().VariablePos == 0) {      State.Stack.back().VariablePos = State.Column;      // Move over * and & if they are bound to the variable name. @@ -255,9 +281,12 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,      Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, /*IndentLevel=*/0,                                    Spaces, State.Column + Spaces); -  if (Current.Type == TT_ObjCSelectorName && State.Stack.back().ColonPos == 0) { -    if (State.Stack.back().Indent + Current.LongestObjCSelectorName > -        State.Column + Spaces + Current.ColumnWidth) +  if (Current.Type == TT_SelectorName && +      !State.Stack.back().ObjCSelectorNameFound) { +    if (Current.LongestObjCSelectorName == 0) +      State.Stack.back().AlignColons = false; +    else if (State.Stack.back().Indent + Current.LongestObjCSelectorName > +             State.Column + Spaces + Current.ColumnWidth)        State.Stack.back().ColonPos =            State.Stack.back().Indent + Current.LongestObjCSelectorName;      else @@ -265,7 +294,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,    }    if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr && -      Current.Type != TT_LineComment) +      (Current.Type != TT_LineComment || Previous.BlockKind == BK_BracedInit))      State.Stack.back().Indent = State.Column + Spaces;    if (State.Stack.back().AvoidBinPacking && startsNextParameter(Current, Style))      State.Stack.back().NoLineBreak = true; @@ -273,17 +302,21 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,      State.Stack.back().ContainsUnwrappedBuilder = true;    State.Column += Spaces; -  if (Current.is(tok::l_paren) && Previous.isOneOf(tok::kw_if, tok::kw_for)) +  if (Current.isNot(tok::comment) && Previous.is(tok::l_paren) && +      Previous.Previous && Previous.Previous->isOneOf(tok::kw_if, tok::kw_for))      // Treat the condition inside an if as if it was a second function      // parameter, i.e. let nested calls have a continuation indent. -    State.Stack.back().LastSpace = State.Column + 1; // 1 is length of "(". -  else if (Previous.is(tok::comma) || Previous.Type == TT_ObjCMethodExpr) +    State.Stack.back().LastSpace = State.Column; +  else if (!Current.isOneOf(tok::comment, tok::caret) && +           (Previous.is(tok::comma) || +            (Previous.is(tok::colon) && Previous.Type == TT_ObjCMethodExpr)))      State.Stack.back().LastSpace = State.Column;    else if ((Previous.Type == TT_BinaryOperator ||              Previous.Type == TT_ConditionalExpr || -            Previous.Type == TT_UnaryOperator ||              Previous.Type == TT_CtorInitializerColon) && -           (Previous.getPrecedence() != prec::Assignment || +           ((Previous.getPrecedence() != prec::Assignment && +             (Previous.isNot(tok::lessless) || Previous.OperatorIndex != 0 || +              !Previous.LastOperator)) ||              Current.StartsBinaryExpression))      // Always indent relative to the RHS of the expression unless this is a      // simple assignment without binary expression on the RHS. Also indent @@ -313,17 +346,16 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,                                                   bool DryRun) {    FormatToken &Current = *State.NextToken;    const FormatToken &Previous = *State.NextToken->Previous; -  // If we are continuing an expression, we want to use the continuation indent. -  unsigned ContinuationIndent = -      std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) + -      Style.ContinuationIndentWidth; +    // Extra penalty that needs to be added because of the way certain line    // breaks are chosen.    unsigned Penalty = 0; -  const FormatToken *PreviousNonComment = -      State.NextToken->getPreviousNonComment(); -  // The first line break on any ParenLevel causes an extra penalty in order +  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 (!State.Stack.back().ContainsLineBreak)      Penalty += 15; @@ -332,96 +364,61 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,    Penalty += State.NextToken->SplitPenalty;    // Breaking before the first "<<" is generally not desirable if the LHS is -  // short. -  if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0 && -      State.Column <= Style.ColumnLimit / 2) +  // short. Also always add the penalty if the LHS is split over mutliple lines +  // to avoid unnecessary line breaks that just work around this penalty. +  if (NextNonComment->is(tok::lessless) && +      State.Stack.back().FirstLessLess == 0 && +      (State.Column <= Style.ColumnLimit / 3 || +       State.Stack.back().BreakBeforeParameter))      Penalty += Style.PenaltyBreakFirstLessLess; -  if (Current.is(tok::l_brace) && Current.BlockKind == BK_Block) { -    State.Column = State.FirstIndent; -  } else if (Current.isOneOf(tok::r_brace, tok::r_square)) { -    if (Current.closesBlockTypeList(Style) || -        (Current.MatchingParen && -         Current.MatchingParen->BlockKind == BK_BracedInit)) -      State.Column = State.Stack[State.Stack.size() - 2].LastSpace; -    else -      State.Column = State.FirstIndent; -  } else if (Current.is(tok::string_literal) && -             State.StartOfStringLiteral != 0) { -    State.Column = State.StartOfStringLiteral; -    State.Stack.back().BreakBeforeParameter = true; -  } else if (Current.is(tok::lessless) && -             State.Stack.back().FirstLessLess != 0) { -    State.Column = State.Stack.back().FirstLessLess; -  } else if (Current.isMemberAccess()) { -    if (State.Stack.back().CallContinuation == 0) { -      State.Column = ContinuationIndent; +  State.Column = getNewLineColumn(State); +  if (NextNonComment->isMemberAccess()) { +    if (State.Stack.back().CallContinuation == 0)        State.Stack.back().CallContinuation = State.Column; -    } else { -      State.Column = State.Stack.back().CallContinuation; -    } -  } else if (State.Stack.back().QuestionColumn != 0 && -             (Current.Type == TT_ConditionalExpr || -              Previous.Type == TT_ConditionalExpr)) { -    State.Column = State.Stack.back().QuestionColumn; -  } else if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0) { -    State.Column = State.Stack.back().VariablePos; -  } else if ((PreviousNonComment && -              PreviousNonComment->ClosesTemplateDeclaration) || -             ((Current.Type == TT_StartOfName || -               Current.is(tok::kw_operator)) && -              State.ParenLevel == 0 && -              (!Style.IndentFunctionDeclarationAfterType || -               State.Line->StartsDefinition))) { -    State.Column = State.Stack.back().Indent; -  } else if (Current.Type == TT_ObjCSelectorName) { -    if (State.Stack.back().ColonPos == 0) { -      State.Stack.back().ColonPos = -          State.Stack.back().Indent + Current.LongestObjCSelectorName; -      State.Column = State.Stack.back().ColonPos - Current.ColumnWidth; -    } else if (State.Stack.back().ColonPos > Current.ColumnWidth) { -      State.Column = State.Stack.back().ColonPos - Current.ColumnWidth; -    } else { -      State.Column = State.Stack.back().Indent; -      State.Stack.back().ColonPos = State.Column + Current.ColumnWidth; +  } else if (NextNonComment->Type == TT_SelectorName) { +    if (!State.Stack.back().ObjCSelectorNameFound) { +      if (NextNonComment->LongestObjCSelectorName == 0) { +        State.Stack.back().AlignColons = false; +      } else { +        State.Stack.back().ColonPos = +            State.Stack.back().Indent + NextNonComment->LongestObjCSelectorName; +      } +    } else if (State.Stack.back().AlignColons && +               State.Stack.back().ColonPos <= NextNonComment->ColumnWidth) { +      State.Stack.back().ColonPos = State.Column + NextNonComment->ColumnWidth;      } -  } else if (Current.Type == TT_ArraySubscriptLSquare) { -    if (State.Stack.back().StartOfArraySubscripts != 0) -      State.Column = State.Stack.back().StartOfArraySubscripts; -    else -      State.Column = ContinuationIndent; -  } else if (Current.Type == TT_StartOfName || -             Previous.isOneOf(tok::coloncolon, tok::equal) || -             Previous.Type == TT_ObjCMethodExpr) { -    State.Column = ContinuationIndent; -  } else if (Current.Type == TT_CtorInitializerColon) { -    State.Column = State.FirstIndent + Style.ConstructorInitializerIndentWidth; -  } else if (Current.Type == TT_CtorInitializerComma) { -    State.Column = State.Stack.back().Indent; -  } else { -    State.Column = State.Stack.back().Indent; -    // Ensure that we fall back to the continuation indent width instead of just -    // flushing continuations left. -    if (State.Column == State.FirstIndent && -        PreviousNonComment->isNot(tok::r_brace)) -      State.Column += Style.ContinuationIndentWidth; +  } else if (PreviousNonComment && PreviousNonComment->is(tok::colon) && +             (PreviousNonComment->Type == TT_ObjCMethodExpr || +              PreviousNonComment->Type == 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(State.Stack.back().LastSpace, State.Stack.back().Indent) + +          Style.ContinuationIndentWidth;    }    if ((Previous.isOneOf(tok::comma, tok::semi) &&         !State.Stack.back().AvoidBinPacking) ||        Previous.Type == TT_BinaryOperator)      State.Stack.back().BreakBeforeParameter = false; -  if (Previous.Type == TT_TemplateCloser && State.ParenLevel == 0) +  if (Previous.Type == TT_TemplateCloser && Current.NestingLevel == 0)      State.Stack.back().BreakBeforeParameter = false; -  if (Current.is(tok::question) || +  if (NextNonComment->is(tok::question) ||        (PreviousNonComment && PreviousNonComment->is(tok::question)))      State.Stack.back().BreakBeforeParameter = true;    if (!DryRun) { -    unsigned Newlines = 1; -    if (Current.is(tok::comment)) -      Newlines = std::max(Newlines, std::min(Current.NewlinesBefore, -                                             Style.MaxEmptyLinesToKeep + 1)); +    unsigned Newlines = std::max( +        1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1));      Whitespaces.replaceWhitespace(Current, Newlines,                                    State.Stack.back().IndentLevel, State.Column,                                    State.Column, State.Line->InPPDirective); @@ -429,51 +426,164 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,    if (!Current.isTrailingComment())      State.Stack.back().LastSpace = State.Column; -  if (Current.isMemberAccess()) -    State.Stack.back().LastSpace += Current.ColumnWidth; -  State.StartOfLineLevel = State.ParenLevel; -  State.LowestLevelOnLine = State.ParenLevel; +  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. -  for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) { -    State.Stack[i].BreakBeforeParameter = true; +  bool JavaScriptFormat = Style.Language == FormatStyle::LK_JavaScript && +                          Current.is(tok::r_brace) && +                          State.Stack.size() > 1 && +                          State.Stack[State.Stack.size() - 2].JSFunctionInlined; +  if (!JavaScriptFormat) { +    for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) { +      State.Stack[i].BreakBeforeParameter = true; +    }    } +    if (PreviousNonComment &&        !PreviousNonComment->isOneOf(tok::comma, tok::semi) &&        PreviousNonComment->Type != TT_TemplateCloser &&        PreviousNonComment->Type != TT_BinaryOperator && -      Current.Type != TT_BinaryOperator &&  -      !PreviousNonComment->opensScope()) +      Current.Type != TT_BinaryOperator && !PreviousNonComment->opensScope())      State.Stack.back().BreakBeforeParameter = true;    // If we break after { or the [ of an array initializer, we should also break    // before the corresponding } or ]. -  if (Previous.is(tok::l_brace) || Previous.Type == TT_ArrayInitializerLSquare) +  if (PreviousNonComment && +      (PreviousNonComment->is(tok::l_brace) || +       PreviousNonComment->Type == TT_ArrayInitializerLSquare))      State.Stack.back().BreakBeforeClosingBrace = true;    if (State.Stack.back().AvoidBinPacking) {      // If we are breaking after '(', '{', '<', this is not bin packing -    // unless AllowAllParametersOfDeclarationOnNextLine is false. +    // unless AllowAllParametersOfDeclarationOnNextLine is false or this is a +    // dict/object literal.      if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) ||            Previous.Type == TT_BinaryOperator) ||          (!Style.AllowAllParametersOfDeclarationOnNextLine && -         State.Line->MustBeDeclaration)) +         State.Line->MustBeDeclaration) || +        Previous.Type == TT_DictLiteral)        State.Stack.back().BreakBeforeParameter = true;    }    return Penalty;  } +unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { +  if (!State.NextToken || !State.NextToken->Previous) +    return 0; +  FormatToken &Current = *State.NextToken; +  const FormatToken &Previous = *State.NextToken->Previous; +  // If we are continuing an expression, we want to use the continuation indent. +  unsigned ContinuationIndent = +      std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) + +      Style.ContinuationIndentWidth; +  const FormatToken *PreviousNonComment = Current.getPreviousNonComment(); +  const FormatToken *NextNonComment = Previous.getNextNonComment(); +  if (!NextNonComment) +    NextNonComment = &Current; +  if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block) +    return Current.NestingLevel == 0 ? State.FirstIndent +                                     : State.Stack.back().Indent; +  if (Current.isOneOf(tok::r_brace, tok::r_square)) { +    if (State.Stack.size() > 1 && +        State.Stack[State.Stack.size() - 2].JSFunctionInlined) +      return State.FirstIndent; +    if (Current.closesBlockTypeList(Style) || +        (Current.MatchingParen && +         Current.MatchingParen->BlockKind == BK_BracedInit)) +      return State.Stack[State.Stack.size() - 2].LastSpace; +    else +      return State.FirstIndent; +  } +  if (Current.is(tok::identifier) && Current.Next && +      Current.Next->Type == TT_DictLiteral) +    return State.Stack.back().Indent; +  if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0) +    return State.StartOfStringLiteral; +  if (NextNonComment->is(tok::lessless) && +      State.Stack.back().FirstLessLess != 0) +    return State.Stack.back().FirstLessLess; +  if (NextNonComment->isMemberAccess()) { +    if (State.Stack.back().CallContinuation == 0) { +      return ContinuationIndent; +    } else { +      return State.Stack.back().CallContinuation; +    } +  } +  if (State.Stack.back().QuestionColumn != 0 && +      ((NextNonComment->is(tok::colon) && +        NextNonComment->Type == TT_ConditionalExpr) || +       Previous.Type == TT_ConditionalExpr)) +    return State.Stack.back().QuestionColumn; +  if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0) +    return State.Stack.back().VariablePos; +  if ((PreviousNonComment && (PreviousNonComment->ClosesTemplateDeclaration || +                              PreviousNonComment->Type == TT_AttributeParen)) || +      (!Style.IndentWrappedFunctionNames && +       (NextNonComment->is(tok::kw_operator) || +        NextNonComment->Type == TT_FunctionDeclarationName))) +    return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent); +  if (NextNonComment->Type == TT_SelectorName) { +    if (!State.Stack.back().ObjCSelectorNameFound) { +      if (NextNonComment->LongestObjCSelectorName == 0) { +        return State.Stack.back().Indent; +      } else { +        return State.Stack.back().Indent + +               NextNonComment->LongestObjCSelectorName - +               NextNonComment->ColumnWidth; +      } +    } else if (!State.Stack.back().AlignColons) { +      return State.Stack.back().Indent; +    } else if (State.Stack.back().ColonPos > NextNonComment->ColumnWidth) { +      return State.Stack.back().ColonPos - NextNonComment->ColumnWidth; +    } else { +      return State.Stack.back().Indent; +    } +  } +  if (NextNonComment->Type == TT_ArraySubscriptLSquare) { +    if (State.Stack.back().StartOfArraySubscripts != 0) +      return State.Stack.back().StartOfArraySubscripts; +    else +      return ContinuationIndent; +  } +  if (NextNonComment->Type == TT_StartOfName || +      Previous.isOneOf(tok::coloncolon, tok::equal)) { +    return ContinuationIndent; +  } +  if (PreviousNonComment && PreviousNonComment->is(tok::colon) && +      (PreviousNonComment->Type == TT_ObjCMethodExpr || +       PreviousNonComment->Type == TT_DictLiteral)) +    return ContinuationIndent; +  if (NextNonComment->Type == TT_CtorInitializerColon) +    return State.FirstIndent + Style.ConstructorInitializerIndentWidth; +  if (NextNonComment->Type == TT_CtorInitializerComma) +    return State.Stack.back().Indent; +  if (State.Stack.back().Indent == State.FirstIndent && PreviousNonComment && +      PreviousNonComment->isNot(tok::r_brace)) +    // Ensure that we fall back to the continuation indent width instead of +    // just flushing continuations left. +    return State.Stack.back().Indent + Style.ContinuationIndentWidth; +  return State.Stack.back().Indent; +} +  unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,                                                      bool DryRun, bool Newline) { -  const FormatToken &Current = *State.NextToken;    assert(State.Stack.size()); +  const FormatToken &Current = *State.NextToken;    if (Current.Type == TT_InheritanceColon)      State.Stack.back().AvoidBinPacking = true; -  if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0) -    State.Stack.back().FirstLessLess = State.Column; +  if (Current.is(tok::lessless) && Current.Type != TT_OverloadedOperator) { +    if (State.Stack.back().FirstLessLess == 0) +      State.Stack.back().FirstLessLess = State.Column; +    else +      State.Stack.back().LastOperatorWrapped = Newline; +  } +  if ((Current.Type == TT_BinaryOperator && Current.isNot(tok::lessless)) || +      Current.Type == TT_ConditionalExpr) +    State.Stack.back().LastOperatorWrapped = Newline;    if (Current.Type == TT_ArraySubscriptLSquare &&        State.Stack.back().StartOfArraySubscripts == 0)      State.Stack.back().StartOfArraySubscripts = State.Column; @@ -484,10 +594,12 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,      State.Stack.back().QuestionColumn = State.Column;    if (!Current.opensScope() && !Current.closesScope())      State.LowestLevelOnLine = -        std::min(State.LowestLevelOnLine, State.ParenLevel); +        std::min(State.LowestLevelOnLine, Current.NestingLevel);    if (Current.isMemberAccess())      State.Stack.back().StartOfFunctionCall = -        Current.LastInChainOfCalls ? 0 : State.Column + Current.ColumnWidth; +        Current.LastOperator ? 0 : State.Column + Current.ColumnWidth; +  if (Current.Type == TT_SelectorName) +    State.Stack.back().ObjCSelectorNameFound = true;    if (Current.Type == TT_CtorInitializerColon) {      // Indent 2 from the column, so:      // SomeClass::SomeClass() @@ -509,8 +621,67 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,    // 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 (Style.Language == FormatStyle::LK_JavaScript) { +    if (Current.isNot(tok::comment) && Previous && Previous->is(tok::l_brace) && +        State.Stack.size() > 1) { +      if (State.Stack[State.Stack.size() - 2].JSFunctionInlined && Newline) { +        for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) { +          State.Stack[i].NoLineBreak = true; +        } +      } +      State.Stack[State.Stack.size() - 2].JSFunctionInlined = false; +    } +    if (Current.TokenText == "function") +      State.Stack.back().JSFunctionInlined = !Newline; +  } + +  moveStatePastFakeLParens(State, Newline); +  moveStatePastScopeOpener(State, Newline); +  moveStatePastScopeCloser(State); +  moveStatePastFakeRParens(State); + +  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; +  unsigned Penalty = breakProtrudingToken(Current, State, DryRun); +  if (State.Column > getColumnLimit(State)) { +    unsigned ExcessCharacters = State.Column - getColumnLimit(State); +    Penalty += Style.PenaltyExcessCharacter * ExcessCharacters; +  } + +  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; +  const FormatToken *Previous = Current.getPreviousNonComment(); +    // Don't add extra indentation for the first fake parenthesis after -  // 'return', assignements or opening <({[. The indentation for these cases +  // 'return', assignments or opening <({[. The indentation for these cases    // is special cased.    bool SkipFirstExtraIndent =        (Previous && (Previous->opensScope() || Previous->is(tok::kw_return) || @@ -531,6 +702,24 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,            std::max(std::max(State.Column, NewParenState.Indent),                     State.Stack.back().LastSpace); +    // 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. +    if (Previous && Previous->getPrecedence() > prec::Assignment && +        (Previous->Type == TT_BinaryOperator || +         Previous->Type == TT_ConditionalExpr) && +        Previous->getPrecedence() != prec::Relational) { +      bool BreakBeforeOperator = Previous->is(tok::lessless) || +                                 (Previous->Type == TT_BinaryOperator && +                                  Style.BreakBeforeBinaryOperators) || +                                 (Previous->Type == TT_ConditionalExpr && +                                  Style.BreakBeforeTernaryOperators); +      if ((!Newline && !BreakBeforeOperator) || +          (!State.Stack.back().LastOperatorWrapped && BreakBeforeOperator)) +        NewParenState.NoLineBreak = 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 @@ -539,6 +728,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,      //       ParameterToInnerFunction));      if (*I > prec::Unknown)        NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column); +    NewParenState.StartOfFunctionCall = State.Column;      // Always indent conditional expressions. Never indent expression where      // the 'operator' is ',', ';' or an assignment (i.e. *I <= @@ -553,131 +743,160 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,      State.Stack.push_back(NewParenState);      SkipFirstExtraIndent = false;    } +} -  // If we encounter an opening (, [, { or <, we add a level to our stacks to -  // prepare for the following tokens. -  if (Current.opensScope()) { -    unsigned NewIndent; -    unsigned NewIndentLevel = State.Stack.back().IndentLevel; -    bool AvoidBinPacking; -    bool BreakBeforeParameter = false; -    if (Current.is(tok::l_brace) || -        Current.Type == TT_ArrayInitializerLSquare) { -      if (Current.MatchingParen && Current.BlockKind == BK_Block) { -        // If this is an l_brace starting a nested block, we pretend (wrt. to -        // indentation) that we already consumed the corresponding r_brace. -        // Thus, we remove all ParenStates caused bake fake parentheses that end -        // at the r_brace. The net effect of this is that we don't indent -        // relative to the l_brace, if the nested block is the last parameter of -        // a function. For example, this formats: -        // -        //   SomeFunction(a, [] { -        //     f();  // break -        //   }); -        // -        // instead of: -        //   SomeFunction(a, [] { -        //                        f();  // break -        //                      }); -        for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i) -          State.Stack.pop_back(); -        NewIndent = State.Stack.back().LastSpace + Style.IndentWidth; -        ++NewIndentLevel; -        BreakBeforeParameter = true; -      } else { -        NewIndent = State.Stack.back().LastSpace; -        if (Current.opensBlockTypeList(Style)) { -          NewIndent += Style.IndentWidth; -          ++NewIndentLevel; -        } else { -          NewIndent += Style.ContinuationIndentWidth; -        } -      } -      const FormatToken *NextNoComment = Current.getNextNonComment(); -      AvoidBinPacking = Current.BlockKind == BK_Block || -                        Current.Type == TT_ArrayInitializerLSquare || -                        Current.Type == TT_DictLiteral || -                        (NextNoComment && -                         NextNoComment->Type == TT_DesignatedInitializerPeriod); -    } else { -      NewIndent = Style.ContinuationIndentWidth + -                  std::max(State.Stack.back().LastSpace, -                           State.Stack.back().StartOfFunctionCall); -      AvoidBinPacking = !Style.BinPackParameters || -                        (Style.ExperimentalAutoDetectBinPacking && -                         (Current.PackingKind == PPK_OnePerLine || -                          (!BinPackInconclusiveFunctions && -                           Current.PackingKind == PPK_Inconclusive))); -      // If this '[' opens an ObjC call, determine whether all parameters fit -      // into one line and put one per line if they don't. -      if (Current.Type == TT_ObjCMethodExpr && -          getLengthToMatchingParen(Current) + State.Column > -              getColumnLimit(State)) -        BreakBeforeParameter = true; +// Remove the fake r_parens after 'Tok'. +static void consumeRParens(LineState& State, const FormatToken &Tok) { +  for (unsigned i = 0, e = Tok.FakeRParens; i != e; ++i) { +    unsigned VariablePos = State.Stack.back().VariablePos; +    assert(State.Stack.size() > 1); +    if (State.Stack.size() == 1) { +      // Do not pop the last element. +      break;      } +    State.Stack.pop_back(); +    State.Stack.back().VariablePos = VariablePos; +  } +} + +// Returns whether 'Tok' opens or closes a scope requiring special handling +// of the subsequent fake r_parens. +// +// For example, if this is an l_brace starting a nested block, we pretend (wrt. +// to indentation) that we already consumed the corresponding r_brace. Thus, we +// remove all ParenStates caused by fake parentheses that end at the r_brace. +// The net effect of this is that we don't indent relative to the l_brace, if +// the nested block is the last parameter of a function. This formats: +// +//   SomeFunction(a, [] { +//     f();  // break +//   }); +// +// instead of: +//   SomeFunction(a, [] { +//                     f();  // break +//                   }); +static bool fakeRParenSpecialCase(const LineState &State) { +  const FormatToken &Tok = *State.NextToken; +  if (!Tok.MatchingParen) +    return false; +  const FormatToken *Left = &Tok; +  if (Tok.isOneOf(tok::r_brace, tok::r_square)) +    Left = Tok.MatchingParen; +  return !State.Stack.back().HasMultipleNestedBlocks && +         Left->isOneOf(tok::l_brace, tok::l_square) && +         (Left->BlockKind == BK_Block || +          Left->Type == TT_ArrayInitializerLSquare || +          Left->Type == TT_DictLiteral); +} + +void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) { +  // Don't remove FakeRParens attached to r_braces that surround nested blocks +  // as they will have been removed early (see above). +  if (fakeRParenSpecialCase(State)) +    return; + +  consumeRParens(State, *State.NextToken); +} -    bool NoLineBreak = State.Stack.back().NoLineBreak || -                       (Current.Type == TT_TemplateOpener && -                        State.Stack.back().ContainsUnwrappedBuilder); -    State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, -                                     State.Stack.back().LastSpace, -                                     AvoidBinPacking, NoLineBreak)); -    State.Stack.back().BreakBeforeParameter = BreakBeforeParameter; -    ++State.ParenLevel; +void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, +                                                    bool Newline) { +  const FormatToken &Current = *State.NextToken; +  if (!Current.opensScope()) +    return; + +  if (Current.MatchingParen && Current.BlockKind == BK_Block) { +    moveStateToNewBlock(State); +    return;    } +  unsigned NewIndent; +  unsigned NewIndentLevel = State.Stack.back().IndentLevel; +  bool AvoidBinPacking; +  bool BreakBeforeParameter = false; +  if (Current.is(tok::l_brace) || Current.Type == TT_ArrayInitializerLSquare) { +    if (fakeRParenSpecialCase(State)) +      consumeRParens(State, *Current.MatchingParen); + +    NewIndent = State.Stack.back().LastSpace; +    if (Current.opensBlockTypeList(Style)) { +      NewIndent += Style.IndentWidth; +      NewIndent = std::min(State.Column + 2, NewIndent); +      ++NewIndentLevel; +    } else { +      NewIndent += Style.ContinuationIndentWidth; +      NewIndent = std::min(State.Column + 1, NewIndent); +    } +    const FormatToken *NextNoComment = Current.getNextNonComment(); +    AvoidBinPacking = Current.Type == TT_ArrayInitializerLSquare || +                      Current.Type == TT_DictLiteral || +                      Style.Language == FormatStyle::LK_Proto || +                      !Style.BinPackParameters || +                      (NextNoComment && +                       NextNoComment->Type == TT_DesignatedInitializerPeriod); +  } else { +    NewIndent = Style.ContinuationIndentWidth + +                std::max(State.Stack.back().LastSpace, +                         State.Stack.back().StartOfFunctionCall); +    AvoidBinPacking = !Style.BinPackParameters || +                      (Style.ExperimentalAutoDetectBinPacking && +                       (Current.PackingKind == PPK_OnePerLine || +                        (!BinPackInconclusiveFunctions && +                         Current.PackingKind == PPK_Inconclusive))); +    // If this '[' opens an ObjC call, determine whether all parameters fit +    // into one line and put one per line if they don't. +    if (Current.Type == TT_ObjCMethodExpr && Style.ColumnLimit != 0 && +        getLengthToMatchingParen(Current) + State.Column > +            getColumnLimit(State)) +      BreakBeforeParameter = true; +  } +  bool NoLineBreak = State.Stack.back().NoLineBreak || +                     (Current.Type == TT_TemplateOpener && +                      State.Stack.back().ContainsUnwrappedBuilder); +  State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, +                                   State.Stack.back().LastSpace, +                                   AvoidBinPacking, NoLineBreak)); +  State.Stack.back().BreakBeforeParameter = BreakBeforeParameter; +  State.Stack.back().HasMultipleNestedBlocks = Current.BlockParameterCount > 1; +} + +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) ||         (Current.is(tok::r_brace) && State.NextToken != State.Line->First) || -       State.NextToken->Type == TT_TemplateCloser)) { +       State.NextToken->Type == TT_TemplateCloser))      State.Stack.pop_back(); -    --State.ParenLevel; -  } +    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))        State.Stack.back().StartOfArraySubscripts = 0;    } +} -  // Remove scopes created by fake parenthesis. -  if (Current.isNot(tok::r_brace) || -      (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) { -    // Don't remove FakeRParens attached to r_braces that surround nested blocks -    // as they will have been removed early (see above). -    for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) { -      unsigned VariablePos = State.Stack.back().VariablePos; -      State.Stack.pop_back(); -      State.Stack.back().VariablePos = VariablePos; -    } -  } - -  if (Current.is(tok::string_literal) && State.StartOfStringLiteral == 0) { -    State.StartOfStringLiteral = State.Column; -  } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash, -                              tok::string_literal)) { -    State.StartOfStringLiteral = 0; -  } - -  State.Column += Current.ColumnWidth; -  State.NextToken = State.NextToken->Next; -  unsigned Penalty = breakProtrudingToken(Current, State, DryRun); -  if (State.Column > getColumnLimit(State)) { -    unsigned ExcessCharacters = State.Column - getColumnLimit(State); -    Penalty += Style.PenaltyExcessCharacter * ExcessCharacters; -  } - -  // 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->format(State, this, DryRun); - -  return Penalty; +void ContinuationIndenter::moveStateToNewBlock(LineState &State) { +  // If we have already found more than one lambda introducers on this level, we +  // opt out of this because similarity between the lambdas is more important. +  if (fakeRParenSpecialCase(State)) +    consumeRParens(State, *State.NextToken->MatchingParen); + +  // For some reason, ObjC blocks are indented like continuations. +  unsigned NewIndent = State.Stack.back().LastSpace + +                       (State.NextToken->Type == TT_ObjCBlockLBrace +                            ? Style.ContinuationIndentWidth +                            : Style.IndentWidth); +  State.Stack.push_back(ParenState( +      NewIndent, /*NewIndentLevel=*/State.Stack.back().IndentLevel + 1, +      State.Stack.back().LastSpace, /*AvoidBinPacking=*/true, +      State.Stack.back().NoLineBreak)); +  State.Stack.back().BreakBeforeParameter = true;  }  unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current, @@ -696,8 +915,7 @@ unsigned ContinuationIndenter::addMultilineToken(const FormatToken &Current,    return 0;  } -static bool getRawStringLiteralPrefixPostfix(StringRef Text, -                                             StringRef &Prefix, +static bool getRawStringLiteralPrefixPostfix(StringRef Text, StringRef &Prefix,                                               StringRef &Postfix) {    if (Text.startswith(Prefix = "R\"") || Text.startswith(Prefix = "uR\"") ||        Text.startswith(Prefix = "UR\"") || Text.startswith(Prefix = "u8R\"") || @@ -727,19 +945,14 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,    if (Current.Type == TT_ImplicitStringLiteral)      return 0; -  if (!Current.isOneOf(tok::string_literal, tok::wide_string_literal, -                       tok::utf8_string_literal, tok::utf16_string_literal, -                       tok::utf32_string_literal, tok::comment)) +  if (!Current.isStringLiteral() && !Current.is(tok::comment))      return 0; -  llvm::OwningPtr<BreakableToken> Token; +  std::unique_ptr<BreakableToken> Token;    unsigned StartColumn = State.Column - Current.ColumnWidth;    unsigned ColumnLimit = getColumnLimit(State); -  if (Current.isOneOf(tok::string_literal, tok::wide_string_literal, -                      tok::utf8_string_literal, tok::utf16_string_literal, -                      tok::utf32_string_literal) && -      Current.Type != TT_ImplicitStringLiteral) { +  if (Current.isStringLiteral()) {      // 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). @@ -755,13 +968,20 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,      StringRef Text = Current.TokenText;      StringRef Prefix;      StringRef Postfix; +    bool IsNSStringLiteral = false;      // 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.startswith("\"") && Current.Previous && +        Current.Previous->is(tok::at)) { +      IsNSStringLiteral = true; +      Prefix = "@\""; +    }      if ((Text.endswith(Postfix = "\"") && -         (Text.startswith(Prefix = "\"") || Text.startswith(Prefix = "u\"") || -          Text.startswith(Prefix = "U\"") || Text.startswith(Prefix = "u8\"") || +         (IsNSStringLiteral || Text.startswith(Prefix = "\"") || +          Text.startswith(Prefix = "u\"") || Text.startswith(Prefix = "U\"") || +          Text.startswith(Prefix = "u8\"") ||            Text.startswith(Prefix = "L\""))) ||          (Text.startswith(Prefix = "_T(\"") && Text.endswith(Postfix = "\")")) ||          getRawStringLiteralPrefixPostfix(Text, Prefix, Postfix)) { @@ -772,12 +992,16 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,        return 0;      }    } else if (Current.Type == TT_BlockComment && Current.isTrailingComment()) { +    if (CommentPragmasRegex.match(Current.TokenText.substr(2))) +      return 0;      Token.reset(new BreakableBlockComment(          Current, State.Line->Level, StartColumn, Current.OriginalColumn,          !Current.Previous, State.Line->InPPDirective, Encoding, Style));    } else if (Current.Type == TT_LineComment && -             (Current.Previous == NULL || +             (Current.Previous == nullptr ||                Current.Previous->Type != TT_ImplicitStringLiteral)) { +    if (CommentPragmasRegex.match(Current.TokenText.substr(2))) +      return 0;      Token.reset(new BreakableLineComment(Current, State.Line->Level,                                           StartColumn, /*InPPDirective=*/false,                                           Encoding, Style)); @@ -822,6 +1046,12 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,          break;        } +      // 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) +        break; +        assert(NewRemainingTokenColumns < RemainingTokenColumns);        if (!DryRun)          Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces); @@ -848,8 +1078,8 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,          State.Stack[i].BreakBeforeParameter = true;      } -    Penalty += Current.is(tok::string_literal) ? Style.PenaltyBreakString -                                               : Style.PenaltyBreakComment; +    Penalty += Current.isStringLiteral() ? Style.PenaltyBreakString +                                         : Style.PenaltyBreakComment;      State.Stack.back().LastSpace = StartColumn;    } @@ -861,18 +1091,19 @@ unsigned ContinuationIndenter::getColumnLimit(const LineState &State) const {    return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0);  } -bool ContinuationIndenter::NextIsMultilineString(const LineState &State) { +bool ContinuationIndenter::nextIsMultilineString(const LineState &State) {    const FormatToken &Current = *State.NextToken; -  if (!Current.is(tok::string_literal)) +  if (!Current.isStringLiteral() || Current.Type == TT_ImplicitStringLiteral)      return false;    // We never consider raw string literals "multiline" for the purpose of -  // AlwaysBreakBeforeMultilineStrings implementation. +  // AlwaysBreakBeforeMultilineStrings implementation as they are special-cased +  // (see TokenAnnotator::mustBreakBefore().    if (Current.TokenText.startswith("R\""))      return false;    if (Current.IsMultiline)      return true;    if (Current.getNextNonComment() && -      Current.getNextNonComment()->is(tok::string_literal)) +      Current.getNextNonComment()->isStringLiteral())      return true; // Implicit concatenation.    if (State.Column + Current.ColumnWidth + Current.UnbreakableTailLength >        Style.ColumnLimit)  | 
