23#include "llvm/ADT/StringSet.h"
24#include "llvm/Support/Debug.h"
27#define DEBUG_TYPE "format-indenter"
44 Previous->isOneOf(tok::kw_return, TT_RequiresClause));
93 int MatchingStackIndex = Stack.size() - 1;
99 while (MatchingStackIndex >= 0 && Stack[MatchingStackIndex].Tok != LBrace)
100 --MatchingStackIndex;
101 return MatchingStackIndex >= 0 ? &Stack[MatchingStackIndex] :
nullptr;
103 for (; End->Next; End = End->Next) {
104 if (End->Next->CanBreakBefore)
106 if (!End->Next->closesScope())
108 if (End->Next->MatchingParen &&
109 End->Next->MatchingParen->isOneOf(
110 tok::l_brace, TT_ArrayInitializerLSquare, tok::less)) {
111 const ParenState *State = FindParenState(End->Next->MatchingParen);
112 if (State && State->BreakBeforeClosingBrace)
135 if (Current.
is(TT_CtorInitializerComma) &&
142 ((
Previous.isNot(TT_CtorInitializerComma) ||
145 (
Previous.isNot(TT_InheritanceComma) ||
151 if (LessTok.
isNot(tok::less))
163 if (TokenText.size() < 5
164 || !TokenText.starts_with(
"R\"") || !TokenText.ends_with(
"\"")) {
171 size_t LParenPos = TokenText.substr(0, 19).find_first_of(
'(');
172 if (LParenPos == StringRef::npos)
174 StringRef Delimiter = TokenText.substr(2, LParenPos - 2);
177 size_t RParenPos = TokenText.size() - Delimiter.size() - 2;
178 if (TokenText[RParenPos] !=
')')
180 if (!TokenText.substr(RParenPos + 1).starts_with(Delimiter))
192 return StringRef(Format.CanonicalDelimiter);
199 std::optional<FormatStyle> LanguageStyle =
201 if (!LanguageStyle) {
204 RawStringFormat.Language, &PredefinedStyle)) {
206 PredefinedStyle.
Language = RawStringFormat.Language;
208 LanguageStyle = PredefinedStyle;
211 for (StringRef Delimiter : RawStringFormat.Delimiters)
213 for (StringRef EnclosingFunction : RawStringFormat.EnclosingFunctions)
218std::optional<FormatStyle>
226std::optional<FormatStyle>
228 StringRef EnclosingFunction)
const {
240 bool BinPackInconclusiveFunctions)
241 : Style(Style), Keywords(Keywords), SourceMgr(SourceMgr),
242 Whitespaces(Whitespaces), Encoding(Encoding),
243 BinPackInconclusiveFunctions(BinPackInconclusiveFunctions),
244 CommentPragmasRegex(Style.CommentPragmas), RawStringFormats(Style) {}
247 unsigned FirstStartColumn,
251 State.FirstIndent = FirstIndent;
252 if (FirstStartColumn &&
Line->First->NewlinesBefore == 0)
253 State.Column = FirstStartColumn;
255 State.Column = FirstIndent;
265 State.NextToken =
Line->First;
266 State.Stack.push_back(
ParenState(
nullptr, FirstIndent, FirstIndent,
269 State.NoContinuation =
false;
270 State.StartOfStringLiteral = 0;
271 State.NoLineBreak =
false;
272 State.StartOfLineLevel = 0;
273 State.LowestLevelOnLine = 0;
274 State.IgnoreStackForComparison =
false;
279 auto &CurrentState = State.Stack.back();
280 CurrentState.AvoidBinPacking =
true;
281 CurrentState.BreakBeforeParameter =
true;
282 CurrentState.AlignColons =
false;
286 moveStateToNextToken(State, DryRun,
false);
293 const auto &CurrentState = State.Stack.back();
294 assert(&
Previous == Current.Previous);
295 if (!Current.CanBreakBefore && !(CurrentState.BreakBeforeClosingBrace &&
296 Current.closesBlockOrBlockTypeList(Style))) {
301 if (!Current.MustBreakBefore &&
Previous.is(tok::l_brace) &&
304 Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma)) {
313 State.LowestLevelOnLine < State.StartOfLineLevel &&
314 State.LowestLevelOnLine < Current.NestingLevel) {
317 if (Current.isMemberAccess() && CurrentState.ContainsUnwrappedBuilder)
322 if (
Previous.is(tok::l_brace) && State.Stack.size() > 1 &&
323 State.Stack[State.Stack.size() - 2].NestedBlockInlined &&
324 State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks &&
331 if (Current.is(TT_FunctionDeclarationName)) {
338 assert(State.Column >= State.FirstIndent);
339 if (State.Column - State.FirstIndent < 6)
346 if (!Current.isOneOf(TT_BinaryOperator, tok::comma) &&
351 Current.isNot(TT_LambdaLBrace)) &&
352 CurrentState.NoLineBreakInOperand) {
359 if (Current.is(TT_ConditionalExpr) &&
Previous.is(tok::r_paren) &&
361 Previous.MatchingParen->Previous->MatchingParen &&
362 Previous.MatchingParen->Previous->MatchingParen->is(TT_LambdaLBrace)) {
364 assert(
Previous.MatchingParen->Previous->is(tok::r_brace));
368 return !State.NoLineBreak && !CurrentState.NoLineBreak;
374 const auto &CurrentState = State.Stack.back();
376 Current.is(TT_LambdaLBrace) &&
Previous.isNot(TT_LineComment)) {
380 if (Current.MustBreakBefore ||
381 (Current.is(TT_InlineASMColon) &&
387 if (CurrentState.BreakBeforeClosingBrace &&
388 (Current.closesBlockOrBlockTypeList(Style) ||
389 (Current.is(tok::r_brace) &&
390 Current.isBlockIndentedInitRBrace(Style)))) {
393 if (CurrentState.BreakBeforeClosingParen && Current.is(tok::r_paren))
397 Current.ObjCSelectorNameParts > 1 &&
398 Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)) {
403 if (CurrentState.IsCSharpGenericTypeConstraint &&
404 Previous.isNot(TT_CSharpGenericTypeConstraintComma)) {
408 (
Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) &&
409 State.Line->First->isNot(TT_AttributeSquare) && Style.
isCpp() &&
418 Previous.is(TT_ConditionalExpr))) &&
419 CurrentState.BreakBeforeParameter && !Current.isTrailingComment() &&
420 !Current.isOneOf(tok::r_paren, tok::r_brace)) {
423 if (CurrentState.IsChainedConditional &&
425 Current.is(tok::colon)) ||
431 (
Previous.is(TT_ArrayInitializerLSquare) &&
440 const FormatToken &BreakConstructorInitializersToken =
444 if (BreakConstructorInitializersToken.
is(TT_CtorInitializerColon) &&
445 (State.Column + State.Line->Last->TotalLength -
Previous.TotalLength >
447 CurrentState.BreakBeforeParameter) &&
448 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
455 if (Current.is(TT_ObjCMethodExpr) &&
Previous.isNot(TT_SelectorName) &&
456 State.Line->startsWith(TT_ObjCMethodSpecifier)) {
459 if (Current.is(TT_SelectorName) &&
Previous.isNot(tok::at) &&
460 CurrentState.ObjCSelectorNameFound && CurrentState.BreakBeforeParameter &&
462 !Current.startsSequence(TT_SelectorName, tok::colon, tok::caret))) {
466 unsigned NewLineColumn = getNewLineColumn(State);
467 if (Current.isMemberAccess() && Style.
ColumnLimit != 0 &&
469 (State.Column > NewLineColumn ||
470 Current.NestingLevel < State.StartOfLineLevel)) {
475 (CurrentState.CallContinuation != 0 ||
476 CurrentState.BreakBeforeParameter) &&
482 !(State.Column <= NewLineColumn && Style.
isJavaScript()) &&
483 !(
Previous.closesScopeAfterBlock() && State.Column <= NewLineColumn)) {
489 if (
Previous.ClosesTemplateDeclaration && CurrentState.BreakBeforeParameter &&
490 Current.CanBreakBefore) {
494 if (State.Line->First->isNot(tok::kw_enum) && State.Column <= NewLineColumn)
499 Previous.is(tok::comma) || Current.NestingLevel < 2) &&
500 !
Previous.isOneOf(tok::kw_return, tok::lessless, tok::at,
502 !
Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
503 nextIsMultilineString(State)) {
510 if (
Previous.is(TT_BinaryOperator) && Current.CanBreakBefore) {
511 const auto PreviousPrecedence =
Previous.getPrecedence();
513 CurrentState.BreakBeforeParameter && !Current.isTrailingComment()) {
514 const bool LHSIsBinaryExpr =
527 const bool IsComparison =
532 Previous.Previous->isNot(TT_BinaryOperator);
536 }
else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore &&
537 CurrentState.BreakBeforeParameter) {
542 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator) &&
543 CurrentState.BreakBeforeParameter && CurrentState.FirstLessLess == 0) {
547 if (Current.NestingLevel == 0 && !Current.isTrailingComment()) {
552 if (
Previous.ClosesTemplateDeclaration) {
553 if (Current.is(tok::kw_concept)) {
563 if (Current.is(TT_RequiresClause)) {
574 Current.NewlinesBefore > 0);
576 if (
Previous.is(TT_FunctionAnnotationRParen) &&
580 if (
Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) &&
581 Current.isNot(TT_LeadingJavaAnnotation)) {
590 static const llvm::StringSet<> BreakBeforeDecoratedTokens = {
"get",
"set",
592 if (BreakBeforeDecoratedTokens.contains(Current.TokenText))
596 if (Current.is(TT_FunctionDeclarationName) &&
597 !State.Line->ReturnTypeWrapped &&
604 CurrentState.BreakBeforeParameter) {
613 !Current.isOneOf(tok::r_brace, tok::comment)) {
617 if (Current.is(tok::lessless) &&
620 Previous.TokenText ==
"\'\\n\'")))) {
627 if (State.NoContinuation)
635 unsigned ExtraSpaces) {
637 assert(State.NextToken->Previous);
640 assert(!State.Stack.empty());
641 State.NoContinuation =
false;
643 if (Current.is(TT_ImplicitStringLiteral) &&
644 (!
Previous.Tok.getIdentifierInfo() ||
645 Previous.Tok.getIdentifierInfo()->getPPKeywordID() ==
646 tok::pp_not_keyword)) {
649 if (Current.LastNewlineOffset != 0) {
652 State.Column = EndColumn;
654 unsigned StartColumn =
656 assert(EndColumn >= StartColumn);
657 State.Column += EndColumn - StartColumn;
659 moveStateToNextToken(State, DryRun,
false);
663 unsigned Penalty = 0;
665 Penalty = addTokenOnNewLine(State, DryRun);
667 addTokenOnCurrentLine(State, DryRun, ExtraSpaces);
669 return moveStateToNextToken(State, DryRun, Newline) + Penalty;
672void ContinuationIndenter::addTokenOnCurrentLine(
LineState &State,
bool DryRun,
673 unsigned ExtraSpaces) {
675 assert(State.NextToken->Previous);
677 auto &CurrentState = State.Stack.back();
679 bool DisallowLineBreaksOnThisLine =
681 Style.
isCpp() && [&Current] {
687 auto PrevNonComment = Current.getPreviousNonComment();
688 if (!PrevNonComment || PrevNonComment->isNot(tok::l_paren))
690 if (Current.isOneOf(tok::comment, tok::l_paren, TT_LambdaLSquare))
692 auto BlockParameterCount = PrevNonComment->BlockParameterCount;
693 if (BlockParameterCount == 0)
697 if (BlockParameterCount > 1)
701 if (!PrevNonComment->Role)
703 auto Comma = PrevNonComment->Role->lastComma();
706 auto Next = Comma->getNextNonComment();
708 !Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret);
711 if (DisallowLineBreaksOnThisLine)
712 State.NoLineBreak =
true;
714 if (Current.is(tok::equal) &&
715 (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&
716 CurrentState.VariablePos == 0 &&
718 Previous.Previous->isNot(TT_DesignatedInitializerPeriod))) {
719 CurrentState.VariablePos = State.Column;
722 while (Tok && CurrentState.VariablePos >= Tok->ColumnWidth) {
723 CurrentState.VariablePos -= Tok->ColumnWidth;
724 if (Tok->SpacesRequiredBefore != 0)
728 if (
Previous.PartOfMultiVariableDeclStmt)
729 CurrentState.LastSpace = CurrentState.VariablePos;
732 unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces;
735 int PPColumnCorrection = 0;
737 Previous.is(tok::hash) && State.FirstIndent > 0 &&
741 Spaces += State.FirstIndent;
748 PPColumnCorrection = -1;
753 State.Column + Spaces + PPColumnCorrection,
754 false, State.Line->InMacroBody);
760 Current.is(TT_InheritanceColon)) {
761 CurrentState.NoLineBreak =
true;
765 CurrentState.NoLineBreak =
true;
768 if (Current.is(TT_SelectorName) && !CurrentState.ObjCSelectorNameFound) {
769 unsigned MinIndent = std::max(
771 unsigned FirstColonPos = State.Column + Spaces + Current.ColumnWidth;
772 if (Current.LongestObjCSelectorName == 0)
773 CurrentState.AlignColons =
false;
774 else if (MinIndent + Current.LongestObjCSelectorName > FirstColonPos)
775 CurrentState.ColonPos = MinIndent + Current.LongestObjCSelectorName;
777 CurrentState.ColonPos = FirstColonPos;
784 auto IsOpeningBracket = [&](
const FormatToken &Tok) {
785 auto IsStartOfBracedList = [&]() {
786 return Tok.is(tok::l_brace) && Tok.isNot(
BK_Block) &&
789 if (!Tok.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) &&
790 !IsStartOfBracedList()) {
795 if (Tok.Previous->isIf())
797 return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while,
802 IsOpeningBracket(
Previous) && State.Column > getNewLineColumn(State) &&
810 Current.FakeLParens.size() > 0 &&
812 CurrentState.NoLineBreak =
true;
815 CurrentState.NoLineBreak =
true;
822 !CurrentState.IsCSharpGenericTypeConstraint &&
Previous.opensScope() &&
824 Previous.isNot(TT_TableGenDAGArgOpener) &&
825 Previous.isNot(TT_TableGenDAGArgOpenerToBreak) &&
826 !(Current.MacroParent &&
Previous.MacroParent) &&
827 (Current.isNot(TT_LineComment) ||
829 CurrentState.Indent = State.Column + Spaces;
830 CurrentState.IsAligned =
true;
833 CurrentState.NoLineBreak =
true;
835 State.Column > getNewLineColumn(State)) {
836 CurrentState.ContainsUnwrappedBuilder =
true;
839 if (Current.is(TT_TrailingReturnArrow) &&
841 CurrentState.NoLineBreak =
true;
843 if (Current.isMemberAccess() &&
Previous.is(tok::r_paren) &&
852 CurrentState.NoLineBreak =
true;
859 const FormatToken *
P = Current.getPreviousNonComment();
860 if (Current.isNot(tok::comment) &&
P &&
861 (
P->isOneOf(TT_BinaryOperator, tok::comma) ||
862 (
P->is(TT_ConditionalExpr) &&
P->is(tok::colon))) &&
863 !
P->isOneOf(TT_OverloadedOperator, TT_CtorInitializerComma) &&
867 bool BreakBeforeOperator =
868 P->MustBreakBefore ||
P->is(tok::lessless) ||
869 (
P->is(TT_BinaryOperator) &&
875 bool HasTwoOperands =
P->OperatorIndex == 0 && !
P->NextOperator &&
876 P->isNot(TT_ConditionalExpr);
877 if ((!BreakBeforeOperator &&
880 (!CurrentState.LastOperatorWrapped && BreakBeforeOperator)) {
881 CurrentState.NoLineBreakInOperand =
true;
885 State.Column += Spaces;
886 if (Current.isNot(tok::comment) &&
Previous.is(tok::l_paren) &&
891 CurrentState.LastSpace = State.Column;
892 CurrentState.NestedBlockIndent = State.Column;
893 }
else if (!Current.isOneOf(tok::comment, tok::caret) &&
895 Previous.isNot(TT_OverloadedOperator)) ||
897 CurrentState.LastSpace = State.Column;
898 }
else if (
Previous.is(TT_CtorInitializerColon) &&
899 (!Current.isTrailingComment() || Current.NewlinesBefore > 0) &&
902 CurrentState.Indent = State.Column;
903 CurrentState.LastSpace = State.Column;
904 }
else if (
Previous.isOneOf(TT_ConditionalExpr, TT_CtorInitializerColon)) {
905 CurrentState.LastSpace = State.Column;
906 }
else if (
Previous.is(TT_BinaryOperator) &&
910 Current.StartsBinaryExpression)) {
914 CurrentState.LastSpace = State.Column;
915 }
else if (
Previous.is(TT_InheritanceColon)) {
916 CurrentState.Indent = State.Column;
917 CurrentState.LastSpace = State.Column;
918 }
else if (Current.is(TT_CSharpGenericTypeConstraintColon)) {
919 CurrentState.ColonPos = State.Column;
927 const FormatToken *Next =
Previous.MatchingParen->getNextNonComment();
928 if (Next && Next->isMemberAccess() && State.Stack.size() > 1 &&
929 State.Stack[State.Stack.size() - 2].CallContinuation == 0) {
930 CurrentState.LastSpace = State.Column;
936unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
938 FormatToken &Current = *State.NextToken;
939 assert(State.NextToken->Previous);
940 const FormatToken &
Previous = *State.NextToken->Previous;
941 auto &CurrentState = State.Stack.back();
945 unsigned Penalty = 0;
947 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
948 const FormatToken *NextNonComment =
Previous.getNextNonComment();
950 NextNonComment = &Current;
953 if (!CurrentState.ContainsLineBreak)
955 CurrentState.ContainsLineBreak =
true;
957 Penalty += State.NextToken->SplitPenalty;
962 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess == 0 &&
964 CurrentState.BreakBeforeParameter)) {
968 State.Column = getNewLineColumn(State);
982 if (State.Column > State.FirstIndent) {
997 if (Current.isNot(TT_TrailingReturnArrow) &&
999 !PreviousNonComment || PreviousNonComment->isNot(tok::equal) ||
1001 CurrentState.NestedBlockIndent = State.Column;
1004 if (NextNonComment->isMemberAccess()) {
1005 if (CurrentState.CallContinuation == 0)
1006 CurrentState.CallContinuation = State.Column;
1007 }
else if (NextNonComment->is(TT_SelectorName)) {
1008 if (!CurrentState.ObjCSelectorNameFound) {
1009 if (NextNonComment->LongestObjCSelectorName == 0) {
1010 CurrentState.AlignColons =
false;
1012 CurrentState.ColonPos =
1014 ? std::max(CurrentState.Indent,
1016 : CurrentState.Indent) +
1018 NextNonComment->ColumnWidth);
1020 }
else if (CurrentState.AlignColons &&
1021 CurrentState.ColonPos <= NextNonComment->ColumnWidth) {
1022 CurrentState.ColonPos = State.Column + NextNonComment->ColumnWidth;
1024 }
else if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
1025 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
1035 if (State.Stack.size() > 1) {
1036 State.Stack[State.Stack.size() - 2].LastSpace =
1037 std::max(CurrentState.LastSpace, CurrentState.Indent) +
1042 if ((PreviousNonComment &&
1043 PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
1044 !CurrentState.AvoidBinPacking) ||
1046 CurrentState.BreakBeforeParameter =
false;
1048 if (PreviousNonComment &&
1049 (PreviousNonComment->isOneOf(TT_TemplateCloser, TT_JavaAnnotation) ||
1050 PreviousNonComment->ClosesRequiresClause) &&
1051 Current.NestingLevel == 0) {
1052 CurrentState.BreakBeforeParameter =
false;
1054 if (NextNonComment->is(tok::question) ||
1055 (PreviousNonComment && PreviousNonComment->is(tok::question))) {
1056 CurrentState.BreakBeforeParameter =
true;
1058 if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore)
1059 CurrentState.BreakBeforeParameter =
false;
1063 if (Current.is(tok::r_brace) && Current.MatchingParen &&
1066 !Current.MatchingParen->Children.empty()) {
1070 MaxEmptyLinesToKeep = 1;
1073 std::max(1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
1074 bool ContinuePPDirective =
1077 CurrentState.IsAligned, ContinuePPDirective);
1080 if (!Current.isTrailingComment())
1081 CurrentState.LastSpace = State.Column;
1082 if (Current.is(tok::lessless)) {
1086 CurrentState.LastSpace += 3;
1089 State.StartOfLineLevel = Current.NestingLevel;
1090 State.LowestLevelOnLine = Current.NestingLevel;
1094 bool NestedBlockSpecialCase =
1095 (!Style.
isCpp() && Current.is(tok::r_brace) && State.Stack.size() > 1 &&
1096 State.Stack[State.Stack.size() - 2].NestedBlockInlined) ||
1100 NestedBlockSpecialCase =
1101 NestedBlockSpecialCase ||
1102 (Current.MatchingParen &&
1103 Current.MatchingParen->is(TT_RequiresExpressionLBrace));
1104 if (!NestedBlockSpecialCase) {
1105 auto ParentLevelIt = std::next(State.Stack.rbegin());
1107 Current.MatchingParen && Current.MatchingParen->is(TT_LambdaLBrace)) {
1122 auto FindCurrentLevel = [&](
const auto &It) {
1123 return std::find_if(It, State.Stack.rend(), [](
const auto &PState) {
1124 return PState.Tok != nullptr;
1127 auto MaybeIncrement = [&](
const auto &It) {
1128 return It != State.Stack.rend() ? std::next(It) : It;
1130 auto LambdaLevelIt = FindCurrentLevel(State.Stack.rbegin());
1131 auto LevelContainingLambdaIt =
1132 FindCurrentLevel(MaybeIncrement(LambdaLevelIt));
1133 ParentLevelIt = MaybeIncrement(LevelContainingLambdaIt);
1135 for (
auto I = ParentLevelIt, E = State.Stack.rend(); I != E; ++I)
1136 I->BreakBeforeParameter =
true;
1139 if (PreviousNonComment &&
1140 !PreviousNonComment->isOneOf(tok::comma, tok::colon, tok::semi) &&
1141 ((PreviousNonComment->isNot(TT_TemplateCloser) &&
1142 !PreviousNonComment->ClosesRequiresClause) ||
1143 Current.NestingLevel != 0) &&
1144 !PreviousNonComment->isOneOf(
1145 TT_BinaryOperator, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
1146 TT_LeadingJavaAnnotation) &&
1147 Current.isNot(TT_BinaryOperator) && !PreviousNonComment->opensScope() &&
1151 Current.isNot(TT_LambdaLBrace))) {
1152 CurrentState.BreakBeforeParameter =
true;
1157 if (PreviousNonComment &&
1158 (PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1160 CurrentState.BreakBeforeClosingBrace =
true;
1163 if (PreviousNonComment && PreviousNonComment->is(tok::l_paren)) {
1164 CurrentState.BreakBeforeClosingParen =
1168 if (CurrentState.AvoidBinPacking) {
1173 bool PreviousIsBreakingCtorInitializerColon =
1174 PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1176 bool AllowAllConstructorInitializersOnNextLine =
1179 if (!(
Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
1180 PreviousIsBreakingCtorInitializerColon) ||
1182 State.Line->MustBeDeclaration) ||
1184 !State.Line->MustBeDeclaration) ||
1185 (!AllowAllConstructorInitializersOnNextLine &&
1186 PreviousIsBreakingCtorInitializerColon) ||
1188 CurrentState.BreakBeforeParameter =
true;
1194 if (PreviousIsBreakingCtorInitializerColon &&
1195 AllowAllConstructorInitializersOnNextLine) {
1196 CurrentState.BreakBeforeParameter =
false;
1203unsigned ContinuationIndenter::getNewLineColumn(
const LineState &State) {
1204 if (!State.NextToken || !State.NextToken->Previous)
1207 FormatToken &Current = *State.NextToken;
1208 const auto &CurrentState = State.Stack.back();
1210 if (CurrentState.IsCSharpGenericTypeConstraint &&
1211 Current.isNot(TT_CSharpGenericTypeConstraint)) {
1212 return CurrentState.ColonPos + 2;
1215 const FormatToken &
Previous = *Current.Previous;
1217 unsigned ContinuationIndent =
1218 std::max(CurrentState.LastSpace, CurrentState.Indent) +
1220 const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
1221 const FormatToken *NextNonComment =
Previous.getNextNonComment();
1222 if (!NextNonComment)
1223 NextNonComment = &Current;
1228 return std::max(CurrentState.LastSpace,
1234 if (Style.
isVerilog() && PreviousNonComment &&
1236 return State.FirstIndent;
1240 State.Line->First->is(tok::kw_enum)) {
1241 return (Style.
IndentWidth * State.Line->First->IndentLevel) +
1245 if ((NextNonComment->is(tok::l_brace) && NextNonComment->is(
BK_Block)) ||
1247 if (Current.NestingLevel == 0 ||
1249 State.NextToken->is(TT_LambdaLBrace))) {
1250 return State.FirstIndent;
1252 return CurrentState.Indent;
1254 if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
1256 State.Stack.size() > 1) {
1257 if (Current.closesBlockOrBlockTypeList(Style))
1258 return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
1259 if (Current.MatchingParen && Current.MatchingParen->is(
BK_BracedInit))
1260 return State.Stack[State.Stack.size() - 2].LastSpace;
1261 return State.FirstIndent;
1278 if (Current.is(tok::r_paren) && State.Stack.size() > 1 &&
1280 Current.Next->isOneOf(tok::semi, tok::kw_const, tok::l_brace))) {
1281 return State.Stack[State.Stack.size() - 2].LastSpace;
1285 if (Style.
isTableGen() && Current.is(TT_TableGenDAGArgCloser) &&
1286 State.Stack.size() > 1) {
1287 return State.Stack[State.Stack.size() - 2].LastSpace;
1290 (Current.is(tok::r_paren) ||
1291 (Current.is(tok::r_brace) && Current.MatchingParen &&
1293 State.Stack.size() > 1) {
1294 return State.Stack[State.Stack.size() - 2].LastSpace;
1296 if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
1297 return State.Stack[State.Stack.size() - 2].LastSpace;
1305 if (Current.is(tok::identifier) && Current.Next &&
1306 (!Style.
isVerilog() || Current.Next->is(tok::colon)) &&
1307 (Current.Next->is(TT_DictLiteral) ||
1308 (Style.
isProto() && Current.Next->isOneOf(tok::less, tok::l_brace)))) {
1309 return CurrentState.Indent;
1311 if (NextNonComment->is(TT_ObjCStringLiteral) &&
1312 State.StartOfStringLiteral != 0) {
1313 return State.StartOfStringLiteral - 1;
1315 if (NextNonComment->isStringLiteral() && State.StartOfStringLiteral != 0)
1316 return State.StartOfStringLiteral;
1317 if (NextNonComment->is(tok::lessless) && CurrentState.FirstLessLess != 0)
1318 return CurrentState.FirstLessLess;
1319 if (NextNonComment->isMemberAccess()) {
1320 if (CurrentState.CallContinuation == 0)
1321 return ContinuationIndent;
1322 return CurrentState.CallContinuation;
1324 if (CurrentState.QuestionColumn != 0 &&
1325 ((NextNonComment->is(tok::colon) &&
1326 NextNonComment->is(TT_ConditionalExpr)) ||
1327 Previous.is(TT_ConditionalExpr))) {
1328 if (((NextNonComment->is(tok::colon) && NextNonComment->Next &&
1329 !NextNonComment->Next->FakeLParens.empty() &&
1331 (
Previous.is(tok::colon) && !Current.FakeLParens.empty() &&
1333 !CurrentState.IsWrappedConditional) {
1338 unsigned Indent = CurrentState.Indent;
1345 return CurrentState.QuestionColumn;
1347 if (
Previous.is(tok::comma) && CurrentState.VariablePos != 0)
1348 return CurrentState.VariablePos;
1349 if (Current.is(TT_RequiresClause)) {
1355 return CurrentState.Indent;
1360 if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
1361 TT_InheritanceComma)) {
1364 if ((PreviousNonComment &&
1365 (PreviousNonComment->ClosesTemplateDeclaration ||
1366 PreviousNonComment->ClosesRequiresClause ||
1367 (PreviousNonComment->is(TT_AttributeMacro) &&
1368 Current.isNot(tok::l_paren)) ||
1369 PreviousNonComment->isOneOf(
1370 TT_AttributeRParen, TT_AttributeSquare, TT_FunctionAnnotationRParen,
1371 TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
1373 NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName))) {
1374 return std::max(CurrentState.LastSpace, CurrentState.Indent);
1376 if (NextNonComment->is(TT_SelectorName)) {
1377 if (!CurrentState.ObjCSelectorNameFound) {
1378 unsigned MinIndent = CurrentState.Indent;
1380 MinIndent = std::max(MinIndent,
1393 std::max(NextNonComment->LongestObjCSelectorName,
1394 NextNonComment->ColumnWidth) -
1395 NextNonComment->ColumnWidth;
1397 if (!CurrentState.AlignColons)
1398 return CurrentState.Indent;
1399 if (CurrentState.ColonPos > NextNonComment->ColumnWidth)
1400 return CurrentState.ColonPos - NextNonComment->ColumnWidth;
1401 return CurrentState.Indent;
1403 if (NextNonComment->is(tok::colon) && NextNonComment->is(TT_ObjCMethodExpr))
1404 return CurrentState.ColonPos;
1405 if (NextNonComment->is(TT_ArraySubscriptLSquare)) {
1406 if (CurrentState.StartOfArraySubscripts != 0) {
1407 return CurrentState.StartOfArraySubscripts;
1410 return CurrentState.Indent;
1412 return ContinuationIndent;
1417 if (State.Line->InPragmaDirective) {
1418 FormatToken *PragmaType = State.Line->First->Next->Next;
1419 if (PragmaType && PragmaType->TokenText.equals(
"omp"))
1425 if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 &&
1426 NextNonComment->Next && NextNonComment->Next->is(TT_ObjCMethodExpr)) {
1427 return CurrentState.Indent;
1430 if (NextNonComment->isOneOf(TT_StartOfName, TT_PointerOrReference) ||
1431 Previous.isOneOf(tok::coloncolon, tok::equal, TT_JsTypeColon)) {
1432 return ContinuationIndent;
1434 if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
1435 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
1436 return ContinuationIndent;
1438 if (NextNonComment->is(TT_CtorInitializerComma))
1439 return CurrentState.Indent;
1440 if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
1442 return CurrentState.Indent;
1444 if (PreviousNonComment && PreviousNonComment->is(TT_InheritanceColon) &&
1446 return CurrentState.Indent;
1449 Previous.isNot(TT_TableGenDAGArgOperatorToBreak) &&
1450 !Current.isBinaryOperator() &&
1451 !Current.isOneOf(tok::colon, tok::comment)) {
1452 return ContinuationIndent;
1454 if (Current.is(TT_ProtoExtensionLSquare))
1455 return CurrentState.Indent;
1456 if (Current.isBinaryOperator() && CurrentState.UnindentOperator) {
1457 return CurrentState.Indent - Current.Tok.getLength() -
1458 Current.SpacesRequiredBefore;
1460 if (Current.is(tok::comment) && NextNonComment->isBinaryOperator() &&
1461 CurrentState.UnindentOperator) {
1462 return CurrentState.Indent - NextNonComment->Tok.getLength() -
1463 NextNonComment->SpacesRequiredBefore;
1465 if (CurrentState.Indent == State.FirstIndent && PreviousNonComment &&
1466 !PreviousNonComment->isOneOf(tok::r_brace, TT_CtorInitializerComma)) {
1471 return CurrentState.Indent;
1486unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
1487 bool DryRun,
bool Newline) {
1488 assert(State.Stack.size());
1489 const FormatToken &Current = *State.NextToken;
1490 auto &CurrentState = State.Stack.back();
1492 if (Current.is(TT_CSharpGenericTypeConstraint))
1493 CurrentState.IsCSharpGenericTypeConstraint =
true;
1494 if (Current.isOneOf(tok::comma, TT_BinaryOperator))
1495 CurrentState.NoLineBreakInOperand =
false;
1496 if (Current.isOneOf(TT_InheritanceColon, TT_CSharpGenericTypeConstraintColon))
1497 CurrentState.AvoidBinPacking =
true;
1498 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator)) {
1499 if (CurrentState.FirstLessLess == 0)
1500 CurrentState.FirstLessLess = State.Column;
1502 CurrentState.LastOperatorWrapped = Newline;
1504 if (Current.is(TT_BinaryOperator) && Current.isNot(tok::lessless))
1505 CurrentState.LastOperatorWrapped = Newline;
1506 if (Current.is(TT_ConditionalExpr) && Current.Previous &&
1507 Current.Previous->isNot(TT_ConditionalExpr)) {
1508 CurrentState.LastOperatorWrapped = Newline;
1510 if (Current.is(TT_ArraySubscriptLSquare) &&
1511 CurrentState.StartOfArraySubscripts == 0) {
1512 CurrentState.StartOfArraySubscripts = State.Column;
1515 auto IsWrappedConditional = [](
const FormatToken &Tok) {
1516 if (!(Tok.is(TT_ConditionalExpr) && Tok.is(tok::question)))
1518 if (Tok.MustBreakBefore)
1521 const FormatToken *Next = Tok.getNextNonComment();
1522 return Next && Next->MustBreakBefore;
1524 if (IsWrappedConditional(Current))
1525 CurrentState.IsWrappedConditional =
true;
1527 CurrentState.QuestionColumn = State.Column;
1529 const FormatToken *
Previous = Current.Previous;
1533 CurrentState.QuestionColumn = State.Column;
1535 if (!Current.opensScope() && !Current.closesScope() &&
1536 Current.isNot(TT_PointerOrReference)) {
1537 State.LowestLevelOnLine =
1538 std::min(State.LowestLevelOnLine, Current.NestingLevel);
1540 if (Current.isMemberAccess())
1541 CurrentState.StartOfFunctionCall = !Current.NextOperator ? 0 : State.Column;
1542 if (Current.is(TT_SelectorName))
1543 CurrentState.ObjCSelectorNameFound =
true;
1544 if (Current.is(TT_CtorInitializerColon) &&
1555 CurrentState.NestedBlockIndent = CurrentState.Indent;
1557 CurrentState.AvoidBinPacking =
true;
1558 CurrentState.BreakBeforeParameter =
1563 CurrentState.BreakBeforeParameter =
false;
1566 if (Current.is(TT_CtorInitializerColon) &&
1568 CurrentState.Indent =
1570 CurrentState.NestedBlockIndent = CurrentState.Indent;
1572 CurrentState.AvoidBinPacking =
true;
1574 CurrentState.BreakBeforeParameter =
false;
1576 if (Current.is(TT_InheritanceColon)) {
1577 CurrentState.Indent =
1580 if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
1581 CurrentState.NestedBlockIndent = State.Column + Current.ColumnWidth + 1;
1582 if (Current.isOneOf(TT_LambdaLSquare, TT_TrailingReturnArrow))
1583 CurrentState.LastSpace = State.Column;
1584 if (Current.is(TT_RequiresExpression) &&
1586 CurrentState.NestedBlockIndent = State.Column;
1590 const FormatToken *
Previous = Current.getPreviousNonComment();
1598 if (Current.isNot(tok::comment) && !Current.ClosesRequiresClause &&
1600 Previous->isNot(TT_DictLiteral) && State.Stack.size() > 1 &&
1601 !CurrentState.HasMultipleNestedBlocks) {
1602 if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
1603 for (ParenState &PState : llvm::drop_end(State.Stack))
1604 PState.NoLineBreak =
true;
1605 State.Stack[State.Stack.size() - 2].NestedBlockInlined =
false;
1607 if (
Previous && (
Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr) ||
1608 (
Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) &&
1609 !
Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)))) {
1610 CurrentState.NestedBlockInlined =
1614 moveStatePastFakeLParens(State, Newline);
1615 moveStatePastScopeCloser(State);
1618 bool AllowBreak = !State.Stack.back().NoLineBreak &&
1619 !State.Stack.back().NoLineBreakInOperand;
1620 moveStatePastScopeOpener(State, Newline);
1621 moveStatePastFakeRParens(State);
1623 if (Current.is(TT_ObjCStringLiteral) && State.StartOfStringLiteral == 0)
1624 State.StartOfStringLiteral = State.Column + 1;
1625 if (Current.is(TT_CSharpStringLiteral) && State.StartOfStringLiteral == 0) {
1626 State.StartOfStringLiteral = State.Column + 1;
1627 }
else if (Current.is(TT_TableGenMultiLineString) &&
1628 State.StartOfStringLiteral == 0) {
1629 State.StartOfStringLiteral = State.Column + 1;
1630 }
else if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
1631 State.StartOfStringLiteral = State.Column;
1632 }
else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
1633 !Current.isStringLiteral()) {
1634 State.StartOfStringLiteral = 0;
1637 State.Column += Current.ColumnWidth;
1638 State.NextToken = State.NextToken->Next;
1643 if (Style.
isVerilog() && State.NextToken &&
1644 State.NextToken->MustBreakBefore &&
1647 CurrentState.Indent = State.FirstIndent;
1651 handleEndOfLine(Current, State, DryRun, AllowBreak, Newline);
1654 Current.Role->formatFromToken(State,
this, DryRun);
1661 Penalty +=
Previous->Role->formatAfterToken(State,
this, DryRun);
1666void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
1668 const FormatToken &Current = *State.NextToken;
1669 if (Current.FakeLParens.empty())
1672 const FormatToken *
Previous = Current.getPreviousNonComment();
1677 bool SkipFirstExtraIndent =
1680 Previous->isOneOf(tok::semi, tok::kw_return, TT_RequiresClause) ||
1684 for (
const auto &PrecedenceLevel : llvm::reverse(Current.FakeLParens)) {
1685 const auto &CurrentState = State.Stack.back();
1686 ParenState NewParenState = CurrentState;
1687 NewParenState.Tok =
nullptr;
1688 NewParenState.ContainsLineBreak =
false;
1689 NewParenState.LastOperatorWrapped =
true;
1690 NewParenState.IsChainedConditional =
false;
1691 NewParenState.IsWrappedConditional =
false;
1692 NewParenState.UnindentOperator =
false;
1693 NewParenState.NoLineBreak =
1694 NewParenState.NoLineBreak || CurrentState.NoLineBreakInOperand;
1698 NewParenState.AvoidBinPacking =
false;
1703 if (!Current.isTrailingComment() &&
1709 PrecedenceLevel !=
prec::Comma || Current.NestingLevel == 0) &&
1712 TT_TableGenDAGArgListCommaToBreak)))) {
1713 NewParenState.Indent = std::max(
1714 std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
1721 State.Stack.size() > 1) {
1722 NewParenState.Indent = State.Stack[State.Stack.size() - 2].Indent +
1734 NewParenState.UnindentOperator =
true;
1737 NewParenState.IsAligned =
true;
1747 NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
1749 Current.isNot(TT_UnaryOperator) &&
1751 NewParenState.StartOfFunctionCall = State.Column;
1761 &PrecedenceLevel == &Current.FakeLParens.back() &&
1762 !CurrentState.IsWrappedConditional) {
1763 NewParenState.IsChainedConditional =
true;
1764 NewParenState.UnindentOperator = State.Stack.back().UnindentOperator;
1767 !Current.isTrailingComment())) {
1771 NewParenState.BreakBeforeParameter =
false;
1772 State.Stack.push_back(NewParenState);
1773 SkipFirstExtraIndent =
false;
1777void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
1778 for (
unsigned i = 0, e = State.NextToken->FakeRParens; i != e; ++i) {
1779 unsigned VariablePos = State.Stack.back().VariablePos;
1780 if (State.Stack.size() == 1) {
1784 State.Stack.pop_back();
1785 State.Stack.back().VariablePos = VariablePos;
1791 State.Stack.back().LastSpace -= Style.
IndentWidth;
1795void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
1797 const FormatToken &Current = *State.NextToken;
1798 if (!Current.opensScope())
1801 const auto &CurrentState = State.Stack.back();
1804 if (Current.isOneOf(tok::less, tok::l_paren) &&
1805 CurrentState.IsCSharpGenericTypeConstraint) {
1809 if (Current.MatchingParen && Current.is(
BK_Block)) {
1810 moveStateToNewBlock(State, Newline);
1815 unsigned LastSpace = CurrentState.LastSpace;
1816 bool AvoidBinPacking;
1817 bool BreakBeforeParameter =
false;
1818 unsigned NestedBlockIndent = std::max(CurrentState.StartOfFunctionCall,
1819 CurrentState.NestedBlockIndent);
1820 if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1822 if (Current.opensBlockOrBlockTypeList(Style)) {
1824 std::min(State.Column, CurrentState.NestedBlockIndent);
1825 }
else if (Current.is(tok::l_brace)) {
1832 const FormatToken *NextNonComment = Current.getNextNonComment();
1833 bool EndsInComma = Current.MatchingParen &&
1834 Current.MatchingParen->Previous &&
1835 Current.MatchingParen->Previous->is(tok::comma);
1836 AvoidBinPacking = EndsInComma || Current.is(TT_DictLiteral) ||
1838 (NextNonComment && NextNonComment->isOneOf(
1839 TT_DesignatedInitializerPeriod,
1840 TT_DesignatedInitializerLSquare));
1841 BreakBeforeParameter = EndsInComma;
1842 if (Current.ParameterCount > 1)
1843 NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
1847 std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall);
1849 if (Style.
isTableGen() && Current.is(TT_TableGenDAGArgOpenerToBreak) &&
1855 const FormatToken *Next = Current.Next;
1856 if (Next && Next->is(TT_TableGenDAGArgOperatorID))
1857 NewIndent = State.Column + Next->TokenText.size() + 2;
1864 if (Current.is(tok::less) && Current.ParentBracket == tok::l_paren) {
1865 NewIndent = std::max(NewIndent, CurrentState.Indent);
1866 LastSpace = std::max(LastSpace, CurrentState.Indent);
1870 Current.MatchingParen &&
1871 Current.MatchingParen->getPreviousNonComment() &&
1872 Current.MatchingParen->getPreviousNonComment()->is(tok::comma);
1876 bool ObjCBinPackProtocolList =
1881 bool BinPackDeclaration =
1883 (State.Line->Type ==
LT_ObjCDecl && ObjCBinPackProtocolList);
1885 bool GenericSelection =
1886 Current.getPreviousNonComment() &&
1887 Current.getPreviousNonComment()->is(tok::kw__Generic);
1890 (CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection ||
1892 (State.Line->MustBeDeclaration && !BinPackDeclaration) ||
1898 if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen &&
1905 BreakBeforeParameter =
true;
1910 for (
const FormatToken *Tok = &Current;
1911 Tok && Tok != Current.MatchingParen; Tok = Tok->Next) {
1912 if (Tok->MustBreakBefore ||
1913 (Tok->CanBreakBefore && Tok->NewlinesBefore > 0)) {
1914 BreakBeforeParameter =
true;
1922 BreakBeforeParameter =
true;
1928 Current.Children.empty() &&
1929 !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) &&
1930 (CurrentState.NoLineBreak || CurrentState.NoLineBreakInOperand ||
1931 (Current.is(TT_TemplateOpener) &&
1932 CurrentState.ContainsUnwrappedBuilder));
1933 State.Stack.push_back(
1934 ParenState(&Current, NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
1935 auto &NewState = State.Stack.back();
1936 NewState.NestedBlockIndent = NestedBlockIndent;
1937 NewState.BreakBeforeParameter = BreakBeforeParameter;
1938 NewState.HasMultipleNestedBlocks = (Current.BlockParameterCount > 1);
1941 Current.is(tok::l_paren)) {
1943 FormatToken
const *next = Current.Next;
1945 if (next->is(TT_LambdaLSquare)) {
1946 NewState.HasMultipleNestedBlocks =
true;
1953 NewState.IsInsideObjCArrayLiteral = Current.is(TT_ArrayInitializerLSquare) &&
1955 Current.Previous->is(tok::at);
1958void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
1959 const FormatToken &Current = *State.NextToken;
1960 if (!Current.closesScope())
1965 if (State.Stack.size() > 1 &&
1966 (Current.isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
1967 (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
1968 State.NextToken->is(TT_TemplateCloser) ||
1969 State.NextToken->is(TT_TableGenListCloser) ||
1970 (Current.is(tok::greater) && Current.is(TT_DictLiteral)))) {
1971 State.Stack.pop_back();
1974 auto &CurrentState = State.Stack.back();
1986 if (CurrentState.BreakBeforeParameter && Current.MatchingParen &&
1987 Current.MatchingParen->Previous) {
1988 const FormatToken &CurrentScopeOpener = *Current.MatchingParen->Previous;
1989 if (CurrentScopeOpener.is(TT_ObjCMethodExpr) &&
1990 CurrentScopeOpener.MatchingParen) {
1991 int NecessarySpaceInLine =
1993 CurrentScopeOpener.TotalLength - Current.TotalLength - 1;
1994 if (State.Column + Current.ColumnWidth + NecessarySpaceInLine <=
1996 CurrentState.BreakBeforeParameter =
false;
2001 if (Current.is(tok::r_square)) {
2003 const FormatToken *NextNonComment = Current.getNextNonComment();
2004 if (NextNonComment && NextNonComment->isNot(tok::l_square))
2005 CurrentState.StartOfArraySubscripts = 0;
2009void ContinuationIndenter::moveStateToNewBlock(LineState &State,
bool NewLine) {
2011 State.NextToken->is(TT_LambdaLBrace) &&
2012 !State.Line->MightBeFunctionDecl) {
2013 State.Stack.back().NestedBlockIndent = State.FirstIndent;
2015 unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
2017 unsigned NewIndent =
2018 NestedBlockIndent + (State.NextToken->is(TT_ObjCBlockLBrace)
2028 State.NextToken->is(TT_LambdaLBrace);
2030 State.Stack.push_back(ParenState(State.NextToken, NewIndent,
2031 State.Stack.back().LastSpace,
2032 true, NoLineBreak));
2033 State.Stack.back().NestedBlockIndent = NestedBlockIndent;
2034 State.Stack.back().BreakBeforeParameter =
true;
2040 size_t LastNewlinePos =
Text.find_last_of(
"\n");
2041 if (LastNewlinePos == StringRef::npos) {
2042 return StartColumn +
2046 0, TabWidth, Encoding);
2050unsigned ContinuationIndenter::reformatRawStringLiteral(
2051 const FormatToken &Current, LineState &State,
2052 const FormatStyle &RawStringStyle,
bool DryRun,
bool Newline) {
2053 unsigned StartColumn = State.Column - Current.ColumnWidth;
2055 StringRef NewDelimiter =
2057 if (NewDelimiter.empty())
2058 NewDelimiter = OldDelimiter;
2061 unsigned OldPrefixSize = 3 + OldDelimiter.size();
2062 unsigned OldSuffixSize = 2 + OldDelimiter.size();
2065 std::string RawText = std::string(
2066 Current.TokenText.substr(OldPrefixSize).drop_back(OldSuffixSize));
2067 if (NewDelimiter != OldDelimiter) {
2070 std::string CanonicalDelimiterSuffix = (
")" + NewDelimiter +
"\"").str();
2071 if (StringRef(RawText).contains(CanonicalDelimiterSuffix))
2072 NewDelimiter = OldDelimiter;
2075 unsigned NewPrefixSize = 3 + NewDelimiter.size();
2076 unsigned NewSuffixSize = 2 + NewDelimiter.size();
2079 unsigned FirstStartColumn = StartColumn + NewPrefixSize;
2090 bool ContentStartsOnNewline = Current.TokenText[OldPrefixSize] ==
'\n';
2112 unsigned CurrentIndent =
2113 (!Newline && Current.Next && Current.Next->is(tok::r_paren))
2114 ? State.Stack.back().NestedBlockIndent
2115 : State.Stack.back().Indent;
2116 unsigned NextStartColumn = ContentStartsOnNewline
2128 unsigned LastStartColumn =
2129 Current.NewlinesBefore ? FirstStartColumn - NewPrefixSize : CurrentIndent;
2132 RawStringStyle, RawText, {tooling::Range(0, RawText.size())},
2133 FirstStartColumn, NextStartColumn, LastStartColumn,
"<stdin>",
2137 tooling::Replacements NoFixes;
2139 return addMultilineToken(Current, State);
2141 if (NewDelimiter != OldDelimiter) {
2144 SourceLocation PrefixDelimiterStart =
2145 Current.Tok.getLocation().getLocWithOffset(2);
2146 auto PrefixErr = Whitespaces.
addReplacement(tooling::Replacement(
2147 SourceMgr, PrefixDelimiterStart, OldDelimiter.size(), NewDelimiter));
2150 <<
"Failed to update the prefix delimiter of a raw string: "
2151 << llvm::toString(std::move(PrefixErr)) <<
"\n";
2155 SourceLocation SuffixDelimiterStart =
2156 Current.Tok.getLocation().getLocWithOffset(Current.TokenText.size() -
2157 1 - OldDelimiter.size());
2158 auto SuffixErr = Whitespaces.
addReplacement(tooling::Replacement(
2159 SourceMgr, SuffixDelimiterStart, OldDelimiter.size(), NewDelimiter));
2162 <<
"Failed to update the suffix delimiter of a raw string: "
2163 << llvm::toString(std::move(SuffixErr)) <<
"\n";
2166 SourceLocation OriginLoc =
2167 Current.Tok.getLocation().getLocWithOffset(OldPrefixSize);
2168 for (
const tooling::Replacement &Fix : Fixes.first) {
2170 SourceMgr, OriginLoc.getLocWithOffset(Fix.getOffset()),
2171 Fix.getLength(), Fix.getReplacementText()));
2173 llvm::errs() <<
"Failed to reformat raw string: "
2174 << llvm::toString(std::move(Err)) <<
"\n";
2179 *NewCode, FirstStartColumn, Style.
TabWidth, Encoding);
2180 State.Column = RawLastLineEndColumn + NewSuffixSize;
2184 unsigned PrefixExcessCharacters =
2189 ContentStartsOnNewline || (NewCode->find(
'\n') != std::string::npos);
2192 for (ParenState &
Paren : State.Stack)
2193 Paren.BreakBeforeParameter =
true;
2198unsigned ContinuationIndenter::addMultilineToken(
const FormatToken &Current,
2201 for (ParenState &
Paren : State.Stack)
2202 Paren.BreakBeforeParameter =
true;
2204 unsigned ColumnsUsed = State.Column;
2207 State.Column = Current.LastLineColumnWidth;
2214unsigned ContinuationIndenter::handleEndOfLine(
const FormatToken &Current,
2215 LineState &State,
bool DryRun,
2216 bool AllowBreak,
bool Newline) {
2217 unsigned Penalty = 0;
2220 auto RawStringStyle = getRawStringStyle(Current, State);
2221 if (RawStringStyle && !Current.Finalized) {
2222 Penalty = reformatRawStringLiteral(Current, State, *RawStringStyle, DryRun,
2224 }
else if (Current.IsMultiline && Current.isNot(TT_BlockComment)) {
2227 Penalty = addMultilineToken(Current, State);
2230 LineState OriginalState = State;
2234 bool Strict =
false;
2237 bool Exceeded =
false;
2238 std::tie(Penalty, Exceeded) = breakProtrudingToken(
2239 Current, State, AllowBreak,
true, Strict);
2243 LineState StrictState = OriginalState;
2244 unsigned StrictPenalty =
2245 breakProtrudingToken(Current, StrictState, AllowBreak,
2248 Strict = StrictPenalty <= Penalty;
2250 Penalty = StrictPenalty;
2251 State = StrictState;
2257 breakProtrudingToken(Current, OriginalState, AllowBreak,
false,
2262 unsigned ExcessCharacters = State.Column -
getColumnLimit(State);
2273 if (!Tok || Tok->isNot(tok::l_paren))
2278 if (Tok->is(TT_TemplateCloser)) {
2283 if (!Tok || Tok->isNot(tok::identifier))
2288std::optional<FormatStyle>
2289ContinuationIndenter::getRawStringStyle(
const FormatToken &Current,
2290 const LineState &State) {
2291 if (!Current.isStringLiteral())
2292 return std::nullopt;
2295 return std::nullopt;
2297 if (!RawStringStyle && Delimiter->empty()) {
2301 if (!RawStringStyle)
2302 return std::nullopt;
2304 return RawStringStyle;
2307std::unique_ptr<BreakableToken>
2308ContinuationIndenter::createBreakableToken(
const FormatToken &Current,
2309 LineState &State,
bool AllowBreak) {
2310 unsigned StartColumn = State.Column - Current.ColumnWidth;
2311 if (Current.isStringLiteral()) {
2328 if (Current.IsUnterminatedLiteral)
2332 if (State.Stack.back().IsInsideObjCArrayLiteral)
2339 if (Style.
isVerilog() && Current.Previous &&
2340 Current.Previous->isOneOf(tok::kw_export, Keywords.
kw_import)) {
2343 StringRef
Text = Current.TokenText;
2349 unsigned UnbreakableTailLength = (State.NextToken &&
canBreak(State))
2351 : Current.UnbreakableTailLength;
2357 Text.ends_with(
"'")) {
2359 }
else if (Style.
isCSharp() &&
Text.starts_with(
"@\"") &&
2360 Text.ends_with(
"\"")) {
2362 }
else if (
Text.starts_with(
"\"") &&
Text.ends_with(
"\"")) {
2367 return std::make_unique<BreakableStringLiteralUsingOperators>(
2368 Current, QuoteStyle,
2370 UnbreakableTailLength, State.Line->InPPDirective, Encoding, Style);
2379 if ((
Text.ends_with(Postfix =
"\"") &&
2380 (
Text.starts_with(Prefix =
"@\"") ||
Text.starts_with(Prefix =
"\"") ||
2381 Text.starts_with(Prefix =
"u\"") ||
2382 Text.starts_with(Prefix =
"U\"") ||
2383 Text.starts_with(Prefix =
"u8\"") ||
2384 Text.starts_with(Prefix =
"L\""))) ||
2385 (
Text.starts_with(Prefix =
"_T(\"") &&
2386 Text.ends_with(Postfix =
"\")"))) {
2387 return std::make_unique<BreakableStringLiteral>(
2388 Current, StartColumn, Prefix, Postfix, UnbreakableTailLength,
2389 State.Line->InPPDirective, Encoding, Style);
2391 }
else if (Current.is(TT_BlockComment)) {
2399 return std::make_unique<BreakableBlockComment>(
2400 Current, StartColumn, Current.OriginalColumn, !Current.Previous,
2401 State.Line->InPPDirective, Encoding, Style, Whitespaces.
useCRLF());
2402 }
else if (Current.is(TT_LineComment) &&
2403 (!Current.Previous ||
2404 Current.Previous->isNot(TT_ImplicitStringLiteral))) {
2405 bool RegularComments = [&]() {
2406 for (
const FormatToken *T = &Current; T && T->is(TT_LineComment);
2408 if (!(T->TokenText.starts_with(
"//") || T->TokenText.starts_with(
"#")))
2414 CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
2418 return std::make_unique<BreakableLineCommentSection>(
2419 Current, StartColumn,
false, Encoding, Style);
2424std::pair<unsigned, bool>
2425ContinuationIndenter::breakProtrudingToken(
const FormatToken &Current,
2426 LineState &State,
bool AllowBreak,
2427 bool DryRun,
bool Strict) {
2428 std::unique_ptr<const BreakableToken> Token =
2429 createBreakableToken(Current, State, AllowBreak);
2432 assert(Token->getLineCount() > 0);
2434 if (Current.is(TT_LineComment)) {
2438 if (ColumnLimit == 0) {
2441 ColumnLimit = std::numeric_limits<
decltype(ColumnLimit)>
::max();
2443 if (Current.UnbreakableTailLength >= ColumnLimit)
2447 unsigned StartColumn = State.Column - Current.ColumnWidth;
2448 unsigned NewBreakPenalty = Current.isStringLiteral()
2453 bool Exceeded =
false;
2455 bool BreakInserted = Token->introducesBreakBeforeToken();
2458 bool NewBreakBefore =
false;
2462 bool Reflow =
false;
2465 unsigned TailOffset = 0;
2467 unsigned ContentStartColumn =
2468 Token->getContentStartColumn(0,
false);
2470 unsigned RemainingTokenColumns =
2471 Token->getRemainingLength(0, TailOffset, ContentStartColumn);
2474 Token->adaptStartOfLine(0, Whitespaces);
2476 unsigned ContentIndent = 0;
2477 unsigned Penalty = 0;
2478 LLVM_DEBUG(llvm::dbgs() <<
"Breaking protruding token at column "
2479 << StartColumn <<
".\n");
2480 for (
unsigned LineIndex = 0, EndIndex = Token->getLineCount();
2481 LineIndex != EndIndex; ++LineIndex) {
2482 LLVM_DEBUG(llvm::dbgs()
2483 <<
" Line: " << LineIndex <<
" (Reflow: " << Reflow <<
")\n");
2484 NewBreakBefore =
false;
2488 bool TryReflow = Reflow;
2490 while (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2491 LLVM_DEBUG(llvm::dbgs() <<
" Over limit, need: "
2492 << (ContentStartColumn + RemainingTokenColumns)
2493 <<
", space: " << ColumnLimit
2494 <<
", reflown prefix: " << ContentStartColumn
2495 <<
", offset in line: " << TailOffset <<
"\n");
2501 Token->getSplit(LineIndex, TailOffset, ColumnLimit,
2502 ContentStartColumn, CommentPragmasRegex);
2503 if (
Split.first == StringRef::npos) {
2506 if (LineIndex < EndIndex - 1) {
2510 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2512 LLVM_DEBUG(llvm::dbgs() <<
" No break opportunity.\n");
2515 assert(
Split.first != 0);
2517 if (Token->supportsReflow()) {
2537 unsigned ToSplitColumns = Token->getRangeLength(
2538 LineIndex, TailOffset,
Split.first, ContentStartColumn);
2539 LLVM_DEBUG(llvm::dbgs() <<
" ToSplit: " << ToSplitColumns <<
"\n");
2542 LineIndex, TailOffset +
Split.first +
Split.second, ColumnLimit,
2543 ContentStartColumn + ToSplitColumns + 1, CommentPragmasRegex);
2546 unsigned ToNextSplitColumns = 0;
2547 if (NextSplit.first == StringRef::npos) {
2548 ToNextSplitColumns = Token->getRemainingLength(LineIndex, TailOffset,
2549 ContentStartColumn);
2551 ToNextSplitColumns = Token->getRangeLength(
2552 LineIndex, TailOffset,
2553 Split.first +
Split.second + NextSplit.first, ContentStartColumn);
2557 ToNextSplitColumns =
2558 Token->getLengthAfterCompression(ToNextSplitColumns, Split);
2559 LLVM_DEBUG(llvm::dbgs()
2560 <<
" ContentStartColumn: " << ContentStartColumn <<
"\n");
2561 LLVM_DEBUG(llvm::dbgs()
2562 <<
" ToNextSplit: " << ToNextSplitColumns <<
"\n");
2565 bool ContinueOnLine =
2566 ContentStartColumn + ToNextSplitColumns <= ColumnLimit;
2567 unsigned ExcessCharactersPenalty = 0;
2568 if (!ContinueOnLine && !Strict) {
2571 ExcessCharactersPenalty =
2572 (ContentStartColumn + ToNextSplitColumns - ColumnLimit) *
2574 LLVM_DEBUG(llvm::dbgs()
2575 <<
" Penalty excess: " << ExcessCharactersPenalty
2576 <<
"\n break : " << NewBreakPenalty <<
"\n");
2577 if (ExcessCharactersPenalty < NewBreakPenalty) {
2579 ContinueOnLine =
true;
2582 if (ContinueOnLine) {
2583 LLVM_DEBUG(llvm::dbgs() <<
" Continuing on line...\n");
2588 Token->compressWhitespace(LineIndex, TailOffset, Split,
2592 ContentStartColumn += ToSplitColumns + 1;
2593 Penalty += ExcessCharactersPenalty;
2595 RemainingTokenColumns = Token->getRemainingLength(
2596 LineIndex, TailOffset, ContentStartColumn);
2600 LLVM_DEBUG(llvm::dbgs() <<
" Breaking...\n");
2605 ContentIndent = Token->getContentIndent(LineIndex);
2606 LLVM_DEBUG(llvm::dbgs()
2607 <<
" ContentIndent: " << ContentIndent <<
"\n");
2608 ContentStartColumn = ContentIndent + Token->getContentStartColumn(
2611 unsigned NewRemainingTokenColumns = Token->getRemainingLength(
2612 LineIndex, TailOffset +
Split.first +
Split.second,
2613 ContentStartColumn);
2614 if (NewRemainingTokenColumns == 0) {
2617 ContentStartColumn =
2618 Token->getContentStartColumn(LineIndex,
true);
2619 NewRemainingTokenColumns = Token->getRemainingLength(
2620 LineIndex, TailOffset +
Split.first +
Split.second,
2621 ContentStartColumn);
2627 if (NewRemainingTokenColumns >= RemainingTokenColumns) {
2632 LLVM_DEBUG(llvm::dbgs() <<
" Breaking at: " << TailOffset +
Split.first
2633 <<
", " <<
Split.second <<
"\n");
2635 Token->insertBreak(LineIndex, TailOffset, Split, ContentIndent,
2639 Penalty += NewBreakPenalty;
2641 RemainingTokenColumns = NewRemainingTokenColumns;
2642 BreakInserted =
true;
2643 NewBreakBefore =
true;
2647 if (LineIndex + 1 != EndIndex) {
2648 unsigned NextLineIndex = LineIndex + 1;
2649 if (NewBreakBefore) {
2668 ContentStartColumn += RemainingTokenColumns + 1;
2673 Token->getReflowSplit(NextLineIndex, CommentPragmasRegex);
2674 LLVM_DEBUG(llvm::dbgs()
2675 <<
" Size of reflown text: " << ContentStartColumn
2676 <<
"\n Potential reflow split: ");
2677 if (SplitBeforeNext.first != StringRef::npos) {
2678 LLVM_DEBUG(llvm::dbgs() << SplitBeforeNext.first <<
", "
2679 << SplitBeforeNext.second <<
"\n");
2680 TailOffset = SplitBeforeNext.first + SplitBeforeNext.second;
2683 RemainingTokenColumns = Token->getRemainingLength(
2684 NextLineIndex, TailOffset, ContentStartColumn);
2686 if (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
2687 LLVM_DEBUG(llvm::dbgs()
2688 <<
" Over limit after reflow, need: "
2689 << (ContentStartColumn + RemainingTokenColumns)
2690 <<
", space: " << ColumnLimit
2691 <<
", reflown prefix: " << ContentStartColumn
2692 <<
", offset in line: " << TailOffset <<
"\n");
2698 Token->getSplit(NextLineIndex, TailOffset, ColumnLimit,
2699 ContentStartColumn, CommentPragmasRegex);
2700 if (
Split.first == StringRef::npos) {
2701 LLVM_DEBUG(llvm::dbgs() <<
" Did not find later break\n");
2707 unsigned ToSplitColumns = Token->getRangeLength(
2708 NextLineIndex, TailOffset,
Split.first, ContentStartColumn);
2709 if (ContentStartColumn + ToSplitColumns > ColumnLimit) {
2710 LLVM_DEBUG(llvm::dbgs() <<
" Next split protrudes, need: "
2711 << (ContentStartColumn + ToSplitColumns)
2712 <<
", space: " << ColumnLimit);
2713 unsigned ExcessCharactersPenalty =
2714 (ContentStartColumn + ToSplitColumns - ColumnLimit) *
2716 if (NewBreakPenalty < ExcessCharactersPenalty)
2722 LLVM_DEBUG(llvm::dbgs() <<
"not found.\n");
2730 ContentStartColumn =
2731 Token->getContentStartColumn(NextLineIndex,
false);
2732 RemainingTokenColumns = Token->getRemainingLength(
2733 NextLineIndex, TailOffset, ContentStartColumn);
2736 Token->adaptStartOfLine(NextLineIndex, Whitespaces);
2751 if (NewBreakBefore) {
2752 assert(Penalty >= NewBreakPenalty);
2753 Penalty -= NewBreakPenalty;
2756 Token->reflow(NextLineIndex, Whitespaces);
2762 Token->getSplitAfterLastLine(TailOffset);
2763 if (SplitAfterLastLine.first != StringRef::npos) {
2764 LLVM_DEBUG(llvm::dbgs() <<
"Replacing whitespace after last line.\n");
2769 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
2772 Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
2775 ContentStartColumn =
2776 Token->getContentStartColumn(Token->getLineCount() - 1,
true);
2777 RemainingTokenColumns = Token->getRemainingLength(
2778 Token->getLineCount() - 1,
2779 TailOffset + SplitAfterLastLine.first + SplitAfterLastLine.second,
2780 ContentStartColumn);
2783 State.Column = ContentStartColumn + RemainingTokenColumns -
2784 Current.UnbreakableTailLength;
2786 if (BreakInserted) {
2788 Token->updateAfterBroken(Whitespaces);
2793 if (Current.isNot(TT_LineComment))
2794 for (ParenState &
Paren : State.Stack)
2795 Paren.BreakBeforeParameter =
true;
2797 if (Current.is(TT_BlockComment))
2798 State.NoContinuation =
true;
2800 State.Stack.back().LastSpace = StartColumn;
2803 Token->updateNextToken(State);
2805 return {Penalty, Exceeded};
2810 return Style.
ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
2813bool ContinuationIndenter::nextIsMultilineString(
const LineState &State) {
2815 if (!Current.isStringLiteral() || Current.is(TT_ImplicitStringLiteral))
2820 if (Current.TokenText.starts_with(
"R\""))
2822 if (Current.IsMultiline)
2824 if (Current.getNextNonComment() &&
2825 Current.getNextNonComment()->isStringLiteral()) {
2829 State.Column + Current.ColumnWidth + Current.UnbreakableTailLength >
Declares BreakableToken, BreakableStringLiteral, BreakableComment, BreakableBlockComment and Breakabl...
This file implements an indenter that manages the indentation of continuations.
Defines and computes precedence levels for binary/ternary operators.
Defines the SourceManager interface.
unsigned LongestObjCSelectorName
Defines the clang::TokenKind enum and support functions.
WhitespaceManager class manages whitespace around tokens and their replacements.
__DEVICE__ int max(int __a, int __b)
This class handles loading and caching of source files into memory.
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
The JSON file list parser is used to communicate input to InstallAPI.
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()))