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.startswith(
"R\"") || !TokenText.endswith(
"\"")) {
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).startswith(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) && State.Column < 6) {
338 if (!Current.isOneOf(TT_BinaryOperator, tok::comma) &&
343 Current.isNot(TT_LambdaLBrace)) &&
344 CurrentState.NoLineBreakInOperand) {
351 if (Current.is(TT_ConditionalExpr) &&
Previous.is(tok::r_paren) &&
353 Previous.MatchingParen->Previous->MatchingParen &&
354 Previous.MatchingParen->Previous->MatchingParen->is(TT_LambdaLBrace)) {
356 assert(
Previous.MatchingParen->Previous->is(tok::r_brace));
360 return !State.NoLineBreak && !CurrentState.NoLineBreak;
366 const auto &CurrentState = State.Stack.back();
368 Current.is(TT_LambdaLBrace) &&
Previous.isNot(TT_LineComment)) {
372 if (Current.MustBreakBefore ||
373 (Current.is(TT_InlineASMColon) &&
379 if (CurrentState.BreakBeforeClosingBrace &&
380 (Current.closesBlockOrBlockTypeList(Style) ||
381 (Current.is(tok::r_brace) &&
382 Current.isBlockIndentedInitRBrace(Style)))) {
385 if (CurrentState.BreakBeforeClosingParen && Current.is(tok::r_paren))
389 Current.ObjCSelectorNameParts > 1 &&
390 Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)) {
395 if (CurrentState.IsCSharpGenericTypeConstraint &&
396 Previous.isNot(TT_CSharpGenericTypeConstraintComma)) {
400 (
Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) &&
410 Previous.is(TT_ConditionalExpr))) &&
411 CurrentState.BreakBeforeParameter && !Current.isTrailingComment() &&
412 !Current.isOneOf(tok::r_paren, tok::r_brace)) {
415 if (CurrentState.IsChainedConditional &&
417 Current.is(tok::colon)) ||
423 (
Previous.is(TT_ArrayInitializerLSquare) &&
432 const FormatToken &BreakConstructorInitializersToken =
436 if (BreakConstructorInitializersToken.
is(TT_CtorInitializerColon) &&
437 (State.Column + State.Line->Last->TotalLength -
Previous.TotalLength >
439 CurrentState.BreakBeforeParameter) &&
440 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
447 if (Current.is(TT_ObjCMethodExpr) &&
Previous.isNot(TT_SelectorName) &&
448 State.Line->startsWith(TT_ObjCMethodSpecifier)) {
451 if (Current.is(TT_SelectorName) &&
Previous.isNot(tok::at) &&
452 CurrentState.ObjCSelectorNameFound && CurrentState.BreakBeforeParameter &&
454 !Current.startsSequence(TT_SelectorName, tok::colon, tok::caret))) {
458 unsigned NewLineColumn = getNewLineColumn(State);
459 if (Current.isMemberAccess() && Style.
ColumnLimit != 0 &&
461 (State.Column > NewLineColumn ||
462 Current.NestingLevel < State.StartOfLineLevel)) {
467 (CurrentState.CallContinuation != 0 ||
468 CurrentState.BreakBeforeParameter) &&
474 !(State.Column <= NewLineColumn && Style.
isJavaScript()) &&
475 !(
Previous.closesScopeAfterBlock() && State.Column <= NewLineColumn)) {
481 if (
Previous.ClosesTemplateDeclaration && CurrentState.BreakBeforeParameter &&
482 Current.CanBreakBefore) {
486 if (State.Line->First->isNot(tok::kw_enum) && State.Column <= NewLineColumn)
491 Previous.is(tok::comma) || Current.NestingLevel < 2) &&
492 !
Previous.isOneOf(tok::kw_return, tok::lessless, tok::at,
494 !
Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
495 nextIsMultilineString(State)) {
502 if (
Previous.is(TT_BinaryOperator) && Current.CanBreakBefore) {
503 const auto PreviousPrecedence =
Previous.getPrecedence();
505 CurrentState.BreakBeforeParameter && !Current.isTrailingComment()) {
506 const bool LHSIsBinaryExpr =
519 const bool IsComparison =
524 Previous.Previous->isNot(TT_BinaryOperator);
528 }
else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore &&
529 CurrentState.BreakBeforeParameter) {
534 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator) &&
535 CurrentState.BreakBeforeParameter && CurrentState.FirstLessLess == 0) {
539 if (Current.NestingLevel == 0 && !Current.isTrailingComment()) {
544 if (
Previous.ClosesTemplateDeclaration) {
545 if (Current.is(tok::kw_concept)) {
555 if (Current.is(TT_RequiresClause)) {
566 if (
Previous.is(TT_FunctionAnnotationRParen) &&
570 if (
Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) &&
571 Current.isNot(TT_LeadingJavaAnnotation)) {
580 static const llvm::StringSet<> BreakBeforeDecoratedTokens = {
"get",
"set",
582 if (BreakBeforeDecoratedTokens.contains(Current.TokenText))
587 if (((Current.is(TT_FunctionDeclarationName) &&
588 !State.Line->ReturnTypeWrapped &&
595 (Current.is(tok::kw_operator) &&
Previous.isNot(tok::coloncolon))) &&
596 Previous.isNot(tok::kw_template) && CurrentState.BreakBeforeParameter) {
605 !Current.isOneOf(tok::r_brace, tok::comment)) {
609 if (Current.is(tok::lessless) &&
612 Previous.TokenText ==
"\'\\n\'")))) {
619 if (State.NoContinuation)
627 unsigned ExtraSpaces) {
629 assert(State.NextToken->Previous);
632 assert(!State.Stack.empty());
633 State.NoContinuation =
false;
635 if (Current.is(TT_ImplicitStringLiteral) &&
636 (!
Previous.Tok.getIdentifierInfo() ||
637 Previous.Tok.getIdentifierInfo()->getPPKeywordID() ==
638 tok::pp_not_keyword)) {
641 if (Current.LastNewlineOffset != 0) {
644 State.Column = EndColumn;
646 unsigned StartColumn =
648 assert(EndColumn >= StartColumn);
649 State.Column += EndColumn - StartColumn;
651 moveStateToNextToken(State, DryRun,
false);
655 unsigned Penalty = 0;
657 Penalty = addTokenOnNewLine(State, DryRun);
659 addTokenOnCurrentLine(State, DryRun, ExtraSpaces);
661 return moveStateToNextToken(State, DryRun, Newline) + Penalty;
664void ContinuationIndenter::addTokenOnCurrentLine(
LineState &State,
bool DryRun,
665 unsigned ExtraSpaces) {
667 assert(State.NextToken->Previous);
669 auto &CurrentState = State.Stack.back();
671 bool DisallowLineBreaksOnThisLine =
673 Style.
isCpp() && [&Current] {
679 auto PrevNonComment = Current.getPreviousNonComment();
680 if (!PrevNonComment || PrevNonComment->isNot(tok::l_paren))
682 if (Current.isOneOf(tok::comment, tok::l_paren, TT_LambdaLSquare))
684 auto BlockParameterCount = PrevNonComment->BlockParameterCount;
685 if (BlockParameterCount == 0)
689 if (BlockParameterCount > 1)
693 if (!PrevNonComment->Role)
695 auto Comma = PrevNonComment->Role->lastComma();
698 auto Next = Comma->getNextNonComment();
700 !Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret);
703 if (DisallowLineBreaksOnThisLine)
704 State.NoLineBreak =
true;
706 if (Current.is(tok::equal) &&
707 (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&
708 CurrentState.VariablePos == 0) {
709 CurrentState.VariablePos = State.Column;
712 while (Tok && CurrentState.VariablePos >= Tok->ColumnWidth) {
713 CurrentState.VariablePos -= Tok->ColumnWidth;
714 if (Tok->SpacesRequiredBefore != 0)
718 if (
Previous.PartOfMultiVariableDeclStmt)
719 CurrentState.LastSpace = CurrentState.VariablePos;
722 unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces;
725 int PPColumnCorrection = 0;
727 Previous.is(tok::hash) && State.FirstIndent > 0 &&
731 Spaces += State.FirstIndent;
738 PPColumnCorrection = -1;
743 State.Column + Spaces + PPColumnCorrection);
749 Current.is(TT_InheritanceColon)) {
750 CurrentState.NoLineBreak =
true;
754 CurrentState.NoLineBreak =
true;
757 if (Current.is(TT_SelectorName) && !CurrentState.ObjCSelectorNameFound) {
758 unsigned MinIndent = std::max(
760 unsigned FirstColonPos = State.Column + Spaces + Current.ColumnWidth;
761 if (Current.LongestObjCSelectorName == 0)
762 CurrentState.AlignColons =
false;
763 else if (MinIndent + Current.LongestObjCSelectorName > FirstColonPos)
764 CurrentState.ColonPos = MinIndent + Current.LongestObjCSelectorName;
766 CurrentState.ColonPos = FirstColonPos;
775 (
Previous.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) ||
778 State.Column > getNewLineColumn(State) &&
780 !
Previous.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while,
789 Current.FakeLParens.size() > 0 &&
791 CurrentState.NoLineBreak =
true;
794 CurrentState.NoLineBreak =
true;
801 !CurrentState.IsCSharpGenericTypeConstraint &&
Previous.opensScope() &&
803 !(Current.MacroParent &&
Previous.MacroParent) &&
804 (Current.isNot(TT_LineComment) ||
806 CurrentState.Indent = State.Column + Spaces;
807 CurrentState.IsAligned =
true;
810 CurrentState.NoLineBreak =
true;
812 State.Column > getNewLineColumn(State)) {
813 CurrentState.ContainsUnwrappedBuilder =
true;
817 CurrentState.NoLineBreak =
true;
818 if (Current.isMemberAccess() &&
Previous.is(tok::r_paren) &&
827 CurrentState.NoLineBreak =
true;
834 const FormatToken *
P = Current.getPreviousNonComment();
835 if (Current.isNot(tok::comment) &&
P &&
836 (
P->isOneOf(TT_BinaryOperator, tok::comma) ||
837 (
P->is(TT_ConditionalExpr) &&
P->is(tok::colon))) &&
838 !
P->isOneOf(TT_OverloadedOperator, TT_CtorInitializerComma) &&
842 bool BreakBeforeOperator =
843 P->MustBreakBefore ||
P->is(tok::lessless) ||
844 (
P->is(TT_BinaryOperator) &&
850 bool HasTwoOperands =
P->OperatorIndex == 0 && !
P->NextOperator &&
851 P->isNot(TT_ConditionalExpr);
852 if ((!BreakBeforeOperator &&
855 (!CurrentState.LastOperatorWrapped && BreakBeforeOperator)) {
856 CurrentState.NoLineBreakInOperand =
true;
860 State.Column += Spaces;
861 if (Current.isNot(tok::comment) &&
Previous.is(tok::l_paren) &&
866 CurrentState.LastSpace = State.Column;
867 CurrentState.NestedBlockIndent = State.Column;
868 }
else if (!Current.isOneOf(tok::comment, tok::caret) &&
870 Previous.isNot(TT_OverloadedOperator)) ||
872 CurrentState.LastSpace = State.Column;
873 }
else if (
Previous.is(TT_CtorInitializerColon) &&
874 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
877 CurrentState.Indent = State.Column;
878 CurrentState.LastSpace = State.Column;
879 }
else if (
Previous.isOneOf(TT_ConditionalExpr, TT_CtorInitializerColon)) {
880 CurrentState.LastSpace = State.Column;
881 }
else if (
Previous.is(TT_BinaryOperator) &&
885 Current.StartsBinaryExpression)) {
889 CurrentState.LastSpace = State.Column;
890 }
else if (
Previous.is(TT_InheritanceColon)) {
891 CurrentState.Indent = State.Column;
892 CurrentState.LastSpace = State.Column;
893 }
else if (Current.is(TT_CSharpGenericTypeConstraintColon)) {
894 CurrentState.ColonPos = State.Column;
902 const FormatToken *Next =
Previous.MatchingParen->getNextNonComment();
903 if (Next && Next->isMemberAccess() && State.Stack.size() > 1 &&
904 State.Stack[State.Stack.size() - 2].CallContinuation == 0) {
905 CurrentState.LastSpace = State.Column;
911unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
913 FormatToken &Current = *State.NextToken;
914 assert(State.NextToken->Previous);
915 const FormatToken &
Previous = *State.NextToken->Previous;
916 auto &CurrentState = State.Stack.back();
920 unsigned Penalty = 0;
922 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
923 const FormatToken *NextNonComment =
Previous.getNextNonComment();
925 NextNonComment = &Current;
928 if (!CurrentState.ContainsLineBreak)
930 CurrentState.ContainsLineBreak =
true;
932 Penalty += State.NextToken->SplitPenalty;
937 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess == 0 &&
939 CurrentState.BreakBeforeParameter)) {
943 State.Column = getNewLineColumn(State);
957 if (State.Column > State.FirstIndent) {
972 if (Current.isNot(TT_LambdaArrow) &&
974 !PreviousNonComment || PreviousNonComment->isNot(tok::equal) ||
976 CurrentState.NestedBlockIndent = State.Column;
979 if (NextNonComment->isMemberAccess()) {
980 if (CurrentState.CallContinuation == 0)
981 CurrentState.CallContinuation = State.Column;
982 }
else if (NextNonComment->is(TT_SelectorName)) {
983 if (!CurrentState.ObjCSelectorNameFound) {
984 if (NextNonComment->LongestObjCSelectorName == 0) {
985 CurrentState.AlignColons =
false;
987 CurrentState.ColonPos =
989 ? std::max(CurrentState.Indent,
991 : CurrentState.Indent) +
993 NextNonComment->ColumnWidth);
995 }
else if (CurrentState.AlignColons &&
996 CurrentState.ColonPos <= NextNonComment->ColumnWidth) {
997 CurrentState.ColonPos = State.Column + NextNonComment->ColumnWidth;
999 }
else if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
1000 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
1010 if (State.Stack.size() > 1) {
1011 State.Stack[State.Stack.size() - 2].LastSpace =
1012 std::max(CurrentState.LastSpace, CurrentState.Indent) +
1017 if ((PreviousNonComment &&
1018 PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
1019 !CurrentState.AvoidBinPacking) ||
1021 CurrentState.BreakBeforeParameter =
false;
1023 if (PreviousNonComment &&
1024 (PreviousNonComment->isOneOf(TT_TemplateCloser, TT_JavaAnnotation) ||
1025 PreviousNonComment->ClosesRequiresClause) &&
1026 Current.NestingLevel == 0) {
1027 CurrentState.BreakBeforeParameter =
false;
1029 if (NextNonComment->is(tok::question) ||
1030 (PreviousNonComment && PreviousNonComment->is(tok::question))) {
1031 CurrentState.BreakBeforeParameter =
true;
1033 if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore)
1034 CurrentState.BreakBeforeParameter =
false;
1038 if (Current.is(tok::r_brace) && Current.MatchingParen &&
1041 !Current.MatchingParen->Children.empty()) {
1045 MaxEmptyLinesToKeep = 1;
1048 std::max(1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
1049 bool ContinuePPDirective =
1052 CurrentState.IsAligned, ContinuePPDirective);
1055 if (!Current.isTrailingComment())
1056 CurrentState.LastSpace = State.Column;
1057 if (Current.is(tok::lessless)) {
1061 CurrentState.LastSpace += 3;
1064 State.StartOfLineLevel = Current.NestingLevel;
1065 State.LowestLevelOnLine = Current.NestingLevel;
1069 bool NestedBlockSpecialCase =
1070 (!Style.
isCpp() && Current.is(tok::r_brace) && State.Stack.size() > 1 &&
1071 State.Stack[State.Stack.size() - 2].NestedBlockInlined) ||
1075 NestedBlockSpecialCase =
1076 NestedBlockSpecialCase ||
1077 (Current.MatchingParen &&
1078 Current.MatchingParen->is(TT_RequiresExpressionLBrace));
1079 if (!NestedBlockSpecialCase) {
1080 auto ParentLevelIt = std::next(State.Stack.rbegin());
1082 Current.MatchingParen && Current.MatchingParen->is(TT_LambdaLBrace)) {
1097 auto FindCurrentLevel = [&](
const auto &It) {
1098 return std::find_if(It, State.Stack.rend(), [](
const auto &PState) {
1099 return PState.Tok != nullptr;
1102 auto MaybeIncrement = [&](
const auto &It) {
1103 return It != State.Stack.rend() ? std::next(It) : It;
1105 auto LambdaLevelIt = FindCurrentLevel(State.Stack.rbegin());
1106 auto LevelContainingLambdaIt =
1107 FindCurrentLevel(MaybeIncrement(LambdaLevelIt));
1108 ParentLevelIt = MaybeIncrement(LevelContainingLambdaIt);
1110 for (
auto I = ParentLevelIt, E = State.Stack.rend(); I != E; ++I)
1111 I->BreakBeforeParameter =
true;
1114 if (PreviousNonComment &&
1115 !PreviousNonComment->isOneOf(tok::comma, tok::colon, tok::semi) &&
1116 ((PreviousNonComment->isNot(TT_TemplateCloser) &&
1117 !PreviousNonComment->ClosesRequiresClause) ||
1118 Current.NestingLevel != 0) &&
1119 !PreviousNonComment->isOneOf(
1120 TT_BinaryOperator, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
1121 TT_LeadingJavaAnnotation) &&
1122 Current.isNot(TT_BinaryOperator) && !PreviousNonComment->opensScope() &&
1126 Current.isNot(TT_LambdaLBrace))) {
1127 CurrentState.BreakBeforeParameter =
true;
1132 if (PreviousNonComment &&
1133 (PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1135 CurrentState.BreakBeforeClosingBrace =
true;
1138 if (PreviousNonComment && PreviousNonComment->is(tok::l_paren)) {
1139 CurrentState.BreakBeforeClosingParen =
1143 if (CurrentState.AvoidBinPacking) {
1148 bool PreviousIsBreakingCtorInitializerColon =
1149 PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1151 bool AllowAllConstructorInitializersOnNextLine =
1154 if (!(
Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
1155 PreviousIsBreakingCtorInitializerColon) ||
1157 State.Line->MustBeDeclaration) ||
1159 !State.Line->MustBeDeclaration) ||
1160 (!AllowAllConstructorInitializersOnNextLine &&
1161 PreviousIsBreakingCtorInitializerColon) ||
1163 CurrentState.BreakBeforeParameter =
true;
1169 if (PreviousIsBreakingCtorInitializerColon &&
1170 AllowAllConstructorInitializersOnNextLine) {
1171 CurrentState.BreakBeforeParameter =
false;
1178unsigned ContinuationIndenter::getNewLineColumn(
const LineState &State) {
1179 if (!State.NextToken || !State.NextToken->Previous)
1182 FormatToken &Current = *State.NextToken;
1183 const auto &CurrentState = State.Stack.back();
1185 if (CurrentState.IsCSharpGenericTypeConstraint &&
1186 Current.isNot(TT_CSharpGenericTypeConstraint)) {
1187 return CurrentState.ColonPos + 2;
1190 const FormatToken &
Previous = *Current.Previous;
1192 unsigned ContinuationIndent =
1193 std::max(CurrentState.LastSpace, CurrentState.Indent) +
1195 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
1196 const FormatToken *NextNonComment =
Previous.getNextNonComment();
1197 if (!NextNonComment)
1198 NextNonComment = &Current;
1203 return std::max(CurrentState.LastSpace,
1210 return State.FirstIndent;
1213 State.Line->First->is(tok::kw_enum)) {
1214 return (Style.
IndentWidth * State.Line->First->IndentLevel) +
1218 if ((NextNonComment->is(tok::l_brace) && NextNonComment->is(
BK_Block)) ||
1220 if (Current.NestingLevel == 0 ||
1222 State.NextToken->is(TT_LambdaLBrace))) {
1223 return State.FirstIndent;
1225 return CurrentState.Indent;
1227 if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
1228 (Current.is(tok::greater) &&
1231 State.Stack.size() > 1) {
1232 if (Current.closesBlockOrBlockTypeList(Style))
1233 return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
1234 if (Current.MatchingParen && Current.MatchingParen->is(
BK_BracedInit))
1235 return State.Stack[State.Stack.size() - 2].LastSpace;
1236 return State.FirstIndent;
1253 if (Current.is(tok::r_paren) && State.Stack.size() > 1 &&
1255 Current.Next->isOneOf(tok::semi, tok::kw_const, tok::l_brace))) {
1256 return State.Stack[State.Stack.size() - 2].LastSpace;
1259 (Current.is(tok::r_paren) ||
1260 (Current.is(tok::r_brace) &&
1262 State.Stack.size() > 1) {
1263 return State.Stack[State.Stack.size() - 2].LastSpace;
1265 if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
1266 return State.Stack[State.Stack.size() - 2].LastSpace;
1274 if (Current.is(tok::identifier) && Current.Next &&
1275 (!Style.
isVerilog() || Current.Next->is(tok::colon)) &&
1276 (Current.Next->is(TT_DictLiteral) ||
1279 Current.Next->isOneOf(tok::less, tok::l_brace)))) {
1280 return CurrentState.Indent;
1282 if (NextNonComment->is(TT_ObjCStringLiteral) &&
1283 State.StartOfStringLiteral != 0) {
1284 return State.StartOfStringLiteral - 1;
1286 if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0)
1287 return State.StartOfStringLiteral;
1288 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess != 0)
1289 return CurrentState.FirstLessLess;
1290 if (NextNonComment->isMemberAccess()) {
1291 if (CurrentState.CallContinuation == 0)
1292 return ContinuationIndent;
1293 return CurrentState.CallContinuation;
1295 if (CurrentState.QuestionColumn != 0 &&
1296 ((NextNonComment->is(tok::colon) &&
1297 NextNonComment->is(TT_ConditionalExpr)) ||
1298 Previous.is(TT_ConditionalExpr))) {
1299 if (((NextNonComment->is(tok::colon) && NextNonComment->Next &&
1300 !NextNonComment->Next->FakeLParens.empty() &&
1302 (
Previous.is(tok::colon) && !Current.FakeLParens.empty() &&
1304 !CurrentState.IsWrappedConditional) {
1309 unsigned Indent = CurrentState.Indent;
1316 return CurrentState.QuestionColumn;
1318 if (
Previous.is(tok::comma) && CurrentState.VariablePos != 0)
1319 return CurrentState.VariablePos;
1320 if (Current.is(TT_RequiresClause)) {
1326 return CurrentState.Indent;
1331 if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
1332 TT_InheritanceComma)) {
1335 if ((PreviousNonComment &&
1336 (PreviousNonComment->ClosesTemplateDeclaration ||
1337 PreviousNonComment->ClosesRequiresClause ||
1338 PreviousNonComment->isOneOf(
1339 TT_AttributeRParen, TT_AttributeSquare, TT_FunctionAnnotationRParen,
1340 TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
1342 NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName))) {
1343 return std::max(CurrentState.LastSpace, CurrentState.Indent);
1345 if (NextNonComment->is(TT_SelectorName)) {
1346 if (!CurrentState.ObjCSelectorNameFound) {
1347 unsigned MinIndent = CurrentState.Indent;
1349 MinIndent = std::max(MinIndent,
1362 std::max(NextNonComment->LongestObjCSelectorName,
1363 NextNonComment->ColumnWidth) -
1364 NextNonComment->ColumnWidth;
1366 if (!CurrentState.AlignColons)
1367 return CurrentState.Indent;
1368 if (CurrentState.ColonPos > NextNonComment->ColumnWidth)
1369 return CurrentState.ColonPos - NextNonComment->ColumnWidth;
1370 return CurrentState.Indent;
1372 if (NextNonComment->is(tok::colon) && NextNonComment->is(TT_ObjCMethodExpr))
1373 return CurrentState.ColonPos;
1374 if (NextNonComment->is(TT_ArraySubscriptLSquare)) {
1375 if (CurrentState.StartOfArraySubscripts != 0) {
1376 return CurrentState.StartOfArraySubscripts;
1379 return CurrentState.Indent;
1381 return ContinuationIndent;
1386 if (State.Line->InPragmaDirective) {
1387 FormatToken *PragmaType = State.Line->First->Next->Next;
1388 if (PragmaType && PragmaType->TokenText.equals(
"omp"))
1394 if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 &&
1395 NextNonComment->Next && NextNonComment->Next->is(TT_ObjCMethodExpr)) {
1396 return CurrentState.Indent;
1399 if (NextNonComment->isOneOf(TT_StartOfName, TT_PointerOrReference) ||
1400 Previous.isOneOf(tok::coloncolon, tok::equal, TT_JsTypeColon)) {
1401 return ContinuationIndent;
1403 if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
1404 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
1405 return ContinuationIndent;
1407 if (NextNonComment->is(TT_CtorInitializerComma))
1408 return CurrentState.Indent;
1409 if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1411 return CurrentState.Indent;
1413 if (PreviousNonComment && PreviousNonComment->is(TT_InheritanceColon) &&
1415 return CurrentState.Indent;
1417 if (
Previous.is(tok::r_paren) && !Current.isBinaryOperator() &&
1418 !Current.isOneOf(tok::colon, tok::comment)) {
1419 return ContinuationIndent;
1421 if (Current.is(TT_ProtoExtensionLSquare))
1422 return CurrentState.Indent;
1423 if (Current.isBinaryOperator() && CurrentState.UnindentOperator) {
1424 return CurrentState.Indent - Current.Tok.getLength() -
1425 Current.SpacesRequiredBefore;
1427 if (Current.isOneOf(tok::comment, TT_BlockComment, TT_LineComment) &&
1428 NextNonComment->isBinaryOperator() && CurrentState.UnindentOperator) {
1429 return CurrentState.Indent - NextNonComment->Tok.getLength() -
1430 NextNonComment->SpacesRequiredBefore;
1432 if (CurrentState.Indent == State.FirstIndent && PreviousNonComment &&
1433 !PreviousNonComment->isOneOf(tok::r_brace, TT_CtorInitializerComma)) {
1438 return CurrentState.Indent;
1453unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
1454 bool DryRun,
bool Newline) {
1455 assert(State.Stack.size());
1456 const FormatToken &Current = *State.NextToken;
1457 auto &CurrentState = State.Stack.back();
1459 if (Current.is(TT_CSharpGenericTypeConstraint))
1460 CurrentState.IsCSharpGenericTypeConstraint =
true;
1461 if (Current.isOneOf(tok::comma, TT_BinaryOperator))
1462 CurrentState.NoLineBreakInOperand =
false;
1463 if (Current.isOneOf(TT_InheritanceColon, TT_CSharpGenericTypeConstraintColon))
1464 CurrentState.AvoidBinPacking =
true;
1465 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator)) {
1466 if (CurrentState.FirstLessLess == 0)
1467 CurrentState.FirstLessLess = State.Column;
1469 CurrentState.LastOperatorWrapped = Newline;
1471 if (Current.is(TT_BinaryOperator) && Current.isNot(tok::lessless))
1472 CurrentState.LastOperatorWrapped = Newline;
1473 if (Current.is(TT_ConditionalExpr) && Current.Previous &&
1474 Current.Previous->isNot(TT_ConditionalExpr)) {
1475 CurrentState.LastOperatorWrapped = Newline;
1477 if (Current.is(TT_ArraySubscriptLSquare) &&
1478 CurrentState.StartOfArraySubscripts == 0) {
1479 CurrentState.StartOfArraySubscripts = State.Column;
1482 auto IsWrappedConditional = [](
const FormatToken &Tok) {
1483 if (!(Tok.is(TT_ConditionalExpr) && Tok.is(tok::question)))
1485 if (Tok.MustBreakBefore)
1488 const FormatToken *Next = Tok.getNextNonComment();
1489 return Next && Next->MustBreakBefore;
1491 if (IsWrappedConditional(Current))
1492 CurrentState.IsWrappedConditional =
true;
1494 CurrentState.QuestionColumn = State.Column;
1496 const FormatToken *
Previous = Current.Previous;
1500 CurrentState.QuestionColumn = State.Column;
1502 if (!Current.opensScope() && !Current.closesScope() &&
1503 Current.isNot(TT_PointerOrReference)) {
1504 State.LowestLevelOnLine =
1505 std::min(State.LowestLevelOnLine, Current.NestingLevel);
1507 if (Current.isMemberAccess())
1508 CurrentState.StartOfFunctionCall = !Current.NextOperator ? 0 : State.Column;
1509 if (Current.is(TT_SelectorName))
1510 CurrentState.ObjCSelectorNameFound =
true;
1511 if (Current.is(TT_CtorInitializerColon) &&
1522 CurrentState.NestedBlockIndent = CurrentState.Indent;
1524 CurrentState.AvoidBinPacking =
true;
1525 CurrentState.BreakBeforeParameter =
1530 CurrentState.BreakBeforeParameter =
false;
1533 if (Current.is(TT_CtorInitializerColon) &&
1535 CurrentState.Indent =
1537 CurrentState.NestedBlockIndent = CurrentState.Indent;
1539 CurrentState.AvoidBinPacking =
true;
1541 CurrentState.BreakBeforeParameter =
false;
1543 if (Current.is(TT_InheritanceColon)) {
1544 CurrentState.Indent =
1547 if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
1548 CurrentState.NestedBlockIndent = State.Column + Current.ColumnWidth + 1;
1549 if (Current.isOneOf(TT_LambdaLSquare, TT_LambdaArrow))
1550 CurrentState.LastSpace = State.Column;
1551 if (Current.is(TT_RequiresExpression) &&
1553 CurrentState.NestedBlockIndent = State.Column;
1557 const FormatToken *
Previous = Current.getPreviousNonComment();
1565 if (Current.isNot(tok::comment) && !Current.ClosesRequiresClause &&
1567 Previous->isNot(TT_DictLiteral) && State.Stack.size() > 1 &&
1568 !CurrentState.HasMultipleNestedBlocks) {
1569 if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
1570 for (ParenState &PState : llvm::drop_end(State.Stack))
1571 PState.NoLineBreak =
true;
1572 State.Stack[State.Stack.size() - 2].NestedBlockInlined =
false;
1574 if (
Previous && (
Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr) ||
1575 (
Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) &&
1576 !
Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)))) {
1577 CurrentState.NestedBlockInlined =
1581 moveStatePastFakeLParens(State, Newline);
1582 moveStatePastScopeCloser(State);
1585 bool AllowBreak = !State.Stack.back().NoLineBreak &&
1586 !State.Stack.back().NoLineBreakInOperand;
1587 moveStatePastScopeOpener(State, Newline);
1588 moveStatePastFakeRParens(State);
1590 if (Current.is(TT_ObjCStringLiteral) && State.StartOfStringLiteral == 0)
1591 State.StartOfStringLiteral = State.Column + 1;
1592 if (Current.is(TT_CSharpStringLiteral) && State.StartOfStringLiteral == 0) {
1593 State.StartOfStringLiteral = State.Column + 1;
1594 }
else if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
1595 State.StartOfStringLiteral = State.Column;
1596 }
else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
1597 !Current.isStringLiteral()) {
1598 State.StartOfStringLiteral = 0;
1601 State.Column += Current.ColumnWidth;
1602 State.NextToken = State.NextToken->Next;
1607 if (Style.
isVerilog() && State.NextToken &&
1608 State.NextToken->MustBreakBefore &&
1614 handleEndOfLine(Current, State, DryRun, AllowBreak, Newline);
1617 Current.Role->formatFromToken(State,
this, DryRun);
1624 Penalty +=
Previous->Role->formatAfterToken(State,
this, DryRun);
1629void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
1631 const FormatToken &Current = *State.NextToken;
1632 if (Current.FakeLParens.empty())
1635 const FormatToken *
Previous = Current.getPreviousNonComment();
1640 bool SkipFirstExtraIndent =
1643 Previous->isOneOf(tok::semi, tok::kw_return, TT_RequiresClause) ||
1647 for (
const auto &PrecedenceLevel : llvm::reverse(Current.FakeLParens)) {
1648 const auto &CurrentState = State.Stack.back();
1649 ParenState NewParenState = CurrentState;
1650 NewParenState.Tok =
nullptr;
1651 NewParenState.ContainsLineBreak =
false;
1652 NewParenState.LastOperatorWrapped =
true;
1653 NewParenState.IsChainedConditional =
false;
1654 NewParenState.IsWrappedConditional =
false;
1655 NewParenState.UnindentOperator =
false;
1656 NewParenState.NoLineBreak =
1657 NewParenState.NoLineBreak || CurrentState.NoLineBreakInOperand;
1661 NewParenState.AvoidBinPacking =
false;
1666 if (!Current.isTrailingComment() &&
1672 PrecedenceLevel !=
prec::Comma || Current.NestingLevel == 0)) {
1673 NewParenState.Indent = std::max(
1674 std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
1681 NewParenState.Indent = CurrentState.LastSpace;
1691 NewParenState.UnindentOperator =
true;
1694 NewParenState.IsAligned =
true;
1704 NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
1706 Current.isNot(TT_UnaryOperator) &&
1708 NewParenState.StartOfFunctionCall = State.Column;
1718 &PrecedenceLevel == &Current.FakeLParens.back() &&
1719 !CurrentState.IsWrappedConditional) {
1720 NewParenState.IsChainedConditional =
true;
1721 NewParenState.UnindentOperator = State.Stack.back().UnindentOperator;
1724 !Current.isTrailingComment())) {
1728 NewParenState.BreakBeforeParameter =
false;
1729 State.Stack.push_back(NewParenState);
1730 SkipFirstExtraIndent =
false;
1734void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
1735 for (
unsigned i = 0, e = State.NextToken->FakeRParens; i != e; ++i) {
1736 unsigned VariablePos = State.Stack.back().VariablePos;
1737 if (State.Stack.size() == 1) {
1741 State.Stack.pop_back();
1742 State.Stack.back().VariablePos = VariablePos;
1748 State.Stack.back().LastSpace -= Style.
IndentWidth;
1752void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
1754 const FormatToken &Current = *State.NextToken;
1755 if (!Current.opensScope())
1758 const auto &CurrentState = State.Stack.back();
1761 if (Current.isOneOf(tok::less, tok::l_paren) &&
1762 CurrentState.IsCSharpGenericTypeConstraint) {
1766 if (Current.MatchingParen && Current.is(
BK_Block)) {
1767 moveStateToNewBlock(State);
1772 unsigned LastSpace = CurrentState.LastSpace;
1773 bool AvoidBinPacking;
1774 bool BreakBeforeParameter =
false;
1775 unsigned NestedBlockIndent = std::max(CurrentState.StartOfFunctionCall,
1776 CurrentState.NestedBlockIndent);
1777 if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1779 if (Current.opensBlockOrBlockTypeList(Style)) {
1781 std::min(State.Column, CurrentState.NestedBlockIndent);
1782 }
else if (Current.is(tok::l_brace)) {
1789 const FormatToken *NextNonComment = Current.getNextNonComment();
1790 bool EndsInComma = Current.MatchingParen &&
1791 Current.MatchingParen->Previous &&
1792 Current.MatchingParen->Previous->is(tok::comma);
1793 AvoidBinPacking = EndsInComma || Current.is(TT_DictLiteral) ||
1797 (NextNonComment && NextNonComment->isOneOf(
1798 TT_DesignatedInitializerPeriod,
1799 TT_DesignatedInitializerLSquare));
1800 BreakBeforeParameter = EndsInComma;
1801 if (Current.ParameterCount > 1)
1802 NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
1806 std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall);
1812 if (Current.is(tok::less) && Current.ParentBracket == tok::l_paren) {
1813 NewIndent = std::max(NewIndent, CurrentState.Indent);
1814 LastSpace = std::max(LastSpace, CurrentState.Indent);
1818 Current.MatchingParen &&
1819 Current.MatchingParen->getPreviousNonComment() &&
1820 Current.MatchingParen->getPreviousNonComment()->is(tok::comma);
1824 bool ObjCBinPackProtocolList =
1829 bool BinPackDeclaration =
1831 (State.Line->Type ==
LT_ObjCDecl && ObjCBinPackProtocolList);
1833 bool GenericSelection =
1834 Current.getPreviousNonComment() &&
1835 Current.getPreviousNonComment()->is(tok::kw__Generic);
1838 (CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection ||
1840 (State.Line->MustBeDeclaration && !BinPackDeclaration) ||
1846 if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen &&
1853 BreakBeforeParameter =
true;
1858 for (
const FormatToken *Tok = &Current;
1859 Tok && Tok != Current.MatchingParen; Tok = Tok->Next) {
1860 if (Tok->MustBreakBefore ||
1861 (Tok->CanBreakBefore && Tok->NewlinesBefore > 0)) {
1862 BreakBeforeParameter =
true;
1870 BreakBeforeParameter =
true;
1876 Current.Children.empty() &&
1877 !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) &&
1878 (CurrentState.NoLineBreak || CurrentState.NoLineBreakInOperand ||
1879 (Current.is(TT_TemplateOpener) &&
1880 CurrentState.ContainsUnwrappedBuilder));
1881 State.Stack.push_back(
1882 ParenState(&Current, NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
1883 auto &NewState = State.Stack.back();
1884 NewState.NestedBlockIndent = NestedBlockIndent;
1885 NewState.BreakBeforeParameter = BreakBeforeParameter;
1886 NewState.HasMultipleNestedBlocks = (Current.BlockParameterCount > 1);
1889 Current.is(tok::l_paren)) {
1891 FormatToken
const *next = Current.Next;
1893 if (next->is(TT_LambdaLSquare)) {
1894 NewState.HasMultipleNestedBlocks =
true;
1901 NewState.IsInsideObjCArrayLiteral = Current.is(TT_ArrayInitializerLSquare) &&
1903 Current.Previous->is(tok::at);
1906void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
1907 const FormatToken &Current = *State.NextToken;
1908 if (!Current.closesScope())
1913 if (State.Stack.size() > 1 &&
1914 (Current.isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
1915 (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
1916 State.NextToken->is(TT_TemplateCloser) ||
1917 (Current.is(tok::greater) && Current.is(TT_DictLiteral)))) {
1918 State.Stack.pop_back();
1921 auto &CurrentState = State.Stack.back();
1933 if (CurrentState.BreakBeforeParameter && Current.MatchingParen &&
1934 Current.MatchingParen->Previous) {
1935 const FormatToken &CurrentScopeOpener = *Current.MatchingParen->Previous;
1936 if (CurrentScopeOpener.is(TT_ObjCMethodExpr) &&
1937 CurrentScopeOpener.MatchingParen) {
1938 int NecessarySpaceInLine =
1940 CurrentScopeOpener.TotalLength - Current.TotalLength - 1;
1941 if (State.Column + Current.ColumnWidth + NecessarySpaceInLine <=
1943 CurrentState.BreakBeforeParameter =
false;
1948 if (Current.is(tok::r_square)) {
1950 const FormatToken *NextNonComment = Current.getNextNonComment();
1951 if (NextNonComment && NextNonComment->isNot(tok::l_square))
1952 CurrentState.StartOfArraySubscripts = 0;
1956void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
1958 State.NextToken->is(TT_LambdaLBrace) &&
1959 !State.Line->MightBeFunctionDecl) {
1960 State.Stack.back().NestedBlockIndent = State.FirstIndent;
1962 unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
1964 unsigned NewIndent =
1965 NestedBlockIndent + (State.NextToken->is(TT_ObjCBlockLBrace)
1968 State.Stack.push_back(ParenState(State.NextToken, NewIndent,
1969 State.Stack.back().LastSpace,
1972 State.Stack.back().NestedBlockIndent = NestedBlockIndent;
1973 State.Stack.back().BreakBeforeParameter =
true;
1979 size_t LastNewlinePos =
Text.find_last_of(
"\n");
1980 if (LastNewlinePos == StringRef::npos) {
1981 return StartColumn +
1985 0, TabWidth, Encoding);
1989unsigned ContinuationIndenter::reformatRawStringLiteral(
1990 const FormatToken &Current, LineState &State,
1991 const FormatStyle &RawStringStyle,
bool DryRun,
bool Newline) {
1992 unsigned StartColumn = State.Column - Current.ColumnWidth;
1994 StringRef NewDelimiter =
1996 if (NewDelimiter.empty())
1997 NewDelimiter = OldDelimiter;
2000 unsigned OldPrefixSize = 3 + OldDelimiter.size();
2001 unsigned OldSuffixSize = 2 + OldDelimiter.size();
2004 std::string RawText = std::string(
2005 Current.TokenText.substr(OldPrefixSize).drop_back(OldSuffixSize));
2006 if (NewDelimiter != OldDelimiter) {
2009 std::string CanonicalDelimiterSuffix = (
")" + NewDelimiter +
"\"").str();
2010 if (StringRef(RawText).contains(CanonicalDelimiterSuffix))
2011 NewDelimiter = OldDelimiter;
2014 unsigned NewPrefixSize = 3 + NewDelimiter.size();
2015 unsigned NewSuffixSize = 2 + NewDelimiter.size();
2018 unsigned FirstStartColumn = StartColumn + NewPrefixSize;
2029 bool ContentStartsOnNewline = Current.TokenText[OldPrefixSize] ==
'\n';
2051 unsigned CurrentIndent =
2052 (!Newline && Current.Next && Current.Next->is(tok::r_paren))
2053 ? State.Stack.back().NestedBlockIndent
2054 : State.Stack.back().Indent;
2055 unsigned NextStartColumn = ContentStartsOnNewline
2067 unsigned LastStartColumn =
2068 Current.NewlinesBefore ? FirstStartColumn - NewPrefixSize : CurrentIndent;
2071 RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
2072 FirstStartColumn, NextStartColumn, LastStartColumn,
"<stdin>",
2076 tooling::Replacements NoFixes;
2078 return addMultilineToken(Current, State);
2080 if (NewDelimiter != OldDelimiter) {
2083 SourceLocation PrefixDelimiterStart =
2084 Current.Tok.getLocation().getLocWithOffset(2);
2085 auto PrefixErr = Whitespaces.
addReplacement(tooling::Replacement(
2086 SourceMgr, PrefixDelimiterStart, OldDelimiter.size(), NewDelimiter));
2089 <<
"Failed to update the prefix delimiter of a raw string: "
2090 << llvm::toString(std::move(PrefixErr)) <<
"\n";
2094 SourceLocation SuffixDelimiterStart =
2095 Current.Tok.getLocation().getLocWithOffset(Current.TokenText.size() -
2096 1 - OldDelimiter.size());
2097 auto SuffixErr = Whitespaces.
addReplacement(tooling::Replacement(
2098 SourceMgr, SuffixDelimiterStart, OldDelimiter.size(), NewDelimiter));
2101 <<
"Failed to update the suffix delimiter of a raw string: "
2102 << llvm::toString(std::move(SuffixErr)) <<
"\n";
2105 SourceLocation OriginLoc =
2106 Current.Tok.getLocation().getLocWithOffset(OldPrefixSize);
2107 for (
const tooling::Replacement &Fix : Fixes.first) {
2109 SourceMgr, OriginLoc.getLocWithOffset(Fix.getOffset()),
2110 Fix.getLength(), Fix.getReplacementText()));
2112 llvm::errs() <<
"Failed to reformat raw string: "
2113 << llvm::toString(std::move(Err)) <<
"\n";
2118 *NewCode, FirstStartColumn, Style.
TabWidth, Encoding);
2119 State.Column = RawLastLineEndColumn + NewSuffixSize;
2123 unsigned PrefixExcessCharacters =
2128 ContentStartsOnNewline || (NewCode->find(
'\n') != std::string::npos);
2131 for (ParenState &
Paren : State.Stack)
2132 Paren.BreakBeforeParameter =
true;
2137unsigned ContinuationIndenter::addMultilineToken(
const FormatToken &Current,
2140 for (ParenState &
Paren : State.Stack)
2141 Paren.BreakBeforeParameter =
true;
2143 unsigned ColumnsUsed = State.Column;
2146 State.Column = Current.LastLineColumnWidth;
2153unsigned ContinuationIndenter::handleEndOfLine(
const FormatToken &Current,
2154 LineState &State,
bool DryRun,
2155 bool AllowBreak,
bool Newline) {
2156 unsigned Penalty = 0;
2159 auto RawStringStyle = getRawStringStyle(Current, State);
2160 if (RawStringStyle && !Current.Finalized) {
2161 Penalty = reformatRawStringLiteral(Current, State, *RawStringStyle, DryRun,
2163 }
else if (Current.IsMultiline && Current.isNot(TT_BlockComment)) {
2166 Penalty = addMultilineToken(Current, State);
2169 LineState OriginalState = State;
2173 bool Strict =
false;
2176 bool Exceeded =
false;
2177 std::tie(Penalty, Exceeded) = breakProtrudingToken(
2178 Current, State, AllowBreak,
true, Strict);
2182 LineState StrictState = OriginalState;
2183 unsigned StrictPenalty =
2184 breakProtrudingToken(Current, StrictState, AllowBreak,
2187 Strict = StrictPenalty <= Penalty;
2189 Penalty = StrictPenalty;
2190 State = StrictState;
2196 breakProtrudingToken(Current, OriginalState, AllowBreak,
false,
2201 unsigned ExcessCharacters = State.Column -
getColumnLimit(State);
2212 if (!Tok || Tok->isNot(tok::l_paren))
2217 if (Tok->is(TT_TemplateCloser)) {
2222 if (!Tok || Tok->isNot(tok::identifier))
2227std::optional<FormatStyle>
2228ContinuationIndenter::getRawStringStyle(
const FormatToken &Current,
2229 const LineState &State) {
2230 if (!Current.isStringLiteral())
2231 return std::nullopt;
2234 return std::nullopt;
2236 if (!RawStringStyle && Delimiter->empty()) {
2240 if (!RawStringStyle)
2241 return std::nullopt;
2243 return RawStringStyle;
2246std::unique_ptr<BreakableToken>
2247ContinuationIndenter::createBreakableToken(
const FormatToken &Current,
2248 LineState &State,
bool AllowBreak) {
2249 unsigned StartColumn = State.Column - Current.ColumnWidth;
2250 if (Current.isStringLiteral()) {
2267 if (Current.IsUnterminatedLiteral)
2271 if (State.Stack.back().IsInsideObjCArrayLiteral)
2278 if (Style.
isVerilog() && Current.Previous &&
2279 Current.Previous->isOneOf(tok::kw_export, Keywords.
kw_import)) {
2282 StringRef
Text = Current.TokenText;
2288 unsigned UnbreakableTailLength = (State.NextToken &&
canBreak(State))
2290 : Current.UnbreakableTailLength;
2297 }
else if (Style.
isCSharp() &&
Text.startswith(
"@\"") &&
2298 Text.endswith(
"\"")) {
2300 }
else if (
Text.startswith(
"\"") &&
Text.endswith(
"\"")) {
2305 return std::make_unique<BreakableStringLiteralUsingOperators>(
2306 Current, QuoteStyle,
2308 UnbreakableTailLength, State.Line->InPPDirective, Encoding, Style);
2317 if ((
Text.endswith(Postfix =
"\"") &&
2318 (
Text.startswith(Prefix =
"@\"") ||
Text.startswith(Prefix =
"\"") ||
2319 Text.startswith(Prefix =
"u\"") ||
Text.startswith(Prefix =
"U\"") ||
2320 Text.startswith(Prefix =
"u8\"") ||
2321 Text.startswith(Prefix =
"L\""))) ||
2322 (
Text.startswith(Prefix =
"_T(\"") &&
Text.endswith(Postfix =
"\")"))) {
2323 return std::make_unique<BreakableStringLiteral>(
2324 Current, StartColumn, Prefix, Postfix, UnbreakableTailLength,
2325 State.Line->InPPDirective, Encoding, Style);
2327 }
else if (Current.is(TT_BlockComment)) {
2335 return std::make_unique<BreakableBlockComment>(
2336 Current, StartColumn, Current.OriginalColumn, !Current.Previous,
2337 State.Line->InPPDirective, Encoding, Style, Whitespaces.
useCRLF());
2338 }
else if (Current.is(TT_LineComment) &&
2339 (!Current.Previous ||
2340 Current.Previous->isNot(TT_ImplicitStringLiteral))) {
2341 bool RegularComments = [&]() {
2342 for (
const FormatToken *T = &Current; T && T->is(TT_LineComment);
2344 if (!(T->TokenText.startswith(
"//") || T->TokenText.startswith(
"#")))
2350 CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
2354 return std::make_unique<BreakableLineCommentSection>(
2355 Current, StartColumn,
false, Encoding, Style);
2360std::pair<unsigned, bool>
2361ContinuationIndenter::breakProtrudingToken(
const FormatToken &Current,
2362 LineState &State,
bool AllowBreak,
2363 bool DryRun,
bool Strict) {
2364 std::unique_ptr<const BreakableToken> Token =
2365 createBreakableToken(Current, State, AllowBreak);
2368 assert(Token->getLineCount() > 0);
2370 if (Current.is(TT_LineComment)) {
2374 if (ColumnLimit == 0) {
2377 ColumnLimit = std::numeric_limits<
decltype(ColumnLimit)>
::max();
2379 if (Current.UnbreakableTailLength >= ColumnLimit)
2383 unsigned StartColumn = State.Column - Current.ColumnWidth;
2384 unsigned NewBreakPenalty = Current.isStringLiteral()
2389 bool Exceeded =
false;
2391 bool BreakInserted = Token->introducesBreakBeforeToken();
2394 bool NewBreakBefore =
false;
2398 bool Reflow =
false;
2401 unsigned TailOffset = 0;
2403 unsigned ContentStartColumn =
2404 Token->getContentStartColumn(0,
false);
2406 unsigned RemainingTokenColumns =
2407 Token->getRemainingLength(0, TailOffset, ContentStartColumn);
2410 Token->adaptStartOfLine(0, Whitespaces);
2412 unsigned ContentIndent = 0;
2413 unsigned Penalty = 0;
2414 LLVM_DEBUG(llvm::dbgs() <<
"Breaking protruding token at column "
2415 << StartColumn <<
".\n");
2416 for (
unsigned LineIndex = 0, EndIndex = Token->getLineCount();
2417 LineIndex != EndIndex; ++LineIndex) {
2418 LLVM_DEBUG(llvm::dbgs()
2419 <<
" Line: " << LineIndex <<
" (Reflow: " << Reflow <<
")\n");
2420 NewBreakBefore =
false;
2424 bool TryReflow = Reflow;
2426 while (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2427 LLVM_DEBUG(llvm::dbgs() <<
" Over limit, need: "
2428 << (ContentStartColumn + RemainingTokenColumns)
2429 <<
", space: " << ColumnLimit
2430 <<
", reflown prefix: " << ContentStartColumn
2431 <<
", offset in line: " << TailOffset <<
"\n");
2437 Token->getSplit(LineIndex, TailOffset, ColumnLimit,
2438 ContentStartColumn, CommentPragmasRegex);
2439 if (
Split.first == StringRef::npos) {
2442 if (LineIndex < EndIndex - 1) {
2446 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2448 LLVM_DEBUG(llvm::dbgs() <<
" No break opportunity.\n");
2451 assert(
Split.first != 0);
2453 if (Token->supportsReflow()) {
2473 unsigned ToSplitColumns = Token->getRangeLength(
2474 LineIndex, TailOffset,
Split.first, ContentStartColumn);
2475 LLVM_DEBUG(llvm::dbgs() <<
" ToSplit: " << ToSplitColumns <<
"\n");
2478 LineIndex, TailOffset +
Split.first +
Split.second, ColumnLimit,
2479 ContentStartColumn + ToSplitColumns + 1, CommentPragmasRegex);
2482 unsigned ToNextSplitColumns = 0;
2483 if (NextSplit.first == StringRef::npos) {
2484 ToNextSplitColumns = Token->getRemainingLength(LineIndex, TailOffset,
2485 ContentStartColumn);
2487 ToNextSplitColumns = Token->getRangeLength(
2488 LineIndex, TailOffset,
2489 Split.first +
Split.second + NextSplit.first, ContentStartColumn);
2493 ToNextSplitColumns =
2494 Token->getLengthAfterCompression(ToNextSplitColumns, Split);
2495 LLVM_DEBUG(llvm::dbgs()
2496 <<
" ContentStartColumn: " << ContentStartColumn <<
"\n");
2497 LLVM_DEBUG(llvm::dbgs()
2498 <<
" ToNextSplit: " << ToNextSplitColumns <<
"\n");
2501 bool ContinueOnLine =
2502 ContentStartColumn + ToNextSplitColumns <= ColumnLimit;
2503 unsigned ExcessCharactersPenalty = 0;
2504 if (!ContinueOnLine && !Strict) {
2507 ExcessCharactersPenalty =
2508 (ContentStartColumn + ToNextSplitColumns - ColumnLimit) *
2510 LLVM_DEBUG(llvm::dbgs()
2511 <<
" Penalty excess: " << ExcessCharactersPenalty
2512 <<
"\n break : " << NewBreakPenalty <<
"\n");
2513 if (ExcessCharactersPenalty < NewBreakPenalty) {
2515 ContinueOnLine =
true;
2518 if (ContinueOnLine) {
2519 LLVM_DEBUG(llvm::dbgs() <<
" Continuing on line...\n");
2524 Token->compressWhitespace(LineIndex, TailOffset, Split,
2528 ContentStartColumn += ToSplitColumns + 1;
2529 Penalty += ExcessCharactersPenalty;
2531 RemainingTokenColumns = Token->getRemainingLength(
2532 LineIndex, TailOffset, ContentStartColumn);
2536 LLVM_DEBUG(llvm::dbgs() <<
" Breaking...\n");
2541 ContentIndent = Token->getContentIndent(LineIndex);
2542 LLVM_DEBUG(llvm::dbgs()
2543 <<
" ContentIndent: " << ContentIndent <<
"\n");
2544 ContentStartColumn = ContentIndent + Token->getContentStartColumn(
2547 unsigned NewRemainingTokenColumns = Token->getRemainingLength(
2548 LineIndex, TailOffset +
Split.first +
Split.second,
2549 ContentStartColumn);
2550 if (NewRemainingTokenColumns == 0) {
2553 ContentStartColumn =
2554 Token->getContentStartColumn(LineIndex,
true);
2555 NewRemainingTokenColumns = Token->getRemainingLength(
2556 LineIndex, TailOffset +
Split.first +
Split.second,
2557 ContentStartColumn);
2563 if (NewRemainingTokenColumns >= RemainingTokenColumns) {
2568 LLVM_DEBUG(llvm::dbgs() <<
" Breaking at: " << TailOffset +
Split.first
2569 <<
", " <<
Split.second <<
"\n");
2571 Token->insertBreak(LineIndex, TailOffset, Split, ContentIndent,
2575 Penalty += NewBreakPenalty;
2577 RemainingTokenColumns = NewRemainingTokenColumns;
2578 BreakInserted =
true;
2579 NewBreakBefore =
true;
2583 if (LineIndex + 1 != EndIndex) {
2584 unsigned NextLineIndex = LineIndex + 1;
2585 if (NewBreakBefore) {
2604 ContentStartColumn += RemainingTokenColumns + 1;
2609 Token->getReflowSplit(NextLineIndex, CommentPragmasRegex);
2610 LLVM_DEBUG(llvm::dbgs()
2611 <<
" Size of reflown text: " << ContentStartColumn
2612 <<
"\n Potential reflow split: ");
2613 if (SplitBeforeNext.first != StringRef::npos) {
2614 LLVM_DEBUG(llvm::dbgs() << SplitBeforeNext.first <<
", "
2615 << SplitBeforeNext.second <<
"\n");
2616 TailOffset = SplitBeforeNext.first + SplitBeforeNext.second;
2619 RemainingTokenColumns = Token->getRemainingLength(
2620 NextLineIndex, TailOffset, ContentStartColumn);
2622 if (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2623 LLVM_DEBUG(llvm::dbgs()
2624 <<
" Over limit after reflow, need: "
2625 << (ContentStartColumn + RemainingTokenColumns)
2626 <<
", space: " << ColumnLimit
2627 <<
", reflown prefix: " << ContentStartColumn
2628 <<
", offset in line: " << TailOffset <<
"\n");
2634 Token->getSplit(NextLineIndex, TailOffset, ColumnLimit,
2635 ContentStartColumn, CommentPragmasRegex);
2636 if (
Split.first == StringRef::npos) {
2637 LLVM_DEBUG(llvm::dbgs() <<
" Did not find later break\n");
2643 unsigned ToSplitColumns = Token->getRangeLength(
2644 NextLineIndex, TailOffset,
Split.first, ContentStartColumn);
2645 if (ContentStartColumn + ToSplitColumns > ColumnLimit) {
2646 LLVM_DEBUG(llvm::dbgs() <<
" Next split protrudes, need: "
2647 << (ContentStartColumn + ToSplitColumns)
2648 <<
", space: " << ColumnLimit);
2649 unsigned ExcessCharactersPenalty =
2650 (ContentStartColumn + ToSplitColumns - ColumnLimit) *
2652 if (NewBreakPenalty < ExcessCharactersPenalty)
2658 LLVM_DEBUG(llvm::dbgs() <<
"not found.\n");
2666 ContentStartColumn =
2667 Token->getContentStartColumn(NextLineIndex,
false);
2668 RemainingTokenColumns = Token->getRemainingLength(
2669 NextLineIndex, TailOffset, ContentStartColumn);
2672 Token->adaptStartOfLine(NextLineIndex, Whitespaces);
2687 if (NewBreakBefore) {
2688 assert(Penalty >= NewBreakPenalty);
2689 Penalty -= NewBreakPenalty;
2692 Token->reflow(NextLineIndex, Whitespaces);
2698 Token->getSplitAfterLastLine(TailOffset);
2699 if (SplitAfterLastLine.first != StringRef::npos) {
2700 LLVM_DEBUG(llvm::dbgs() <<
"Replacing whitespace after last line.\n");
2705 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2708 Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
2711 ContentStartColumn =
2712 Token->getContentStartColumn(Token->getLineCount() - 1,
true);
2713 RemainingTokenColumns = Token->getRemainingLength(
2714 Token->getLineCount() - 1,
2715 TailOffset + SplitAfterLastLine.first + SplitAfterLastLine.second,
2716 ContentStartColumn);
2719 State.Column = ContentStartColumn + RemainingTokenColumns -
2720 Current.UnbreakableTailLength;
2722 if (BreakInserted) {
2724 Token->updateAfterBroken(Whitespaces);
2729 if (Current.isNot(TT_LineComment))
2730 for (ParenState &
Paren : State.Stack)
2731 Paren.BreakBeforeParameter =
true;
2733 if (Current.is(TT_BlockComment))
2734 State.NoContinuation =
true;
2736 State.Stack.back().LastSpace = StartColumn;
2739 Token->updateNextToken(State);
2741 return {Penalty, Exceeded};
2746 return Style.
ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
2749bool ContinuationIndenter::nextIsMultilineString(
const LineState &State) {
2751 if (!Current.isStringLiteral() || Current.is(TT_ImplicitStringLiteral))
2756 if (Current.TokenText.startswith(
"R\""))
2758 if (Current.IsMultiline)
2760 if (Current.getNextNonComment() &&
2761 Current.getNextNonComment()->isStringLiteral()) {
2765 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()))