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)
135 if (Current.
is(TT_CtorInitializerComma) &&
142 ((
Previous.isNot(TT_CtorInitializerComma) ||
145 (
Previous.isNot(TT_InheritanceComma) ||
151 if (LessTok.
isNot(tok::less))
163 if (TokenText.size() < 5
164 || !TokenText.starts_with(
"R\"") || !TokenText.ends_with(
"\"")) {
171 size_t LParenPos = TokenText.substr(0, 19).find_first_of(
'(');
172 if (LParenPos == StringRef::npos)
174 StringRef Delimiter = TokenText.substr(2, LParenPos - 2);
177 size_t RParenPos = TokenText.size() - Delimiter.size() - 2;
178 if (TokenText[RParenPos] !=
')')
180 if (!TokenText.substr(RParenPos + 1).starts_with(Delimiter))
192 return StringRef(Format.CanonicalDelimiter);
199 std::optional<FormatStyle> LanguageStyle =
201 if (!LanguageStyle) {
204 RawStringFormat.Language, &PredefinedStyle)) {
206 PredefinedStyle.
Language = RawStringFormat.Language;
208 LanguageStyle = PredefinedStyle;
211 for (StringRef Delimiter : RawStringFormat.Delimiters)
213 for (StringRef EnclosingFunction : RawStringFormat.EnclosingFunctions)
218std::optional<FormatStyle>
226std::optional<FormatStyle>
228 StringRef EnclosingFunction)
const {
240 bool BinPackInconclusiveFunctions)
241 : Style(Style), Keywords(Keywords), SourceMgr(SourceMgr),
242 Whitespaces(Whitespaces), Encoding(Encoding),
243 BinPackInconclusiveFunctions(BinPackInconclusiveFunctions),
244 CommentPragmasRegex(Style.CommentPragmas), RawStringFormats(Style) {}
247 unsigned FirstStartColumn,
251 State.FirstIndent = FirstIndent;
252 if (FirstStartColumn &&
Line->First->NewlinesBefore == 0)
253 State.Column = FirstStartColumn;
255 State.Column = FirstIndent;
265 State.NextToken =
Line->First;
266 State.Stack.push_back(
ParenState(
nullptr, FirstIndent, FirstIndent,
269 State.NoContinuation =
false;
270 State.StartOfStringLiteral = 0;
271 State.NoLineBreak =
false;
272 State.StartOfLineLevel = 0;
273 State.LowestLevelOnLine = 0;
274 State.IgnoreStackForComparison =
false;
279 auto &CurrentState = State.Stack.back();
280 CurrentState.AvoidBinPacking =
true;
281 CurrentState.BreakBeforeParameter =
true;
282 CurrentState.AlignColons =
false;
286 moveStateToNextToken(State, DryRun,
false);
293 const auto &CurrentState = State.Stack.back();
294 assert(&
Previous == Current.Previous);
295 if (!Current.CanBreakBefore && !(CurrentState.BreakBeforeClosingBrace &&
296 Current.closesBlockOrBlockTypeList(Style))) {
301 if (!Current.MustBreakBefore &&
Previous.is(tok::l_brace) &&
304 Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma)) {
313 State.LowestLevelOnLine < State.StartOfLineLevel &&
314 State.LowestLevelOnLine < Current.NestingLevel) {
317 if (Current.isMemberAccess() && CurrentState.ContainsUnwrappedBuilder)
322 if (
Previous.is(tok::l_brace) && State.Stack.size() > 1 &&
323 State.Stack[State.Stack.size() - 2].NestedBlockInlined &&
324 State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks &&
331 if (Current.is(TT_FunctionDeclarationName)) {
338 assert(State.Column >= State.FirstIndent);
339 if (State.Column - State.FirstIndent < 6)
346 if (!Current.isOneOf(TT_BinaryOperator, tok::comma) &&
351 Current.isNot(TT_LambdaLBrace)) &&
352 CurrentState.NoLineBreakInOperand) {
359 if (Current.is(TT_ConditionalExpr) &&
Previous.is(tok::r_paren) &&
361 Previous.MatchingParen->Previous->MatchingParen &&
362 Previous.MatchingParen->Previous->MatchingParen->is(TT_LambdaLBrace)) {
364 assert(
Previous.MatchingParen->Previous->is(tok::r_brace));
368 return !State.NoLineBreak && !CurrentState.NoLineBreak;
374 const auto &CurrentState = State.Stack.back();
376 Current.is(TT_LambdaLBrace) &&
Previous.isNot(TT_LineComment)) {
380 if (Current.MustBreakBefore ||
381 (Current.is(TT_InlineASMColon) &&
387 if (CurrentState.BreakBeforeClosingBrace &&
388 (Current.closesBlockOrBlockTypeList(Style) ||
389 (Current.is(tok::r_brace) &&
390 Current.isBlockIndentedInitRBrace(Style)))) {
393 if (CurrentState.BreakBeforeClosingParen && Current.is(tok::r_paren))
397 Current.ObjCSelectorNameParts > 1 &&
398 Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)) {
403 if (CurrentState.IsCSharpGenericTypeConstraint &&
404 Previous.isNot(TT_CSharpGenericTypeConstraintComma)) {
408 (
Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) &&
409 State.Line->First->isNot(TT_AttributeSquare) && Style.
isCpp() &&
418 Previous.is(TT_ConditionalExpr))) &&
419 CurrentState.BreakBeforeParameter && !Current.isTrailingComment() &&
420 !Current.isOneOf(tok::r_paren, tok::r_brace)) {
423 if (CurrentState.IsChainedConditional &&
425 Current.is(tok::colon)) ||
431 (
Previous.is(TT_ArrayInitializerLSquare) &&
440 const FormatToken &BreakConstructorInitializersToken =
444 if (BreakConstructorInitializersToken.
is(TT_CtorInitializerColon) &&
445 (State.Column + State.Line->Last->TotalLength -
Previous.TotalLength >
447 CurrentState.BreakBeforeParameter) &&
448 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
455 if (Current.is(TT_ObjCMethodExpr) &&
Previous.isNot(TT_SelectorName) &&
456 State.Line->startsWith(TT_ObjCMethodSpecifier)) {
459 if (Current.is(TT_SelectorName) &&
Previous.isNot(tok::at) &&
460 CurrentState.ObjCSelectorNameFound && CurrentState.BreakBeforeParameter &&
462 !Current.startsSequence(TT_SelectorName, tok::colon, tok::caret))) {
466 unsigned NewLineColumn = getNewLineColumn(State);
467 if (Current.isMemberAccess() && Style.
ColumnLimit != 0 &&
469 (State.Column > NewLineColumn ||
470 Current.NestingLevel < State.StartOfLineLevel)) {
475 (CurrentState.CallContinuation != 0 ||
476 CurrentState.BreakBeforeParameter) &&
482 !(State.Column <= NewLineColumn && Style.
isJavaScript()) &&
483 !(
Previous.closesScopeAfterBlock() && State.Column <= NewLineColumn)) {
489 if (
Previous.ClosesTemplateDeclaration && CurrentState.BreakBeforeParameter &&
490 Current.CanBreakBefore) {
494 if (State.Line->First->isNot(tok::kw_enum) && State.Column <= NewLineColumn)
499 Previous.is(tok::comma) || Current.NestingLevel < 2) &&
500 !
Previous.isOneOf(tok::kw_return, tok::lessless, tok::at,
502 !
Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
503 nextIsMultilineString(State)) {
510 if (
Previous.is(TT_BinaryOperator) && Current.CanBreakBefore) {
511 const auto PreviousPrecedence =
Previous.getPrecedence();
513 CurrentState.BreakBeforeParameter && !Current.isTrailingComment()) {
514 const bool LHSIsBinaryExpr =
527 const bool IsComparison =
532 Previous.Previous->isNot(TT_BinaryOperator);
536 }
else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore &&
537 CurrentState.BreakBeforeParameter) {
542 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator) &&
543 CurrentState.BreakBeforeParameter && CurrentState.FirstLessLess == 0) {
547 if (Current.NestingLevel == 0 && !Current.isTrailingComment()) {
552 if (
Previous.ClosesTemplateDeclaration) {
553 if (Current.is(tok::kw_concept)) {
563 if (Current.is(TT_RequiresClause)) {
574 Current.NewlinesBefore > 0);
576 if (
Previous.is(TT_FunctionAnnotationRParen) &&
580 if (
Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) &&
581 Current.isNot(TT_LeadingJavaAnnotation)) {
590 static const llvm::StringSet<> BreakBeforeDecoratedTokens = {
"get",
"set",
592 if (BreakBeforeDecoratedTokens.contains(Current.TokenText))
596 if (Current.is(TT_FunctionDeclarationName) &&
597 !State.Line->ReturnTypeWrapped &&
604 CurrentState.BreakBeforeParameter) {
613 !Current.isOneOf(tok::r_brace, tok::comment)) {
617 if (Current.is(tok::lessless) &&
620 Previous.TokenText ==
"\'\\n\'")))) {
627 if (State.NoContinuation)
635 unsigned ExtraSpaces) {
637 assert(State.NextToken->Previous);
640 assert(!State.Stack.empty());
641 State.NoContinuation =
false;
643 if (Current.is(TT_ImplicitStringLiteral) &&
644 (!
Previous.Tok.getIdentifierInfo() ||
645 Previous.Tok.getIdentifierInfo()->getPPKeywordID() ==
646 tok::pp_not_keyword)) {
649 if (Current.LastNewlineOffset != 0) {
652 State.Column = EndColumn;
654 unsigned StartColumn =
656 assert(EndColumn >= StartColumn);
657 State.Column += EndColumn - StartColumn;
659 moveStateToNextToken(State, DryRun,
false);
663 unsigned Penalty = 0;
665 Penalty = addTokenOnNewLine(State, DryRun);
667 addTokenOnCurrentLine(State, DryRun, ExtraSpaces);
669 return moveStateToNextToken(State, DryRun, Newline) + Penalty;
672void ContinuationIndenter::addTokenOnCurrentLine(
LineState &State,
bool DryRun,
673 unsigned ExtraSpaces) {
675 assert(State.NextToken->Previous);
677 auto &CurrentState = State.Stack.back();
679 bool DisallowLineBreaksOnThisLine =
681 Style.
isCpp() && [&Current] {
687 const auto *Prev = Current.Previous;
691 if (Prev->is(TT_BlockComment) && Current.SpacesRequiredBefore == 0)
693 const auto *PrevNonComment = Current.getPreviousNonComment();
694 if (!PrevNonComment || PrevNonComment->isNot(tok::l_paren))
696 if (Current.isOneOf(tok::comment, tok::l_paren, TT_LambdaLSquare))
698 auto BlockParameterCount = PrevNonComment->BlockParameterCount;
699 if (BlockParameterCount == 0)
703 if (BlockParameterCount > 1)
707 if (!PrevNonComment->Role)
709 auto Comma = PrevNonComment->Role->lastComma();
712 auto Next = Comma->getNextNonComment();
714 !Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret);
717 if (DisallowLineBreaksOnThisLine)
718 State.NoLineBreak =
true;
720 if (Current.is(tok::equal) &&
721 (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&
722 CurrentState.VariablePos == 0 &&
724 Previous.Previous->isNot(TT_DesignatedInitializerPeriod))) {
725 CurrentState.VariablePos = State.Column;
728 while (Tok && CurrentState.VariablePos >= Tok->ColumnWidth) {
729 CurrentState.VariablePos -= Tok->ColumnWidth;
730 if (Tok->SpacesRequiredBefore != 0)
734 if (
Previous.PartOfMultiVariableDeclStmt)
735 CurrentState.LastSpace = CurrentState.VariablePos;
738 unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces;
741 int PPColumnCorrection = 0;
743 Previous.is(tok::hash) && State.FirstIndent > 0 &&
747 Spaces += State.FirstIndent;
754 PPColumnCorrection = -1;
759 State.Column + Spaces + PPColumnCorrection,
760 false, State.Line->InMacroBody);
766 Current.is(TT_InheritanceColon)) {
767 CurrentState.NoLineBreak =
true;
771 CurrentState.NoLineBreak =
true;
774 if (Current.is(TT_SelectorName) && !CurrentState.ObjCSelectorNameFound) {
775 unsigned MinIndent = std::max(
777 unsigned FirstColonPos = State.Column + Spaces + Current.ColumnWidth;
778 if (Current.LongestObjCSelectorName == 0)
779 CurrentState.AlignColons =
false;
780 else if (MinIndent + Current.LongestObjCSelectorName > FirstColonPos)
781 CurrentState.ColonPos = MinIndent + Current.LongestObjCSelectorName;
783 CurrentState.ColonPos = FirstColonPos;
790 auto IsOpeningBracket = [&](
const FormatToken &Tok) {
791 auto IsStartOfBracedList = [&]() {
792 return Tok.is(tok::l_brace) && Tok.isNot(
BK_Block) &&
795 if (!Tok.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) &&
796 !IsStartOfBracedList()) {
801 if (Tok.Previous->isIf())
803 return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while,
806 auto IsFunctionCallParen = [](
const FormatToken &Tok) {
807 return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous &&
808 Tok.Previous->is(tok::identifier);
810 const auto IsInTemplateString = [
this](
const FormatToken &Tok) {
813 for (
const auto *Prev = &Tok; Prev; Prev = Prev->Previous) {
814 if (Prev->is(TT_TemplateString) && Prev->opensScope())
816 if (Prev->is(TT_TemplateString) && Prev->closesScope())
822 const auto IsSimpleFunction = [&](
const FormatToken &Tok) {
823 if (!Tok.FakeLParens.empty() && Tok.FakeLParens.back() >
prec::Unknown)
825 const auto *
Previous = Tok.Previous;
827 TT_LambdaDefinitionLParen) &&
831 if (IsOpeningBracket(Tok) || IsInTemplateString(Tok))
833 const auto *Next = Tok.Next;
834 return !Next || Next->isMemberAccess() ||
835 Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next);
839 IsOpeningBracket(
Previous) && State.Column > getNewLineColumn(State) &&
847 !IsSimpleFunction(Current)) {
848 CurrentState.NoLineBreak =
true;
852 CurrentState.NoLineBreak =
true;
859 !CurrentState.IsCSharpGenericTypeConstraint &&
Previous.opensScope() &&
861 Previous.isNot(TT_TableGenDAGArgOpener) &&
862 Previous.isNot(TT_TableGenDAGArgOpenerToBreak) &&
863 !(Current.MacroParent &&
Previous.MacroParent) &&
864 (Current.isNot(TT_LineComment) ||
866 !IsInTemplateString(Current)) {
867 CurrentState.Indent = State.Column + Spaces;
868 CurrentState.IsAligned =
true;
871 CurrentState.NoLineBreak =
true;
873 State.Column > getNewLineColumn(State)) {
874 CurrentState.ContainsUnwrappedBuilder =
true;
877 if (Current.is(TT_TrailingReturnArrow) &&
879 CurrentState.NoLineBreak =
true;
881 if (Current.isMemberAccess() &&
Previous.is(tok::r_paren) &&
890 CurrentState.NoLineBreak =
true;
897 const FormatToken *
P = Current.getPreviousNonComment();
898 if (Current.isNot(tok::comment) &&
P &&
899 (
P->isOneOf(TT_BinaryOperator, tok::comma) ||
900 (
P->is(TT_ConditionalExpr) &&
P->is(tok::colon))) &&
901 !
P->isOneOf(TT_OverloadedOperator, TT_CtorInitializerComma) &&
905 bool BreakBeforeOperator =
906 P->MustBreakBefore ||
P->is(tok::lessless) ||
907 (
P->is(TT_BinaryOperator) &&
913 bool HasTwoOperands =
P->OperatorIndex == 0 && !
P->NextOperator &&
914 P->isNot(TT_ConditionalExpr);
915 if ((!BreakBeforeOperator &&
918 (!CurrentState.LastOperatorWrapped && BreakBeforeOperator)) {
919 CurrentState.NoLineBreakInOperand =
true;
923 State.Column += Spaces;
924 if (Current.isNot(tok::comment) &&
Previous.is(tok::l_paren) &&
929 CurrentState.LastSpace = State.Column;
930 CurrentState.NestedBlockIndent = State.Column;
931 }
else if (!Current.isOneOf(tok::comment, tok::caret) &&
933 Previous.isNot(TT_OverloadedOperator)) ||
935 CurrentState.LastSpace = State.Column;
936 }
else if (
Previous.is(TT_CtorInitializerColon) &&
937 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
940 CurrentState.Indent = State.Column;
941 CurrentState.LastSpace = State.Column;
942 }
else if (
Previous.isOneOf(TT_ConditionalExpr, TT_CtorInitializerColon)) {
943 CurrentState.LastSpace = State.Column;
944 }
else if (
Previous.is(TT_BinaryOperator) &&
948 Current.StartsBinaryExpression)) {
952 CurrentState.LastSpace = State.Column;
953 }
else if (
Previous.is(TT_InheritanceColon)) {
954 CurrentState.Indent = State.Column;
955 CurrentState.LastSpace = State.Column;
956 }
else if (Current.is(TT_CSharpGenericTypeConstraintColon)) {
957 CurrentState.ColonPos = State.Column;
965 const FormatToken *Next =
Previous.MatchingParen->getNextNonComment();
966 if (Next && Next->isMemberAccess() && State.Stack.size() > 1 &&
967 State.Stack[State.Stack.size() - 2].CallContinuation == 0) {
968 CurrentState.LastSpace = State.Column;
974unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
976 FormatToken &Current = *State.NextToken;
977 assert(State.NextToken->Previous);
978 const FormatToken &
Previous = *State.NextToken->Previous;
979 auto &CurrentState = State.Stack.back();
983 unsigned Penalty = 0;
985 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
986 const FormatToken *NextNonComment =
Previous.getNextNonComment();
988 NextNonComment = &Current;
991 if (!CurrentState.ContainsLineBreak)
993 CurrentState.ContainsLineBreak =
true;
995 Penalty += State.NextToken->SplitPenalty;
1000 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess == 0 &&
1002 CurrentState.BreakBeforeParameter)) {
1006 State.Column = getNewLineColumn(State);
1020 if (State.Column > State.FirstIndent) {
1035 if (Current.isNot(TT_TrailingReturnArrow) &&
1037 !PreviousNonComment || PreviousNonComment->isNot(tok::equal) ||
1039 CurrentState.NestedBlockIndent = State.Column;
1042 if (NextNonComment->isMemberAccess()) {
1043 if (CurrentState.CallContinuation == 0)
1044 CurrentState.CallContinuation = State.Column;
1045 }
else if (NextNonComment->is(TT_SelectorName)) {
1046 if (!CurrentState.ObjCSelectorNameFound) {
1047 if (NextNonComment->LongestObjCSelectorName == 0) {
1048 CurrentState.AlignColons =
false;
1050 CurrentState.ColonPos =
1052 ? std::max(CurrentState.Indent,
1054 : CurrentState.Indent) +
1056 NextNonComment->ColumnWidth);
1058 }
else if (CurrentState.AlignColons &&
1059 CurrentState.ColonPos <= NextNonComment->ColumnWidth) {
1060 CurrentState.ColonPos = State.Column + NextNonComment->ColumnWidth;
1062 }
else if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
1063 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
1073 if (State.Stack.size() > 1) {
1074 State.Stack[State.Stack.size() - 2].LastSpace =
1075 std::max(CurrentState.LastSpace, CurrentState.Indent) +
1080 if ((PreviousNonComment &&
1081 PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
1082 !CurrentState.AvoidBinPacking) ||
1084 CurrentState.BreakBeforeParameter =
false;
1086 if (PreviousNonComment &&
1087 (PreviousNonComment->isOneOf(TT_TemplateCloser, TT_JavaAnnotation) ||
1088 PreviousNonComment->ClosesRequiresClause) &&
1089 Current.NestingLevel == 0) {
1090 CurrentState.BreakBeforeParameter =
false;
1092 if (NextNonComment->is(tok::question) ||
1093 (PreviousNonComment && PreviousNonComment->is(tok::question))) {
1094 CurrentState.BreakBeforeParameter =
true;
1096 if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore)
1097 CurrentState.BreakBeforeParameter =
false;
1101 if (Current.is(tok::r_brace) && Current.MatchingParen &&
1104 !Current.MatchingParen->Children.empty()) {
1108 MaxEmptyLinesToKeep = 1;
1111 std::max(1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
1112 bool ContinuePPDirective =
1115 CurrentState.IsAligned, ContinuePPDirective);
1118 if (!Current.isTrailingComment())
1119 CurrentState.LastSpace = State.Column;
1120 if (Current.is(tok::lessless)) {
1124 CurrentState.LastSpace += 3;
1127 State.StartOfLineLevel = Current.NestingLevel;
1128 State.LowestLevelOnLine = Current.NestingLevel;
1132 bool NestedBlockSpecialCase =
1133 (!Style.
isCpp() && Current.is(tok::r_brace) && State.Stack.size() > 1 &&
1134 State.Stack[State.Stack.size() - 2].NestedBlockInlined) ||
1138 NestedBlockSpecialCase =
1139 NestedBlockSpecialCase ||
1140 (Current.MatchingParen &&
1141 Current.MatchingParen->is(TT_RequiresExpressionLBrace));
1142 if (!NestedBlockSpecialCase) {
1143 auto ParentLevelIt = std::next(State.Stack.rbegin());
1145 Current.MatchingParen && Current.MatchingParen->is(TT_LambdaLBrace)) {
1160 auto FindCurrentLevel = [&](
const auto &It) {
1161 return std::find_if(It, State.Stack.rend(), [](
const auto &PState) {
1162 return PState.Tok != nullptr;
1165 auto MaybeIncrement = [&](
const auto &It) {
1166 return It != State.Stack.rend() ? std::next(It) : It;
1168 auto LambdaLevelIt = FindCurrentLevel(State.Stack.rbegin());
1169 auto LevelContainingLambdaIt =
1170 FindCurrentLevel(MaybeIncrement(LambdaLevelIt));
1171 ParentLevelIt = MaybeIncrement(LevelContainingLambdaIt);
1173 for (
auto I = ParentLevelIt,
E = State.Stack.rend(); I !=
E; ++I)
1174 I->BreakBeforeParameter =
true;
1177 if (PreviousNonComment &&
1178 !PreviousNonComment->isOneOf(tok::comma, tok::colon, tok::semi) &&
1179 ((PreviousNonComment->isNot(TT_TemplateCloser) &&
1180 !PreviousNonComment->ClosesRequiresClause) ||
1181 Current.NestingLevel != 0) &&
1182 !PreviousNonComment->isOneOf(
1183 TT_BinaryOperator, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
1184 TT_LeadingJavaAnnotation) &&
1185 Current.isNot(TT_BinaryOperator) && !PreviousNonComment->opensScope() &&
1189 Current.isNot(TT_LambdaLBrace))) {
1190 CurrentState.BreakBeforeParameter =
true;
1195 if (PreviousNonComment &&
1196 (PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1198 CurrentState.BreakBeforeClosingBrace =
true;
1201 if (PreviousNonComment && PreviousNonComment->is(tok::l_paren)) {
1202 CurrentState.BreakBeforeClosingParen =
1206 if (CurrentState.AvoidBinPacking) {
1211 bool PreviousIsBreakingCtorInitializerColon =
1212 PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1214 bool AllowAllConstructorInitializersOnNextLine =
1217 if (!(
Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
1218 PreviousIsBreakingCtorInitializerColon) ||
1220 State.Line->MustBeDeclaration) ||
1222 !State.Line->MustBeDeclaration) ||
1223 (!AllowAllConstructorInitializersOnNextLine &&
1224 PreviousIsBreakingCtorInitializerColon) ||
1226 CurrentState.BreakBeforeParameter =
true;
1232 if (PreviousIsBreakingCtorInitializerColon &&
1233 AllowAllConstructorInitializersOnNextLine) {
1234 CurrentState.BreakBeforeParameter =
false;
1241unsigned ContinuationIndenter::getNewLineColumn(
const LineState &State) {
1242 if (!State.NextToken || !State.NextToken->Previous)
1245 FormatToken &Current = *State.NextToken;
1246 const auto &CurrentState = State.Stack.back();
1248 if (CurrentState.IsCSharpGenericTypeConstraint &&
1249 Current.isNot(TT_CSharpGenericTypeConstraint)) {
1250 return CurrentState.ColonPos + 2;
1253 const FormatToken &
Previous = *Current.Previous;
1255 unsigned ContinuationIndent =
1256 std::max(CurrentState.LastSpace, CurrentState.Indent) +
1258 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
1259 const FormatToken *NextNonComment =
Previous.getNextNonComment();
1260 if (!NextNonComment)
1261 NextNonComment = &Current;
1266 return std::max(CurrentState.LastSpace,
1272 if (Style.
isVerilog() && PreviousNonComment &&
1274 return State.FirstIndent;
1278 State.Line->First->is(tok::kw_enum)) {
1279 return (Style.
IndentWidth * State.Line->First->IndentLevel) +
1283 if ((NextNonComment->is(tok::l_brace) && NextNonComment->is(
BK_Block)) ||
1285 if (Current.NestingLevel == 0 ||
1287 State.NextToken->is(TT_LambdaLBrace))) {
1288 return State.FirstIndent;
1290 return CurrentState.Indent;
1292 if (Current.is(TT_TrailingReturnArrow) &&
1293 Previous.isOneOf(tok::kw_noexcept, tok::kw_mutable, tok::kw_constexpr,
1294 tok::kw_consteval, tok::kw_static, TT_AttributeSquare)) {
1295 return ContinuationIndent;
1297 if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
1299 State.Stack.size() > 1) {
1300 if (Current.closesBlockOrBlockTypeList(Style))
1301 return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
1302 if (Current.MatchingParen && Current.MatchingParen->is(
BK_BracedInit))
1303 return State.Stack[State.Stack.size() - 2].LastSpace;
1304 return State.FirstIndent;
1321 if (Current.is(tok::r_paren) && State.Stack.size() > 1 &&
1323 Current.Next->isOneOf(tok::semi, tok::kw_const, tok::l_brace))) {
1324 return State.Stack[State.Stack.size() - 2].LastSpace;
1328 if (Style.
isTableGen() && Current.is(TT_TableGenDAGArgCloser) &&
1329 State.Stack.size() > 1) {
1330 return State.Stack[State.Stack.size() - 2].LastSpace;
1333 (Current.is(tok::r_paren) ||
1334 (Current.is(tok::r_brace) && Current.MatchingParen &&
1336 State.Stack.size() > 1) {
1337 return State.Stack[State.Stack.size() - 2].LastSpace;
1339 if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
1340 return State.Stack[State.Stack.size() - 2].LastSpace;
1348 if (Current.is(tok::identifier) && Current.Next &&
1349 (!Style.
isVerilog() || Current.Next->is(tok::colon)) &&
1350 (Current.Next->is(TT_DictLiteral) ||
1351 (Style.
isProto() && Current.Next->isOneOf(tok::less, tok::l_brace)))) {
1352 return CurrentState.Indent;
1354 if (NextNonComment->is(TT_ObjCStringLiteral) &&
1355 State.StartOfStringLiteral != 0) {
1356 return State.StartOfStringLiteral - 1;
1358 if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0)
1359 return State.StartOfStringLiteral;
1360 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess != 0)
1361 return CurrentState.FirstLessLess;
1362 if (NextNonComment->isMemberAccess()) {
1363 if (CurrentState.CallContinuation == 0)
1364 return ContinuationIndent;
1365 return CurrentState.CallContinuation;
1367 if (CurrentState.QuestionColumn != 0 &&
1368 ((NextNonComment->is(tok::colon) &&
1369 NextNonComment->is(TT_ConditionalExpr)) ||
1370 Previous.is(TT_ConditionalExpr))) {
1371 if (((NextNonComment->is(tok::colon) && NextNonComment->Next &&
1372 !NextNonComment->Next->FakeLParens.empty() &&
1374 (
Previous.is(tok::colon) && !Current.FakeLParens.empty() &&
1376 !CurrentState.IsWrappedConditional) {
1381 unsigned Indent = CurrentState.Indent;
1388 return CurrentState.QuestionColumn;
1390 if (
Previous.is(tok::comma) && CurrentState.VariablePos != 0)
1391 return CurrentState.VariablePos;
1392 if (Current.is(TT_RequiresClause)) {
1398 return CurrentState.Indent;
1403 if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
1404 TT_InheritanceComma)) {
1407 if ((PreviousNonComment &&
1408 (PreviousNonComment->ClosesTemplateDeclaration ||
1409 PreviousNonComment->ClosesRequiresClause ||
1410 (PreviousNonComment->is(TT_AttributeMacro) &&
1411 Current.isNot(tok::l_paren)) ||
1412 PreviousNonComment->isOneOf(
1413 TT_AttributeRParen, TT_AttributeSquare, TT_FunctionAnnotationRParen,
1414 TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
1416 NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName))) {
1417 return std::max(CurrentState.LastSpace, CurrentState.Indent);
1419 if (NextNonComment->is(TT_SelectorName)) {
1420 if (!CurrentState.ObjCSelectorNameFound) {
1421 unsigned MinIndent = CurrentState.Indent;
1423 MinIndent = std::max(MinIndent,
1436 std::max(NextNonComment->LongestObjCSelectorName,
1437 NextNonComment->ColumnWidth) -
1438 NextNonComment->ColumnWidth;
1440 if (!CurrentState.AlignColons)
1441 return CurrentState.Indent;
1442 if (CurrentState.ColonPos > NextNonComment->ColumnWidth)
1443 return CurrentState.ColonPos - NextNonComment->ColumnWidth;
1444 return CurrentState.Indent;
1446 if (NextNonComment->is(tok::colon) && NextNonComment->is(TT_ObjCMethodExpr))
1447 return CurrentState.ColonPos;
1448 if (NextNonComment->is(TT_ArraySubscriptLSquare)) {
1449 if (CurrentState.StartOfArraySubscripts != 0) {
1450 return CurrentState.StartOfArraySubscripts;
1453 return CurrentState.Indent;
1455 return ContinuationIndent;
1460 if (State.Line->InPragmaDirective) {
1461 FormatToken *PragmaType = State.Line->First->Next->Next;
1462 if (PragmaType && PragmaType->TokenText ==
"omp")
1468 if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 &&
1469 NextNonComment->Next && NextNonComment->Next->is(TT_ObjCMethodExpr)) {
1470 return CurrentState.Indent;
1473 if (NextNonComment->isOneOf(TT_StartOfName, TT_PointerOrReference) ||
1474 Previous.isOneOf(tok::coloncolon, tok::equal, TT_JsTypeColon)) {
1475 return ContinuationIndent;
1477 if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
1478 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
1479 return ContinuationIndent;
1481 if (NextNonComment->is(TT_CtorInitializerComma))
1482 return CurrentState.Indent;
1483 if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1485 return CurrentState.Indent;
1487 if (PreviousNonComment && PreviousNonComment->is(TT_InheritanceColon) &&
1489 return CurrentState.Indent;
1492 Previous.isNot(TT_TableGenDAGArgOperatorToBreak) &&
1493 !Current.isBinaryOperator() &&
1494 !Current.isOneOf(tok::colon, tok::comment)) {
1495 return ContinuationIndent;
1497 if (Current.is(TT_ProtoExtensionLSquare))
1498 return CurrentState.Indent;
1499 if (Current.isBinaryOperator() && CurrentState.UnindentOperator) {
1500 return CurrentState.Indent - Current.Tok.getLength() -
1501 Current.SpacesRequiredBefore;
1503 if (Current.is(tok::comment) && NextNonComment->isBinaryOperator() &&
1504 CurrentState.UnindentOperator) {
1505 return CurrentState.Indent - NextNonComment->Tok.getLength() -
1506 NextNonComment->SpacesRequiredBefore;
1508 if (CurrentState.Indent == State.FirstIndent && PreviousNonComment &&
1509 !PreviousNonComment->isOneOf(tok::r_brace, TT_CtorInitializerComma)) {
1514 return CurrentState.Indent;
1529unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
1530 bool DryRun,
bool Newline) {
1531 assert(State.Stack.size());
1532 const FormatToken &Current = *State.NextToken;
1533 auto &CurrentState = State.Stack.back();
1535 if (Current.is(TT_CSharpGenericTypeConstraint))
1536 CurrentState.IsCSharpGenericTypeConstraint =
true;
1537 if (Current.isOneOf(tok::comma, TT_BinaryOperator))
1538 CurrentState.NoLineBreakInOperand =
false;
1539 if (Current.isOneOf(TT_InheritanceColon, TT_CSharpGenericTypeConstraintColon))
1540 CurrentState.AvoidBinPacking =
true;
1541 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator)) {
1542 if (CurrentState.FirstLessLess == 0)
1543 CurrentState.FirstLessLess = State.Column;
1545 CurrentState.LastOperatorWrapped = Newline;
1547 if (Current.is(TT_BinaryOperator) && Current.isNot(tok::lessless))
1548 CurrentState.LastOperatorWrapped = Newline;
1549 if (Current.is(TT_ConditionalExpr) && Current.Previous &&
1550 Current.Previous->isNot(TT_ConditionalExpr)) {
1551 CurrentState.LastOperatorWrapped = Newline;
1553 if (Current.is(TT_ArraySubscriptLSquare) &&
1554 CurrentState.StartOfArraySubscripts == 0) {
1555 CurrentState.StartOfArraySubscripts = State.Column;
1558 auto IsWrappedConditional = [](
const FormatToken &Tok) {
1559 if (!(Tok.is(TT_ConditionalExpr) && Tok.is(tok::question)))
1561 if (Tok.MustBreakBefore)
1564 const FormatToken *Next = Tok.getNextNonComment();
1565 return Next && Next->MustBreakBefore;
1567 if (IsWrappedConditional(Current))
1568 CurrentState.IsWrappedConditional =
true;
1570 CurrentState.QuestionColumn = State.Column;
1572 const FormatToken *
Previous = Current.Previous;
1576 CurrentState.QuestionColumn = State.Column;
1578 if (!Current.opensScope() && !Current.closesScope() &&
1579 Current.isNot(TT_PointerOrReference)) {
1580 State.LowestLevelOnLine =
1581 std::min(State.LowestLevelOnLine, Current.NestingLevel);
1583 if (Current.isMemberAccess())
1584 CurrentState.StartOfFunctionCall = !Current.NextOperator ? 0 : State.Column;
1585 if (Current.is(TT_SelectorName))
1586 CurrentState.ObjCSelectorNameFound =
true;
1587 if (Current.is(TT_CtorInitializerColon) &&
1598 CurrentState.NestedBlockIndent = CurrentState.Indent;
1600 CurrentState.AvoidBinPacking =
true;
1601 CurrentState.BreakBeforeParameter =
1606 CurrentState.BreakBeforeParameter =
false;
1609 if (Current.is(TT_CtorInitializerColon) &&
1611 CurrentState.Indent =
1613 CurrentState.NestedBlockIndent = CurrentState.Indent;
1615 CurrentState.AvoidBinPacking =
true;
1617 CurrentState.BreakBeforeParameter =
false;
1619 if (Current.is(TT_InheritanceColon)) {
1620 CurrentState.Indent =
1623 if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
1624 CurrentState.NestedBlockIndent = State.Column + Current.ColumnWidth + 1;
1625 if (Current.isOneOf(TT_LambdaLSquare, TT_TrailingReturnArrow))
1626 CurrentState.LastSpace = State.Column;
1627 if (Current.is(TT_RequiresExpression) &&
1629 CurrentState.NestedBlockIndent = State.Column;
1633 const FormatToken *
Previous = Current.getPreviousNonComment();
1641 if (Current.isNot(tok::comment) && !Current.ClosesRequiresClause &&
1643 Previous->isNot(TT_DictLiteral) && State.Stack.size() > 1 &&
1644 !CurrentState.HasMultipleNestedBlocks) {
1645 if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
1646 for (ParenState &PState : llvm::drop_end(State.Stack))
1647 PState.NoLineBreak =
true;
1648 State.Stack[State.Stack.size() - 2].NestedBlockInlined =
false;
1650 if (
Previous && (
Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr) ||
1651 (
Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) &&
1652 !
Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)))) {
1653 CurrentState.NestedBlockInlined =
1657 moveStatePastFakeLParens(State, Newline);
1658 moveStatePastScopeCloser(State);
1661 bool AllowBreak = !State.Stack.back().NoLineBreak &&
1662 !State.Stack.back().NoLineBreakInOperand;
1663 moveStatePastScopeOpener(State, Newline);
1664 moveStatePastFakeRParens(State);
1666 if (Current.is(TT_ObjCStringLiteral) && State.StartOfStringLiteral == 0)
1667 State.StartOfStringLiteral = State.Column + 1;
1668 if (Current.is(TT_CSharpStringLiteral) && State.StartOfStringLiteral == 0) {
1669 State.StartOfStringLiteral = State.Column + 1;
1670 }
else if (Current.is(TT_TableGenMultiLineString) &&
1671 State.StartOfStringLiteral == 0) {
1672 State.StartOfStringLiteral = State.Column + 1;
1673 }
else if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
1674 State.StartOfStringLiteral = State.Column;
1675 }
else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
1676 !Current.isStringLiteral()) {
1677 State.StartOfStringLiteral = 0;
1680 State.Column += Current.ColumnWidth;
1681 State.NextToken = State.NextToken->Next;
1686 if (Style.
isVerilog() && State.NextToken &&
1687 State.NextToken->MustBreakBefore &&
1690 CurrentState.Indent = State.FirstIndent;
1694 handleEndOfLine(Current, State, DryRun, AllowBreak, Newline);
1697 Current.Role->formatFromToken(State,
this, DryRun);
1704 Penalty +=
Previous->Role->formatAfterToken(State,
this, DryRun);
1709void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
1711 const FormatToken &Current = *State.NextToken;
1712 if (Current.FakeLParens.empty())
1715 const FormatToken *
Previous = Current.getPreviousNonComment();
1720 bool SkipFirstExtraIndent =
1723 Previous->isOneOf(tok::semi, tok::kw_return, TT_RequiresClause) ||
1727 for (
const auto &PrecedenceLevel : llvm::reverse(Current.FakeLParens)) {
1728 const auto &CurrentState = State.Stack.back();
1729 ParenState NewParenState = CurrentState;
1730 NewParenState.Tok =
nullptr;
1731 NewParenState.ContainsLineBreak =
false;
1732 NewParenState.LastOperatorWrapped =
true;
1733 NewParenState.IsChainedConditional =
false;
1734 NewParenState.IsWrappedConditional =
false;
1735 NewParenState.UnindentOperator =
false;
1736 NewParenState.NoLineBreak =
1737 NewParenState.NoLineBreak || CurrentState.NoLineBreakInOperand;
1741 NewParenState.AvoidBinPacking =
false;
1746 if (!Current.isTrailingComment() &&
1752 PrecedenceLevel >
prec::Comma || Current.NestingLevel == 0) &&
1755 TT_TableGenDAGArgListCommaToBreak)))) {
1756 NewParenState.Indent = std::max(
1757 std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
1764 State.Stack.size() > 1) {
1765 NewParenState.Indent = State.Stack[State.Stack.size() - 2].Indent +
1777 NewParenState.UnindentOperator =
true;
1780 NewParenState.IsAligned =
true;
1790 NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
1792 Current.isNot(TT_UnaryOperator) &&
1794 NewParenState.StartOfFunctionCall = State.Column;
1804 &PrecedenceLevel == &Current.FakeLParens.back() &&
1805 !CurrentState.IsWrappedConditional) {
1806 NewParenState.IsChainedConditional =
true;
1807 NewParenState.UnindentOperator = State.Stack.back().UnindentOperator;
1810 !Current.isTrailingComment())) {
1814 NewParenState.BreakBeforeParameter =
false;
1815 State.Stack.push_back(NewParenState);
1816 SkipFirstExtraIndent =
false;
1820void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
1821 for (
unsigned i = 0, e = State.NextToken->FakeRParens; i != e; ++i) {
1822 unsigned VariablePos = State.Stack.back().VariablePos;
1823 if (State.Stack.size() == 1) {
1827 State.Stack.pop_back();
1828 State.Stack.back().VariablePos = VariablePos;
1834 State.Stack.back().LastSpace -= Style.
IndentWidth;
1838void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
1840 const FormatToken &Current = *State.NextToken;
1841 if (!Current.opensScope())
1844 const auto &CurrentState = State.Stack.back();
1847 if (Current.isOneOf(tok::less, tok::l_paren) &&
1848 CurrentState.IsCSharpGenericTypeConstraint) {
1852 if (Current.MatchingParen && Current.is(
BK_Block)) {
1853 moveStateToNewBlock(State, Newline);
1858 unsigned LastSpace = CurrentState.LastSpace;
1859 bool AvoidBinPacking;
1860 bool BreakBeforeParameter =
false;
1861 unsigned NestedBlockIndent = std::max(CurrentState.StartOfFunctionCall,
1862 CurrentState.NestedBlockIndent);
1863 if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1865 if (Current.opensBlockOrBlockTypeList(Style)) {
1867 std::min(State.Column, CurrentState.NestedBlockIndent);
1868 }
else if (Current.is(tok::l_brace)) {
1875 const FormatToken *NextNonComment = Current.getNextNonComment();
1876 bool EndsInComma = Current.MatchingParen &&
1877 Current.MatchingParen->Previous &&
1878 Current.MatchingParen->Previous->is(tok::comma);
1879 AvoidBinPacking = EndsInComma || Current.is(TT_DictLiteral) ||
1881 (NextNonComment && NextNonComment->isOneOf(
1882 TT_DesignatedInitializerPeriod,
1883 TT_DesignatedInitializerLSquare));
1884 BreakBeforeParameter = EndsInComma;
1885 if (Current.ParameterCount > 1)
1886 NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
1890 std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall);
1892 if (Style.
isTableGen() && Current.is(TT_TableGenDAGArgOpenerToBreak) &&
1898 const FormatToken *Next = Current.Next;
1899 if (Next && Next->is(TT_TableGenDAGArgOperatorID))
1900 NewIndent = State.Column + Next->TokenText.size() + 2;
1907 if (Current.is(tok::less) && Current.ParentBracket == tok::l_paren) {
1908 NewIndent = std::max(NewIndent, CurrentState.Indent);
1909 LastSpace = std::max(LastSpace, CurrentState.Indent);
1913 Current.MatchingParen &&
1914 Current.MatchingParen->getPreviousNonComment() &&
1915 Current.MatchingParen->getPreviousNonComment()->is(tok::comma);
1919 bool ObjCBinPackProtocolList =
1924 bool BinPackDeclaration =
1926 (State.Line->Type ==
LT_ObjCDecl && ObjCBinPackProtocolList);
1928 bool GenericSelection =
1929 Current.getPreviousNonComment() &&
1930 Current.getPreviousNonComment()->is(tok::kw__Generic);
1933 (CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection ||
1935 (State.Line->MustBeDeclaration && !BinPackDeclaration) ||
1941 if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen &&
1948 BreakBeforeParameter =
true;
1953 for (
const FormatToken *Tok = &Current;
1954 Tok && Tok != Current.MatchingParen; Tok = Tok->Next) {
1955 if (Tok->MustBreakBefore ||
1956 (Tok->CanBreakBefore && Tok->NewlinesBefore > 0)) {
1957 BreakBeforeParameter =
true;
1965 BreakBeforeParameter =
true;
1971 Current.Children.empty() &&
1972 !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) &&
1973 (CurrentState.NoLineBreak || CurrentState.NoLineBreakInOperand ||
1974 (Current.is(TT_TemplateOpener) &&
1975 CurrentState.ContainsUnwrappedBuilder));
1976 State.Stack.push_back(
1977 ParenState(&Current, NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
1978 auto &NewState = State.Stack.back();
1979 NewState.NestedBlockIndent = NestedBlockIndent;
1980 NewState.BreakBeforeParameter = BreakBeforeParameter;
1981 NewState.HasMultipleNestedBlocks = (Current.BlockParameterCount > 1);
1984 Current.is(tok::l_paren)) {
1986 FormatToken
const *next = Current.Next;
1988 if (next->is(TT_LambdaLSquare)) {
1989 NewState.HasMultipleNestedBlocks =
true;
1996 NewState.IsInsideObjCArrayLiteral = Current.is(TT_ArrayInitializerLSquare) &&
1998 Current.Previous->is(tok::at);
2001void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
2002 const FormatToken &Current = *State.NextToken;
2003 if (!Current.closesScope())
2008 if (State.Stack.size() > 1 &&
2009 (Current.isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
2010 (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
2011 State.NextToken->is(TT_TemplateCloser) ||
2012 State.NextToken->is(TT_TableGenListCloser) ||
2013 (Current.is(tok::greater) && Current.is(TT_DictLiteral)))) {
2014 State.Stack.pop_back();
2017 auto &CurrentState = State.Stack.back();
2029 if (CurrentState.BreakBeforeParameter && Current.MatchingParen &&
2030 Current.MatchingParen->Previous) {
2031 const FormatToken &CurrentScopeOpener = *Current.MatchingParen->Previous;
2032 if (CurrentScopeOpener.is(TT_ObjCMethodExpr) &&
2033 CurrentScopeOpener.MatchingParen) {
2034 int NecessarySpaceInLine =
2036 CurrentScopeOpener.TotalLength - Current.TotalLength - 1;
2037 if (State.Column + Current.ColumnWidth + NecessarySpaceInLine <=
2039 CurrentState.BreakBeforeParameter =
false;
2044 if (Current.is(tok::r_square)) {
2046 const FormatToken *NextNonComment = Current.getNextNonComment();
2047 if (NextNonComment && NextNonComment->isNot(tok::l_square))
2048 CurrentState.StartOfArraySubscripts = 0;
2052void ContinuationIndenter::moveStateToNewBlock(LineState &State,
bool NewLine) {
2054 State.NextToken->is(TT_LambdaLBrace) &&
2055 !State.Line->MightBeFunctionDecl) {
2056 State.Stack.back().NestedBlockIndent = State.FirstIndent;
2058 unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
2060 unsigned NewIndent =
2061 NestedBlockIndent + (State.NextToken->is(TT_ObjCBlockLBrace)
2071 State.NextToken->is(TT_LambdaLBrace);
2073 State.Stack.push_back(ParenState(State.NextToken, NewIndent,
2074 State.Stack.back().LastSpace,
2075 true, NoLineBreak));
2076 State.Stack.back().NestedBlockIndent = NestedBlockIndent;
2077 State.Stack.back().BreakBeforeParameter =
true;
2083 size_t LastNewlinePos =
Text.find_last_of(
"\n");
2084 if (LastNewlinePos == StringRef::npos) {
2085 return StartColumn +
2089 0, TabWidth, Encoding);
2093unsigned ContinuationIndenter::reformatRawStringLiteral(
2094 const FormatToken &Current, LineState &State,
2095 const FormatStyle &RawStringStyle,
bool DryRun,
bool Newline) {
2096 unsigned StartColumn = State.Column - Current.ColumnWidth;
2098 StringRef NewDelimiter =
2100 if (NewDelimiter.empty())
2101 NewDelimiter = OldDelimiter;
2104 unsigned OldPrefixSize = 3 + OldDelimiter.size();
2105 unsigned OldSuffixSize = 2 + OldDelimiter.size();
2108 std::string RawText = std::string(
2109 Current.TokenText.substr(OldPrefixSize).drop_back(OldSuffixSize));
2110 if (NewDelimiter != OldDelimiter) {
2113 std::string CanonicalDelimiterSuffix = (
")" + NewDelimiter +
"\"").str();
2114 if (StringRef(RawText).contains(CanonicalDelimiterSuffix))
2115 NewDelimiter = OldDelimiter;
2118 unsigned NewPrefixSize = 3 + NewDelimiter.size();
2119 unsigned NewSuffixSize = 2 + NewDelimiter.size();
2122 unsigned FirstStartColumn = StartColumn + NewPrefixSize;
2133 bool ContentStartsOnNewline = Current.TokenText[OldPrefixSize] ==
'\n';
2155 unsigned CurrentIndent =
2156 (!Newline && Current.Next && Current.Next->is(tok::r_paren))
2157 ? State.Stack.back().NestedBlockIndent
2158 : State.Stack.back().Indent;
2159 unsigned NextStartColumn = ContentStartsOnNewline
2171 unsigned LastStartColumn =
2172 Current.NewlinesBefore ? FirstStartColumn - NewPrefixSize : CurrentIndent;
2175 RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
2176 FirstStartColumn, NextStartColumn, LastStartColumn,
"<stdin>",
2180 tooling::Replacements NoFixes;
2182 return addMultilineToken(Current, State);
2184 if (NewDelimiter != OldDelimiter) {
2187 SourceLocation PrefixDelimiterStart =
2188 Current.Tok.getLocation().getLocWithOffset(2);
2189 auto PrefixErr = Whitespaces.
addReplacement(tooling::Replacement(
2190 SourceMgr, PrefixDelimiterStart, OldDelimiter.size(), NewDelimiter));
2193 <<
"Failed to update the prefix delimiter of a raw string: "
2194 << llvm::toString(std::move(PrefixErr)) <<
"\n";
2198 SourceLocation SuffixDelimiterStart =
2199 Current.Tok.getLocation().getLocWithOffset(Current.TokenText.size() -
2200 1 - OldDelimiter.size());
2201 auto SuffixErr = Whitespaces.
addReplacement(tooling::Replacement(
2202 SourceMgr, SuffixDelimiterStart, OldDelimiter.size(), NewDelimiter));
2205 <<
"Failed to update the suffix delimiter of a raw string: "
2206 << llvm::toString(std::move(SuffixErr)) <<
"\n";
2209 SourceLocation OriginLoc =
2210 Current.Tok.getLocation().getLocWithOffset(OldPrefixSize);
2211 for (
const tooling::Replacement &Fix : Fixes.first) {
2213 SourceMgr, OriginLoc.getLocWithOffset(Fix.getOffset()),
2214 Fix.getLength(), Fix.getReplacementText()));
2216 llvm::errs() <<
"Failed to reformat raw string: "
2217 << llvm::toString(std::move(Err)) <<
"\n";
2222 *NewCode, FirstStartColumn, Style.
TabWidth, Encoding);
2223 State.Column = RawLastLineEndColumn + NewSuffixSize;
2227 unsigned PrefixExcessCharacters =
2232 ContentStartsOnNewline || (NewCode->find(
'\n') != std::string::npos);
2235 for (ParenState &
Paren : State.Stack)
2236 Paren.BreakBeforeParameter =
true;
2241unsigned ContinuationIndenter::addMultilineToken(
const FormatToken &Current,
2244 for (ParenState &
Paren : State.Stack)
2245 Paren.BreakBeforeParameter =
true;
2247 unsigned ColumnsUsed = State.Column;
2250 State.Column = Current.LastLineColumnWidth;
2257unsigned ContinuationIndenter::handleEndOfLine(
const FormatToken &Current,
2258 LineState &State,
bool DryRun,
2259 bool AllowBreak,
bool Newline) {
2260 unsigned Penalty = 0;
2263 auto RawStringStyle = getRawStringStyle(Current, State);
2264 if (RawStringStyle && !Current.Finalized) {
2265 Penalty = reformatRawStringLiteral(Current, State, *RawStringStyle, DryRun,
2267 }
else if (Current.IsMultiline && Current.isNot(TT_BlockComment)) {
2270 Penalty = addMultilineToken(Current, State);
2273 LineState OriginalState = State;
2277 bool Strict =
false;
2280 bool Exceeded =
false;
2281 std::tie(Penalty, Exceeded) = breakProtrudingToken(
2282 Current, State, AllowBreak,
true, Strict);
2286 LineState StrictState = OriginalState;
2287 unsigned StrictPenalty =
2288 breakProtrudingToken(Current, StrictState, AllowBreak,
2291 Strict = StrictPenalty <= Penalty;
2293 Penalty = StrictPenalty;
2294 State = StrictState;
2300 breakProtrudingToken(Current, OriginalState, AllowBreak,
false,
2305 unsigned ExcessCharacters = State.Column -
getColumnLimit(State);
2316 if (!Tok || Tok->isNot(tok::l_paren))
2321 if (Tok->is(TT_TemplateCloser)) {
2326 if (!Tok || Tok->isNot(tok::identifier))
2331std::optional<FormatStyle>
2332ContinuationIndenter::getRawStringStyle(
const FormatToken &Current,
2333 const LineState &State) {
2334 if (!Current.isStringLiteral())
2335 return std::nullopt;
2338 return std::nullopt;
2340 if (!RawStringStyle && Delimiter->empty()) {
2344 if (!RawStringStyle)
2345 return std::nullopt;
2347 return RawStringStyle;
2350std::unique_ptr<BreakableToken>
2351ContinuationIndenter::createBreakableToken(
const FormatToken &Current,
2352 LineState &State,
bool AllowBreak) {
2353 unsigned StartColumn = State.Column - Current.ColumnWidth;
2354 if (Current.isStringLiteral()) {
2371 if (Current.IsUnterminatedLiteral)
2375 if (State.Stack.back().IsInsideObjCArrayLiteral)
2382 if (Style.
isVerilog() && Current.Previous &&
2383 Current.Previous->isOneOf(tok::kw_export, Keywords.
kw_import)) {
2386 StringRef
Text = Current.TokenText;
2392 unsigned UnbreakableTailLength = (State.NextToken &&
canBreak(State))
2394 : Current.UnbreakableTailLength;
2400 Text.ends_with(
"'")) {
2402 }
else if (Style.
isCSharp() &&
Text.starts_with(
"@\"") &&
2403 Text.ends_with(
"\"")) {
2405 }
else if (
Text.starts_with(
"\"") &&
Text.ends_with(
"\"")) {
2410 return std::make_unique<BreakableStringLiteralUsingOperators>(
2411 Current, QuoteStyle,
2413 UnbreakableTailLength, State.Line->InPPDirective, Encoding, Style);
2422 if ((
Text.ends_with(Postfix =
"\"") &&
2423 (
Text.starts_with(Prefix =
"@\"") ||
Text.starts_with(Prefix =
"\"") ||
2424 Text.starts_with(Prefix =
"u\"") ||
2425 Text.starts_with(Prefix =
"U\"") ||
2426 Text.starts_with(Prefix =
"u8\"") ||
2427 Text.starts_with(Prefix =
"L\""))) ||
2428 (
Text.starts_with(Prefix =
"_T(\"") &&
2429 Text.ends_with(Postfix =
"\")"))) {
2430 return std::make_unique<BreakableStringLiteral>(
2431 Current, StartColumn, Prefix, Postfix, UnbreakableTailLength,
2432 State.Line->InPPDirective, Encoding, Style);
2434 }
else if (Current.is(TT_BlockComment)) {
2442 return std::make_unique<BreakableBlockComment>(
2443 Current, StartColumn, Current.OriginalColumn, !Current.Previous,
2444 State.Line->InPPDirective, Encoding, Style, Whitespaces.
useCRLF());
2445 }
else if (Current.is(TT_LineComment) &&
2446 (!Current.Previous ||
2447 Current.Previous->isNot(TT_ImplicitStringLiteral))) {
2448 bool RegularComments = [&]() {
2449 for (
const FormatToken *
T = &Current;
T &&
T->is(TT_LineComment);
2451 if (!(
T->TokenText.starts_with(
"//") ||
T->TokenText.starts_with(
"#")))
2457 CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
2461 return std::make_unique<BreakableLineCommentSection>(
2462 Current, StartColumn,
false, Encoding, Style);
2467std::pair<unsigned, bool>
2468ContinuationIndenter::breakProtrudingToken(
const FormatToken &Current,
2469 LineState &State,
bool AllowBreak,
2470 bool DryRun,
bool Strict) {
2471 std::unique_ptr<const BreakableToken> Token =
2472 createBreakableToken(Current, State, AllowBreak);
2475 assert(Token->getLineCount() > 0);
2477 if (Current.is(TT_LineComment)) {
2481 if (ColumnLimit == 0) {
2484 ColumnLimit = std::numeric_limits<
decltype(ColumnLimit)>
::max();
2486 if (Current.UnbreakableTailLength >= ColumnLimit)
2490 unsigned StartColumn = State.Column - Current.ColumnWidth;
2491 unsigned NewBreakPenalty = Current.isStringLiteral()
2496 bool Exceeded =
false;
2498 bool BreakInserted = Token->introducesBreakBeforeToken();
2501 bool NewBreakBefore =
false;
2505 bool Reflow =
false;
2508 unsigned TailOffset = 0;
2510 unsigned ContentStartColumn =
2511 Token->getContentStartColumn(0,
false);
2513 unsigned RemainingTokenColumns =
2514 Token->getRemainingLength(0, TailOffset, ContentStartColumn);
2517 Token->adaptStartOfLine(0, Whitespaces);
2519 unsigned ContentIndent = 0;
2520 unsigned Penalty = 0;
2521 LLVM_DEBUG(llvm::dbgs() <<
"Breaking protruding token at column "
2522 << StartColumn <<
".\n");
2523 for (
unsigned LineIndex = 0, EndIndex = Token->getLineCount();
2524 LineIndex != EndIndex; ++LineIndex) {
2525 LLVM_DEBUG(llvm::dbgs()
2526 <<
" Line: " << LineIndex <<
" (Reflow: " << Reflow <<
")\n");
2527 NewBreakBefore =
false;
2531 bool TryReflow = Reflow;
2533 while (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2534 LLVM_DEBUG(llvm::dbgs() <<
" Over limit, need: "
2535 << (ContentStartColumn + RemainingTokenColumns)
2536 <<
", space: " << ColumnLimit
2537 <<
", reflown prefix: " << ContentStartColumn
2538 <<
", offset in line: " << TailOffset <<
"\n");
2544 Token->getSplit(LineIndex, TailOffset, ColumnLimit,
2545 ContentStartColumn, CommentPragmasRegex);
2546 if (
Split.first == StringRef::npos) {
2549 if (LineIndex < EndIndex - 1) {
2553 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2555 LLVM_DEBUG(llvm::dbgs() <<
" No break opportunity.\n");
2558 assert(
Split.first != 0);
2560 if (Token->supportsReflow()) {
2580 unsigned ToSplitColumns = Token->getRangeLength(
2581 LineIndex, TailOffset,
Split.first, ContentStartColumn);
2582 LLVM_DEBUG(llvm::dbgs() <<
" ToSplit: " << ToSplitColumns <<
"\n");
2585 LineIndex, TailOffset +
Split.first +
Split.second, ColumnLimit,
2586 ContentStartColumn + ToSplitColumns + 1, CommentPragmasRegex);
2589 unsigned ToNextSplitColumns = 0;
2590 if (NextSplit.first == StringRef::npos) {
2591 ToNextSplitColumns = Token->getRemainingLength(LineIndex, TailOffset,
2592 ContentStartColumn);
2594 ToNextSplitColumns = Token->getRangeLength(
2595 LineIndex, TailOffset,
2596 Split.first +
Split.second + NextSplit.first, ContentStartColumn);
2600 ToNextSplitColumns =
2601 Token->getLengthAfterCompression(ToNextSplitColumns, Split);
2602 LLVM_DEBUG(llvm::dbgs()
2603 <<
" ContentStartColumn: " << ContentStartColumn <<
"\n");
2604 LLVM_DEBUG(llvm::dbgs()
2605 <<
" ToNextSplit: " << ToNextSplitColumns <<
"\n");
2608 bool ContinueOnLine =
2609 ContentStartColumn + ToNextSplitColumns <= ColumnLimit;
2610 unsigned ExcessCharactersPenalty = 0;
2611 if (!ContinueOnLine && !Strict) {
2614 ExcessCharactersPenalty =
2615 (ContentStartColumn + ToNextSplitColumns - ColumnLimit) *
2617 LLVM_DEBUG(llvm::dbgs()
2618 <<
" Penalty excess: " << ExcessCharactersPenalty
2619 <<
"\n break : " << NewBreakPenalty <<
"\n");
2620 if (ExcessCharactersPenalty < NewBreakPenalty) {
2622 ContinueOnLine =
true;
2625 if (ContinueOnLine) {
2626 LLVM_DEBUG(llvm::dbgs() <<
" Continuing on line...\n");
2631 Token->compressWhitespace(LineIndex, TailOffset, Split,
2635 ContentStartColumn += ToSplitColumns + 1;
2636 Penalty += ExcessCharactersPenalty;
2638 RemainingTokenColumns = Token->getRemainingLength(
2639 LineIndex, TailOffset, ContentStartColumn);
2643 LLVM_DEBUG(llvm::dbgs() <<
" Breaking...\n");
2648 ContentIndent = Token->getContentIndent(LineIndex);
2649 LLVM_DEBUG(llvm::dbgs()
2650 <<
" ContentIndent: " << ContentIndent <<
"\n");
2651 ContentStartColumn = ContentIndent + Token->getContentStartColumn(
2654 unsigned NewRemainingTokenColumns = Token->getRemainingLength(
2655 LineIndex, TailOffset +
Split.first +
Split.second,
2656 ContentStartColumn);
2657 if (NewRemainingTokenColumns == 0) {
2660 ContentStartColumn =
2661 Token->getContentStartColumn(LineIndex,
true);
2662 NewRemainingTokenColumns = Token->getRemainingLength(
2663 LineIndex, TailOffset +
Split.first +
Split.second,
2664 ContentStartColumn);
2670 if (NewRemainingTokenColumns >= RemainingTokenColumns) {
2675 LLVM_DEBUG(llvm::dbgs() <<
" Breaking at: " << TailOffset +
Split.first
2676 <<
", " <<
Split.second <<
"\n");
2678 Token->insertBreak(LineIndex, TailOffset, Split, ContentIndent,
2682 Penalty += NewBreakPenalty;
2684 RemainingTokenColumns = NewRemainingTokenColumns;
2685 BreakInserted =
true;
2686 NewBreakBefore =
true;
2690 if (LineIndex + 1 != EndIndex) {
2691 unsigned NextLineIndex = LineIndex + 1;
2692 if (NewBreakBefore) {
2711 ContentStartColumn += RemainingTokenColumns + 1;
2716 Token->getReflowSplit(NextLineIndex, CommentPragmasRegex);
2717 LLVM_DEBUG(llvm::dbgs()
2718 <<
" Size of reflown text: " << ContentStartColumn
2719 <<
"\n Potential reflow split: ");
2720 if (SplitBeforeNext.first != StringRef::npos) {
2721 LLVM_DEBUG(llvm::dbgs() << SplitBeforeNext.first <<
", "
2722 << SplitBeforeNext.second <<
"\n");
2723 TailOffset = SplitBeforeNext.first + SplitBeforeNext.second;
2726 RemainingTokenColumns = Token->getRemainingLength(
2727 NextLineIndex, TailOffset, ContentStartColumn);
2729 if (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2730 LLVM_DEBUG(llvm::dbgs()
2731 <<
" Over limit after reflow, need: "
2732 << (ContentStartColumn + RemainingTokenColumns)
2733 <<
", space: " << ColumnLimit
2734 <<
", reflown prefix: " << ContentStartColumn
2735 <<
", offset in line: " << TailOffset <<
"\n");
2741 Token->getSplit(NextLineIndex, TailOffset, ColumnLimit,
2742 ContentStartColumn, CommentPragmasRegex);
2743 if (
Split.first == StringRef::npos) {
2744 LLVM_DEBUG(llvm::dbgs() <<
" Did not find later break\n");
2750 unsigned ToSplitColumns = Token->getRangeLength(
2751 NextLineIndex, TailOffset,
Split.first, ContentStartColumn);
2752 if (ContentStartColumn + ToSplitColumns > ColumnLimit) {
2753 LLVM_DEBUG(llvm::dbgs() <<
" Next split protrudes, need: "
2754 << (ContentStartColumn + ToSplitColumns)
2755 <<
", space: " << ColumnLimit);
2756 unsigned ExcessCharactersPenalty =
2757 (ContentStartColumn + ToSplitColumns - ColumnLimit) *
2759 if (NewBreakPenalty < ExcessCharactersPenalty)
2765 LLVM_DEBUG(llvm::dbgs() <<
"not found.\n");
2773 ContentStartColumn =
2774 Token->getContentStartColumn(NextLineIndex,
false);
2775 RemainingTokenColumns = Token->getRemainingLength(
2776 NextLineIndex, TailOffset, ContentStartColumn);
2779 Token->adaptStartOfLine(NextLineIndex, Whitespaces);
2794 if (NewBreakBefore) {
2795 assert(Penalty >= NewBreakPenalty);
2796 Penalty -= NewBreakPenalty;
2799 Token->reflow(NextLineIndex, Whitespaces);
2805 Token->getSplitAfterLastLine(TailOffset);
2806 if (SplitAfterLastLine.first != StringRef::npos) {
2807 LLVM_DEBUG(llvm::dbgs() <<
"Replacing whitespace after last line.\n");
2812 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2815 Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
2818 ContentStartColumn =
2819 Token->getContentStartColumn(Token->getLineCount() - 1,
true);
2820 RemainingTokenColumns = Token->getRemainingLength(
2821 Token->getLineCount() - 1,
2822 TailOffset + SplitAfterLastLine.first + SplitAfterLastLine.second,
2823 ContentStartColumn);
2826 State.Column = ContentStartColumn + RemainingTokenColumns -
2827 Current.UnbreakableTailLength;
2829 if (BreakInserted) {
2831 Token->updateAfterBroken(Whitespaces);
2836 if (Current.isNot(TT_LineComment))
2837 for (ParenState &
Paren : State.Stack)
2838 Paren.BreakBeforeParameter =
true;
2840 if (Current.is(TT_BlockComment))
2841 State.NoContinuation =
true;
2843 State.Stack.back().LastSpace = StartColumn;
2846 Token->updateNextToken(State);
2848 return {Penalty, Exceeded};
2853 return Style.
ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
2856bool ContinuationIndenter::nextIsMultilineString(
const LineState &State) {
2858 if (!Current.isStringLiteral() || Current.is(TT_ImplicitStringLiteral))
2863 if (Current.TokenText.starts_with(
"R\""))
2865 if (Current.IsMultiline)
2867 if (Current.getNextNonComment() &&
2868 Current.getNextNonComment()->isStringLiteral()) {
2872 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
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