23#include "llvm/ADT/StringSet.h"
24#include "llvm/Support/Debug.h"
27#define DEBUG_TYPE "format-indenter"
44 Previous->isOneOf(tok::kw_return, TT_RequiresClause));
93 int MatchingStackIndex = Stack.size() - 1;
99 while (MatchingStackIndex >= 0 && Stack[MatchingStackIndex].Tok != LBrace)
100 --MatchingStackIndex;
101 return MatchingStackIndex >= 0 ? &Stack[MatchingStackIndex] :
nullptr;
103 for (; End->Next; End = End->Next) {
104 if (End->Next->CanBreakBefore)
106 if (!End->Next->closesScope())
108 if (End->Next->MatchingParen &&
109 End->Next->MatchingParen->isOneOf(
110 tok::l_brace, TT_ArrayInitializerLSquare, tok::less)) {
111 const ParenState *State = FindParenState(End->Next->MatchingParen);
112 if (State && State->BreakBeforeClosingBrace)
136 if (Current.
is(TT_CtorInitializerComma) &&
143 ((
Previous.isNot(TT_CtorInitializerComma) ||
146 (
Previous.isNot(TT_InheritanceComma) ||
153 bool HasTwoOperands =
Token.OperatorIndex == 0 && !
Token.NextOperator;
154 return Token.
is(TT_BinaryOperator) && !HasTwoOperands &&
177 if (LessTok.
isNot(tok::less))
189 if (TokenText.size() < 5
190 || !TokenText.starts_with(
"R\"") || !TokenText.ends_with(
"\"")) {
197 size_t LParenPos = TokenText.substr(0, 19).find_first_of(
'(');
198 if (LParenPos == StringRef::npos)
200 StringRef Delimiter = TokenText.substr(2, LParenPos - 2);
203 size_t RParenPos = TokenText.size() - Delimiter.size() - 2;
204 if (TokenText[RParenPos] !=
')')
206 if (!TokenText.substr(RParenPos + 1).starts_with(Delimiter))
218 return StringRef(Format.CanonicalDelimiter);
225 std::optional<FormatStyle> LanguageStyle =
227 if (!LanguageStyle) {
230 RawStringFormat.Language, &PredefinedStyle)) {
232 PredefinedStyle.
Language = RawStringFormat.Language;
234 LanguageStyle = PredefinedStyle;
237 for (StringRef Delimiter : RawStringFormat.Delimiters)
239 for (StringRef EnclosingFunction : RawStringFormat.EnclosingFunctions)
244std::optional<FormatStyle>
252std::optional<FormatStyle>
254 StringRef EnclosingFunction)
const {
266 bool BinPackInconclusiveFunctions)
267 : Style(Style), Keywords(Keywords), SourceMgr(SourceMgr),
268 Whitespaces(Whitespaces), Encoding(Encoding),
269 BinPackInconclusiveFunctions(BinPackInconclusiveFunctions),
270 CommentPragmasRegex(Style.CommentPragmas), RawStringFormats(Style) {}
273 unsigned FirstStartColumn,
277 State.FirstIndent = FirstIndent;
278 if (FirstStartColumn &&
Line->First->NewlinesBefore == 0)
279 State.Column = FirstStartColumn;
281 State.Column = FirstIndent;
291 State.NextToken =
Line->First;
292 State.Stack.push_back(
ParenState(
nullptr, FirstIndent, FirstIndent,
295 State.NoContinuation =
false;
296 State.StartOfStringLiteral = 0;
297 State.NoLineBreak =
false;
298 State.StartOfLineLevel = 0;
299 State.LowestLevelOnLine = 0;
300 State.IgnoreStackForComparison =
false;
305 auto &CurrentState = State.Stack.back();
306 CurrentState.AvoidBinPacking =
true;
307 CurrentState.BreakBeforeParameter =
true;
308 CurrentState.AlignColons =
false;
312 moveStateToNextToken(State, DryRun,
false);
319 const auto &CurrentState = State.Stack.back();
320 assert(&
Previous == Current.Previous);
321 if (!Current.CanBreakBefore && !(CurrentState.BreakBeforeClosingBrace &&
322 Current.closesBlockOrBlockTypeList(Style))) {
327 if (!Current.MustBreakBefore &&
Previous.is(tok::l_brace) &&
330 Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma)) {
339 State.LowestLevelOnLine < State.StartOfLineLevel &&
340 State.LowestLevelOnLine < Current.NestingLevel) {
343 if (Current.isMemberAccess() && CurrentState.ContainsUnwrappedBuilder)
348 if (
Previous.is(tok::l_brace) && State.Stack.size() > 1 &&
349 State.Stack[State.Stack.size() - 2].NestedBlockInlined &&
350 State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks &&
357 if (Current.is(TT_FunctionDeclarationName)) {
364 assert(State.Column >= State.FirstIndent);
365 if (State.Column - State.FirstIndent < 6)
372 if (!Current.isOneOf(TT_BinaryOperator, tok::comma) &&
377 Current.isNot(TT_LambdaLBrace)) &&
378 CurrentState.NoLineBreakInOperand) {
385 if (Current.is(TT_ConditionalExpr) &&
Previous.is(tok::r_paren) &&
387 Previous.MatchingParen->Previous->MatchingParen &&
388 Previous.MatchingParen->Previous->MatchingParen->is(TT_LambdaLBrace)) {
390 assert(
Previous.MatchingParen->Previous->is(tok::r_brace));
394 return !State.NoLineBreak && !CurrentState.NoLineBreak;
400 const auto &CurrentState = State.Stack.back();
402 Current.is(TT_LambdaLBrace) &&
Previous.isNot(TT_LineComment)) {
406 if (Current.MustBreakBefore ||
407 (Current.is(TT_InlineASMColon) &&
413 if (CurrentState.BreakBeforeClosingBrace &&
414 (Current.closesBlockOrBlockTypeList(Style) ||
415 (Current.is(tok::r_brace) &&
416 Current.isBlockIndentedInitRBrace(Style)))) {
419 if (CurrentState.BreakBeforeClosingParen && Current.is(tok::r_paren))
423 Current.ObjCSelectorNameParts > 1 &&
424 Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)) {
429 if (CurrentState.IsCSharpGenericTypeConstraint &&
430 Previous.isNot(TT_CSharpGenericTypeConstraintComma)) {
434 (
Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) &&
435 State.Line->First->isNot(TT_AttributeSquare) && Style.
isCpp() &&
444 Previous.is(TT_ConditionalExpr))) &&
445 CurrentState.BreakBeforeParameter && !Current.isTrailingComment() &&
446 !Current.isOneOf(tok::r_paren, tok::r_brace)) {
449 if (CurrentState.IsChainedConditional &&
451 Current.is(tok::colon)) ||
457 (
Previous.is(TT_ArrayInitializerLSquare) &&
466 const FormatToken &BreakConstructorInitializersToken =
470 if (BreakConstructorInitializersToken.
is(TT_CtorInitializerColon) &&
471 (State.Column + State.Line->Last->TotalLength -
Previous.TotalLength >
473 CurrentState.BreakBeforeParameter) &&
474 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
481 if (Current.is(TT_ObjCMethodExpr) &&
Previous.isNot(TT_SelectorName) &&
482 State.Line->startsWith(TT_ObjCMethodSpecifier)) {
485 if (Current.is(TT_SelectorName) &&
Previous.isNot(tok::at) &&
486 CurrentState.ObjCSelectorNameFound && CurrentState.BreakBeforeParameter &&
488 !Current.startsSequence(TT_SelectorName, tok::colon, tok::caret))) {
492 unsigned NewLineColumn = getNewLineColumn(State);
493 if (Current.isMemberAccess() && Style.
ColumnLimit != 0 &&
495 (State.Column > NewLineColumn ||
496 Current.NestingLevel < State.StartOfLineLevel)) {
501 (CurrentState.CallContinuation != 0 ||
502 CurrentState.BreakBeforeParameter) &&
508 !(State.Column <= NewLineColumn && Style.
isJavaScript()) &&
509 !(
Previous.closesScopeAfterBlock() && State.Column <= NewLineColumn)) {
515 if (
Previous.ClosesTemplateDeclaration && CurrentState.BreakBeforeParameter &&
516 Current.CanBreakBefore) {
520 if (State.Line->First->isNot(tok::kw_enum) && State.Column <= NewLineColumn)
525 Previous.is(tok::comma) || Current.NestingLevel < 2) &&
526 !
Previous.isOneOf(tok::kw_return, tok::lessless, tok::at,
528 !
Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
529 nextIsMultilineString(State)) {
536 if (
Previous.is(TT_BinaryOperator) && Current.CanBreakBefore) {
537 const auto PreviousPrecedence =
Previous.getPrecedence();
539 CurrentState.BreakBeforeParameter && !Current.isTrailingComment()) {
540 const bool LHSIsBinaryExpr =
553 const bool IsComparison =
558 Previous.Previous->isNot(TT_BinaryOperator);
562 }
else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore &&
563 CurrentState.BreakBeforeParameter) {
568 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator) &&
569 CurrentState.BreakBeforeParameter && CurrentState.FirstLessLess == 0) {
573 if (Current.NestingLevel == 0 && !Current.isTrailingComment()) {
578 if (
Previous.ClosesTemplateDeclaration) {
579 if (Current.is(tok::kw_concept)) {
589 if (Current.is(TT_RequiresClause)) {
600 Current.NewlinesBefore > 0);
602 if (
Previous.is(TT_FunctionAnnotationRParen) &&
606 if (
Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) &&
607 Current.isNot(TT_LeadingJavaAnnotation)) {
616 static const llvm::StringSet<> BreakBeforeDecoratedTokens = {
"get",
"set",
618 if (BreakBeforeDecoratedTokens.contains(Current.TokenText))
622 if (Current.is(TT_FunctionDeclarationName) &&
623 !State.Line->ReturnTypeWrapped &&
630 CurrentState.BreakBeforeParameter) {
639 !Current.isOneOf(tok::r_brace, tok::comment)) {
643 if (Current.is(tok::lessless) &&
646 Previous.TokenText ==
"\'\\n\'")))) {
653 if (State.NoContinuation)
661 unsigned ExtraSpaces) {
663 assert(State.NextToken->Previous);
666 assert(!State.Stack.empty());
667 State.NoContinuation =
false;
669 if (Current.is(TT_ImplicitStringLiteral) &&
670 (!
Previous.Tok.getIdentifierInfo() ||
671 Previous.Tok.getIdentifierInfo()->getPPKeywordID() ==
672 tok::pp_not_keyword)) {
675 if (Current.LastNewlineOffset != 0) {
678 State.Column = EndColumn;
680 unsigned StartColumn =
682 assert(EndColumn >= StartColumn);
683 State.Column += EndColumn - StartColumn;
685 moveStateToNextToken(State, DryRun,
false);
689 unsigned Penalty = 0;
691 Penalty = addTokenOnNewLine(State, DryRun);
693 addTokenOnCurrentLine(State, DryRun, ExtraSpaces);
695 return moveStateToNextToken(State, DryRun, Newline) + Penalty;
698void ContinuationIndenter::addTokenOnCurrentLine(
LineState &State,
bool DryRun,
699 unsigned ExtraSpaces) {
701 assert(State.NextToken->Previous);
703 auto &CurrentState = State.Stack.back();
705 bool DisallowLineBreaksOnThisLine =
707 Style.
isCpp() && [&Current] {
713 const auto *Prev = Current.Previous;
717 if (Prev->is(TT_BlockComment) && Current.SpacesRequiredBefore == 0)
719 const auto *PrevNonComment = Current.getPreviousNonComment();
720 if (!PrevNonComment || PrevNonComment->isNot(tok::l_paren))
722 if (Current.isOneOf(tok::comment, tok::l_paren, TT_LambdaLSquare))
724 auto BlockParameterCount = PrevNonComment->BlockParameterCount;
725 if (BlockParameterCount == 0)
729 if (BlockParameterCount > 1)
733 if (!PrevNonComment->Role)
735 auto Comma = PrevNonComment->Role->lastComma();
738 auto Next = Comma->getNextNonComment();
740 !Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret);
743 if (DisallowLineBreaksOnThisLine)
744 State.NoLineBreak =
true;
746 if (Current.is(tok::equal) &&
747 (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&
748 CurrentState.VariablePos == 0 &&
750 Previous.Previous->isNot(TT_DesignatedInitializerPeriod))) {
751 CurrentState.VariablePos = State.Column;
754 while (Tok && CurrentState.VariablePos >= Tok->ColumnWidth) {
755 CurrentState.VariablePos -= Tok->ColumnWidth;
756 if (Tok->SpacesRequiredBefore != 0)
760 if (
Previous.PartOfMultiVariableDeclStmt)
761 CurrentState.LastSpace = CurrentState.VariablePos;
764 unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces;
767 int PPColumnCorrection = 0;
769 Previous.is(tok::hash) && State.FirstIndent > 0 &&
773 Spaces += State.FirstIndent;
780 PPColumnCorrection = -1;
785 State.Column + Spaces + PPColumnCorrection,
786 false, State.Line->InMacroBody);
792 Current.is(TT_InheritanceColon)) {
793 CurrentState.NoLineBreak =
true;
797 CurrentState.NoLineBreak =
true;
800 if (Current.is(TT_SelectorName) && !CurrentState.ObjCSelectorNameFound) {
801 unsigned MinIndent = std::max(
803 unsigned FirstColonPos = State.Column + Spaces + Current.ColumnWidth;
804 if (Current.LongestObjCSelectorName == 0)
805 CurrentState.AlignColons =
false;
806 else if (MinIndent + Current.LongestObjCSelectorName > FirstColonPos)
807 CurrentState.ColonPos = MinIndent + Current.LongestObjCSelectorName;
809 CurrentState.ColonPos = FirstColonPos;
816 auto IsOpeningBracket = [&](
const FormatToken &Tok) {
817 auto IsStartOfBracedList = [&]() {
818 return Tok.is(tok::l_brace) && Tok.isNot(
BK_Block) &&
821 if (!Tok.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) &&
822 !IsStartOfBracedList()) {
827 if (Tok.Previous->isIf())
829 return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while,
832 auto IsFunctionCallParen = [](
const FormatToken &Tok) {
833 return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous &&
834 Tok.Previous->is(tok::identifier);
836 const auto IsInTemplateString = [
this](
const FormatToken &Tok) {
839 for (
const auto *Prev = &Tok; Prev; Prev = Prev->Previous) {
840 if (Prev->is(TT_TemplateString) && Prev->opensScope())
842 if (Prev->is(TT_TemplateString) && Prev->closesScope())
848 const auto IsSimpleFunction = [&](
const FormatToken &Tok) {
849 if (!Tok.FakeLParens.empty() && Tok.FakeLParens.back() >
prec::Unknown)
851 const auto *
Previous = Tok.Previous;
853 TT_LambdaDefinitionLParen) &&
857 if (IsOpeningBracket(Tok) || IsInTemplateString(Tok))
859 const auto *Next = Tok.Next;
860 return !Next || Next->isMemberAccess() ||
861 Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next);
865 IsOpeningBracket(
Previous) && State.Column > getNewLineColumn(State) &&
873 !IsSimpleFunction(Current)) {
874 CurrentState.NoLineBreak =
true;
878 CurrentState.NoLineBreak =
true;
885 !CurrentState.IsCSharpGenericTypeConstraint &&
Previous.opensScope() &&
887 Previous.isNot(TT_TableGenDAGArgOpener) &&
888 Previous.isNot(TT_TableGenDAGArgOpenerToBreak) &&
889 !(Current.MacroParent &&
Previous.MacroParent) &&
890 (Current.isNot(TT_LineComment) ||
892 !IsInTemplateString(Current)) {
893 CurrentState.Indent = State.Column + Spaces;
894 CurrentState.IsAligned =
true;
897 CurrentState.NoLineBreak =
true;
899 CurrentState.NoLineBreak =
true;
902 State.Column > getNewLineColumn(State)) {
903 CurrentState.ContainsUnwrappedBuilder =
true;
906 if (Current.is(TT_TrailingReturnArrow) &&
908 CurrentState.NoLineBreak =
true;
910 if (Current.isMemberAccess() &&
Previous.is(tok::r_paren) &&
919 CurrentState.NoLineBreak =
true;
926 const FormatToken *
P = Current.getPreviousNonComment();
927 if (Current.isNot(tok::comment) &&
P &&
928 (
P->isOneOf(TT_BinaryOperator, tok::comma) ||
929 (
P->is(TT_ConditionalExpr) &&
P->is(tok::colon))) &&
930 !
P->isOneOf(TT_OverloadedOperator, TT_CtorInitializerComma) &&
934 bool BreakBeforeOperator =
935 P->MustBreakBefore ||
P->is(tok::lessless) ||
936 (
P->is(TT_BinaryOperator) &&
942 bool HasTwoOperands =
P->OperatorIndex == 0 && !
P->NextOperator &&
943 P->isNot(TT_ConditionalExpr);
944 if ((!BreakBeforeOperator &&
947 (!CurrentState.LastOperatorWrapped && BreakBeforeOperator)) {
948 CurrentState.NoLineBreakInOperand =
true;
952 State.Column += Spaces;
953 if (Current.isNot(tok::comment) &&
Previous.is(tok::l_paren) &&
958 CurrentState.LastSpace = State.Column;
959 CurrentState.NestedBlockIndent = State.Column;
960 }
else if (!Current.isOneOf(tok::comment, tok::caret) &&
962 Previous.isNot(TT_OverloadedOperator)) ||
964 CurrentState.LastSpace = State.Column;
965 }
else if (
Previous.is(TT_CtorInitializerColon) &&
966 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
969 CurrentState.Indent = State.Column;
970 CurrentState.LastSpace = State.Column;
971 }
else if (
Previous.isOneOf(TT_ConditionalExpr, TT_CtorInitializerColon)) {
972 CurrentState.LastSpace = State.Column;
973 }
else if (
Previous.is(TT_BinaryOperator) &&
977 Current.StartsBinaryExpression)) {
981 CurrentState.LastSpace = State.Column;
982 }
else if (
Previous.is(TT_InheritanceColon)) {
983 CurrentState.Indent = State.Column;
984 CurrentState.LastSpace = State.Column;
985 }
else if (Current.is(TT_CSharpGenericTypeConstraintColon)) {
986 CurrentState.ColonPos = State.Column;
994 const FormatToken *Next =
Previous.MatchingParen->getNextNonComment();
995 if (Next && Next->isMemberAccess() && State.Stack.size() > 1 &&
996 State.Stack[State.Stack.size() - 2].CallContinuation == 0) {
997 CurrentState.LastSpace = State.Column;
1003unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
1005 FormatToken &Current = *State.NextToken;
1006 assert(State.NextToken->Previous);
1007 const FormatToken &
Previous = *State.NextToken->Previous;
1008 auto &CurrentState = State.Stack.back();
1012 unsigned Penalty = 0;
1014 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
1015 const FormatToken *NextNonComment =
Previous.getNextNonComment();
1016 if (!NextNonComment)
1017 NextNonComment = &Current;
1020 if (!CurrentState.ContainsLineBreak)
1022 CurrentState.ContainsLineBreak =
true;
1024 Penalty += State.NextToken->SplitPenalty;
1029 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess == 0 &&
1031 CurrentState.BreakBeforeParameter)) {
1035 State.Column = getNewLineColumn(State);
1049 if (State.Column > State.FirstIndent) {
1064 if (Current.isNot(TT_TrailingReturnArrow) &&
1066 !PreviousNonComment || PreviousNonComment->isNot(tok::equal) ||
1068 CurrentState.NestedBlockIndent = State.Column;
1071 if (NextNonComment->isMemberAccess()) {
1072 if (CurrentState.CallContinuation == 0)
1073 CurrentState.CallContinuation = State.Column;
1074 }
else if (NextNonComment->is(TT_SelectorName)) {
1075 if (!CurrentState.ObjCSelectorNameFound) {
1076 if (NextNonComment->LongestObjCSelectorName == 0) {
1077 CurrentState.AlignColons =
false;
1079 CurrentState.ColonPos =
1081 ? std::max(CurrentState.Indent,
1083 : CurrentState.Indent) +
1085 NextNonComment->ColumnWidth);
1087 }
else if (CurrentState.AlignColons &&
1088 CurrentState.ColonPos <= NextNonComment->ColumnWidth) {
1089 CurrentState.ColonPos = State.Column + NextNonComment->ColumnWidth;
1091 }
else if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
1092 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
1102 if (State.Stack.size() > 1) {
1103 State.Stack[State.Stack.size() - 2].LastSpace =
1104 std::max(CurrentState.LastSpace, CurrentState.Indent) +
1109 if ((PreviousNonComment &&
1110 PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
1111 !CurrentState.AvoidBinPacking) ||
1113 CurrentState.BreakBeforeParameter =
false;
1115 if (PreviousNonComment &&
1116 (PreviousNonComment->isOneOf(TT_TemplateCloser, TT_JavaAnnotation) ||
1117 PreviousNonComment->ClosesRequiresClause) &&
1118 Current.NestingLevel == 0) {
1119 CurrentState.BreakBeforeParameter =
false;
1121 if (NextNonComment->is(tok::question) ||
1122 (PreviousNonComment && PreviousNonComment->is(tok::question))) {
1123 CurrentState.BreakBeforeParameter =
true;
1125 if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore)
1126 CurrentState.BreakBeforeParameter =
false;
1130 if (Current.is(tok::r_brace) && Current.MatchingParen &&
1133 !Current.MatchingParen->Children.empty()) {
1137 MaxEmptyLinesToKeep = 1;
1140 std::max(1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
1141 bool ContinuePPDirective =
1144 CurrentState.IsAligned, ContinuePPDirective);
1147 if (!Current.isTrailingComment())
1148 CurrentState.LastSpace = State.Column;
1149 if (Current.is(tok::lessless)) {
1153 CurrentState.LastSpace += 3;
1156 State.StartOfLineLevel = Current.NestingLevel;
1157 State.LowestLevelOnLine = Current.NestingLevel;
1161 bool NestedBlockSpecialCase =
1162 (!Style.
isCpp() && Current.is(tok::r_brace) && State.Stack.size() > 1 &&
1163 State.Stack[State.Stack.size() - 2].NestedBlockInlined) ||
1167 NestedBlockSpecialCase =
1168 NestedBlockSpecialCase ||
1169 (Current.MatchingParen &&
1170 Current.MatchingParen->is(TT_RequiresExpressionLBrace));
1171 if (!NestedBlockSpecialCase) {
1172 auto ParentLevelIt = std::next(State.Stack.rbegin());
1174 Current.MatchingParen && Current.MatchingParen->is(TT_LambdaLBrace)) {
1189 auto FindCurrentLevel = [&](
const auto &It) {
1190 return std::find_if(It, State.Stack.rend(), [](
const auto &PState) {
1191 return PState.Tok != nullptr;
1194 auto MaybeIncrement = [&](
const auto &It) {
1195 return It != State.Stack.rend() ? std::next(It) : It;
1197 auto LambdaLevelIt = FindCurrentLevel(State.Stack.rbegin());
1198 auto LevelContainingLambdaIt =
1199 FindCurrentLevel(MaybeIncrement(LambdaLevelIt));
1200 ParentLevelIt = MaybeIncrement(LevelContainingLambdaIt);
1202 for (
auto I = ParentLevelIt,
E = State.Stack.rend(); I !=
E; ++I)
1203 I->BreakBeforeParameter =
true;
1206 if (PreviousNonComment &&
1207 !PreviousNonComment->isOneOf(tok::comma, tok::colon, tok::semi) &&
1208 ((PreviousNonComment->isNot(TT_TemplateCloser) &&
1209 !PreviousNonComment->ClosesRequiresClause) ||
1210 Current.NestingLevel != 0) &&
1211 !PreviousNonComment->isOneOf(
1212 TT_BinaryOperator, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
1213 TT_LeadingJavaAnnotation) &&
1214 Current.isNot(TT_BinaryOperator) && !PreviousNonComment->opensScope() &&
1218 Current.isNot(TT_LambdaLBrace))) {
1219 CurrentState.BreakBeforeParameter =
true;
1224 if (PreviousNonComment &&
1225 (PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1227 CurrentState.BreakBeforeClosingBrace =
true;
1230 if (PreviousNonComment && PreviousNonComment->is(tok::l_paren)) {
1231 CurrentState.BreakBeforeClosingParen =
1235 if (CurrentState.AvoidBinPacking) {
1240 bool PreviousIsBreakingCtorInitializerColon =
1241 PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1243 bool AllowAllConstructorInitializersOnNextLine =
1246 if (!(
Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
1247 PreviousIsBreakingCtorInitializerColon) ||
1249 State.Line->MustBeDeclaration) ||
1251 !State.Line->MustBeDeclaration) ||
1252 (!AllowAllConstructorInitializersOnNextLine &&
1253 PreviousIsBreakingCtorInitializerColon) ||
1255 CurrentState.BreakBeforeParameter =
true;
1261 if (PreviousIsBreakingCtorInitializerColon &&
1262 AllowAllConstructorInitializersOnNextLine) {
1263 CurrentState.BreakBeforeParameter =
false;
1268 CurrentState.BreakBeforeParameter =
true;
1273unsigned ContinuationIndenter::getNewLineColumn(
const LineState &State) {
1274 if (!State.NextToken || !State.NextToken->Previous)
1277 FormatToken &Current = *State.NextToken;
1278 const auto &CurrentState = State.Stack.back();
1280 if (CurrentState.IsCSharpGenericTypeConstraint &&
1281 Current.isNot(TT_CSharpGenericTypeConstraint)) {
1282 return CurrentState.ColonPos + 2;
1285 const FormatToken &
Previous = *Current.Previous;
1287 unsigned ContinuationIndent =
1288 std::max(CurrentState.LastSpace, CurrentState.Indent) +
1290 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
1291 const FormatToken *NextNonComment =
Previous.getNextNonComment();
1292 if (!NextNonComment)
1293 NextNonComment = &Current;
1298 return std::max(CurrentState.LastSpace,
1304 if (Style.
isVerilog() && PreviousNonComment &&
1306 return State.FirstIndent;
1310 State.Line->First->is(tok::kw_enum)) {
1311 return (Style.
IndentWidth * State.Line->First->IndentLevel) +
1315 if ((NextNonComment->is(tok::l_brace) && NextNonComment->is(
BK_Block)) ||
1317 if (Current.NestingLevel == 0 ||
1319 State.NextToken->is(TT_LambdaLBrace))) {
1320 return State.FirstIndent;
1322 return CurrentState.Indent;
1324 if (Current.is(TT_TrailingReturnArrow) &&
1325 Previous.isOneOf(tok::kw_noexcept, tok::kw_mutable, tok::kw_constexpr,
1326 tok::kw_consteval, tok::kw_static, TT_AttributeSquare)) {
1327 return ContinuationIndent;
1329 if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
1331 State.Stack.size() > 1) {
1332 if (Current.closesBlockOrBlockTypeList(Style))
1333 return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
1334 if (Current.MatchingParen && Current.MatchingParen->is(
BK_BracedInit))
1335 return State.Stack[State.Stack.size() - 2].LastSpace;
1336 return State.FirstIndent;
1353 if (Current.is(tok::r_paren) && State.Stack.size() > 1 &&
1355 Current.Next->isOneOf(tok::semi, tok::kw_const, tok::l_brace))) {
1356 return State.Stack[State.Stack.size() - 2].LastSpace;
1360 if (Style.
isTableGen() && Current.is(TT_TableGenDAGArgCloser) &&
1361 State.Stack.size() > 1) {
1362 return State.Stack[State.Stack.size() - 2].LastSpace;
1365 (Current.is(tok::r_paren) ||
1366 (Current.is(tok::r_brace) && Current.MatchingParen &&
1368 State.Stack.size() > 1) {
1369 return State.Stack[State.Stack.size() - 2].LastSpace;
1371 if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
1372 return State.Stack[State.Stack.size() - 2].LastSpace;
1380 if (Current.is(tok::identifier) && Current.Next &&
1381 (!Style.
isVerilog() || Current.Next->is(tok::colon)) &&
1382 (Current.Next->is(TT_DictLiteral) ||
1383 (Style.
isProto() && Current.Next->isOneOf(tok::less, tok::l_brace)))) {
1384 return CurrentState.Indent;
1386 if (NextNonComment->is(TT_ObjCStringLiteral) &&
1387 State.StartOfStringLiteral != 0) {
1388 return State.StartOfStringLiteral - 1;
1390 if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0)
1391 return State.StartOfStringLiteral;
1392 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess != 0)
1393 return CurrentState.FirstLessLess;
1394 if (NextNonComment->isMemberAccess()) {
1395 if (CurrentState.CallContinuation == 0)
1396 return ContinuationIndent;
1397 return CurrentState.CallContinuation;
1399 if (CurrentState.QuestionColumn != 0 &&
1400 ((NextNonComment->is(tok::colon) &&
1401 NextNonComment->is(TT_ConditionalExpr)) ||
1402 Previous.is(TT_ConditionalExpr))) {
1403 if (((NextNonComment->is(tok::colon) && NextNonComment->Next &&
1404 !NextNonComment->Next->FakeLParens.empty() &&
1406 (
Previous.is(tok::colon) && !Current.FakeLParens.empty() &&
1408 !CurrentState.IsWrappedConditional) {
1413 unsigned Indent = CurrentState.Indent;
1420 return CurrentState.QuestionColumn;
1422 if (
Previous.is(tok::comma) && CurrentState.VariablePos != 0)
1423 return CurrentState.VariablePos;
1424 if (Current.is(TT_RequiresClause)) {
1430 return CurrentState.Indent;
1435 if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
1436 TT_InheritanceComma)) {
1439 if ((PreviousNonComment &&
1440 (PreviousNonComment->ClosesTemplateDeclaration ||
1441 PreviousNonComment->ClosesRequiresClause ||
1442 (PreviousNonComment->is(TT_AttributeMacro) &&
1443 Current.isNot(tok::l_paren)) ||
1444 PreviousNonComment->isOneOf(
1445 TT_AttributeRParen, TT_AttributeSquare, TT_FunctionAnnotationRParen,
1446 TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
1448 NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName))) {
1449 return std::max(CurrentState.LastSpace, CurrentState.Indent);
1451 if (NextNonComment->is(TT_SelectorName)) {
1452 if (!CurrentState.ObjCSelectorNameFound) {
1453 unsigned MinIndent = CurrentState.Indent;
1455 MinIndent = std::max(MinIndent,
1468 std::max(NextNonComment->LongestObjCSelectorName,
1469 NextNonComment->ColumnWidth) -
1470 NextNonComment->ColumnWidth;
1472 if (!CurrentState.AlignColons)
1473 return CurrentState.Indent;
1474 if (CurrentState.ColonPos > NextNonComment->ColumnWidth)
1475 return CurrentState.ColonPos - NextNonComment->ColumnWidth;
1476 return CurrentState.Indent;
1478 if (NextNonComment->is(tok::colon) && NextNonComment->is(TT_ObjCMethodExpr))
1479 return CurrentState.ColonPos;
1480 if (NextNonComment->is(TT_ArraySubscriptLSquare)) {
1481 if (CurrentState.StartOfArraySubscripts != 0) {
1482 return CurrentState.StartOfArraySubscripts;
1485 return CurrentState.Indent;
1487 return ContinuationIndent;
1492 if (State.Line->InPragmaDirective) {
1493 FormatToken *PragmaType = State.Line->First->Next->Next;
1494 if (PragmaType && PragmaType->TokenText ==
"omp")
1500 if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 &&
1501 NextNonComment->Next && NextNonComment->Next->is(TT_ObjCMethodExpr)) {
1502 return CurrentState.Indent;
1505 if (NextNonComment->isOneOf(TT_StartOfName, TT_PointerOrReference) ||
1506 Previous.isOneOf(tok::coloncolon, tok::equal, TT_JsTypeColon)) {
1507 return ContinuationIndent;
1509 if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
1510 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
1511 return ContinuationIndent;
1513 if (NextNonComment->is(TT_CtorInitializerComma))
1514 return CurrentState.Indent;
1515 if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1517 return CurrentState.Indent;
1519 if (PreviousNonComment && PreviousNonComment->is(TT_InheritanceColon) &&
1521 return CurrentState.Indent;
1524 Previous.isNot(TT_TableGenDAGArgOperatorToBreak) &&
1525 !Current.isBinaryOperator() &&
1526 !Current.isOneOf(tok::colon, tok::comment)) {
1527 return ContinuationIndent;
1529 if (Current.is(TT_ProtoExtensionLSquare))
1530 return CurrentState.Indent;
1531 if (Current.isBinaryOperator() && CurrentState.UnindentOperator) {
1532 return CurrentState.Indent - Current.Tok.getLength() -
1533 Current.SpacesRequiredBefore;
1535 if (Current.is(tok::comment) && NextNonComment->isBinaryOperator() &&
1536 CurrentState.UnindentOperator) {
1537 return CurrentState.Indent - NextNonComment->Tok.getLength() -
1538 NextNonComment->SpacesRequiredBefore;
1540 if (CurrentState.Indent == State.FirstIndent && PreviousNonComment &&
1541 !PreviousNonComment->isOneOf(tok::r_brace, TT_CtorInitializerComma)) {
1546 return CurrentState.Indent;
1561unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
1562 bool DryRun,
bool Newline) {
1563 assert(State.Stack.size());
1564 const FormatToken &Current = *State.NextToken;
1565 auto &CurrentState = State.Stack.back();
1567 if (Current.is(TT_CSharpGenericTypeConstraint))
1568 CurrentState.IsCSharpGenericTypeConstraint =
true;
1569 if (Current.isOneOf(tok::comma, TT_BinaryOperator))
1570 CurrentState.NoLineBreakInOperand =
false;
1571 if (Current.isOneOf(TT_InheritanceColon, TT_CSharpGenericTypeConstraintColon))
1572 CurrentState.AvoidBinPacking =
true;
1573 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator)) {
1574 if (CurrentState.FirstLessLess == 0)
1575 CurrentState.FirstLessLess = State.Column;
1577 CurrentState.LastOperatorWrapped = Newline;
1579 if (Current.is(TT_BinaryOperator) && Current.isNot(tok::lessless))
1580 CurrentState.LastOperatorWrapped = Newline;
1581 if (Current.is(TT_ConditionalExpr) && Current.Previous &&
1582 Current.Previous->isNot(TT_ConditionalExpr)) {
1583 CurrentState.LastOperatorWrapped = Newline;
1585 if (Current.is(TT_ArraySubscriptLSquare) &&
1586 CurrentState.StartOfArraySubscripts == 0) {
1587 CurrentState.StartOfArraySubscripts = State.Column;
1590 auto IsWrappedConditional = [](
const FormatToken &Tok) {
1591 if (!(Tok.is(TT_ConditionalExpr) && Tok.is(tok::question)))
1593 if (Tok.MustBreakBefore)
1596 const FormatToken *Next = Tok.getNextNonComment();
1597 return Next && Next->MustBreakBefore;
1599 if (IsWrappedConditional(Current))
1600 CurrentState.IsWrappedConditional =
true;
1602 CurrentState.QuestionColumn = State.Column;
1604 const FormatToken *
Previous = Current.Previous;
1608 CurrentState.QuestionColumn = State.Column;
1610 if (!Current.opensScope() && !Current.closesScope() &&
1611 Current.isNot(TT_PointerOrReference)) {
1612 State.LowestLevelOnLine =
1613 std::min(State.LowestLevelOnLine, Current.NestingLevel);
1615 if (Current.isMemberAccess())
1616 CurrentState.StartOfFunctionCall = !Current.NextOperator ? 0 : State.Column;
1617 if (Current.is(TT_SelectorName))
1618 CurrentState.ObjCSelectorNameFound =
true;
1619 if (Current.is(TT_CtorInitializerColon) &&
1630 CurrentState.NestedBlockIndent = CurrentState.Indent;
1632 CurrentState.AvoidBinPacking =
true;
1633 CurrentState.BreakBeforeParameter =
1638 CurrentState.BreakBeforeParameter =
false;
1641 if (Current.is(TT_CtorInitializerColon) &&
1643 CurrentState.Indent =
1645 CurrentState.NestedBlockIndent = CurrentState.Indent;
1647 CurrentState.AvoidBinPacking =
true;
1649 CurrentState.BreakBeforeParameter =
false;
1651 if (Current.is(TT_InheritanceColon)) {
1652 CurrentState.Indent =
1655 if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
1656 CurrentState.NestedBlockIndent = State.Column + Current.ColumnWidth + 1;
1657 if (Current.isOneOf(TT_LambdaLSquare, TT_TrailingReturnArrow))
1658 CurrentState.LastSpace = State.Column;
1659 if (Current.is(TT_RequiresExpression) &&
1661 CurrentState.NestedBlockIndent = State.Column;
1665 const FormatToken *
Previous = Current.getPreviousNonComment();
1673 if (Current.isNot(tok::comment) && !Current.ClosesRequiresClause &&
1675 Previous->isNot(TT_DictLiteral) && State.Stack.size() > 1 &&
1676 !CurrentState.HasMultipleNestedBlocks) {
1677 if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
1678 for (ParenState &PState : llvm::drop_end(State.Stack))
1679 PState.NoLineBreak =
true;
1680 State.Stack[State.Stack.size() - 2].NestedBlockInlined =
false;
1682 if (
Previous && (
Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr) ||
1683 (
Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) &&
1684 !
Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)))) {
1685 CurrentState.NestedBlockInlined =
1689 moveStatePastFakeLParens(State, Newline);
1690 moveStatePastScopeCloser(State);
1693 bool AllowBreak = !State.Stack.back().NoLineBreak &&
1694 !State.Stack.back().NoLineBreakInOperand;
1695 moveStatePastScopeOpener(State, Newline);
1696 moveStatePastFakeRParens(State);
1698 if (Current.is(TT_ObjCStringLiteral) && State.StartOfStringLiteral == 0)
1699 State.StartOfStringLiteral = State.Column + 1;
1700 if (Current.is(TT_CSharpStringLiteral) && State.StartOfStringLiteral == 0) {
1701 State.StartOfStringLiteral = State.Column + 1;
1702 }
else if (Current.is(TT_TableGenMultiLineString) &&
1703 State.StartOfStringLiteral == 0) {
1704 State.StartOfStringLiteral = State.Column + 1;
1705 }
else if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
1706 State.StartOfStringLiteral = State.Column;
1707 }
else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
1708 !Current.isStringLiteral()) {
1709 State.StartOfStringLiteral = 0;
1712 State.Column += Current.ColumnWidth;
1713 State.NextToken = State.NextToken->Next;
1718 if (Style.
isVerilog() && State.NextToken &&
1719 State.NextToken->MustBreakBefore &&
1722 CurrentState.Indent = State.FirstIndent;
1726 handleEndOfLine(Current, State, DryRun, AllowBreak, Newline);
1729 Current.Role->formatFromToken(State,
this, DryRun);
1736 Penalty +=
Previous->Role->formatAfterToken(State,
this, DryRun);
1741void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
1743 const FormatToken &Current = *State.NextToken;
1744 if (Current.FakeLParens.empty())
1747 const FormatToken *
Previous = Current.getPreviousNonComment();
1752 bool SkipFirstExtraIndent =
1755 Previous->isOneOf(tok::semi, tok::kw_return, TT_RequiresClause) ||
1759 for (
const auto &PrecedenceLevel : llvm::reverse(Current.FakeLParens)) {
1760 const auto &CurrentState = State.Stack.back();
1761 ParenState NewParenState = CurrentState;
1762 NewParenState.Tok =
nullptr;
1763 NewParenState.ContainsLineBreak =
false;
1764 NewParenState.LastOperatorWrapped =
true;
1765 NewParenState.IsChainedConditional =
false;
1766 NewParenState.IsWrappedConditional =
false;
1767 NewParenState.UnindentOperator =
false;
1768 NewParenState.NoLineBreak =
1769 NewParenState.NoLineBreak || CurrentState.NoLineBreakInOperand;
1773 NewParenState.AvoidBinPacking =
false;
1778 if (!Current.isTrailingComment() &&
1784 PrecedenceLevel >
prec::Comma || Current.NestingLevel == 0) &&
1787 TT_TableGenDAGArgListCommaToBreak)))) {
1788 NewParenState.Indent = std::max(
1789 std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
1796 State.Stack.size() > 1) {
1797 NewParenState.Indent = State.Stack[State.Stack.size() - 2].Indent +
1809 NewParenState.UnindentOperator =
true;
1812 NewParenState.IsAligned =
true;
1822 NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
1824 Current.isNot(TT_UnaryOperator) &&
1826 NewParenState.StartOfFunctionCall = State.Column;
1836 &PrecedenceLevel == &Current.FakeLParens.back() &&
1837 !CurrentState.IsWrappedConditional) {
1838 NewParenState.IsChainedConditional =
true;
1839 NewParenState.UnindentOperator = State.Stack.back().UnindentOperator;
1842 !Current.isTrailingComment())) {
1846 NewParenState.BreakBeforeParameter =
false;
1847 State.Stack.push_back(NewParenState);
1848 SkipFirstExtraIndent =
false;
1852void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
1853 for (
unsigned i = 0, e = State.NextToken->FakeRParens; i != e; ++i) {
1854 unsigned VariablePos = State.Stack.back().VariablePos;
1855 if (State.Stack.size() == 1) {
1859 State.Stack.pop_back();
1860 State.Stack.back().VariablePos = VariablePos;
1866 State.Stack.back().LastSpace -= Style.
IndentWidth;
1870void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
1872 const FormatToken &Current = *State.NextToken;
1873 if (!Current.opensScope())
1876 const auto &CurrentState = State.Stack.back();
1879 if (Current.isOneOf(tok::less, tok::l_paren) &&
1880 CurrentState.IsCSharpGenericTypeConstraint) {
1884 if (Current.MatchingParen && Current.is(
BK_Block)) {
1885 moveStateToNewBlock(State, Newline);
1890 unsigned LastSpace = CurrentState.LastSpace;
1891 bool AvoidBinPacking;
1892 bool BreakBeforeParameter =
false;
1893 unsigned NestedBlockIndent = std::max(CurrentState.StartOfFunctionCall,
1894 CurrentState.NestedBlockIndent);
1895 if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1897 if (Current.opensBlockOrBlockTypeList(Style)) {
1899 std::min(State.Column, CurrentState.NestedBlockIndent);
1900 }
else if (Current.is(tok::l_brace)) {
1907 const FormatToken *NextNonComment = Current.getNextNonComment();
1908 bool EndsInComma = Current.MatchingParen &&
1909 Current.MatchingParen->Previous &&
1910 Current.MatchingParen->Previous->is(tok::comma);
1911 AvoidBinPacking = EndsInComma || Current.is(TT_DictLiteral) ||
1913 (NextNonComment && NextNonComment->isOneOf(
1914 TT_DesignatedInitializerPeriod,
1915 TT_DesignatedInitializerLSquare));
1916 BreakBeforeParameter = EndsInComma;
1917 if (Current.ParameterCount > 1)
1918 NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
1922 std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall);
1924 if (Style.
isTableGen() && Current.is(TT_TableGenDAGArgOpenerToBreak) &&
1930 const FormatToken *Next = Current.Next;
1931 if (Next && Next->is(TT_TableGenDAGArgOperatorID))
1932 NewIndent = State.Column + Next->TokenText.size() + 2;
1939 if (Current.is(tok::less) && Current.ParentBracket == tok::l_paren) {
1940 NewIndent = std::max(NewIndent, CurrentState.Indent);
1941 LastSpace = std::max(LastSpace, CurrentState.Indent);
1945 Current.MatchingParen &&
1946 Current.MatchingParen->getPreviousNonComment() &&
1947 Current.MatchingParen->getPreviousNonComment()->is(tok::comma);
1951 bool ObjCBinPackProtocolList =
1956 bool BinPackDeclaration =
1958 (State.Line->Type ==
LT_ObjCDecl && ObjCBinPackProtocolList);
1960 bool GenericSelection =
1961 Current.getPreviousNonComment() &&
1962 Current.getPreviousNonComment()->is(tok::kw__Generic);
1965 (CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection ||
1967 (State.Line->MustBeDeclaration && !BinPackDeclaration) ||
1973 if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen &&
1980 BreakBeforeParameter =
true;
1985 for (
const FormatToken *Tok = &Current;
1986 Tok && Tok != Current.MatchingParen; Tok = Tok->Next) {
1987 if (Tok->MustBreakBefore ||
1988 (Tok->CanBreakBefore && Tok->NewlinesBefore > 0)) {
1989 BreakBeforeParameter =
true;
1997 BreakBeforeParameter =
true;
2003 Current.Children.empty() &&
2004 !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) &&
2005 (CurrentState.NoLineBreak || CurrentState.NoLineBreakInOperand ||
2006 (Current.is(TT_TemplateOpener) &&
2007 CurrentState.ContainsUnwrappedBuilder));
2008 State.Stack.push_back(
2009 ParenState(&Current, NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
2010 auto &NewState = State.Stack.back();
2011 NewState.NestedBlockIndent = NestedBlockIndent;
2012 NewState.BreakBeforeParameter = BreakBeforeParameter;
2013 NewState.HasMultipleNestedBlocks = (Current.BlockParameterCount > 1);
2016 Current.is(tok::l_paren)) {
2018 FormatToken
const *next = Current.Next;
2020 if (next->is(TT_LambdaLSquare)) {
2021 NewState.HasMultipleNestedBlocks =
true;
2028 NewState.IsInsideObjCArrayLiteral = Current.is(TT_ArrayInitializerLSquare) &&
2030 Current.Previous->is(tok::at);
2033void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
2034 const FormatToken &Current = *State.NextToken;
2035 if (!Current.closesScope())
2040 if (State.Stack.size() > 1 &&
2041 (Current.isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
2042 (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
2043 State.NextToken->is(TT_TemplateCloser) ||
2044 State.NextToken->is(TT_TableGenListCloser) ||
2045 (Current.is(tok::greater) && Current.is(TT_DictLiteral)))) {
2046 State.Stack.pop_back();
2049 auto &CurrentState = State.Stack.back();
2061 if (CurrentState.BreakBeforeParameter && Current.MatchingParen &&
2062 Current.MatchingParen->Previous) {
2063 const FormatToken &CurrentScopeOpener = *Current.MatchingParen->Previous;
2064 if (CurrentScopeOpener.is(TT_ObjCMethodExpr) &&
2065 CurrentScopeOpener.MatchingParen) {
2066 int NecessarySpaceInLine =
2068 CurrentScopeOpener.TotalLength - Current.TotalLength - 1;
2069 if (State.Column + Current.ColumnWidth + NecessarySpaceInLine <=
2071 CurrentState.BreakBeforeParameter =
false;
2076 if (Current.is(tok::r_square)) {
2078 const FormatToken *NextNonComment = Current.getNextNonComment();
2079 if (NextNonComment && NextNonComment->isNot(tok::l_square))
2080 CurrentState.StartOfArraySubscripts = 0;
2084void ContinuationIndenter::moveStateToNewBlock(LineState &State,
bool NewLine) {
2086 State.NextToken->is(TT_LambdaLBrace) &&
2087 !State.Line->MightBeFunctionDecl) {
2088 State.Stack.back().NestedBlockIndent = State.FirstIndent;
2090 unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
2092 unsigned NewIndent =
2093 NestedBlockIndent + (State.NextToken->is(TT_ObjCBlockLBrace)
2103 State.NextToken->is(TT_LambdaLBrace);
2105 State.Stack.push_back(ParenState(State.NextToken, NewIndent,
2106 State.Stack.back().LastSpace,
2107 true, NoLineBreak));
2108 State.Stack.back().NestedBlockIndent = NestedBlockIndent;
2109 State.Stack.back().BreakBeforeParameter =
true;
2115 size_t LastNewlinePos =
Text.find_last_of(
"\n");
2116 if (LastNewlinePos == StringRef::npos) {
2117 return StartColumn +
2121 0, TabWidth, Encoding);
2125unsigned ContinuationIndenter::reformatRawStringLiteral(
2126 const FormatToken &Current, LineState &State,
2127 const FormatStyle &RawStringStyle,
bool DryRun,
bool Newline) {
2128 unsigned StartColumn = State.Column - Current.ColumnWidth;
2130 StringRef NewDelimiter =
2132 if (NewDelimiter.empty())
2133 NewDelimiter = OldDelimiter;
2136 unsigned OldPrefixSize = 3 + OldDelimiter.size();
2137 unsigned OldSuffixSize = 2 + OldDelimiter.size();
2140 std::string RawText = std::string(
2141 Current.TokenText.substr(OldPrefixSize).drop_back(OldSuffixSize));
2142 if (NewDelimiter != OldDelimiter) {
2145 std::string CanonicalDelimiterSuffix = (
")" + NewDelimiter +
"\"").str();
2146 if (StringRef(RawText).contains(CanonicalDelimiterSuffix))
2147 NewDelimiter = OldDelimiter;
2150 unsigned NewPrefixSize = 3 + NewDelimiter.size();
2151 unsigned NewSuffixSize = 2 + NewDelimiter.size();
2154 unsigned FirstStartColumn = StartColumn + NewPrefixSize;
2165 bool ContentStartsOnNewline = Current.TokenText[OldPrefixSize] ==
'\n';
2187 unsigned CurrentIndent =
2188 (!Newline && Current.Next && Current.Next->is(tok::r_paren))
2189 ? State.Stack.back().NestedBlockIndent
2190 : State.Stack.back().Indent;
2191 unsigned NextStartColumn = ContentStartsOnNewline
2203 unsigned LastStartColumn =
2204 Current.NewlinesBefore ? FirstStartColumn - NewPrefixSize : CurrentIndent;
2207 RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
2208 FirstStartColumn, NextStartColumn, LastStartColumn,
"<stdin>",
2212 tooling::Replacements NoFixes;
2214 return addMultilineToken(Current, State);
2216 if (NewDelimiter != OldDelimiter) {
2219 SourceLocation PrefixDelimiterStart =
2220 Current.Tok.getLocation().getLocWithOffset(2);
2221 auto PrefixErr = Whitespaces.
addReplacement(tooling::Replacement(
2222 SourceMgr, PrefixDelimiterStart, OldDelimiter.size(), NewDelimiter));
2225 <<
"Failed to update the prefix delimiter of a raw string: "
2226 << llvm::toString(std::move(PrefixErr)) <<
"\n";
2230 SourceLocation SuffixDelimiterStart =
2231 Current.Tok.getLocation().getLocWithOffset(Current.TokenText.size() -
2232 1 - OldDelimiter.size());
2233 auto SuffixErr = Whitespaces.
addReplacement(tooling::Replacement(
2234 SourceMgr, SuffixDelimiterStart, OldDelimiter.size(), NewDelimiter));
2237 <<
"Failed to update the suffix delimiter of a raw string: "
2238 << llvm::toString(std::move(SuffixErr)) <<
"\n";
2241 SourceLocation OriginLoc =
2242 Current.Tok.getLocation().getLocWithOffset(OldPrefixSize);
2243 for (
const tooling::Replacement &Fix : Fixes.first) {
2245 SourceMgr, OriginLoc.getLocWithOffset(Fix.getOffset()),
2246 Fix.getLength(), Fix.getReplacementText()));
2248 llvm::errs() <<
"Failed to reformat raw string: "
2249 << llvm::toString(std::move(Err)) <<
"\n";
2254 *NewCode, FirstStartColumn, Style.
TabWidth, Encoding);
2255 State.Column = RawLastLineEndColumn + NewSuffixSize;
2259 unsigned PrefixExcessCharacters =
2264 ContentStartsOnNewline || (NewCode->find(
'\n') != std::string::npos);
2267 for (ParenState &
Paren : State.Stack)
2268 Paren.BreakBeforeParameter =
true;
2273unsigned ContinuationIndenter::addMultilineToken(
const FormatToken &Current,
2276 for (ParenState &
Paren : State.Stack)
2277 Paren.BreakBeforeParameter =
true;
2279 unsigned ColumnsUsed = State.Column;
2282 State.Column = Current.LastLineColumnWidth;
2289unsigned ContinuationIndenter::handleEndOfLine(
const FormatToken &Current,
2290 LineState &State,
bool DryRun,
2291 bool AllowBreak,
bool Newline) {
2292 unsigned Penalty = 0;
2295 auto RawStringStyle = getRawStringStyle(Current, State);
2296 if (RawStringStyle && !Current.Finalized) {
2297 Penalty = reformatRawStringLiteral(Current, State, *RawStringStyle, DryRun,
2299 }
else if (Current.IsMultiline && Current.isNot(TT_BlockComment)) {
2302 Penalty = addMultilineToken(Current, State);
2305 LineState OriginalState = State;
2309 bool Strict =
false;
2312 bool Exceeded =
false;
2313 std::tie(Penalty, Exceeded) = breakProtrudingToken(
2314 Current, State, AllowBreak,
true, Strict);
2318 LineState StrictState = OriginalState;
2319 unsigned StrictPenalty =
2320 breakProtrudingToken(Current, StrictState, AllowBreak,
2323 Strict = StrictPenalty <= Penalty;
2325 Penalty = StrictPenalty;
2326 State = StrictState;
2332 breakProtrudingToken(Current, OriginalState, AllowBreak,
false,
2337 unsigned ExcessCharacters = State.Column -
getColumnLimit(State);
2348 if (!Tok || Tok->isNot(tok::l_paren))
2353 if (Tok->is(TT_TemplateCloser)) {
2358 if (!Tok || Tok->isNot(tok::identifier))
2363std::optional<FormatStyle>
2364ContinuationIndenter::getRawStringStyle(
const FormatToken &Current,
2365 const LineState &State) {
2366 if (!Current.isStringLiteral())
2367 return std::nullopt;
2370 return std::nullopt;
2372 if (!RawStringStyle && Delimiter->empty()) {
2376 if (!RawStringStyle)
2377 return std::nullopt;
2379 return RawStringStyle;
2382std::unique_ptr<BreakableToken>
2383ContinuationIndenter::createBreakableToken(
const FormatToken &Current,
2384 LineState &State,
bool AllowBreak) {
2385 unsigned StartColumn = State.Column - Current.ColumnWidth;
2386 if (Current.isStringLiteral()) {
2403 if (Current.IsUnterminatedLiteral)
2407 if (State.Stack.back().IsInsideObjCArrayLiteral)
2414 if (Style.
isVerilog() && Current.Previous &&
2415 Current.Previous->isOneOf(tok::kw_export, Keywords.
kw_import)) {
2418 StringRef
Text = Current.TokenText;
2424 unsigned UnbreakableTailLength = (State.NextToken &&
canBreak(State))
2426 : Current.UnbreakableTailLength;
2432 Text.ends_with(
"'")) {
2434 }
else if (Style.
isCSharp() &&
Text.starts_with(
"@\"") &&
2435 Text.ends_with(
"\"")) {
2437 }
else if (
Text.starts_with(
"\"") &&
Text.ends_with(
"\"")) {
2442 return std::make_unique<BreakableStringLiteralUsingOperators>(
2443 Current, QuoteStyle,
2445 UnbreakableTailLength, State.Line->InPPDirective, Encoding, Style);
2454 if ((
Text.ends_with(Postfix =
"\"") &&
2455 (
Text.starts_with(Prefix =
"@\"") ||
Text.starts_with(Prefix =
"\"") ||
2456 Text.starts_with(Prefix =
"u\"") ||
2457 Text.starts_with(Prefix =
"U\"") ||
2458 Text.starts_with(Prefix =
"u8\"") ||
2459 Text.starts_with(Prefix =
"L\""))) ||
2460 (
Text.starts_with(Prefix =
"_T(\"") &&
2461 Text.ends_with(Postfix =
"\")"))) {
2462 return std::make_unique<BreakableStringLiteral>(
2463 Current, StartColumn, Prefix, Postfix, UnbreakableTailLength,
2464 State.Line->InPPDirective, Encoding, Style);
2466 }
else if (Current.is(TT_BlockComment)) {
2474 return std::make_unique<BreakableBlockComment>(
2475 Current, StartColumn, Current.OriginalColumn, !Current.Previous,
2476 State.Line->InPPDirective, Encoding, Style, Whitespaces.
useCRLF());
2477 }
else if (Current.is(TT_LineComment) &&
2478 (!Current.Previous ||
2479 Current.Previous->isNot(TT_ImplicitStringLiteral))) {
2480 bool RegularComments = [&]() {
2481 for (
const FormatToken *
T = &Current;
T &&
T->is(TT_LineComment);
2483 if (!(
T->TokenText.starts_with(
"//") ||
T->TokenText.starts_with(
"#")))
2489 CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
2493 return std::make_unique<BreakableLineCommentSection>(
2494 Current, StartColumn,
false, Encoding, Style);
2499std::pair<unsigned, bool>
2500ContinuationIndenter::breakProtrudingToken(
const FormatToken &Current,
2501 LineState &State,
bool AllowBreak,
2502 bool DryRun,
bool Strict) {
2503 std::unique_ptr<const BreakableToken> Token =
2504 createBreakableToken(Current, State, AllowBreak);
2507 assert(Token->getLineCount() > 0);
2509 if (Current.is(TT_LineComment)) {
2513 if (ColumnLimit == 0) {
2516 ColumnLimit = std::numeric_limits<
decltype(ColumnLimit)>
::max();
2518 if (Current.UnbreakableTailLength >= ColumnLimit)
2522 unsigned StartColumn = State.Column - Current.ColumnWidth;
2523 unsigned NewBreakPenalty = Current.isStringLiteral()
2528 bool Exceeded =
false;
2530 bool BreakInserted = Token->introducesBreakBeforeToken();
2533 bool NewBreakBefore =
false;
2537 bool Reflow =
false;
2540 unsigned TailOffset = 0;
2542 unsigned ContentStartColumn =
2543 Token->getContentStartColumn(0,
false);
2545 unsigned RemainingTokenColumns =
2546 Token->getRemainingLength(0, TailOffset, ContentStartColumn);
2549 Token->adaptStartOfLine(0, Whitespaces);
2551 unsigned ContentIndent = 0;
2552 unsigned Penalty = 0;
2553 LLVM_DEBUG(llvm::dbgs() <<
"Breaking protruding token at column "
2554 << StartColumn <<
".\n");
2555 for (
unsigned LineIndex = 0, EndIndex = Token->getLineCount();
2556 LineIndex != EndIndex; ++LineIndex) {
2557 LLVM_DEBUG(llvm::dbgs()
2558 <<
" Line: " << LineIndex <<
" (Reflow: " << Reflow <<
")\n");
2559 NewBreakBefore =
false;
2563 bool TryReflow = Reflow;
2565 while (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2566 LLVM_DEBUG(llvm::dbgs() <<
" Over limit, need: "
2567 << (ContentStartColumn + RemainingTokenColumns)
2568 <<
", space: " << ColumnLimit
2569 <<
", reflown prefix: " << ContentStartColumn
2570 <<
", offset in line: " << TailOffset <<
"\n");
2576 Token->getSplit(LineIndex, TailOffset, ColumnLimit,
2577 ContentStartColumn, CommentPragmasRegex);
2578 if (
Split.first == StringRef::npos) {
2581 if (LineIndex < EndIndex - 1) {
2585 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2587 LLVM_DEBUG(llvm::dbgs() <<
" No break opportunity.\n");
2590 assert(
Split.first != 0);
2592 if (Token->supportsReflow()) {
2612 unsigned ToSplitColumns = Token->getRangeLength(
2613 LineIndex, TailOffset,
Split.first, ContentStartColumn);
2614 LLVM_DEBUG(llvm::dbgs() <<
" ToSplit: " << ToSplitColumns <<
"\n");
2617 LineIndex, TailOffset +
Split.first +
Split.second, ColumnLimit,
2618 ContentStartColumn + ToSplitColumns + 1, CommentPragmasRegex);
2621 unsigned ToNextSplitColumns = 0;
2622 if (NextSplit.first == StringRef::npos) {
2623 ToNextSplitColumns = Token->getRemainingLength(LineIndex, TailOffset,
2624 ContentStartColumn);
2626 ToNextSplitColumns = Token->getRangeLength(
2627 LineIndex, TailOffset,
2628 Split.first +
Split.second + NextSplit.first, ContentStartColumn);
2632 ToNextSplitColumns =
2633 Token->getLengthAfterCompression(ToNextSplitColumns, Split);
2634 LLVM_DEBUG(llvm::dbgs()
2635 <<
" ContentStartColumn: " << ContentStartColumn <<
"\n");
2636 LLVM_DEBUG(llvm::dbgs()
2637 <<
" ToNextSplit: " << ToNextSplitColumns <<
"\n");
2640 bool ContinueOnLine =
2641 ContentStartColumn + ToNextSplitColumns <= ColumnLimit;
2642 unsigned ExcessCharactersPenalty = 0;
2643 if (!ContinueOnLine && !Strict) {
2646 ExcessCharactersPenalty =
2647 (ContentStartColumn + ToNextSplitColumns - ColumnLimit) *
2649 LLVM_DEBUG(llvm::dbgs()
2650 <<
" Penalty excess: " << ExcessCharactersPenalty
2651 <<
"\n break : " << NewBreakPenalty <<
"\n");
2652 if (ExcessCharactersPenalty < NewBreakPenalty) {
2654 ContinueOnLine =
true;
2657 if (ContinueOnLine) {
2658 LLVM_DEBUG(llvm::dbgs() <<
" Continuing on line...\n");
2663 Token->compressWhitespace(LineIndex, TailOffset, Split,
2667 ContentStartColumn += ToSplitColumns + 1;
2668 Penalty += ExcessCharactersPenalty;
2670 RemainingTokenColumns = Token->getRemainingLength(
2671 LineIndex, TailOffset, ContentStartColumn);
2675 LLVM_DEBUG(llvm::dbgs() <<
" Breaking...\n");
2680 ContentIndent = Token->getContentIndent(LineIndex);
2681 LLVM_DEBUG(llvm::dbgs()
2682 <<
" ContentIndent: " << ContentIndent <<
"\n");
2683 ContentStartColumn = ContentIndent + Token->getContentStartColumn(
2686 unsigned NewRemainingTokenColumns = Token->getRemainingLength(
2687 LineIndex, TailOffset +
Split.first +
Split.second,
2688 ContentStartColumn);
2689 if (NewRemainingTokenColumns == 0) {
2692 ContentStartColumn =
2693 Token->getContentStartColumn(LineIndex,
true);
2694 NewRemainingTokenColumns = Token->getRemainingLength(
2695 LineIndex, TailOffset +
Split.first +
Split.second,
2696 ContentStartColumn);
2702 if (NewRemainingTokenColumns >= RemainingTokenColumns) {
2707 LLVM_DEBUG(llvm::dbgs() <<
" Breaking at: " << TailOffset +
Split.first
2708 <<
", " <<
Split.second <<
"\n");
2710 Token->insertBreak(LineIndex, TailOffset, Split, ContentIndent,
2714 Penalty += NewBreakPenalty;
2716 RemainingTokenColumns = NewRemainingTokenColumns;
2717 BreakInserted =
true;
2718 NewBreakBefore =
true;
2722 if (LineIndex + 1 != EndIndex) {
2723 unsigned NextLineIndex = LineIndex + 1;
2724 if (NewBreakBefore) {
2743 ContentStartColumn += RemainingTokenColumns + 1;
2748 Token->getReflowSplit(NextLineIndex, CommentPragmasRegex);
2749 LLVM_DEBUG(llvm::dbgs()
2750 <<
" Size of reflown text: " << ContentStartColumn
2751 <<
"\n Potential reflow split: ");
2752 if (SplitBeforeNext.first != StringRef::npos) {
2753 LLVM_DEBUG(llvm::dbgs() << SplitBeforeNext.first <<
", "
2754 << SplitBeforeNext.second <<
"\n");
2755 TailOffset = SplitBeforeNext.first + SplitBeforeNext.second;
2758 RemainingTokenColumns = Token->getRemainingLength(
2759 NextLineIndex, TailOffset, ContentStartColumn);
2761 if (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2762 LLVM_DEBUG(llvm::dbgs()
2763 <<
" Over limit after reflow, need: "
2764 << (ContentStartColumn + RemainingTokenColumns)
2765 <<
", space: " << ColumnLimit
2766 <<
", reflown prefix: " << ContentStartColumn
2767 <<
", offset in line: " << TailOffset <<
"\n");
2773 Token->getSplit(NextLineIndex, TailOffset, ColumnLimit,
2774 ContentStartColumn, CommentPragmasRegex);
2775 if (
Split.first == StringRef::npos) {
2776 LLVM_DEBUG(llvm::dbgs() <<
" Did not find later break\n");
2782 unsigned ToSplitColumns = Token->getRangeLength(
2783 NextLineIndex, TailOffset,
Split.first, ContentStartColumn);
2784 if (ContentStartColumn + ToSplitColumns > ColumnLimit) {
2785 LLVM_DEBUG(llvm::dbgs() <<
" Next split protrudes, need: "
2786 << (ContentStartColumn + ToSplitColumns)
2787 <<
", space: " << ColumnLimit);
2788 unsigned ExcessCharactersPenalty =
2789 (ContentStartColumn + ToSplitColumns - ColumnLimit) *
2791 if (NewBreakPenalty < ExcessCharactersPenalty)
2797 LLVM_DEBUG(llvm::dbgs() <<
"not found.\n");
2805 ContentStartColumn =
2806 Token->getContentStartColumn(NextLineIndex,
false);
2807 RemainingTokenColumns = Token->getRemainingLength(
2808 NextLineIndex, TailOffset, ContentStartColumn);
2811 Token->adaptStartOfLine(NextLineIndex, Whitespaces);
2826 if (NewBreakBefore) {
2827 assert(Penalty >= NewBreakPenalty);
2828 Penalty -= NewBreakPenalty;
2831 Token->reflow(NextLineIndex, Whitespaces);
2837 Token->getSplitAfterLastLine(TailOffset);
2838 if (SplitAfterLastLine.first != StringRef::npos) {
2839 LLVM_DEBUG(llvm::dbgs() <<
"Replacing whitespace after last line.\n");
2844 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2847 Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
2850 ContentStartColumn =
2851 Token->getContentStartColumn(Token->getLineCount() - 1,
true);
2852 RemainingTokenColumns = Token->getRemainingLength(
2853 Token->getLineCount() - 1,
2854 TailOffset + SplitAfterLastLine.first + SplitAfterLastLine.second,
2855 ContentStartColumn);
2858 State.Column = ContentStartColumn + RemainingTokenColumns -
2859 Current.UnbreakableTailLength;
2861 if (BreakInserted) {
2863 Token->updateAfterBroken(Whitespaces);
2868 if (Current.isNot(TT_LineComment))
2869 for (ParenState &
Paren : State.Stack)
2870 Paren.BreakBeforeParameter =
true;
2872 if (Current.is(TT_BlockComment))
2873 State.NoContinuation =
true;
2875 State.Stack.back().LastSpace = StartColumn;
2878 Token->updateNextToken(State);
2880 return {Penalty, Exceeded};
2885 return Style.
ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
2888bool ContinuationIndenter::nextIsMultilineString(
const LineState &State) {
2890 if (!Current.isStringLiteral() || Current.is(TT_ImplicitStringLiteral))
2895 if (Current.TokenText.starts_with(
"R\""))
2897 if (Current.IsMultiline)
2899 if (Current.getNextNonComment() &&
2900 Current.getNextNonComment()->isStringLiteral()) {
2904 State.Column + Current.ColumnWidth + Current.UnbreakableTailLength >
Declares BreakableToken, BreakableStringLiteral, BreakableComment, BreakableBlockComment and Breakabl...
This file implements an indenter that manages the indentation of continuations.
Defines and computes precedence levels for binary/ternary operators.
Defines the SourceManager interface.
unsigned LongestObjCSelectorName
Defines the clang::TokenKind enum and support functions.
WhitespaceManager class manages whitespace around tokens and their replacements.
__DEVICE__ int max(int __a, int __b)
This class handles loading and caching of source files into memory.
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
Token - This structure provides full information about a lexed token.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
Language
The language for the input, used to select and validate the language standard and possible actions.
const FunctionProtoType * T