23#include "llvm/ADT/StringSet.h"
24#include "llvm/Support/Debug.h"
27#define DEBUG_TYPE "format-indenter"
85 int MatchingStackIndex = Stack.size() - 1;
91 while (MatchingStackIndex >= 0 && Stack[MatchingStackIndex].Tok != LBrace)
93 return MatchingStackIndex >= 0 ? &Stack[MatchingStackIndex] :
nullptr;
95 for (; End->Next; End = End->Next) {
96 if (End->Next->CanBreakBefore)
98 if (!End->Next->closesScope())
100 if (End->Next->MatchingParen &&
101 End->Next->MatchingParen->isOneOf(
102 tok::l_brace, TT_ArrayInitializerLSquare, tok::less)) {
103 const ParenState *State = FindParenState(End->Next->MatchingParen);
104 if (State && State->BreakBeforeClosingBrace)
127 if (Current.
is(TT_CtorInitializerComma) &&
134 ((
Previous.isNot(TT_CtorInitializerComma) ||
137 (
Previous.isNot(TT_InheritanceComma) ||
143 if (LessTok.
isNot(tok::less))
155 if (TokenText.size() < 5
156 || !TokenText.startswith(
"R\"") || !TokenText.endswith(
"\"")) {
163 size_t LParenPos = TokenText.substr(0, 19).find_first_of(
'(');
164 if (LParenPos == StringRef::npos)
166 StringRef Delimiter = TokenText.substr(2, LParenPos - 2);
169 size_t RParenPos = TokenText.size() - Delimiter.size() - 2;
170 if (TokenText[RParenPos] !=
')')
172 if (!TokenText.substr(RParenPos + 1).startswith(Delimiter))
184 return StringRef(Format.CanonicalDelimiter);
191 std::optional<FormatStyle> LanguageStyle =
193 if (!LanguageStyle) {
196 RawStringFormat.Language, &PredefinedStyle)) {
198 PredefinedStyle.
Language = RawStringFormat.Language;
200 LanguageStyle = PredefinedStyle;
203 for (StringRef Delimiter : RawStringFormat.Delimiters)
205 for (StringRef EnclosingFunction : RawStringFormat.EnclosingFunctions)
210std::optional<FormatStyle>
218std::optional<FormatStyle>
220 StringRef EnclosingFunction)
const {
232 bool BinPackInconclusiveFunctions)
233 : Style(Style), Keywords(Keywords), SourceMgr(SourceMgr),
234 Whitespaces(Whitespaces), Encoding(Encoding),
235 BinPackInconclusiveFunctions(BinPackInconclusiveFunctions),
236 CommentPragmasRegex(Style.CommentPragmas), RawStringFormats(Style) {}
239 unsigned FirstStartColumn,
243 State.FirstIndent = FirstIndent;
244 if (FirstStartColumn && Line->First->NewlinesBefore == 0)
245 State.Column = FirstStartColumn;
247 State.Column = FirstIndent;
257 State.NextToken = Line->First;
258 State.Stack.push_back(
ParenState(
nullptr, FirstIndent, FirstIndent,
261 State.NoContinuation =
false;
262 State.StartOfStringLiteral = 0;
263 State.StartOfLineLevel = 0;
264 State.LowestLevelOnLine = 0;
265 State.IgnoreStackForComparison =
false;
270 auto &CurrentState = State.Stack.back();
271 CurrentState.AvoidBinPacking =
true;
272 CurrentState.BreakBeforeParameter =
true;
273 CurrentState.AlignColons =
false;
277 moveStateToNextToken(State, DryRun,
false);
284 const auto &CurrentState = State.Stack.back();
285 assert(&
Previous == Current.Previous);
286 if (!Current.CanBreakBefore && !(CurrentState.BreakBeforeClosingBrace &&
287 Current.closesBlockOrBlockTypeList(Style))) {
292 if (!Current.MustBreakBefore &&
Previous.is(tok::l_brace) &&
295 Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma)) {
304 State.LowestLevelOnLine < State.StartOfLineLevel &&
305 State.LowestLevelOnLine < Current.NestingLevel) {
308 if (Current.isMemberAccess() && CurrentState.ContainsUnwrappedBuilder)
313 if (
Previous.is(tok::l_brace) && State.Stack.size() > 1 &&
314 State.Stack[State.Stack.size() - 2].NestedBlockInlined &&
315 State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks) {
321 if (Current.is(TT_FunctionDeclarationName) && State.Column < 6) {
328 if (!Current.isOneOf(TT_BinaryOperator, tok::comma) &&
329 CurrentState.NoLineBreakInOperand) {
336 if (Current.is(TT_ConditionalExpr) &&
Previous.is(tok::r_paren) &&
338 Previous.MatchingParen->Previous->MatchingParen &&
339 Previous.MatchingParen->Previous->MatchingParen->is(TT_LambdaLBrace)) {
341 assert(
Previous.MatchingParen->Previous->is(tok::r_brace));
345 return !CurrentState.NoLineBreak;
351 const auto &CurrentState = State.Stack.back();
353 Current.is(TT_LambdaLBrace) &&
Previous.isNot(TT_LineComment)) {
357 if (Current.MustBreakBefore ||
358 (Current.is(TT_InlineASMColon) &&
363 if (CurrentState.BreakBeforeClosingBrace &&
364 Current.closesBlockOrBlockTypeList(Style)) {
367 if (CurrentState.BreakBeforeClosingParen && Current.is(tok::r_paren))
371 Current.ObjCSelectorNameParts > 1 &&
372 Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)) {
377 if (CurrentState.IsCSharpGenericTypeConstraint &&
378 Previous.isNot(TT_CSharpGenericTypeConstraintComma)) {
382 (
Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) &&
392 Previous.is(TT_ConditionalExpr))) &&
393 CurrentState.BreakBeforeParameter && !Current.isTrailingComment() &&
394 !Current.isOneOf(tok::r_paren, tok::r_brace)) {
397 if (CurrentState.IsChainedConditional &&
399 Current.is(tok::colon)) ||
405 (
Previous.is(TT_ArrayInitializerLSquare) &&
414 const FormatToken &BreakConstructorInitializersToken =
418 if (BreakConstructorInitializersToken.
is(TT_CtorInitializerColon) &&
419 (State.Column + State.Line->Last->TotalLength -
Previous.TotalLength >
421 CurrentState.BreakBeforeParameter) &&
422 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
429 if (Current.is(TT_ObjCMethodExpr) && !
Previous.is(TT_SelectorName) &&
430 State.Line->startsWith(TT_ObjCMethodSpecifier)) {
433 if (Current.is(TT_SelectorName) && !
Previous.is(tok::at) &&
434 CurrentState.ObjCSelectorNameFound && CurrentState.BreakBeforeParameter &&
436 !Current.startsSequence(TT_SelectorName, tok::colon, tok::caret))) {
440 unsigned NewLineColumn = getNewLineColumn(State);
441 if (Current.isMemberAccess() && Style.
ColumnLimit != 0 &&
443 (State.Column > NewLineColumn ||
444 Current.NestingLevel < State.StartOfLineLevel)) {
449 (CurrentState.CallContinuation != 0 ||
450 CurrentState.BreakBeforeParameter) &&
456 !(State.Column <= NewLineColumn && Style.
isJavaScript()) &&
457 !(
Previous.closesScopeAfterBlock() && State.Column <= NewLineColumn)) {
463 if (
Previous.ClosesTemplateDeclaration && CurrentState.BreakBeforeParameter &&
464 Current.CanBreakBefore) {
468 if (!State.Line->First->is(tok::kw_enum) && State.Column <= NewLineColumn)
473 Previous.is(tok::comma) || Current.NestingLevel < 2) &&
474 !
Previous.isOneOf(tok::kw_return, tok::lessless, tok::at,
476 !
Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
477 nextIsMultilineString(State)) {
484 if (
Previous.is(TT_BinaryOperator) && Current.CanBreakBefore) {
485 const auto PreviousPrecedence =
Previous.getPrecedence();
487 CurrentState.BreakBeforeParameter && !Current.isTrailingComment()) {
488 const bool LHSIsBinaryExpr =
501 const bool IsComparison =
506 Previous.Previous->isNot(TT_BinaryOperator);
510 }
else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore &&
511 CurrentState.BreakBeforeParameter) {
516 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator) &&
517 CurrentState.BreakBeforeParameter && CurrentState.FirstLessLess == 0) {
521 if (Current.NestingLevel == 0 && !Current.isTrailingComment()) {
526 if (
Previous.ClosesTemplateDeclaration) {
527 if (Current.is(tok::kw_concept)) {
537 if (Current.is(TT_RequiresClause)) {
548 if (
Previous.is(TT_FunctionAnnotationRParen) &&
552 if (
Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) &&
553 Current.isNot(TT_LeadingJavaAnnotation)) {
562 static const llvm::StringSet<> BreakBeforeDecoratedTokens = {
"get",
"set",
564 if (BreakBeforeDecoratedTokens.contains(Current.TokenText))
569 if (((Current.is(TT_FunctionDeclarationName) &&
570 !State.Line->ReturnTypeWrapped &&
577 (Current.is(tok::kw_operator) && !
Previous.is(tok::coloncolon))) &&
578 !
Previous.is(tok::kw_template) && CurrentState.BreakBeforeParameter) {
587 !Current.isOneOf(tok::r_brace, tok::comment)) {
591 if (Current.is(tok::lessless) &&
594 Previous.TokenText ==
"\'\\n\'")))) {
601 if (State.NoContinuation)
609 unsigned ExtraSpaces) {
611 assert(State.NextToken->Previous);
614 assert(!State.Stack.empty());
615 State.NoContinuation =
false;
617 if ((Current.is(TT_ImplicitStringLiteral) &&
618 (!
Previous.Tok.getIdentifierInfo() ||
619 Previous.Tok.getIdentifierInfo()->getPPKeywordID() ==
620 tok::pp_not_keyword))) {
623 if (Current.LastNewlineOffset != 0) {
626 State.Column = EndColumn;
628 unsigned StartColumn =
630 assert(EndColumn >= StartColumn);
631 State.Column += EndColumn - StartColumn;
633 moveStateToNextToken(State, DryRun,
false);
637 unsigned Penalty = 0;
639 Penalty = addTokenOnNewLine(State, DryRun);
641 addTokenOnCurrentLine(State, DryRun, ExtraSpaces);
643 return moveStateToNextToken(State, DryRun, Newline) + Penalty;
646void ContinuationIndenter::addTokenOnCurrentLine(
LineState &State,
bool DryRun,
647 unsigned ExtraSpaces) {
649 assert(State.NextToken->Previous);
651 auto &CurrentState = State.Stack.back();
653 if (Current.is(tok::equal) &&
654 (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&
655 CurrentState.VariablePos == 0) {
656 CurrentState.VariablePos = State.Column;
659 while (Tok && CurrentState.VariablePos >= Tok->
ColumnWidth) {
665 if (
Previous.PartOfMultiVariableDeclStmt)
666 CurrentState.LastSpace = CurrentState.VariablePos;
669 unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces;
672 int PPColumnCorrection = 0;
674 Previous.is(tok::hash) && State.FirstIndent > 0 &&
678 Spaces += State.FirstIndent;
685 PPColumnCorrection = -1;
690 State.Column + Spaces + PPColumnCorrection);
696 Current.is(TT_InheritanceColon)) {
697 CurrentState.NoLineBreak =
true;
701 CurrentState.NoLineBreak =
true;
704 if (Current.is(TT_SelectorName) && !CurrentState.ObjCSelectorNameFound) {
705 unsigned MinIndent = std::max(
707 unsigned FirstColonPos = State.Column + Spaces + Current.ColumnWidth;
708 if (Current.LongestObjCSelectorName == 0)
709 CurrentState.AlignColons =
false;
710 else if (MinIndent + Current.LongestObjCSelectorName > FirstColonPos)
711 CurrentState.ColonPos = MinIndent + Current.LongestObjCSelectorName;
713 CurrentState.ColonPos = FirstColonPos;
722 (
Previous.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) ||
725 State.Column > getNewLineColumn(State) &&
727 !
Previous.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while,
736 Current.FakeLParens.size() > 0 &&
738 CurrentState.NoLineBreak =
true;
741 CurrentState.NoLineBreak =
true;
748 !CurrentState.IsCSharpGenericTypeConstraint &&
Previous.opensScope() &&
750 !(Current.MacroParent &&
Previous.MacroParent) &&
752 CurrentState.Indent = State.Column + Spaces;
753 CurrentState.IsAligned =
true;
756 CurrentState.NoLineBreak =
true;
758 State.Column > getNewLineColumn(State)) {
759 CurrentState.ContainsUnwrappedBuilder =
true;
763 CurrentState.NoLineBreak =
true;
764 if (Current.isMemberAccess() &&
Previous.is(tok::r_paren) &&
773 CurrentState.NoLineBreak =
true;
780 const FormatToken *
P = Current.getPreviousNonComment();
781 if (!Current.is(tok::comment) &&
P &&
782 (
P->isOneOf(TT_BinaryOperator, tok::comma) ||
783 (
P->is(TT_ConditionalExpr) &&
P->is(tok::colon))) &&
784 !
P->isOneOf(TT_OverloadedOperator, TT_CtorInitializerComma) &&
788 bool BreakBeforeOperator =
789 P->MustBreakBefore ||
P->is(tok::lessless) ||
790 (
P->is(TT_BinaryOperator) &&
796 bool HasTwoOperands =
797 P->OperatorIndex == 0 && !
P->NextOperator && !
P->is(TT_ConditionalExpr);
798 if ((!BreakBeforeOperator &&
801 (!CurrentState.LastOperatorWrapped && BreakBeforeOperator)) {
802 CurrentState.NoLineBreakInOperand =
true;
806 State.Column += Spaces;
807 if (Current.isNot(tok::comment) &&
Previous.is(tok::l_paren) &&
812 CurrentState.LastSpace = State.Column;
813 CurrentState.NestedBlockIndent = State.Column;
814 }
else if (!Current.isOneOf(tok::comment, tok::caret) &&
816 !
Previous.is(TT_OverloadedOperator)) ||
818 CurrentState.LastSpace = State.Column;
819 }
else if (
Previous.is(TT_CtorInitializerColon) &&
820 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
823 CurrentState.Indent = State.Column;
824 CurrentState.LastSpace = State.Column;
825 }
else if ((
Previous.isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
826 TT_CtorInitializerColon)) &&
830 Current.StartsBinaryExpression)) {
835 CurrentState.LastSpace = State.Column;
836 }
else if (
Previous.is(TT_InheritanceColon)) {
837 CurrentState.Indent = State.Column;
838 CurrentState.LastSpace = State.Column;
839 }
else if (Current.is(TT_CSharpGenericTypeConstraintColon)) {
840 CurrentState.ColonPos = State.Column;
848 const FormatToken *Next =
Previous.MatchingParen->getNextNonComment();
849 if (Next && Next->isMemberAccess() && State.Stack.size() > 1 &&
850 State.Stack[State.Stack.size() - 2].CallContinuation == 0) {
851 CurrentState.LastSpace = State.Column;
857unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
859 FormatToken &Current = *State.NextToken;
860 assert(State.NextToken->Previous);
861 const FormatToken &
Previous = *State.NextToken->Previous;
862 auto &CurrentState = State.Stack.back();
866 unsigned Penalty = 0;
868 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
869 const FormatToken *NextNonComment =
Previous.getNextNonComment();
871 NextNonComment = &Current;
874 if (!CurrentState.ContainsLineBreak)
876 CurrentState.ContainsLineBreak =
true;
878 Penalty += State.NextToken->SplitPenalty;
883 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess == 0 &&
885 CurrentState.BreakBeforeParameter)) {
889 State.Column = getNewLineColumn(State);
903 if (State.Column > State.FirstIndent) {
918 if (!Current.is(TT_LambdaArrow) &&
920 !PreviousNonComment || !PreviousNonComment->is(tok::equal) ||
922 CurrentState.NestedBlockIndent = State.Column;
925 if (NextNonComment->isMemberAccess()) {
926 if (CurrentState.CallContinuation == 0)
927 CurrentState.CallContinuation = State.Column;
928 }
else if (NextNonComment->is(TT_SelectorName)) {
929 if (!CurrentState.ObjCSelectorNameFound) {
930 if (NextNonComment->LongestObjCSelectorName == 0) {
931 CurrentState.AlignColons =
false;
933 CurrentState.ColonPos =
935 ? std::max(CurrentState.Indent,
937 : CurrentState.Indent) +
939 NextNonComment->ColumnWidth);
941 }
else if (CurrentState.AlignColons &&
942 CurrentState.ColonPos <= NextNonComment->ColumnWidth) {
943 CurrentState.ColonPos = State.Column + NextNonComment->ColumnWidth;
945 }
else if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
946 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
956 if (State.Stack.size() > 1) {
957 State.Stack[State.Stack.size() - 2].LastSpace =
958 std::max(CurrentState.LastSpace, CurrentState.Indent) +
963 if ((PreviousNonComment &&
964 PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
965 !CurrentState.AvoidBinPacking) ||
967 CurrentState.BreakBeforeParameter =
false;
969 if (PreviousNonComment &&
970 (PreviousNonComment->isOneOf(TT_TemplateCloser, TT_JavaAnnotation) ||
971 PreviousNonComment->ClosesRequiresClause) &&
972 Current.NestingLevel == 0) {
973 CurrentState.BreakBeforeParameter =
false;
975 if (NextNonComment->is(tok::question) ||
976 (PreviousNonComment && PreviousNonComment->is(tok::question))) {
977 CurrentState.BreakBeforeParameter =
true;
979 if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore)
980 CurrentState.BreakBeforeParameter =
false;
984 if (Current.is(tok::r_brace) && Current.MatchingParen &&
987 !Current.MatchingParen->Children.empty()) {
991 MaxEmptyLinesToKeep = 1;
994 std::max(1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
995 bool ContinuePPDirective =
998 CurrentState.IsAligned, ContinuePPDirective);
1001 if (!Current.isTrailingComment())
1002 CurrentState.LastSpace = State.Column;
1003 if (Current.is(tok::lessless)) {
1007 CurrentState.LastSpace += 3;
1010 State.StartOfLineLevel = Current.NestingLevel;
1011 State.LowestLevelOnLine = Current.NestingLevel;
1015 bool NestedBlockSpecialCase =
1016 (!Style.
isCpp() && Current.is(tok::r_brace) && State.Stack.size() > 1 &&
1017 State.Stack[State.Stack.size() - 2].NestedBlockInlined) ||
1021 NestedBlockSpecialCase =
1022 NestedBlockSpecialCase ||
1023 (Current.MatchingParen &&
1024 Current.MatchingParen->is(TT_RequiresExpressionLBrace));
1025 if (!NestedBlockSpecialCase)
1026 for (ParenState &PState : llvm::drop_end(State.Stack))
1027 PState.BreakBeforeParameter =
true;
1029 if (PreviousNonComment &&
1030 !PreviousNonComment->isOneOf(tok::comma, tok::colon, tok::semi) &&
1031 ((PreviousNonComment->isNot(TT_TemplateCloser) &&
1032 !PreviousNonComment->ClosesRequiresClause) ||
1033 Current.NestingLevel != 0) &&
1034 !PreviousNonComment->isOneOf(
1035 TT_BinaryOperator, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
1036 TT_LeadingJavaAnnotation) &&
1037 Current.isNot(TT_BinaryOperator) && !PreviousNonComment->opensScope()) {
1038 CurrentState.BreakBeforeParameter =
true;
1043 if (PreviousNonComment &&
1044 (PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1046 CurrentState.BreakBeforeClosingBrace =
true;
1049 if (PreviousNonComment && PreviousNonComment->is(tok::l_paren)) {
1050 CurrentState.BreakBeforeClosingParen =
1054 if (CurrentState.AvoidBinPacking) {
1059 bool PreviousIsBreakingCtorInitializerColon =
1060 PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1062 bool AllowAllConstructorInitializersOnNextLine =
1065 if (!(
Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
1066 PreviousIsBreakingCtorInitializerColon) ||
1068 State.Line->MustBeDeclaration) ||
1070 !State.Line->MustBeDeclaration) ||
1071 (!AllowAllConstructorInitializersOnNextLine &&
1072 PreviousIsBreakingCtorInitializerColon) ||
1074 CurrentState.BreakBeforeParameter =
true;
1080 if (PreviousIsBreakingCtorInitializerColon &&
1081 AllowAllConstructorInitializersOnNextLine) {
1082 CurrentState.BreakBeforeParameter =
false;
1089unsigned ContinuationIndenter::getNewLineColumn(
const LineState &State) {
1090 if (!State.NextToken || !State.NextToken->Previous)
1093 FormatToken &Current = *State.NextToken;
1094 const auto &CurrentState = State.Stack.back();
1096 if (CurrentState.IsCSharpGenericTypeConstraint &&
1097 Current.isNot(TT_CSharpGenericTypeConstraint)) {
1098 return CurrentState.ColonPos + 2;
1101 const FormatToken &
Previous = *Current.Previous;
1103 unsigned ContinuationIndent =
1104 std::max(CurrentState.LastSpace, CurrentState.Indent) +
1106 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
1107 const FormatToken *NextNonComment =
Previous.getNextNonComment();
1108 if (!NextNonComment)
1109 NextNonComment = &Current;
1114 return std::max(CurrentState.LastSpace,
1123 State.Line->First->is(tok::kw_enum))) {
1124 return (Style.
IndentWidth * State.Line->First->IndentLevel) +
1128 if (NextNonComment->is(tok::l_brace) && NextNonComment->is(
BK_Block))
1129 return Current.NestingLevel == 0 ? State.FirstIndent : CurrentState.Indent;
1130 if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
1131 (Current.is(tok::greater) &&
1134 State.Stack.size() > 1) {
1135 if (Current.closesBlockOrBlockTypeList(Style))
1136 return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
1137 if (Current.MatchingParen && Current.MatchingParen->is(
BK_BracedInit))
1138 return State.Stack[State.Stack.size() - 2].LastSpace;
1139 return State.FirstIndent;
1156 if (Current.is(tok::r_paren) && State.Stack.size() > 1 &&
1158 Current.Next->isOneOf(tok::semi, tok::kw_const, tok::l_brace))) {
1159 return State.Stack[State.Stack.size() - 2].LastSpace;
1162 Current.is(tok::r_paren) && State.Stack.size() > 1) {
1163 return State.Stack[State.Stack.size() - 2].LastSpace;
1165 if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
1166 return State.Stack[State.Stack.size() - 2].LastSpace;
1167 if (Current.is(tok::identifier) && Current.Next &&
1168 (Current.Next->is(TT_DictLiteral) ||
1171 Current.Next->isOneOf(tok::less, tok::l_brace)))) {
1172 return CurrentState.Indent;
1174 if (NextNonComment->is(TT_ObjCStringLiteral) &&
1175 State.StartOfStringLiteral != 0) {
1176 return State.StartOfStringLiteral - 1;
1178 if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0)
1179 return State.StartOfStringLiteral;
1180 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess != 0)
1181 return CurrentState.FirstLessLess;
1182 if (NextNonComment->isMemberAccess()) {
1183 if (CurrentState.CallContinuation == 0)
1184 return ContinuationIndent;
1185 return CurrentState.CallContinuation;
1187 if (CurrentState.QuestionColumn != 0 &&
1188 ((NextNonComment->is(tok::colon) &&
1189 NextNonComment->is(TT_ConditionalExpr)) ||
1190 Previous.is(TT_ConditionalExpr))) {
1191 if (((NextNonComment->is(tok::colon) && NextNonComment->Next &&
1192 !NextNonComment->Next->FakeLParens.empty() &&
1194 (
Previous.is(tok::colon) && !Current.FakeLParens.empty() &&
1196 !CurrentState.IsWrappedConditional) {
1201 unsigned Indent = CurrentState.Indent;
1208 return CurrentState.QuestionColumn;
1210 if (
Previous.is(tok::comma) && CurrentState.VariablePos != 0)
1211 return CurrentState.VariablePos;
1212 if (Current.is(TT_RequiresClause)) {
1218 return CurrentState.Indent;
1223 if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
1224 TT_InheritanceComma)) {
1227 if ((PreviousNonComment &&
1228 (PreviousNonComment->ClosesTemplateDeclaration ||
1229 PreviousNonComment->ClosesRequiresClause ||
1230 PreviousNonComment->isOneOf(
1231 TT_AttributeParen, TT_AttributeSquare, TT_FunctionAnnotationRParen,
1232 TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
1234 NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName))) {
1235 return std::max(CurrentState.LastSpace, CurrentState.Indent);
1237 if (NextNonComment->is(TT_SelectorName)) {
1238 if (!CurrentState.ObjCSelectorNameFound) {
1239 unsigned MinIndent = CurrentState.Indent;
1241 MinIndent = std::max(MinIndent,
1254 std::max(NextNonComment->LongestObjCSelectorName,
1255 NextNonComment->ColumnWidth) -
1256 NextNonComment->ColumnWidth;
1258 if (!CurrentState.AlignColons)
1259 return CurrentState.Indent;
1260 if (CurrentState.ColonPos > NextNonComment->ColumnWidth)
1261 return CurrentState.ColonPos - NextNonComment->ColumnWidth;
1262 return CurrentState.Indent;
1264 if (NextNonComment->is(tok::colon) && NextNonComment->is(TT_ObjCMethodExpr))
1265 return CurrentState.ColonPos;
1266 if (NextNonComment->is(TT_ArraySubscriptLSquare)) {
1267 if (CurrentState.StartOfArraySubscripts != 0) {
1268 return CurrentState.StartOfArraySubscripts;
1271 return CurrentState.Indent;
1273 return ContinuationIndent;
1278 if (State.Line->InPragmaDirective) {
1279 FormatToken *PragmaType = State.Line->First->Next->Next;
1280 if (PragmaType && PragmaType->TokenText.equals(
"omp"))
1286 if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 &&
1287 NextNonComment->Next && NextNonComment->Next->is(TT_ObjCMethodExpr)) {
1288 return CurrentState.Indent;
1291 if (NextNonComment->isOneOf(TT_StartOfName, TT_PointerOrReference) ||
1292 Previous.isOneOf(tok::coloncolon, tok::equal, TT_JsTypeColon)) {
1293 return ContinuationIndent;
1295 if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
1296 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
1297 return ContinuationIndent;
1299 if (NextNonComment->is(TT_CtorInitializerComma))
1300 return CurrentState.Indent;
1301 if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1303 return CurrentState.Indent;
1305 if (PreviousNonComment && PreviousNonComment->is(TT_InheritanceColon) &&
1307 return CurrentState.Indent;
1309 if (
Previous.is(tok::r_paren) && !Current.isBinaryOperator() &&
1310 !Current.isOneOf(tok::colon, tok::comment)) {
1311 return ContinuationIndent;
1313 if (Current.is(TT_ProtoExtensionLSquare))
1314 return CurrentState.Indent;
1315 if (Current.isBinaryOperator() && CurrentState.UnindentOperator) {
1316 return CurrentState.Indent - Current.Tok.getLength() -
1317 Current.SpacesRequiredBefore;
1319 if (Current.isOneOf(tok::comment, TT_BlockComment, TT_LineComment) &&
1320 NextNonComment->isBinaryOperator() && CurrentState.UnindentOperator) {
1321 return CurrentState.Indent - NextNonComment->Tok.getLength() -
1322 NextNonComment->SpacesRequiredBefore;
1324 if (CurrentState.Indent == State.FirstIndent && PreviousNonComment &&
1325 !PreviousNonComment->isOneOf(tok::r_brace, TT_CtorInitializerComma)) {
1330 return CurrentState.Indent;
1345unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
1346 bool DryRun,
bool Newline) {
1347 assert(State.Stack.size());
1348 const FormatToken &Current = *State.NextToken;
1349 auto &CurrentState = State.Stack.back();
1351 if (Current.is(TT_CSharpGenericTypeConstraint))
1352 CurrentState.IsCSharpGenericTypeConstraint =
true;
1353 if (Current.isOneOf(tok::comma, TT_BinaryOperator))
1354 CurrentState.NoLineBreakInOperand =
false;
1355 if (Current.isOneOf(TT_InheritanceColon, TT_CSharpGenericTypeConstraintColon))
1356 CurrentState.AvoidBinPacking =
true;
1357 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator)) {
1358 if (CurrentState.FirstLessLess == 0)
1359 CurrentState.FirstLessLess = State.Column;
1361 CurrentState.LastOperatorWrapped = Newline;
1363 if (Current.is(TT_BinaryOperator) && Current.isNot(tok::lessless))
1364 CurrentState.LastOperatorWrapped = Newline;
1365 if (Current.is(TT_ConditionalExpr) && Current.Previous &&
1366 !Current.Previous->is(TT_ConditionalExpr)) {
1367 CurrentState.LastOperatorWrapped = Newline;
1369 if (Current.is(TT_ArraySubscriptLSquare) &&
1370 CurrentState.StartOfArraySubscripts == 0) {
1371 CurrentState.StartOfArraySubscripts = State.Column;
1374 auto IsWrappedConditional = [](
const FormatToken &Tok) {
1375 if (!(Tok.
is(TT_ConditionalExpr) && Tok.
is(tok::question)))
1381 return Next && Next->MustBreakBefore;
1383 if (IsWrappedConditional(Current))
1384 CurrentState.IsWrappedConditional =
true;
1386 CurrentState.QuestionColumn = State.Column;
1388 const FormatToken *
Previous = Current.Previous;
1392 CurrentState.QuestionColumn = State.Column;
1394 if (!Current.opensScope() && !Current.closesScope() &&
1395 !Current.is(TT_PointerOrReference)) {
1396 State.LowestLevelOnLine =
1397 std::min(State.LowestLevelOnLine, Current.NestingLevel);
1399 if (Current.isMemberAccess())
1400 CurrentState.StartOfFunctionCall = !Current.NextOperator ? 0 : State.Column;
1401 if (Current.is(TT_SelectorName))
1402 CurrentState.ObjCSelectorNameFound =
true;
1403 if (Current.is(TT_CtorInitializerColon) &&
1414 CurrentState.NestedBlockIndent = CurrentState.Indent;
1416 CurrentState.AvoidBinPacking =
true;
1417 CurrentState.BreakBeforeParameter =
1421 CurrentState.BreakBeforeParameter =
false;
1424 if (Current.is(TT_CtorInitializerColon) &&
1426 CurrentState.Indent =
1428 CurrentState.NestedBlockIndent = CurrentState.Indent;
1430 CurrentState.AvoidBinPacking =
true;
1432 if (Current.is(TT_InheritanceColon)) {
1433 CurrentState.Indent =
1436 if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
1437 CurrentState.NestedBlockIndent = State.Column + Current.ColumnWidth + 1;
1438 if (Current.isOneOf(TT_LambdaLSquare, TT_LambdaArrow))
1439 CurrentState.LastSpace = State.Column;
1440 if (Current.is(TT_RequiresExpression) &&
1442 CurrentState.NestedBlockIndent = State.Column;
1446 const FormatToken *
Previous = Current.getPreviousNonComment();
1454 if (Current.isNot(tok::comment) && !Current.ClosesRequiresClause &&
1456 !
Previous->is(TT_DictLiteral) && State.Stack.size() > 1 &&
1457 !CurrentState.HasMultipleNestedBlocks) {
1458 if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
1459 for (ParenState &PState : llvm::drop_end(State.Stack))
1460 PState.NoLineBreak =
true;
1461 State.Stack[State.Stack.size() - 2].NestedBlockInlined =
false;
1463 if (
Previous && (
Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr) ||
1464 (
Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) &&
1465 !
Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)))) {
1466 CurrentState.NestedBlockInlined =
1470 moveStatePastFakeLParens(State, Newline);
1471 moveStatePastScopeCloser(State);
1474 bool AllowBreak = !State.Stack.back().NoLineBreak &&
1475 !State.Stack.back().NoLineBreakInOperand;
1476 moveStatePastScopeOpener(State, Newline);
1477 moveStatePastFakeRParens(State);
1479 if (Current.is(TT_ObjCStringLiteral) && State.StartOfStringLiteral == 0)
1480 State.StartOfStringLiteral = State.Column + 1;
1481 if (Current.is(TT_CSharpStringLiteral) && State.StartOfStringLiteral == 0) {
1482 State.StartOfStringLiteral = State.Column + 1;
1483 }
else if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
1484 State.StartOfStringLiteral = State.Column;
1485 }
else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
1486 !Current.isStringLiteral()) {
1487 State.StartOfStringLiteral = 0;
1490 State.Column += Current.ColumnWidth;
1491 State.NextToken = State.NextToken->Next;
1494 handleEndOfLine(Current, State, DryRun, AllowBreak, Newline);
1497 Current.Role->formatFromToken(State,
this, DryRun);
1504 Penalty +=
Previous->Role->formatAfterToken(State,
this, DryRun);
1509void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
1511 const FormatToken &Current = *State.NextToken;
1512 if (Current.FakeLParens.empty())
1515 const FormatToken *
Previous = Current.getPreviousNonComment();
1520 bool SkipFirstExtraIndent =
1523 Previous->isOneOf(tok::semi, tok::kw_return, TT_RequiresClause) ||
1527 for (
const auto &PrecedenceLevel : llvm::reverse(Current.FakeLParens)) {
1528 const auto &CurrentState = State.Stack.back();
1529 ParenState NewParenState = CurrentState;
1530 NewParenState.Tok =
nullptr;
1531 NewParenState.ContainsLineBreak =
false;
1532 NewParenState.LastOperatorWrapped =
true;
1533 NewParenState.IsChainedConditional =
false;
1534 NewParenState.IsWrappedConditional =
false;
1535 NewParenState.UnindentOperator =
false;
1536 NewParenState.NoLineBreak =
1537 NewParenState.NoLineBreak || CurrentState.NoLineBreakInOperand;
1541 NewParenState.AvoidBinPacking =
false;
1546 if (!Current.isTrailingComment() &&
1552 PrecedenceLevel !=
prec::Comma || Current.NestingLevel == 0)) {
1553 NewParenState.Indent = std::max(
1554 std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
1561 NewParenState.Indent = CurrentState.LastSpace;
1565 Previous->isOneOf(tok::kw_return, TT_RequiresClause) ||
1567 Previous->is(TT_ConditionalExpr))) &&
1572 NewParenState.UnindentOperator =
true;
1575 NewParenState.IsAligned =
true;
1585 NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
1588 NewParenState.StartOfFunctionCall = State.Column;
1598 &PrecedenceLevel == &Current.FakeLParens.back() &&
1599 !CurrentState.IsWrappedConditional) {
1600 NewParenState.IsChainedConditional =
true;
1601 NewParenState.UnindentOperator = State.Stack.back().UnindentOperator;
1604 !Current.isTrailingComment())) {
1608 NewParenState.BreakBeforeParameter =
false;
1609 State.Stack.push_back(NewParenState);
1610 SkipFirstExtraIndent =
false;
1614void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
1615 for (
unsigned i = 0, e = State.NextToken->FakeRParens; i != e; ++i) {
1616 unsigned VariablePos = State.Stack.back().VariablePos;
1617 if (State.Stack.size() == 1) {
1621 State.Stack.pop_back();
1622 State.Stack.back().VariablePos = VariablePos;
1628 State.Stack.back().LastSpace -= Style.
IndentWidth;
1632void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
1634 const FormatToken &Current = *State.NextToken;
1635 if (!Current.opensScope())
1638 const auto &CurrentState = State.Stack.back();
1641 if (Current.isOneOf(tok::less, tok::l_paren) &&
1642 CurrentState.IsCSharpGenericTypeConstraint) {
1646 if (Current.MatchingParen && Current.is(
BK_Block)) {
1647 moveStateToNewBlock(State);
1652 unsigned LastSpace = CurrentState.LastSpace;
1653 bool AvoidBinPacking;
1654 bool BreakBeforeParameter =
false;
1655 unsigned NestedBlockIndent = std::max(CurrentState.StartOfFunctionCall,
1656 CurrentState.NestedBlockIndent);
1657 if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1659 if (Current.opensBlockOrBlockTypeList(Style)) {
1661 std::min(State.Column, CurrentState.NestedBlockIndent);
1665 const FormatToken *NextNoComment = Current.getNextNonComment();
1666 bool EndsInComma = Current.MatchingParen &&
1667 Current.MatchingParen->Previous &&
1668 Current.MatchingParen->Previous->is(tok::comma);
1669 AvoidBinPacking = EndsInComma || Current.is(TT_DictLiteral) ||
1674 NextNoComment->isOneOf(TT_DesignatedInitializerPeriod,
1675 TT_DesignatedInitializerLSquare));
1676 BreakBeforeParameter = EndsInComma;
1677 if (Current.ParameterCount > 1)
1678 NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
1682 std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall);
1688 if (Current.is(tok::less) && Current.ParentBracket == tok::l_paren) {
1689 NewIndent = std::max(NewIndent, CurrentState.Indent);
1690 LastSpace = std::max(LastSpace, CurrentState.Indent);
1694 Current.MatchingParen &&
1695 Current.MatchingParen->getPreviousNonComment() &&
1696 Current.MatchingParen->getPreviousNonComment()->is(tok::comma);
1700 bool ObjCBinPackProtocolList =
1705 bool BinPackDeclaration =
1707 (State.Line->Type ==
LT_ObjCDecl && ObjCBinPackProtocolList);
1709 bool GenericSelection =
1710 Current.getPreviousNonComment() &&
1711 Current.getPreviousNonComment()->is(tok::kw__Generic);
1714 (CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection ||
1716 (State.Line->MustBeDeclaration && !BinPackDeclaration) ||
1722 if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen &&
1729 BreakBeforeParameter =
true;
1734 for (
const FormatToken *Tok = &Current;
1735 Tok && Tok != Current.MatchingParen; Tok = Tok->
Next) {
1738 BreakBeforeParameter =
true;
1746 BreakBeforeParameter =
true;
1752 Current.Children.empty() &&
1753 !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) &&
1754 (CurrentState.NoLineBreak || CurrentState.NoLineBreakInOperand ||
1755 (Current.is(TT_TemplateOpener) &&
1756 CurrentState.ContainsUnwrappedBuilder));
1757 State.Stack.push_back(
1758 ParenState(&Current, NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
1759 auto &NewState = State.Stack.back();
1760 NewState.NestedBlockIndent = NestedBlockIndent;
1761 NewState.BreakBeforeParameter = BreakBeforeParameter;
1762 NewState.HasMultipleNestedBlocks = (Current.BlockParameterCount > 1);
1765 Current.is(tok::l_paren)) {
1767 FormatToken
const *next = Current.Next;
1769 if (next->is(TT_LambdaLSquare)) {
1770 NewState.HasMultipleNestedBlocks =
true;
1777 NewState.IsInsideObjCArrayLiteral = Current.is(TT_ArrayInitializerLSquare) &&
1779 Current.Previous->is(tok::at);
1782void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
1783 const FormatToken &Current = *State.NextToken;
1784 if (!Current.closesScope())
1789 if (State.Stack.size() > 1 &&
1790 (Current.isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
1791 (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
1792 State.NextToken->is(TT_TemplateCloser) ||
1793 (Current.is(tok::greater) && Current.is(TT_DictLiteral)))) {
1794 State.Stack.pop_back();
1797 auto &CurrentState = State.Stack.back();
1809 if (CurrentState.BreakBeforeParameter && Current.MatchingParen &&
1810 Current.MatchingParen->Previous) {
1811 const FormatToken &CurrentScopeOpener = *Current.MatchingParen->Previous;
1812 if (CurrentScopeOpener.is(TT_ObjCMethodExpr) &&
1813 CurrentScopeOpener.MatchingParen) {
1814 int NecessarySpaceInLine =
1816 CurrentScopeOpener.TotalLength - Current.TotalLength - 1;
1817 if (State.Column + Current.ColumnWidth + NecessarySpaceInLine <=
1819 CurrentState.BreakBeforeParameter =
false;
1824 if (Current.is(tok::r_square)) {
1826 const FormatToken *NextNonComment = Current.getNextNonComment();
1827 if (NextNonComment && NextNonComment->isNot(tok::l_square))
1828 CurrentState.StartOfArraySubscripts = 0;
1832void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
1833 unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
1835 unsigned NewIndent =
1836 NestedBlockIndent + (State.NextToken->is(TT_ObjCBlockLBrace)
1839 State.Stack.push_back(ParenState(State.NextToken, NewIndent,
1840 State.Stack.back().LastSpace,
1843 State.Stack.back().NestedBlockIndent = NestedBlockIndent;
1844 State.Stack.back().BreakBeforeParameter =
true;
1850 size_t LastNewlinePos =
Text.find_last_of(
"\n");
1851 if (LastNewlinePos == StringRef::npos) {
1852 return StartColumn +
1856 0, TabWidth, Encoding);
1860unsigned ContinuationIndenter::reformatRawStringLiteral(
1861 const FormatToken &Current, LineState &State,
1862 const FormatStyle &RawStringStyle,
bool DryRun,
bool Newline) {
1863 unsigned StartColumn = State.Column - Current.ColumnWidth;
1865 StringRef NewDelimiter =
1867 if (NewDelimiter.empty())
1868 NewDelimiter = OldDelimiter;
1871 unsigned OldPrefixSize = 3 + OldDelimiter.size();
1872 unsigned OldSuffixSize = 2 + OldDelimiter.size();
1875 std::string RawText = std::string(
1876 Current.TokenText.substr(OldPrefixSize).drop_back(OldSuffixSize));
1877 if (NewDelimiter != OldDelimiter) {
1880 std::string CanonicalDelimiterSuffix = (
")" + NewDelimiter +
"\"").str();
1881 if (StringRef(RawText).contains(CanonicalDelimiterSuffix))
1882 NewDelimiter = OldDelimiter;
1885 unsigned NewPrefixSize = 3 + NewDelimiter.size();
1886 unsigned NewSuffixSize = 2 + NewDelimiter.size();
1889 unsigned FirstStartColumn = StartColumn + NewPrefixSize;
1900 bool ContentStartsOnNewline = Current.TokenText[OldPrefixSize] ==
'\n';
1922 unsigned CurrentIndent =
1923 (!Newline && Current.Next && Current.Next->is(tok::r_paren))
1924 ? State.Stack.back().NestedBlockIndent
1925 : State.Stack.back().Indent;
1926 unsigned NextStartColumn = ContentStartsOnNewline
1938 unsigned LastStartColumn =
1939 Current.NewlinesBefore ? FirstStartColumn - NewPrefixSize : CurrentIndent;
1942 RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
1943 FirstStartColumn, NextStartColumn, LastStartColumn,
"<stdin>",
1947 tooling::Replacements NoFixes;
1949 return addMultilineToken(Current, State);
1951 if (NewDelimiter != OldDelimiter) {
1954 SourceLocation PrefixDelimiterStart =
1955 Current.Tok.getLocation().getLocWithOffset(2);
1956 auto PrefixErr = Whitespaces.
addReplacement(tooling::Replacement(
1957 SourceMgr, PrefixDelimiterStart, OldDelimiter.size(), NewDelimiter));
1960 <<
"Failed to update the prefix delimiter of a raw string: "
1961 << llvm::toString(std::move(PrefixErr)) <<
"\n";
1965 SourceLocation SuffixDelimiterStart =
1966 Current.Tok.getLocation().getLocWithOffset(Current.TokenText.size() -
1967 1 - OldDelimiter.size());
1968 auto SuffixErr = Whitespaces.
addReplacement(tooling::Replacement(
1969 SourceMgr, SuffixDelimiterStart, OldDelimiter.size(), NewDelimiter));
1972 <<
"Failed to update the suffix delimiter of a raw string: "
1973 << llvm::toString(std::move(SuffixErr)) <<
"\n";
1976 SourceLocation OriginLoc =
1977 Current.Tok.getLocation().getLocWithOffset(OldPrefixSize);
1978 for (
const tooling::Replacement &Fix : Fixes.first) {
1980 SourceMgr, OriginLoc.getLocWithOffset(Fix.getOffset()),
1981 Fix.getLength(), Fix.getReplacementText()));
1983 llvm::errs() <<
"Failed to reformat raw string: "
1984 << llvm::toString(std::move(Err)) <<
"\n";
1989 *NewCode, FirstStartColumn, Style.
TabWidth, Encoding);
1990 State.Column = RawLastLineEndColumn + NewSuffixSize;
1994 unsigned PrefixExcessCharacters =
1999 ContentStartsOnNewline || (NewCode->find(
'\n') != std::string::npos);
2002 for (ParenState &
Paren : State.Stack)
2003 Paren.BreakBeforeParameter =
true;
2008unsigned ContinuationIndenter::addMultilineToken(
const FormatToken &Current,
2011 for (ParenState &
Paren : State.Stack)
2012 Paren.BreakBeforeParameter =
true;
2014 unsigned ColumnsUsed = State.Column;
2017 State.Column = Current.LastLineColumnWidth;
2024unsigned ContinuationIndenter::handleEndOfLine(
const FormatToken &Current,
2025 LineState &State,
bool DryRun,
2026 bool AllowBreak,
bool Newline) {
2027 unsigned Penalty = 0;
2030 auto RawStringStyle = getRawStringStyle(Current, State);
2031 if (RawStringStyle && !Current.Finalized) {
2032 Penalty = reformatRawStringLiteral(Current, State, *RawStringStyle, DryRun,
2034 }
else if (Current.IsMultiline && Current.isNot(TT_BlockComment)) {
2037 Penalty = addMultilineToken(Current, State);
2040 LineState OriginalState = State;
2044 bool Strict =
false;
2047 bool Exceeded =
false;
2048 std::tie(Penalty, Exceeded) = breakProtrudingToken(
2049 Current, State, AllowBreak,
true, Strict);
2053 LineState StrictState = OriginalState;
2054 unsigned StrictPenalty =
2055 breakProtrudingToken(Current, StrictState, AllowBreak,
2058 Strict = StrictPenalty <= Penalty;
2060 Penalty = StrictPenalty;
2061 State = StrictState;
2067 breakProtrudingToken(Current, OriginalState, AllowBreak,
false,
2072 unsigned ExcessCharacters = State.Column -
getColumnLimit(State);
2083 if (!Tok || !Tok->
is(tok::l_paren))
2088 if (Tok->
is(TT_TemplateCloser)) {
2093 if (!Tok || !Tok->
is(tok::identifier))
2098std::optional<FormatStyle>
2099ContinuationIndenter::getRawStringStyle(
const FormatToken &Current,
2100 const LineState &State) {
2101 if (!Current.isStringLiteral())
2102 return std::nullopt;
2105 return std::nullopt;
2107 if (!RawStringStyle && Delimiter->empty()) {
2111 if (!RawStringStyle)
2112 return std::nullopt;
2114 return RawStringStyle;
2117std::unique_ptr<BreakableToken>
2118ContinuationIndenter::createBreakableToken(
const FormatToken &Current,
2119 LineState &State,
bool AllowBreak) {
2120 unsigned StartColumn = State.Column - Current.ColumnWidth;
2121 if (Current.isStringLiteral()) {
2140 if (Current.IsUnterminatedLiteral)
2144 if (State.Stack.back().IsInsideObjCArrayLiteral)
2147 StringRef
Text = Current.TokenText;
2154 if ((
Text.endswith(Postfix =
"\"") &&
2155 (
Text.startswith(Prefix =
"@\"") ||
Text.startswith(Prefix =
"\"") ||
2156 Text.startswith(Prefix =
"u\"") ||
Text.startswith(Prefix =
"U\"") ||
2157 Text.startswith(Prefix =
"u8\"") ||
2158 Text.startswith(Prefix =
"L\""))) ||
2159 (
Text.startswith(Prefix =
"_T(\"") &&
Text.endswith(Postfix =
"\")"))) {
2164 unsigned UnbreakableTailLength = (State.NextToken &&
canBreak(State))
2166 : Current.UnbreakableTailLength;
2167 return std::make_unique<BreakableStringLiteral>(
2168 Current, StartColumn, Prefix, Postfix, UnbreakableTailLength,
2169 State.Line->InPPDirective, Encoding, Style);
2171 }
else if (Current.is(TT_BlockComment)) {
2179 return std::make_unique<BreakableBlockComment>(
2180 Current, StartColumn, Current.OriginalColumn, !Current.Previous,
2181 State.Line->InPPDirective, Encoding, Style, Whitespaces.
useCRLF());
2182 }
else if (Current.is(TT_LineComment) &&
2183 (!Current.Previous ||
2184 Current.Previous->isNot(TT_ImplicitStringLiteral))) {
2185 bool RegularComments = [&]() {
2186 for (
const FormatToken *T = &Current; T && T->is(TT_LineComment);
2188 if (!(T->TokenText.startswith(
"//") || T->TokenText.startswith(
"#")))
2194 CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
2198 return std::make_unique<BreakableLineCommentSection>(
2199 Current, StartColumn,
false, Encoding, Style);
2204std::pair<unsigned, bool>
2205ContinuationIndenter::breakProtrudingToken(
const FormatToken &Current,
2206 LineState &State,
bool AllowBreak,
2207 bool DryRun,
bool Strict) {
2208 std::unique_ptr<const BreakableToken> Token =
2209 createBreakableToken(Current, State, AllowBreak);
2212 assert(Token->getLineCount() > 0);
2214 if (Current.is(TT_LineComment)) {
2218 if (ColumnLimit == 0) {
2221 ColumnLimit = std::numeric_limits<
decltype(ColumnLimit)>
::max();
2223 if (Current.UnbreakableTailLength >= ColumnLimit)
2227 unsigned StartColumn = State.Column - Current.ColumnWidth;
2228 unsigned NewBreakPenalty = Current.isStringLiteral()
2233 bool Exceeded =
false;
2235 bool BreakInserted = Token->introducesBreakBeforeToken();
2238 bool NewBreakBefore =
false;
2242 bool Reflow =
false;
2245 unsigned TailOffset = 0;
2247 unsigned ContentStartColumn =
2248 Token->getContentStartColumn(0,
false);
2250 unsigned RemainingTokenColumns =
2251 Token->getRemainingLength(0, TailOffset, ContentStartColumn);
2254 Token->adaptStartOfLine(0, Whitespaces);
2256 unsigned ContentIndent = 0;
2257 unsigned Penalty = 0;
2258 LLVM_DEBUG(llvm::dbgs() <<
"Breaking protruding token at column "
2259 << StartColumn <<
".\n");
2260 for (
unsigned LineIndex = 0, EndIndex = Token->getLineCount();
2261 LineIndex != EndIndex; ++LineIndex) {
2262 LLVM_DEBUG(llvm::dbgs()
2263 <<
" Line: " << LineIndex <<
" (Reflow: " << Reflow <<
")\n");
2264 NewBreakBefore =
false;
2268 bool TryReflow = Reflow;
2270 while (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2271 LLVM_DEBUG(llvm::dbgs() <<
" Over limit, need: "
2272 << (ContentStartColumn + RemainingTokenColumns)
2273 <<
", space: " << ColumnLimit
2274 <<
", reflown prefix: " << ContentStartColumn
2275 <<
", offset in line: " << TailOffset <<
"\n");
2281 Token->getSplit(LineIndex, TailOffset, ColumnLimit,
2282 ContentStartColumn, CommentPragmasRegex);
2283 if (
Split.first == StringRef::npos) {
2286 if (LineIndex < EndIndex - 1) {
2290 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2292 LLVM_DEBUG(llvm::dbgs() <<
" No break opportunity.\n");
2295 assert(
Split.first != 0);
2297 if (Token->supportsReflow()) {
2317 unsigned ToSplitColumns = Token->getRangeLength(
2318 LineIndex, TailOffset,
Split.first, ContentStartColumn);
2319 LLVM_DEBUG(llvm::dbgs() <<
" ToSplit: " << ToSplitColumns <<
"\n");
2322 LineIndex, TailOffset +
Split.first +
Split.second, ColumnLimit,
2323 ContentStartColumn + ToSplitColumns + 1, CommentPragmasRegex);
2326 unsigned ToNextSplitColumns = 0;
2327 if (NextSplit.first == StringRef::npos) {
2328 ToNextSplitColumns = Token->getRemainingLength(LineIndex, TailOffset,
2329 ContentStartColumn);
2331 ToNextSplitColumns = Token->getRangeLength(
2332 LineIndex, TailOffset,
2333 Split.first +
Split.second + NextSplit.first, ContentStartColumn);
2337 ToNextSplitColumns =
2338 Token->getLengthAfterCompression(ToNextSplitColumns, Split);
2339 LLVM_DEBUG(llvm::dbgs()
2340 <<
" ContentStartColumn: " << ContentStartColumn <<
"\n");
2341 LLVM_DEBUG(llvm::dbgs()
2342 <<
" ToNextSplit: " << ToNextSplitColumns <<
"\n");
2345 bool ContinueOnLine =
2346 ContentStartColumn + ToNextSplitColumns <= ColumnLimit;
2347 unsigned ExcessCharactersPenalty = 0;
2348 if (!ContinueOnLine && !Strict) {
2351 ExcessCharactersPenalty =
2352 (ContentStartColumn + ToNextSplitColumns - ColumnLimit) *
2354 LLVM_DEBUG(llvm::dbgs()
2355 <<
" Penalty excess: " << ExcessCharactersPenalty
2356 <<
"\n break : " << NewBreakPenalty <<
"\n");
2357 if (ExcessCharactersPenalty < NewBreakPenalty) {
2359 ContinueOnLine =
true;
2362 if (ContinueOnLine) {
2363 LLVM_DEBUG(llvm::dbgs() <<
" Continuing on line...\n");
2368 Token->compressWhitespace(LineIndex, TailOffset, Split,
2372 ContentStartColumn += ToSplitColumns + 1;
2373 Penalty += ExcessCharactersPenalty;
2375 RemainingTokenColumns = Token->getRemainingLength(
2376 LineIndex, TailOffset, ContentStartColumn);
2380 LLVM_DEBUG(llvm::dbgs() <<
" Breaking...\n");
2385 ContentIndent = Token->getContentIndent(LineIndex);
2386 LLVM_DEBUG(llvm::dbgs()
2387 <<
" ContentIndent: " << ContentIndent <<
"\n");
2388 ContentStartColumn = ContentIndent + Token->getContentStartColumn(
2391 unsigned NewRemainingTokenColumns = Token->getRemainingLength(
2392 LineIndex, TailOffset +
Split.first +
Split.second,
2393 ContentStartColumn);
2394 if (NewRemainingTokenColumns == 0) {
2397 ContentStartColumn =
2398 Token->getContentStartColumn(LineIndex,
true);
2399 NewRemainingTokenColumns = Token->getRemainingLength(
2400 LineIndex, TailOffset +
Split.first +
Split.second,
2401 ContentStartColumn);
2407 if (NewRemainingTokenColumns >= RemainingTokenColumns) {
2412 LLVM_DEBUG(llvm::dbgs() <<
" Breaking at: " << TailOffset +
Split.first
2413 <<
", " <<
Split.second <<
"\n");
2415 Token->insertBreak(LineIndex, TailOffset, Split, ContentIndent,
2419 Penalty += NewBreakPenalty;
2421 RemainingTokenColumns = NewRemainingTokenColumns;
2422 BreakInserted =
true;
2423 NewBreakBefore =
true;
2427 if (LineIndex + 1 != EndIndex) {
2428 unsigned NextLineIndex = LineIndex + 1;
2429 if (NewBreakBefore) {
2448 ContentStartColumn += RemainingTokenColumns + 1;
2453 Token->getReflowSplit(NextLineIndex, CommentPragmasRegex);
2454 LLVM_DEBUG(llvm::dbgs()
2455 <<
" Size of reflown text: " << ContentStartColumn
2456 <<
"\n Potential reflow split: ");
2457 if (SplitBeforeNext.first != StringRef::npos) {
2458 LLVM_DEBUG(llvm::dbgs() << SplitBeforeNext.first <<
", "
2459 << SplitBeforeNext.second <<
"\n");
2460 TailOffset = SplitBeforeNext.first + SplitBeforeNext.second;
2463 RemainingTokenColumns = Token->getRemainingLength(
2464 NextLineIndex, TailOffset, ContentStartColumn);
2466 if (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2467 LLVM_DEBUG(llvm::dbgs()
2468 <<
" Over limit after reflow, need: "
2469 << (ContentStartColumn + RemainingTokenColumns)
2470 <<
", space: " << ColumnLimit
2471 <<
", reflown prefix: " << ContentStartColumn
2472 <<
", offset in line: " << TailOffset <<
"\n");
2478 Token->getSplit(NextLineIndex, TailOffset, ColumnLimit,
2479 ContentStartColumn, CommentPragmasRegex);
2480 if (
Split.first == StringRef::npos) {
2481 LLVM_DEBUG(llvm::dbgs() <<
" Did not find later break\n");
2487 unsigned ToSplitColumns = Token->getRangeLength(
2488 NextLineIndex, TailOffset,
Split.first, ContentStartColumn);
2489 if (ContentStartColumn + ToSplitColumns > ColumnLimit) {
2490 LLVM_DEBUG(llvm::dbgs() <<
" Next split protrudes, need: "
2491 << (ContentStartColumn + ToSplitColumns)
2492 <<
", space: " << ColumnLimit);
2493 unsigned ExcessCharactersPenalty =
2494 (ContentStartColumn + ToSplitColumns - ColumnLimit) *
2496 if (NewBreakPenalty < ExcessCharactersPenalty)
2502 LLVM_DEBUG(llvm::dbgs() <<
"not found.\n");
2510 ContentStartColumn =
2511 Token->getContentStartColumn(NextLineIndex,
false);
2512 RemainingTokenColumns = Token->getRemainingLength(
2513 NextLineIndex, TailOffset, ContentStartColumn);
2516 Token->adaptStartOfLine(NextLineIndex, Whitespaces);
2531 if (NewBreakBefore) {
2532 assert(Penalty >= NewBreakPenalty);
2533 Penalty -= NewBreakPenalty;
2536 Token->reflow(NextLineIndex, Whitespaces);
2542 Token->getSplitAfterLastLine(TailOffset);
2543 if (SplitAfterLastLine.first != StringRef::npos) {
2544 LLVM_DEBUG(llvm::dbgs() <<
"Replacing whitespace after last line.\n");
2549 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2552 Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
2555 ContentStartColumn =
2556 Token->getContentStartColumn(Token->getLineCount() - 1,
true);
2557 RemainingTokenColumns = Token->getRemainingLength(
2558 Token->getLineCount() - 1,
2559 TailOffset + SplitAfterLastLine.first + SplitAfterLastLine.second,
2560 ContentStartColumn);
2563 State.Column = ContentStartColumn + RemainingTokenColumns -
2564 Current.UnbreakableTailLength;
2566 if (BreakInserted) {
2570 if (Current.isNot(TT_LineComment))
2571 for (ParenState &
Paren : State.Stack)
2572 Paren.BreakBeforeParameter =
true;
2574 if (Current.is(TT_BlockComment))
2575 State.NoContinuation =
true;
2577 State.Stack.back().LastSpace = StartColumn;
2580 Token->updateNextToken(State);
2582 return {Penalty, Exceeded};
2587 return Style.
ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
2590bool ContinuationIndenter::nextIsMultilineString(
const LineState &State) {
2592 if (!Current.isStringLiteral() || Current.is(TT_ImplicitStringLiteral))
2597 if (Current.TokenText.startswith(
"R\""))
2599 if (Current.IsMultiline)
2601 if (Current.getNextNonComment() &&
2602 Current.getNextNonComment()->isStringLiteral()) {
2606 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
Language
The language for the input, used to select and validate the language standard and possible actions.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))