22 #include "llvm/Support/Debug.h" 24 #define DEBUG_TYPE "format-indenter" 57 if (Current.
is(TT_CtorInitializerComma) &&
63 ((Previous.
isNot(TT_CtorInitializerComma) ||
66 (Previous.
isNot(TT_InheritanceComma) ||
72 if (LessTok.
isNot(tok::less))
84 if (TokenText.size() < 5
85 || !TokenText.startswith(
"R\"") || !TokenText.endswith(
"\""))
91 size_t LParenPos = TokenText.substr(0, 19).find_first_of(
'(');
92 if (LParenPos == StringRef::npos)
94 StringRef Delimiter = TokenText.substr(2, LParenPos - 2);
97 size_t RParenPos = TokenText.size() - Delimiter.size() - 2;
98 if (TokenText[RParenPos] !=
')')
100 if (!TokenText.substr(RParenPos + 1).startswith(Delimiter))
110 RawStringFormat.Language, &Style)) {
112 Style.
Language = RawStringFormat.Language;
132 bool BinPackInconclusiveFunctions)
133 : Style(Style), Keywords(Keywords), SourceMgr(SourceMgr),
134 Whitespaces(Whitespaces), Encoding(Encoding),
135 BinPackInconclusiveFunctions(BinPackInconclusiveFunctions),
136 CommentPragmasRegex(Style.CommentPragmas), RawStringFormats(Style) {}
139 unsigned FirstStartColumn,
145 State.
Column = FirstStartColumn;
147 State.
Column = FirstIndent;
170 State.
Stack.back().AvoidBinPacking =
true;
171 State.
Stack.back().BreakBeforeParameter =
true;
175 moveStateToNextToken(State, DryRun,
false);
182 assert(&Previous == Current.
Previous);
207 if (Previous.
is(tok::l_brace) && State.
Stack.size() > 1 &&
208 State.
Stack[State.
Stack.size() - 2].NestedBlockInlined &&
209 State.
Stack[State.
Stack.size() - 2].HasMultipleNestedBlocks)
214 if (Current.
is(TT_FunctionDeclarationName) && State.
Column < 6) {
221 if (!Current.
isOneOf(TT_BinaryOperator, tok::comma) &&
222 State.
Stack.back().NoLineBreakInOperand)
225 return !State.
Stack.back().NoLineBreak;
233 if (State.
Stack.back().BreakBeforeClosingBrace &&
239 (Previous.
is(TT_TemplateCloser) && Current.
is(TT_StartOfName) &&
247 Previous.
isNot(tok::question)) ||
249 Previous.
is(TT_ConditionalExpr))) &&
251 !Current.
isOneOf(tok::r_paren, tok::r_brace))
253 if (((Previous.
is(TT_DictLiteral) && Previous.
is(tok::l_brace)) ||
254 (Previous.
is(TT_ArrayInitializerLSquare) &&
262 const FormatToken &BreakConstructorInitializersToken =
266 if (BreakConstructorInitializersToken.
is(TT_CtorInitializerColon) &&
269 State.
Stack.back().BreakBeforeParameter) &&
275 if (Current.
is(TT_ObjCMethodExpr) && !Previous.
is(TT_SelectorName) &&
278 if (Current.
is(TT_SelectorName) && State.
Stack.back().ObjCSelectorNameFound &&
279 State.
Stack.back().BreakBeforeParameter)
282 unsigned NewLineColumn = getNewLineColumn(State);
285 (State.
Column > NewLineColumn ||
290 (State.
Stack.back().CallContinuation != 0 ||
291 State.
Stack.back().BreakBeforeParameter) &&
297 !(State.
Column <= NewLineColumn &&
301 if (State.
Column <= NewLineColumn)
307 !Previous.
isOneOf(tok::kw_return, tok::lessless, tok::at) &&
308 !Previous.
isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
309 nextIsMultilineString(State))
330 bool LHSIsBinaryExpr =
334 State.
Stack.back().BreakBeforeParameter)
337 State.
Stack.back().BreakBeforeParameter) {
342 if (Current.
is(tok::lessless) && Current.
isNot(TT_OverloadedOperator) &&
343 State.
Stack.back().BreakBeforeParameter &&
344 State.
Stack.back().FirstLessLess == 0)
353 if (Previous.
is(TT_FunctionAnnotationRParen))
355 if (Previous.
is(TT_LeadingJavaAnnotation) && Current.
isNot(tok::l_paren) &&
356 Current.
isNot(TT_LeadingJavaAnnotation))
361 if ((Current.
is(TT_FunctionDeclarationName) ||
362 (Current.
is(tok::kw_operator) && !Previous.
is(tok::coloncolon))) &&
363 !Previous.
is(tok::kw_template) && State.
Stack.back().BreakBeforeParameter)
370 Previous.
is(tok::l_brace) && !Current.
isOneOf(tok::r_brace, tok::comment))
373 if (Current.
is(tok::lessless) &&
374 ((Previous.
is(tok::identifier) && Previous.
TokenText ==
"endl") ||
390 unsigned ExtraSpaces) {
393 assert(!State.
Stack.empty());
396 if ((Current.
is(TT_ImplicitStringLiteral) &&
399 tok::pp_not_keyword))) {
407 unsigned StartColumn =
409 assert(EndColumn >= StartColumn);
410 State.
Column += EndColumn - StartColumn;
412 moveStateToNextToken(State, DryRun,
false);
416 unsigned Penalty = 0;
418 Penalty = addTokenOnNewLine(State, DryRun);
420 addTokenOnCurrentLine(State, DryRun, ExtraSpaces);
422 return moveStateToNextToken(State, DryRun, Newline) + Penalty;
425 void ContinuationIndenter::addTokenOnCurrentLine(
LineState &
State,
bool DryRun,
426 unsigned ExtraSpaces) {
429 if (Current.
is(tok::equal) &&
431 State.
Stack.back().VariablePos == 0) {
442 State.
Stack.back().LastSpace = State.
Stack.back().VariablePos;
448 int PPColumnCorrection = 0;
460 PPColumnCorrection = -1;
465 State.
Column + Spaces + PPColumnCorrection);
470 State.
Stack.back().NoLineBreak =
true;
472 if (Current.
is(TT_SelectorName) &&
473 !State.
Stack.back().ObjCSelectorNameFound) {
476 State.
Stack.back().Indent);
479 State.
Stack.back().AlignColons =
false;
483 State.
Stack.back().ColonPos = FirstColonPos;
490 Previous.
isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) &&
491 State.
Column > getNewLineColumn(State) &&
493 tok::kw_for, tok::kw_while, tok::kw_switch)) &&
503 State.
Stack.back().NoLineBreak =
true;
504 if (Previous.
is(TT_TemplateString) && Previous.
opensScope())
505 State.
Stack.back().NoLineBreak =
true;
512 State.
Stack.back().NoLineBreak =
true;
514 State.
Column > getNewLineColumn(State))
515 State.
Stack.back().ContainsUnwrappedBuilder =
true;
518 State.
Stack.back().NoLineBreak =
true;
528 State.
Stack.back().NoLineBreak =
true;
535 if (!Current.
is(tok::comment) && P &&
536 (P->
isOneOf(TT_BinaryOperator, tok::comma) ||
537 (P->
is(TT_ConditionalExpr) && P->
is(tok::colon))) &&
538 !P->
isOneOf(TT_OverloadedOperator, TT_CtorInitializerComma) &&
542 bool BreakBeforeOperator =
544 (P->
is(TT_BinaryOperator) &&
550 bool HasTwoOperands =
552 if ((!BreakBeforeOperator && !(HasTwoOperands && Style.
AlignOperands)) ||
553 (!State.
Stack.back().LastOperatorWrapped && BreakBeforeOperator))
554 State.
Stack.back().NoLineBreakInOperand =
true;
558 if (Current.
isNot(tok::comment) && Previous.
is(tok::l_paren) &&
565 State.
Stack.back().NestedBlockIndent = State.
Column;
566 }
else if (!Current.
isOneOf(tok::comment, tok::caret) &&
567 ((Previous.
is(tok::comma) &&
568 !Previous.
is(TT_OverloadedOperator)) ||
569 (Previous.
is(tok::colon) && Previous.
is(TT_ObjCMethodExpr)))) {
571 }
else if (Previous.
is(TT_CtorInitializerColon) &&
576 }
else if ((Previous.
isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
577 TT_CtorInitializerColon)) &&
586 }
else if (Previous.
is(TT_InheritanceColon)) {
595 bool HasTrailingCall =
false;
600 if (HasTrailingCall && State.
Stack.size() > 1 &&
601 State.
Stack[State.
Stack.size() - 2].CallContinuation == 0)
606 unsigned ContinuationIndenter::addTokenOnNewLine(
LineState &State,
613 unsigned Penalty = 0;
618 NextNonComment = &Current;
621 if (!State.
Stack.back().ContainsLineBreak)
623 State.
Stack.back().ContainsLineBreak =
true;
630 if (NextNonComment->
is(tok::lessless) &&
631 State.
Stack.back().FirstLessLess == 0 &&
633 State.
Stack.back().BreakBeforeParameter))
636 State.
Column = getNewLineColumn(State);
648 if (!Current.
is(TT_LambdaArrow) &&
651 !PreviousNonComment->
is(tok::equal) ||
653 State.
Stack.back().NestedBlockIndent = State.
Column;
656 if (State.
Stack.back().CallContinuation == 0)
657 State.
Stack.back().CallContinuation = State.
Column;
658 }
else if (NextNonComment->
is(TT_SelectorName)) {
659 if (!State.
Stack.back().ObjCSelectorNameFound) {
661 State.
Stack.back().AlignColons =
false;
663 State.
Stack.back().ColonPos =
667 : State.
Stack.back().Indent) +
670 }
else if (State.
Stack.back().AlignColons &&
674 }
else if (PreviousNonComment && PreviousNonComment->
is(tok::colon) &&
675 PreviousNonComment->
isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)) {
685 if (State.
Stack.size() > 1)
686 State.
Stack[State.
Stack.size() - 2].LastSpace =
691 if ((PreviousNonComment &&
692 PreviousNonComment->
isOneOf(tok::comma, tok::semi) &&
693 !State.
Stack.back().AvoidBinPacking) ||
694 Previous.
is(TT_BinaryOperator))
695 State.
Stack.back().BreakBeforeParameter =
false;
696 if (Previous.
isOneOf(TT_TemplateCloser, TT_JavaAnnotation) &&
698 State.
Stack.back().BreakBeforeParameter =
false;
699 if (NextNonComment->
is(tok::question) ||
700 (PreviousNonComment && PreviousNonComment->
is(tok::question)))
701 State.
Stack.back().BreakBeforeParameter =
true;
703 State.
Stack.back().BreakBeforeParameter =
false;
714 MaxEmptyLinesToKeep = 1;
718 bool ContinuePPDirective =
721 ContinuePPDirective);
726 if (Current.
is(tok::lessless))
730 State.
Stack.back().LastSpace += 3;
737 bool NestedBlockSpecialCase =
738 !Style.
isCpp() && Current.
is(tok::r_brace) && State.
Stack.size() > 1 &&
739 State.
Stack[State.
Stack.size() - 2].NestedBlockInlined;
740 if (!NestedBlockSpecialCase)
741 for (
unsigned i = 0, e = State.
Stack.size() - 1; i != e; ++i)
742 State.
Stack[i].BreakBeforeParameter =
true;
744 if (PreviousNonComment &&
745 !PreviousNonComment->
isOneOf(tok::comma, tok::colon, tok::semi) &&
746 (PreviousNonComment->
isNot(TT_TemplateCloser) ||
749 TT_BinaryOperator, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
750 TT_LeadingJavaAnnotation) &&
752 State.
Stack.back().BreakBeforeParameter =
true;
756 if (PreviousNonComment &&
757 (PreviousNonComment->
isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
759 State.
Stack.back().BreakBeforeClosingBrace =
true;
761 if (State.
Stack.back().AvoidBinPacking) {
765 if (!Previous.
isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) ||
768 Previous.
is(TT_DictLiteral))
769 State.
Stack.back().BreakBeforeParameter =
true;
775 unsigned ContinuationIndenter::getNewLineColumn(
const LineState &State) {
781 unsigned ContinuationIndent =
787 NextNonComment = &Current;
797 : State.
Stack.back().Indent;
798 if ((Current.
isOneOf(tok::r_brace, tok::r_square) ||
799 (Current.
is(tok::greater) &&
802 State.
Stack.size() > 1) {
804 return State.
Stack[State.
Stack.size() - 2].NestedBlockIndent;
807 return State.
Stack[State.
Stack.size() - 2].LastSpace;
820 if (Current.
is(tok::r_paren) && State.
Stack.size() > 1 &&
822 return State.
Stack[State.
Stack.size() - 2].LastSpace;
823 if (NextNonComment->
is(TT_TemplateString) && NextNonComment->
closesScope())
824 return State.
Stack[State.
Stack.size() - 2].LastSpace;
825 if (Current.
is(tok::identifier) && Current.
Next &&
826 (Current.
Next->
is(TT_DictLiteral) ||
829 Current.
Next->
isOneOf(TT_TemplateOpener, tok::l_brace))))
830 return State.
Stack.back().Indent;
831 if (NextNonComment->
is(TT_ObjCStringLiteral) &&
836 if (NextNonComment->
is(tok::lessless) &&
837 State.
Stack.back().FirstLessLess != 0)
838 return State.
Stack.back().FirstLessLess;
840 if (State.
Stack.back().CallContinuation == 0)
841 return ContinuationIndent;
842 return State.
Stack.back().CallContinuation;
844 if (State.
Stack.back().QuestionColumn != 0 &&
845 ((NextNonComment->
is(tok::colon) &&
846 NextNonComment->
is(TT_ConditionalExpr)) ||
847 Previous.
is(TT_ConditionalExpr)))
848 return State.
Stack.back().QuestionColumn;
849 if (Previous.
is(tok::comma) && State.
Stack.back().VariablePos != 0)
850 return State.
Stack.back().VariablePos;
851 if ((PreviousNonComment &&
852 (PreviousNonComment->ClosesTemplateDeclaration ||
853 PreviousNonComment->isOneOf(
854 TT_AttributeParen, TT_FunctionAnnotationRParen, TT_JavaAnnotation,
855 TT_LeadingJavaAnnotation))) ||
857 NextNonComment->
isOneOf(tok::kw_operator, TT_FunctionDeclarationName)))
859 if (NextNonComment->
is(TT_SelectorName)) {
860 if (!State.
Stack.back().ObjCSelectorNameFound) {
862 return State.
Stack.back().Indent;
866 : State.
Stack.back().Indent) +
870 if (!State.
Stack.back().AlignColons)
871 return State.
Stack.back().Indent;
874 return State.
Stack.back().Indent;
876 if (NextNonComment->
is(tok::colon) && NextNonComment->
is(TT_ObjCMethodExpr))
877 return State.
Stack.back().ColonPos;
878 if (NextNonComment->
is(TT_ArraySubscriptLSquare)) {
879 if (State.
Stack.back().StartOfArraySubscripts != 0)
880 return State.
Stack.back().StartOfArraySubscripts;
881 return ContinuationIndent;
886 if (NextNonComment->
is(tok::identifier) && NextNonComment->
FakeRParens == 0 &&
887 NextNonComment->
Next && NextNonComment->
Next->
is(TT_ObjCMethodExpr))
888 return State.
Stack.back().Indent;
890 if (NextNonComment->
isOneOf(TT_StartOfName, TT_PointerOrReference) ||
891 Previous.
isOneOf(tok::coloncolon, tok::equal, TT_JsTypeColon))
892 return ContinuationIndent;
893 if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
894 PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral))
895 return ContinuationIndent;
896 if (NextNonComment->
is(TT_CtorInitializerComma))
897 return State.
Stack.back().Indent;
898 if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) &&
900 return State.
Stack.back().Indent;
901 if (NextNonComment->
isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
902 TT_InheritanceComma))
905 !Current.
isOneOf(tok::colon, tok::comment))
906 return ContinuationIndent;
908 PreviousNonComment->isNot(tok::r_brace))
912 return State.
Stack.back().Indent;
915 unsigned ContinuationIndenter::moveStateToNextToken(
LineState &State,
916 bool DryRun,
bool Newline) {
917 assert(State.
Stack.size());
920 if (Current.isOneOf(tok::comma, TT_BinaryOperator))
921 State.
Stack.back().NoLineBreakInOperand =
false;
922 if (Current.is(TT_InheritanceColon))
923 State.
Stack.back().AvoidBinPacking =
true;
924 if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator)) {
925 if (State.
Stack.back().FirstLessLess == 0)
928 State.
Stack.back().LastOperatorWrapped = Newline;
930 if (Current.is(TT_BinaryOperator) && Current.isNot(tok::lessless))
931 State.
Stack.back().LastOperatorWrapped = Newline;
932 if (Current.is(TT_ConditionalExpr) && Current.Previous &&
933 !Current.Previous->is(TT_ConditionalExpr))
934 State.
Stack.back().LastOperatorWrapped = Newline;
935 if (Current.is(TT_ArraySubscriptLSquare) &&
936 State.
Stack.back().StartOfArraySubscripts == 0)
937 State.
Stack.back().StartOfArraySubscripts = State.
Column;
944 if (Previous && Previous->
is(tok::question))
947 if (!Current.opensScope() && !Current.closesScope() &&
948 !Current.is(TT_PointerOrReference))
951 if (Current.isMemberAccess())
952 State.
Stack.back().StartOfFunctionCall =
953 !Current.NextOperator ? 0 : State.
Column;
954 if (Current.is(TT_SelectorName)) {
955 State.
Stack.back().ObjCSelectorNameFound =
true;
957 State.
Stack.back().Indent =
961 if (Current.is(TT_CtorInitializerColon) &&
968 State.
Stack.back().Indent =
973 State.
Stack.back().NestedBlockIndent = State.
Stack.back().Indent;
975 State.
Stack.back().AvoidBinPacking =
true;
976 State.
Stack.back().BreakBeforeParameter =
false;
978 if (Current.is(TT_CtorInitializerColon) &&
980 State.
Stack.back().Indent =
982 State.
Stack.back().NestedBlockIndent = State.
Stack.back().Indent;
984 State.
Stack.back().AvoidBinPacking =
true;
986 if (Current.is(TT_InheritanceColon))
987 State.
Stack.back().Indent =
989 if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
990 State.
Stack.back().NestedBlockIndent =
991 State.
Column + Current.ColumnWidth + 1;
992 if (Current.isOneOf(TT_LambdaLSquare, TT_LambdaArrow))
1004 if (Current.isNot(tok::comment) && Previous &&
1005 Previous->
isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) &&
1006 !Previous->
is(TT_DictLiteral) && State.
Stack.size() > 1) {
1007 if (State.
Stack[State.
Stack.size() - 2].NestedBlockInlined && Newline)
1008 for (
unsigned i = 0, e = State.
Stack.size() - 1; i != e; ++i)
1009 State.
Stack[i].NoLineBreak =
true;
1010 State.
Stack[State.
Stack.size() - 2].NestedBlockInlined =
false;
1013 (Previous->
isOneOf(tok::l_paren, tok::comma, tok::colon) ||
1014 Previous->
isOneOf(TT_BinaryOperator, TT_ConditionalExpr)) &&
1015 !Previous->
isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
1016 State.
Stack.back().NestedBlockInlined =
1021 moveStatePastFakeLParens(State, Newline);
1022 moveStatePastScopeCloser(State);
1023 bool AllowBreak = !State.
Stack.back().NoLineBreak &&
1024 !State.
Stack.back().NoLineBreakInOperand;
1025 moveStatePastScopeOpener(State, Newline);
1026 moveStatePastFakeRParens(State);
1032 else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
1033 !Current.isStringLiteral())
1036 State.
Column += Current.ColumnWidth;
1040 handleEndOfLine(Current, State, DryRun, AllowBreak);
1043 Current.Role->formatFromToken(State,
this, DryRun);
1049 if (Previous && Previous->
Role)
1050 Penalty += Previous->
Role->formatAfterToken(State,
this, DryRun);
1055 void ContinuationIndenter::moveStatePastFakeLParens(
LineState &State,
1063 bool SkipFirstExtraIndent =
1065 Previous->
isOneOf(tok::semi, tok::kw_return) ||
1068 Previous->
is(TT_ObjCMethodExpr)));
1088 (!Previous || Previous->
isNot(tok::kw_return) ||
1094 State.
Stack.back().LastSpace);
1118 State.
Stack.push_back(NewParenState);
1119 SkipFirstExtraIndent =
false;
1123 void ContinuationIndenter::moveStatePastFakeRParens(
LineState &State) {
1125 unsigned VariablePos = State.
Stack.back().VariablePos;
1126 if (State.
Stack.size() == 1) {
1130 State.
Stack.pop_back();
1131 State.
Stack.back().VariablePos = VariablePos;
1135 void ContinuationIndenter::moveStatePastScopeOpener(
LineState &State,
1142 moveStateToNewBlock(State);
1147 unsigned LastSpace = State.
Stack.back().LastSpace;
1148 bool AvoidBinPacking;
1149 bool BreakBeforeParameter =
false;
1150 unsigned NestedBlockIndent =
std::max(State.
Stack.back().StartOfFunctionCall,
1151 State.
Stack.back().NestedBlockIndent);
1152 if (Current.
isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
1164 AvoidBinPacking = EndsInComma || Current.
is(TT_DictLiteral) ||
1169 NextNoComment->
isOneOf(TT_DesignatedInitializerPeriod,
1170 TT_DesignatedInitializerLSquare));
1171 BreakBeforeParameter = EndsInComma;
1173 NestedBlockIndent =
std::max(NestedBlockIndent, State.
Column + 1);
1177 State.
Stack.back().StartOfFunctionCall);
1200 (!BinPackInconclusiveFunctions &&
1209 BreakBeforeParameter =
true;
1217 BreakBeforeParameter =
true;
1225 BreakBeforeParameter =
true;
1232 !Current.
isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) &&
1233 (State.
Stack.back().NoLineBreak ||
1234 State.
Stack.back().NoLineBreakInOperand ||
1235 (Current.
is(TT_TemplateOpener) &&
1236 State.
Stack.back().ContainsUnwrappedBuilder));
1237 State.
Stack.push_back(
1238 ParenState(NewIndent, LastSpace, AvoidBinPacking, NoLineBreak));
1239 State.
Stack.back().NestedBlockIndent = NestedBlockIndent;
1240 State.
Stack.back().BreakBeforeParameter = BreakBeforeParameter;
1244 void ContinuationIndenter::moveStatePastScopeCloser(
LineState &State) {
1251 if (State.
Stack.size() > 1 &&
1252 (Current.
isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
1255 State.
Stack.pop_back();
1257 if (Current.
is(tok::r_square)) {
1260 if (NextNonComment && NextNonComment->
isNot(tok::l_square))
1261 State.
Stack.back().StartOfArraySubscripts = 0;
1265 void ContinuationIndenter::moveStateToNewBlock(
LineState &State) {
1266 unsigned NestedBlockIndent = State.
Stack.back().NestedBlockIndent;
1268 unsigned NewIndent =
1269 NestedBlockIndent + (State.
NextToken->
is(TT_ObjCBlockLBrace)
1275 State.
Stack.back().NestedBlockIndent = NestedBlockIndent;
1276 State.
Stack.back().BreakBeforeParameter =
true;
1282 size_t LastNewlinePos = Text.find_last_of(
"\n");
1283 if (LastNewlinePos == StringRef::npos) {
1284 return StartColumn +
1288 0, TabWidth, Encoding);
1292 unsigned ContinuationIndenter::reformatRawStringLiteral(
1299 unsigned PrefixSize = 3 + Delimiter.size();
1300 unsigned SuffixSize = 2 + Delimiter.size();
1303 unsigned FirstStartColumn = StartColumn + PrefixSize;
1314 bool ContentStartsOnNewline = Current.
TokenText[PrefixSize] ==
'\n';
1315 unsigned NextStartColumn = ContentStartsOnNewline
1328 ? FirstStartColumn - PrefixSize
1329 : State.
Stack.back().Indent;
1331 std::string RawText =
1332 Current.
TokenText.substr(PrefixSize).drop_back(SuffixSize);
1336 FirstStartColumn, NextStartColumn, LastStartColumn,
"<stdin>",
1353 llvm::errs() <<
"Failed to reformat raw string: " 1359 *NewCode, FirstStartColumn, Style.
TabWidth, Encoding);
1360 State.
Column = RawLastLineEndColumn + SuffixSize;
1361 return Fixes.second;
1364 unsigned ContinuationIndenter::addMultilineToken(
const FormatToken &Current,
1367 for (
unsigned i = 0, e = State.
Stack.size(); i != e; ++i)
1368 State.
Stack[i].BreakBeforeParameter =
true;
1370 unsigned ColumnsUsed = State.
Column;
1380 unsigned ContinuationIndenter::handleEndOfLine(
const FormatToken &Current,
1383 unsigned Penalty = 0;
1386 auto RawStringStyle = getRawStringStyle(Current, State);
1387 if (RawStringStyle) {
1388 Penalty = reformatRawStringLiteral(Current, State, *RawStringStyle, DryRun);
1392 Penalty = addMultilineToken(Current, State);
1399 bool Strict =
false;
1402 bool Exceeded =
false;
1403 std::tie(Penalty, Exceeded) = breakProtrudingToken(
1404 Current, State, AllowBreak,
true, Strict);
1409 unsigned StrictPenalty =
1410 breakProtrudingToken(Current, StrictState, AllowBreak,
1413 Strict = StrictPenalty <= Penalty;
1415 Penalty = StrictPenalty;
1416 State = StrictState;
1422 breakProtrudingToken(Current, OriginalState, AllowBreak,
false,
1434 ContinuationIndenter::getRawStringStyle(
const FormatToken &Current,
1441 auto RawStringStyle = RawStringFormats.
get(*Delimiter);
1442 if (!RawStringStyle)
1445 return RawStringStyle;
1448 std::unique_ptr<BreakableToken> ContinuationIndenter::createBreakableToken(
1479 if ((Text.endswith(Postfix =
"\"") &&
1480 (Text.startswith(Prefix =
"@\"") || Text.startswith(Prefix =
"\"") ||
1481 Text.startswith(Prefix =
"u\"") || Text.startswith(Prefix =
"U\"") ||
1482 Text.startswith(Prefix =
"u8\"") ||
1483 Text.startswith(Prefix =
"L\""))) ||
1484 (Text.startswith(Prefix =
"_T(\"") && Text.endswith(Postfix =
"\")"))) {
1485 return llvm::make_unique<BreakableStringLiteral>(
1489 }
else if (Current.
is(TT_BlockComment)) {
1497 return llvm::make_unique<BreakableBlockComment>(
1500 }
else if (Current.
is(TT_LineComment) &&
1504 CommentPragmasRegex.match(Current.
TokenText.substr(2)) ||
1507 return llvm::make_unique<BreakableLineCommentSection>(
1509 false, Encoding, Style);
1514 std::pair<unsigned, bool>
1515 ContinuationIndenter::breakProtrudingToken(
const FormatToken &Current,
1517 bool DryRun,
bool Strict) {
1518 std::unique_ptr<const BreakableToken>
Token =
1519 createBreakableToken(Current, State, AllowBreak);
1522 assert(Token->getLineCount() > 0);
1524 if (Current.
is(TT_LineComment)) {
1538 bool Exceeded =
false;
1540 bool BreakInserted = Token->introducesBreakBeforeToken();
1543 bool NewBreakBefore =
false;
1547 bool Reflow =
false;
1550 unsigned TailOffset = 0;
1552 unsigned ContentStartColumn =
1553 Token->getContentStartColumn(0,
false);
1555 unsigned RemainingTokenColumns =
1556 Token->getRemainingLength(0, TailOffset, ContentStartColumn);
1559 Token->adaptStartOfLine(0, Whitespaces);
1561 unsigned Penalty = 0;
1562 DEBUG(llvm::dbgs() <<
"Breaking protruding token at column " << StartColumn
1564 for (
unsigned LineIndex = 0, EndIndex = Token->getLineCount();
1565 LineIndex != EndIndex; ++LineIndex) {
1566 DEBUG(llvm::dbgs() <<
" Line: " << LineIndex <<
" (Reflow: " << Reflow
1568 NewBreakBefore =
false;
1572 bool TryReflow = Reflow;
1574 while (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
1575 DEBUG(llvm::dbgs() <<
" Over limit, need: " 1576 << (ContentStartColumn + RemainingTokenColumns)
1577 <<
", space: " << ColumnLimit
1578 <<
", reflown prefix: " << ContentStartColumn
1579 <<
", offset in line: " << TailOffset <<
"\n");
1584 BreakableToken::Split Split =
1585 Token->getSplit(LineIndex, TailOffset, ColumnLimit,
1586 ContentStartColumn, CommentPragmasRegex);
1587 if (Split.first == StringRef::npos) {
1590 if (LineIndex < EndIndex - 1)
1593 (ContentStartColumn + RemainingTokenColumns - ColumnLimit);
1594 DEBUG(llvm::dbgs() <<
" No break opportunity.\n");
1597 assert(Split.first != 0);
1599 if (Token->supportsReflow()) {
1619 unsigned ToSplitColumns = Token->getRangeLength(
1620 LineIndex, TailOffset, Split.first, ContentStartColumn);
1621 DEBUG(llvm::dbgs() <<
" ToSplit: " << ToSplitColumns <<
"\n");
1623 BreakableToken::Split NextSplit = Token->getSplit(
1624 LineIndex, TailOffset + Split.first + Split.second, ColumnLimit,
1625 ContentStartColumn + ToSplitColumns + 1, CommentPragmasRegex);
1628 unsigned ToNextSplitColumns = 0;
1629 if (NextSplit.first == StringRef::npos) {
1630 ToNextSplitColumns = Token->getRemainingLength(LineIndex, TailOffset,
1631 ContentStartColumn);
1633 ToNextSplitColumns = Token->getRangeLength(
1634 LineIndex, TailOffset,
1635 Split.first + Split.second + NextSplit.first, ContentStartColumn);
1639 ToNextSplitColumns =
1640 Token->getLengthAfterCompression(ToNextSplitColumns, Split);
1641 DEBUG(llvm::dbgs() <<
" ContentStartColumn: " << ContentStartColumn
1643 DEBUG(llvm::dbgs() <<
" ToNextSplit: " << ToNextSplitColumns <<
"\n");
1646 bool ContinueOnLine =
1647 ContentStartColumn + ToNextSplitColumns <= ColumnLimit;
1648 unsigned ExcessCharactersPenalty = 0;
1649 if (!ContinueOnLine && !Strict) {
1652 ExcessCharactersPenalty =
1653 (ContentStartColumn + ToNextSplitColumns - ColumnLimit) *
1656 <<
" Penalty excess: " << ExcessCharactersPenalty
1657 <<
"\n break : " << NewBreakPenalty <<
"\n");
1658 if (ExcessCharactersPenalty < NewBreakPenalty) {
1660 ContinueOnLine =
true;
1663 if (ContinueOnLine) {
1664 DEBUG(llvm::dbgs() <<
" Continuing on line...\n");
1669 Token->compressWhitespace(LineIndex, TailOffset, Split,
1672 ContentStartColumn += ToSplitColumns + 1;
1673 Penalty += ExcessCharactersPenalty;
1674 TailOffset += Split.first + Split.second;
1675 RemainingTokenColumns = Token->getRemainingLength(
1676 LineIndex, TailOffset, ContentStartColumn);
1680 DEBUG(llvm::dbgs() <<
" Breaking...\n");
1681 ContentStartColumn =
1682 Token->getContentStartColumn(LineIndex,
true);
1683 unsigned NewRemainingTokenColumns = Token->getRemainingLength(
1684 LineIndex, TailOffset + Split.first + Split.second,
1685 ContentStartColumn);
1690 if (NewRemainingTokenColumns == RemainingTokenColumns) {
1694 assert(NewRemainingTokenColumns < RemainingTokenColumns);
1696 DEBUG(llvm::dbgs() <<
" Breaking at: " << TailOffset + Split.first
1697 <<
", " << Split.second <<
"\n");
1699 Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces);
1701 Penalty += NewBreakPenalty;
1702 TailOffset += Split.first + Split.second;
1703 RemainingTokenColumns = NewRemainingTokenColumns;
1704 BreakInserted =
true;
1705 NewBreakBefore =
true;
1709 if (LineIndex + 1 != EndIndex) {
1710 unsigned NextLineIndex = LineIndex + 1;
1729 ContentStartColumn += RemainingTokenColumns + 1;
1733 BreakableToken::Split SplitBeforeNext =
1734 Token->getReflowSplit(NextLineIndex, CommentPragmasRegex);
1735 DEBUG(llvm::dbgs() <<
" Size of reflown text: " << ContentStartColumn
1736 <<
"\n Potential reflow split: ");
1737 if (SplitBeforeNext.first != StringRef::npos) {
1738 DEBUG(llvm::dbgs() << SplitBeforeNext.first <<
", " 1739 << SplitBeforeNext.second <<
"\n");
1740 TailOffset = SplitBeforeNext.first + SplitBeforeNext.second;
1743 RemainingTokenColumns = Token->getRemainingLength(
1744 NextLineIndex, TailOffset, ContentStartColumn);
1746 if (ContentStartColumn + RemainingTokenColumns > ColumnLimit) {
1747 DEBUG(llvm::dbgs() <<
" Over limit after reflow, need: " 1748 << (ContentStartColumn + RemainingTokenColumns)
1749 <<
", space: " << ColumnLimit
1750 <<
", reflown prefix: " << ContentStartColumn
1751 <<
", offset in line: " << TailOffset <<
"\n");
1756 BreakableToken::Split Split =
1757 Token->getSplit(NextLineIndex, TailOffset, ColumnLimit,
1758 ContentStartColumn, CommentPragmasRegex);
1759 if (Split.first == StringRef::npos) {
1760 DEBUG(llvm::dbgs() <<
" Did not find later break\n");
1766 unsigned ToSplitColumns = Token->getRangeLength(
1767 NextLineIndex, TailOffset, Split.first, ContentStartColumn);
1768 if (ContentStartColumn + ToSplitColumns > ColumnLimit) {
1769 DEBUG(llvm::dbgs() <<
" Next split protrudes, need: " 1770 << (ContentStartColumn + ToSplitColumns)
1771 <<
", space: " << ColumnLimit);
1772 unsigned ExcessCharactersPenalty =
1773 (ContentStartColumn + ToSplitColumns - ColumnLimit) *
1775 if (NewBreakPenalty < ExcessCharactersPenalty) {
1782 DEBUG(llvm::dbgs() <<
"not found.\n");
1790 ContentStartColumn =
1791 Token->getContentStartColumn(NextLineIndex,
false);
1792 RemainingTokenColumns = Token->getRemainingLength(
1793 NextLineIndex, TailOffset, ContentStartColumn);
1796 Token->adaptStartOfLine(NextLineIndex, Whitespaces);
1811 if (NewBreakBefore) {
1812 assert(Penalty >= NewBreakPenalty);
1813 Penalty -= NewBreakPenalty;
1816 Token->reflow(NextLineIndex, Whitespaces);
1821 BreakableToken::Split SplitAfterLastLine =
1822 Token->getSplitAfterLastLine(TailOffset);
1823 if (SplitAfterLastLine.first != StringRef::npos) {
1824 DEBUG(llvm::dbgs() <<
"Replacing whitespace after last line.\n");
1826 Token->replaceWhitespaceAfterLastLine(TailOffset, SplitAfterLastLine,
1828 ContentStartColumn =
1829 Token->getContentStartColumn(Token->getLineCount() - 1,
true);
1830 RemainingTokenColumns = Token->getRemainingLength(
1831 Token->getLineCount() - 1,
1832 TailOffset + SplitAfterLastLine.first + SplitAfterLastLine.second,
1833 ContentStartColumn);
1836 State.
Column = ContentStartColumn + RemainingTokenColumns -
1839 if (BreakInserted) {
1843 if (Current.
isNot(TT_LineComment)) {
1844 for (
unsigned i = 0, e = State.
Stack.size(); i != e; ++i)
1845 State.
Stack[i].BreakBeforeParameter =
true;
1848 if (Current.
is(TT_BlockComment))
1851 State.
Stack.back().LastSpace = StartColumn;
1854 Token->updateNextToken(State);
1856 return {Penalty, Exceeded};
1864 bool ContinuationIndenter::nextIsMultilineString(
const LineState &State) {
1871 if (Current.
TokenText.startswith(
"R\""))
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
Defines the SourceManager interface.
Declares BreakableToken, BreakableStringLiteral, BreakableComment, BreakableBlockComment and Breakabl...
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
Token - This structure provides full information about a lexed token.
WhitespaceManager class manages whitespace around tokens and their replacements.
const AnnotatedLine * Line
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
Defines and computes precedence levels for binary/ternary operators.
SourceLocation getEnd() const
Encodes a location in the source.
IdentifierInfo * getIdentifierInfo() const
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
Dataflow Directional Tag Classes.
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
std::string toString(const til::SExpr *E)
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
This file implements an indenter that manages the indentation of continuations.
SourceLocation getBegin() const
This class handles loading and caching of source files into memory.