clang: lib/Format/WhitespaceManager.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallVector.h"
17#include
18
20namespace format {
21
32}
33
51}
52
54 unsigned Spaces,
55 unsigned StartOfTokenColumn,
56 bool IsAligned, bool InPPDirective) {
58 return;
61 Spaces, StartOfTokenColumn, Newlines, "", "",
62 IsAligned, InPPDirective && !Tok.IsFirst,
63 false));
64}
65
67 bool InPPDirective) {
69 return;
70 Changes.push_back(Change(Tok, false,
73 false, InPPDirective && !Tok.IsFirst,
74 false));
75}
76
77llvm::Error
79 return Replaces.add(Replacement);
80}
81
83 size_t LF = Text.count('\n');
84 size_t CR = Text.count('\r') * 2;
85 return LF == CR ? DefaultToCRLF : CR > LF;
86}
87
89 const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars,
90 StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective,
91 unsigned Newlines, int Spaces) {
93 return;
95 Changes.push_back(
96 Change(Tok, true,
98 std::max(0, Spaces), Newlines, PreviousPostfix, CurrentPrefix,
99 true, InPPDirective && !Tok.IsFirst,
100 true));
101}
102
104 if (Changes.empty())
105 return Replaces;
106
108 calculateLineBreakInformation();
109 alignConsecutiveMacros();
110 alignConsecutiveShortCaseStatements(true);
111 alignConsecutiveShortCaseStatements(false);
112 alignConsecutiveDeclarations();
113 alignConsecutiveBitFields();
114 alignConsecutiveAssignments();
116 alignConsecutiveTableGenBreakingDAGArgColons();
117 alignConsecutiveTableGenCondOperatorColons();
118 alignConsecutiveTableGenDefinitions();
119 }
120 alignChainedConditionals();
121 alignTrailingComments();
122 alignEscapedNewlines();
123 alignArrayInitializers();
124 generateChanges();
125
126 return Replaces;
127}
128
129void WhitespaceManager::calculateLineBreakInformation() {
130 Changes[0].PreviousEndOfTokenColumn = 0;
131 Change *LastOutsideTokenChange = &Changes[0];
132 for (unsigned I = 1, e = Changes.size(); I != e; ++I) {
133 auto &C = Changes[I];
134 auto &P = Changes[I - 1];
135 auto &PrevTokLength = P.TokenLength;
137 C.OriginalWhitespaceRange.getBegin();
139 P.OriginalWhitespaceRange.getEnd();
140 unsigned OriginalWhitespaceStartOffset =
141 SourceMgr.getFileOffset(OriginalWhitespaceStart);
142 unsigned PreviousOriginalWhitespaceEndOffset =
143 SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);
144 assert(PreviousOriginalWhitespaceEndOffset <=
145 OriginalWhitespaceStartOffset);
146 const char *const PreviousOriginalWhitespaceEndData =
148 StringRef Text(PreviousOriginalWhitespaceEndData,
150 PreviousOriginalWhitespaceEndData);
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 auto NewlinePos = Text.find_first_of('\n');
173 if (NewlinePos == StringRef::npos) {
174 PrevTokLength = OriginalWhitespaceStartOffset -
175 PreviousOriginalWhitespaceEndOffset +
176 C.PreviousLinePostfix.size() + P.CurrentLinePrefix.size();
177 if (.IsInsideToken)
178 PrevTokLength = std::min(PrevTokLength, P.Tok->ColumnWidth);
179 } else {
180 PrevTokLength = NewlinePos + P.CurrentLinePrefix.size();
181 }
182
183
184
185 if (P.IsInsideToken && P.NewlinesBefore == 0)
186 LastOutsideTokenChange->TokenLength += PrevTokLength + P.Spaces;
187 else
188 LastOutsideTokenChange = &P;
189
190 C.PreviousEndOfTokenColumn = P.StartOfTokenColumn + PrevTokLength;
191
192 P.IsTrailingComment =
193 (C.NewlinesBefore > 0 || C.Tok->is(tok::eof) ||
194 (C.IsInsideToken && C.Tok->is(tok::comment))) &&
195 P.Tok->is(tok::comment) &&
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226 OriginalWhitespaceStart != PreviousOriginalWhitespaceEnd;
227 }
228
229
230 Changes.back().TokenLength = 0;
231 Changes.back().IsTrailingComment = Changes.back().Tok->is(tok::comment);
232
233 const WhitespaceManager::Change *LastBlockComment = nullptr;
234 for (auto &Change : Changes) {
235
236
237
238 if (Change.IsInsideToken && Change.NewlinesBefore == 0)
239 Change.IsTrailingComment = false;
240 Change.StartOfBlockComment = nullptr;
241 Change.IndentationOffset = 0;
242 if (Change.Tok->is(tok::comment)) {
243 if (Change.Tok->is(TT_LineComment) || !Change.IsInsideToken) {
244 LastBlockComment = &Change;
245 } else if ((Change.StartOfBlockComment = LastBlockComment)) {
246 Change.IndentationOffset =
247 Change.StartOfTokenColumn -
248 Change.StartOfBlockComment->StartOfTokenColumn;
249 }
250 } else {
251 LastBlockComment = nullptr;
252 }
253 }
254
255
256
257
258
259 SmallVector<bool, 16> ScopeStack;
260 int ConditionalsLevel = 0;
261 for (auto &Change : Changes) {
262 for (unsigned i = 0, e = Change.Tok->FakeLParens.size(); i != e; ++i) {
263 bool isNestedConditional =
265 !(i == 0 && Change.Tok->Previous &&
266 Change.Tok->Previous->is(TT_ConditionalExpr) &&
267 Change.Tok->Previous->is(tok::colon));
268 if (isNestedConditional)
269 ++ConditionalsLevel;
270 ScopeStack.push_back(isNestedConditional);
271 }
272
273 Change.ConditionalsLevel = ConditionalsLevel;
274
275 for (unsigned i = Change.Tok->FakeRParens; i > 0 && ScopeStack.size(); --i)
276 if (ScopeStack.pop_back_val())
277 --ConditionalsLevel;
278 }
279}
280
281
282
283
284
285template
286static void
288 unsigned Column, bool RightJustify, F &&Matches,
290 bool FoundMatchOnLine = false;
291 int Shift = 0;
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
314
315 for (unsigned i = Start; i != End; ++i) {
316 auto &CurrentChange = Changes[i];
317 if (ScopeStack.size() != 0 &&
318 CurrentChange.indentAndNestingLevel() <
319 Changes[ScopeStack.back()].indentAndNestingLevel()) {
320 ScopeStack.pop_back();
321 }
322
323
324
325 unsigned PreviousNonComment = i - 1;
326 while (PreviousNonComment > Start &&
327 Changes[PreviousNonComment].Tok->is(tok::comment)) {
328 --PreviousNonComment;
329 }
330 if (i != Start && CurrentChange.indentAndNestingLevel() >
331 Changes[PreviousNonComment].indentAndNestingLevel()) {
332 ScopeStack.push_back(i);
333 }
334
335 bool InsideNestedScope = ScopeStack.size() != 0;
336 bool ContinuedStringLiteral = i > Start &&
337 CurrentChange.Tok->is(tok::string_literal) &&
338 Changes[i - 1].Tok->is(tok::string_literal);
339 bool SkipMatchCheck = InsideNestedScope || ContinuedStringLiteral;
340
341 if (CurrentChange.NewlinesBefore > 0 && !SkipMatchCheck) {
342 Shift = 0;
343 FoundMatchOnLine = false;
344 }
345
346
347
348
349 if (!FoundMatchOnLine && !SkipMatchCheck && Matches(CurrentChange)) {
350 FoundMatchOnLine = true;
351 Shift = Column - (RightJustify ? CurrentChange.TokenLength : 0) -
352 CurrentChange.StartOfTokenColumn;
353 CurrentChange.Spaces += Shift;
354
355
356 if (CurrentChange.NewlinesBefore == 0) {
357 CurrentChange.Spaces =
358 std::max(CurrentChange.Spaces,
359 static_cast<int>(CurrentChange.Tok->SpacesRequiredBefore));
360 }
361 }
362
363 if (Shift == 0)
364 continue;
365
366
367
368 if (InsideNestedScope && CurrentChange.NewlinesBefore > 0) {
369 unsigned ScopeStart = ScopeStack.back();
370 auto ShouldShiftBeAdded = [&] {
371
372 if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
373 return true;
374
375
376 if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
377 return false;
378
379
380 if (ScopeStart > Start + 1 &&
381 Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)) {
382 return true;
383 }
384
385
386 if (ScopeStart > Start + 1 &&
387 Changes[ScopeStart - 2].Tok->isOneOf(tok::identifier,
388 TT_TemplateCloser) &&
389 Changes[ScopeStart - 1].Tok->is(tok::l_paren) &&
390 Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) {
391 if (CurrentChange.Tok->MatchingParen &&
392 CurrentChange.Tok->MatchingParen->is(TT_LambdaLBrace)) {
393 return false;
394 }
395 if (Changes[ScopeStart].NewlinesBefore > 0)
396 return false;
397 if (CurrentChange.Tok->is(tok::l_brace) &&
399 return true;
400 }
401 return Style.BinPackArguments;
402 }
403
404
405 if (CurrentChange.Tok->is(TT_ConditionalExpr))
406 return true;
407
408
409 if (CurrentChange.Tok->is(TT_DesignatedInitializerPeriod))
410 return true;
411
412
413 if (CurrentChange.Tok->Previous &&
414 CurrentChange.Tok->Previous->is(TT_ConditionalExpr)) {
415 return true;
416 }
417
418
419 if (ScopeStart > Start + 1 &&
420 Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
421 Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
422 CurrentChange.Tok->is(tok::l_brace) &&
424 return true;
425 }
426
427
428 if (ScopeStart > Start + 1 &&
429 Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
430 Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
431 CurrentChange.Tok->isNot(tok::r_brace)) {
432 for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
433
434 if (OuterScopeStart > Start &&
435 Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace)) {
436 return false;
437 }
438 }
439 if (Changes[ScopeStart].NewlinesBefore > 0)
440 return false;
441 return true;
442 }
443
444
445 if (Changes[ScopeStart - 1].Tok->is(TT_TemplateOpener))
446 return true;
447
448 return false;
449 };
450
451 if (ShouldShiftBeAdded())
452 CurrentChange.Spaces += Shift;
453 }
454
455 if (ContinuedStringLiteral)
456 CurrentChange.Spaces += Shift;
457
458
459 assert(Shift > 0 || Changes[i].NewlinesBefore > 0 ||
460 CurrentChange.Spaces >=
461 static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
462 CurrentChange.Tok->is(tok::eof));
463
464 CurrentChange.StartOfTokenColumn += Shift;
465 if (i + 1 != Changes.size())
466 Changes[i + 1].PreviousEndOfTokenColumn += Shift;
467
468
469
472 CurrentChange.Spaces != 0 &&
473 !CurrentChange.Tok->isOneOf(tok::equal, tok::r_paren,
474 TT_TemplateCloser)) {
475 const bool ReferenceNotRightAligned =
479 Previous >= 0 && Changes[Previous].Tok->is(TT_PointerOrReference);
481 assert(Changes[Previous].Tok->isPointerOrReference());
482 if (Changes[Previous].Tok->isNot(tok::star)) {
483 if (ReferenceNotRightAligned)
484 continue;
486 continue;
487 }
488 Changes[Previous + 1].Spaces -= Shift;
489 Changes[Previous].Spaces += Shift;
490 Changes[Previous].StartOfTokenColumn += Shift;
491 }
492 }
493 }
494}
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527template
530 unsigned StartAt,
532 bool RightJustify = false) {
533
534
535
536
537
538
539
540
541 unsigned WidthLeft = 0;
542
543
544 unsigned WidthAnchor = 0;
545
546
547 unsigned WidthRight = 0;
548
549
550 unsigned StartOfSequence = 0;
551 unsigned EndOfSequence = 0;
552
553
554
555 auto IndentAndNestingLevel = StartAt < Changes.size()
556 ? Changes[StartAt].indentAndNestingLevel()
557 : std::tuple<unsigned, unsigned, unsigned>();
558
559
560
561
562 unsigned CommasBeforeLastMatch = 0;
563 unsigned CommasBeforeMatch = 0;
564
565
566 bool FoundMatchOnLine = false;
567
568
569 bool LineIsComment = true;
570
571
572
573
574
575
576
577
578 auto AlignCurrentSequence = [&] {
579 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
581 WidthLeft + WidthAnchor, RightJustify, Matches,
582 Changes);
583 }
584 WidthLeft = 0;
585 WidthAnchor = 0;
586 WidthRight = 0;
587 StartOfSequence = 0;
588 EndOfSequence = 0;
589 };
590
591 unsigned i = StartAt;
592 for (unsigned e = Changes.size(); i != e; ++i) {
593 auto &CurrentChange = Changes[i];
594 if (CurrentChange.indentAndNestingLevel() < IndentAndNestingLevel)
595 break;
596
597 if (CurrentChange.NewlinesBefore != 0) {
598 CommasBeforeMatch = 0;
599 EndOfSequence = i;
600
601
602 bool EmptyLineBreak =
603 (CurrentChange.NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
604
605
606
607 bool NoMatchBreak =
608 !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);
609
610 if (EmptyLineBreak || NoMatchBreak)
611 AlignCurrentSequence();
612
613
614
615 if (i == 0 || CurrentChange.Tok->isNot(tok::string_literal) ||
616 Changes[i - 1].Tok->isNot(tok::string_literal)) {
617 FoundMatchOnLine = false;
618 }
619 LineIsComment = true;
620 }
621
622 if (CurrentChange.Tok->isNot(tok::comment))
623 LineIsComment = false;
624
625 if (CurrentChange.Tok->is(tok::comma)) {
626 ++CommasBeforeMatch;
627 } else if (CurrentChange.indentAndNestingLevel() > IndentAndNestingLevel) {
628
629 unsigned StoppedAt =
630 AlignTokens(Style, Matches, Changes, i, ACS, RightJustify);
631 i = StoppedAt - 1;
632 continue;
633 }
634
635 if (!Matches(CurrentChange))
636 continue;
637
638
639
640 if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
641 AlignCurrentSequence();
642
643 CommasBeforeLastMatch = CommasBeforeMatch;
644 FoundMatchOnLine = true;
645
646 if (StartOfSequence == 0)
647 StartOfSequence = i;
648
649 unsigned ChangeWidthLeft = CurrentChange.StartOfTokenColumn;
650 unsigned ChangeWidthAnchor = 0;
651 unsigned ChangeWidthRight = 0;
652 if (RightJustify)
653 if (ACS.PadOperators)
654 ChangeWidthAnchor = CurrentChange.TokenLength;
655 else
656 ChangeWidthLeft += CurrentChange.TokenLength;
657 else
658 ChangeWidthRight = CurrentChange.TokenLength;
659 for (unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
660 ChangeWidthRight += Changes[j].Spaces;
661
662
663
664
665
666 if (!Changes[j].IsInsideToken)
667 ChangeWidthRight += Changes[j].TokenLength;
668 }
669
670
671 unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
672 unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
673 unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
674
675 if (Style.ColumnLimit != 0 &&
676 Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
677 AlignCurrentSequence();
678 StartOfSequence = i;
679 WidthLeft = ChangeWidthLeft;
680 WidthAnchor = ChangeWidthAnchor;
681 WidthRight = ChangeWidthRight;
682 } else {
683 WidthLeft = NewLeft;
684 WidthAnchor = NewAnchor;
685 WidthRight = NewRight;
686 }
687 }
688
689 EndOfSequence = i;
690 AlignCurrentSequence();
691 return i;
692}
693
694
695
696
697
698
699
700
702 unsigned &StartOfSequence, unsigned &EndOfSequence, unsigned &MinColumn,
705 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
706 bool FoundMatchOnLine = false;
707 int Shift = 0;
708
709 for (unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
710 if (Changes[I].NewlinesBefore > 0) {
711 Shift = 0;
712 FoundMatchOnLine = false;
713 }
714
715
716
717
718 if (!FoundMatchOnLine && Matches(Changes[I])) {
719 FoundMatchOnLine = true;
720 Shift = MinColumn - Changes[I].StartOfTokenColumn;
721 Changes[I].Spaces += Shift;
722 }
723
724 assert(Shift >= 0);
725 Changes[I].StartOfTokenColumn += Shift;
726 if (I + 1 != Changes.size())
727 Changes[I + 1].PreviousEndOfTokenColumn += Shift;
728 }
729 }
730
731 MinColumn = 0;
732 StartOfSequence = 0;
733 EndOfSequence = 0;
734}
735
736void WhitespaceManager::alignConsecutiveMacros() {
737 if (!Style.AlignConsecutiveMacros.Enabled)
738 return;
739
740 auto AlignMacrosMatches = [](const Change &C) {
741 const FormatToken *Current = C.Tok;
742 unsigned SpacesRequiredBefore = 1;
743
744 if (Current->SpacesRequiredBefore == 0 || !Current->Previous)
745 return false;
746
747 Current = Current->Previous;
748
749
750
751 if (Current->is(tok::r_paren) && Current->MatchingParen) {
752 Current = Current->MatchingParen->Previous;
753 SpacesRequiredBefore = 0;
754 }
755
756 if (!Current || Current->isNot(tok::identifier))
757 return false;
758
759 if (!Current->Previous || Current->Previous->isNot(tok::pp_define))
760 return false;
761
762
763
764
765
766 return Current->Next->SpacesRequiredBefore == SpacesRequiredBefore;
767 };
768
769 unsigned MinColumn = 0;
770
771
772 unsigned StartOfSequence = 0;
773 unsigned EndOfSequence = 0;
774
775
776 bool FoundMatchOnLine = false;
777
778
779 bool LineIsComment = true;
780
781 unsigned I = 0;
782 for (unsigned E = Changes.size(); I != E; ++I) {
783 if (Changes[I].NewlinesBefore != 0) {
784 EndOfSequence = I;
785
786
787 bool EmptyLineBreak = (Changes[I].NewlinesBefore > 1) &&
788 !Style.AlignConsecutiveMacros.AcrossEmptyLines;
789
790
791
792 bool NoMatchBreak =
793 !FoundMatchOnLine &&
794 !(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments);
795
796 if (EmptyLineBreak || NoMatchBreak) {
798 AlignMacrosMatches, Changes);
799 }
800
801
802 FoundMatchOnLine = false;
803 LineIsComment = true;
804 }
805
806 if (Changes[I].Tok->isNot(tok::comment))
807 LineIsComment = false;
808
809 if (!AlignMacrosMatches(Changes[I]))
810 continue;
811
812 FoundMatchOnLine = true;
813
814 if (StartOfSequence == 0)
815 StartOfSequence = I;
816
817 unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn;
818 MinColumn = std::max(MinColumn, ChangeMinColumn);
819 }
820
821 EndOfSequence = I;
823 AlignMacrosMatches, Changes);
824}
825
826void WhitespaceManager::alignConsecutiveAssignments() {
827 if (!Style.AlignConsecutiveAssignments.Enabled)
828 return;
829
831 Style,
832 [&](const Change &C) {
833
834 if (C.NewlinesBefore > 0)
835 return false;
836
837
838 if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
839 return false;
840
841
842 FormatToken *Previous = C.Tok->getPreviousNonComment();
844 return false;
845
846 return Style.AlignConsecutiveAssignments.AlignCompound
848 : (C.Tok->is(tok::equal) ||
849
850
851
852 (Style.isVerilog() && C.Tok->is(tok::lessequal) &&
854 },
855 Changes, 0, Style.AlignConsecutiveAssignments,
856 true);
857}
858
859void WhitespaceManager::alignConsecutiveBitFields() {
860 alignConsecutiveColons(Style.AlignConsecutiveBitFields, TT_BitFieldColon);
861}
862
863void WhitespaceManager::alignConsecutiveColons(
864 const FormatStyle::AlignConsecutiveStyle &AlignStyle, TokenType Type) {
865 if (!AlignStyle.Enabled)
866 return;
867
869 Style,
870 [&](Change const &C) {
871
872 if (C.NewlinesBefore > 0)
873 return false;
874
875
876 if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
877 return false;
878
879 return C.Tok->is(Type);
880 },
881 Changes, 0, AlignStyle);
882}
883
884void WhitespaceManager::alignConsecutiveShortCaseStatements(bool IsExpr) {
885 if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||
886 !(IsExpr ? Style.AllowShortCaseExpressionOnASingleLine
887 : Style.AllowShortCaseLabelsOnASingleLine)) {
888 return;
889 }
890
891 const auto Type = IsExpr ? TT_CaseLabelArrow : TT_CaseLabelColon;
892 const auto &Option = Style.AlignConsecutiveShortCaseStatements;
893 const bool AlignArrowOrColon =
894 IsExpr ? Option.AlignCaseArrows : Option.AlignCaseColons;
895
896 auto Matches = [&](const Change &C) {
897 if (AlignArrowOrColon)
898 return C.Tok->is(Type);
899
900
901
902
903
904 return .IsInsideToken && C.Tok->Previous && C.Tok->Previous->is(Type);
905 };
906
907 unsigned MinColumn = 0;
908
909
910
911
912 unsigned MinEmptyCaseColumn = 0;
913
914
915 unsigned StartOfSequence = 0;
916 unsigned EndOfSequence = 0;
917
918
919 bool FoundMatchOnLine = false;
920
921 bool LineIsComment = true;
922 bool LineIsEmptyCase = false;
923
924 unsigned I = 0;
925 for (unsigned E = Changes.size(); I != E; ++I) {
926 if (Changes[I].NewlinesBefore != 0) {
927
928 bool EmptyLineBreak =
929 (Changes[I].NewlinesBefore > 1) &&
930 !Style.AlignConsecutiveShortCaseStatements.AcrossEmptyLines;
931
932
933
934 bool NoMatchBreak =
935 !FoundMatchOnLine &&
936 !(LineIsComment &&
937 Style.AlignConsecutiveShortCaseStatements.AcrossComments) &&
938 !LineIsEmptyCase;
939
940 if (EmptyLineBreak || NoMatchBreak) {
942 Matches, Changes);
943 MinEmptyCaseColumn = 0;
944 }
945
946
947 FoundMatchOnLine = false;
948 LineIsComment = true;
949 LineIsEmptyCase = false;
950 }
951
952 if (Changes[I].Tok->isNot(tok::comment))
953 LineIsComment = false;
954
955 if (Changes[I].Tok->is(Type)) {
956 LineIsEmptyCase =
957 !Changes[I].Tok->Next || Changes[I].Tok->Next->isTrailingComment();
958
959 if (LineIsEmptyCase) {
960 if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons) {
961 MinEmptyCaseColumn =
962 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn);
963 } else {
964 MinEmptyCaseColumn =
965 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn + 2);
966 }
967 }
968 }
969
970 if (!Matches(Changes[I]))
971 continue;
972
973 if (LineIsEmptyCase)
974 continue;
975
976 FoundMatchOnLine = true;
977
978 if (StartOfSequence == 0)
979 StartOfSequence = I;
980
981 EndOfSequence = I + 1;
982
983 MinColumn = std::max(MinColumn, Changes[I].StartOfTokenColumn);
984
985
986 MinColumn = std::max(MinColumn, MinEmptyCaseColumn);
987 }
988
990 Changes);
991}
992
993void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() {
994 alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons,
995 TT_TableGenDAGArgListColonToAlign);
996}
997
998void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() {
999 alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons,
1000 TT_TableGenCondOperatorColon);
1001}
1002
1003void WhitespaceManager::alignConsecutiveTableGenDefinitions() {
1004 alignConsecutiveColons(Style.AlignConsecutiveTableGenDefinitionColons,
1005 TT_InheritanceColon);
1006}
1007
1008void WhitespaceManager::alignConsecutiveDeclarations() {
1009 if (!Style.AlignConsecutiveDeclarations.Enabled)
1010 return;
1011
1013 Style,
1014 [&](Change const &C) {
1015 if (Style.AlignConsecutiveDeclarations.AlignFunctionPointers) {
1016 for (const auto *Prev = C.Tok->Previous; Prev; Prev = Prev->Previous)
1017 if (Prev->is(tok::equal))
1018 return false;
1019 if (C.Tok->is(TT_FunctionTypeLParen))
1020 return true;
1021 }
1022 if (C.Tok->is(TT_FunctionDeclarationName))
1023 return Style.AlignConsecutiveDeclarations.AlignFunctionDeclarations;
1024 if (C.Tok->isNot(TT_StartOfName))
1025 return false;
1027 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
1028 return false;
1029
1030 for (FormatToken *Next = C.Tok->Next; Next; Next = Next->Next) {
1031 if (Next->is(tok::comment))
1032 continue;
1033 if (Next->is(TT_PointerOrReference))
1034 return false;
1035 if (!Next->Tok.getIdentifierInfo())
1036 break;
1037 if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
1038 tok::kw_operator)) {
1039 return false;
1040 }
1041 }
1042 return true;
1043 },
1044 Changes, 0, Style.AlignConsecutiveDeclarations);
1045}
1046
1047void WhitespaceManager::alignChainedConditionals() {
1048 if (Style.BreakBeforeTernaryOperators) {
1050 Style,
1051 [](Change const &C) {
1052
1053 return C.Tok->is(TT_ConditionalExpr) &&
1054 ((C.Tok->is(tok::question) && .NewlinesBefore) ||
1055 (C.Tok->is(tok::colon) && C.Tok->Next &&
1056 (C.Tok->Next->FakeLParens.size() == 0 ||
1058 },
1059 Changes, 0);
1060 } else {
1061 static auto AlignWrappedOperand = [](Change const &C) {
1062 FormatToken *Previous = C.Tok->getPreviousNonComment();
1063 return C.NewlinesBefore && Previous && Previous->is(TT_ConditionalExpr) &&
1064 (Previous->is(tok::colon) &&
1065 (C.Tok->FakeLParens.size() == 0 ||
1067 };
1068
1069
1070
1071 for (Change &C : Changes)
1072 if (AlignWrappedOperand(C))
1073 C.StartOfTokenColumn -= 2;
1075 Style,
1076 [this](Change const &C) {
1077
1078
1079
1080 return (C.Tok->is(TT_ConditionalExpr) && C.Tok->is(tok::question) &&
1081 &C != &Changes.back() && (&C + 1)->NewlinesBefore == 0 &&
1082 !(&C + 1)->IsTrailingComment) ||
1083 AlignWrappedOperand(C);
1084 },
1085 Changes, 0);
1086 }
1087}
1088
1089void WhitespaceManager::alignTrailingComments() {
1091 return;
1092
1093 const int Size = Changes.size();
1094 int MinColumn = 0;
1095 int StartOfSequence = 0;
1096 bool BreakBeforeNext = false;
1097 int NewLineThreshold = 1;
1099 NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
1100
1101 for (int I = 0, MaxColumn = INT_MAX, Newlines = 0; I < Size; ++I) {
1102 auto &C = Changes[I];
1103 if (C.StartOfBlockComment)
1104 continue;
1105 Newlines += C.NewlinesBefore;
1106 if (.IsTrailingComment)
1107 continue;
1108
1110 const int OriginalSpaces =
1111 C.OriginalWhitespaceRange.getEnd().getRawEncoding() -
1112 C.OriginalWhitespaceRange.getBegin().getRawEncoding() -
1113 C.Tok->LastNewlineOffset;
1114 assert(OriginalSpaces >= 0);
1115 const auto RestoredLineLength =
1116 C.StartOfTokenColumn + C.TokenLength + OriginalSpaces;
1117
1118
1119 if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
1120 break;
1121 C.Spaces = C.NewlinesBefore > 0 ? C.Tok->OriginalColumn : OriginalSpaces;
1122 continue;
1123 }
1124
1125 const int ChangeMinColumn = C.StartOfTokenColumn;
1126 int ChangeMaxColumn;
1127
1128
1129
1130 if (.CreateReplacement)
1131 ChangeMaxColumn = ChangeMinColumn;
1132 else if (Style.ColumnLimit == 0)
1133 ChangeMaxColumn = INT_MAX;
1134 else if (Style.ColumnLimit >= C.TokenLength)
1135 ChangeMaxColumn = Style.ColumnLimit - C.TokenLength;
1136 else
1137 ChangeMaxColumn = ChangeMinColumn;
1138
1139 if (I + 1 < Size && Changes[I + 1].ContinuesPPDirective &&
1140 ChangeMaxColumn >= 2) {
1141 ChangeMaxColumn -= 2;
1142 }
1143
1144 bool WasAlignedWithStartOfNextLine = false;
1145 if (C.NewlinesBefore >= 1) {
1146 const auto CommentColumn =
1148 for (int J = I + 1; J < Size; ++J) {
1149 if (Changes[J].Tok->is(tok::comment))
1150 continue;
1151
1153 Changes[J].OriginalWhitespaceRange.getEnd());
1154
1155
1156 WasAlignedWithStartOfNextLine =
1157 CommentColumn == NextColumn ||
1158 CommentColumn == NextColumn + Style.IndentWidth;
1159 break;
1160 }
1161 }
1162
1163
1164
1165 auto DontAlignThisComment = [](const auto *Tok) {
1166 if (Tok->is(tok::semi)) {
1167 Tok = Tok->getPreviousNonComment();
1168 if (!Tok)
1169 return false;
1170 }
1171 if (Tok->is(tok::r_paren)) {
1172
1173 Tok = Tok->MatchingParen;
1174 if (!Tok)
1175 return false;
1176 Tok = Tok->getPreviousNonComment();
1177 if (!Tok)
1178 return false;
1179 if (Tok->is(TT_DoWhile)) {
1180 const auto *Prev = Tok->getPreviousNonComment();
1181 if (!Prev) {
1182
1183 return true;
1184 }
1185 Tok = Prev;
1186 }
1187 }
1188
1189 if (Tok->isNot(tok::r_brace))
1190 return false;
1191
1192 while (Tok->Previous && Tok->Previous->is(tok::r_brace))
1193 Tok = Tok->Previous;
1194 return Tok->NewlinesBefore > 0;
1195 };
1196
1197 if (I > 0 && C.NewlinesBefore == 0 &&
1198 DontAlignThisComment(Changes[I - 1].Tok)) {
1199 alignTrailingComments(StartOfSequence, I, MinColumn);
1200
1201
1202 MinColumn = 0;
1204 StartOfSequence = I + 1;
1205 } else if (BreakBeforeNext || Newlines > NewLineThreshold ||
1206 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
1207
1208
1209 (C.NewlinesBefore == 1 && I > 0 &&
1210 !Changes[I - 1].IsTrailingComment) ||
1211 WasAlignedWithStartOfNextLine) {
1212 alignTrailingComments(StartOfSequence, I, MinColumn);
1213 MinColumn = ChangeMinColumn;
1214 MaxColumn = ChangeMaxColumn;
1215 StartOfSequence = I;
1216 } else {
1217 MinColumn = std::max(MinColumn, ChangeMinColumn);
1218 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
1219 }
1220 BreakBeforeNext = (I == 0) || (C.NewlinesBefore > 1) ||
1221
1222
1223 (C.NewlinesBefore == 1 && StartOfSequence == I);
1224 Newlines = 0;
1225 }
1226 alignTrailingComments(StartOfSequence, Size, MinColumn);
1227}
1228
1229void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
1231 for (unsigned i = Start; i != End; ++i) {
1233 if (Changes[i].IsTrailingComment)
1234 Shift = Column - Changes[i].StartOfTokenColumn;
1235 if (Changes[i].StartOfBlockComment) {
1236 Shift = Changes[i].IndentationOffset +
1237 Changes[i].StartOfBlockComment->StartOfTokenColumn -
1238 Changes[i].StartOfTokenColumn;
1239 }
1240 if (Shift <= 0)
1241 continue;
1242 Changes[i].Spaces += Shift;
1243 if (i + 1 != Changes.size())
1244 Changes[i + 1].PreviousEndOfTokenColumn += Shift;
1245 Changes[i].StartOfTokenColumn += Shift;
1246 }
1247}
1248
1249void WhitespaceManager::alignEscapedNewlines() {
1250 const auto Align = Style.AlignEscapedNewlines;
1252 return;
1253
1256 const auto MaxColumn = Style.ColumnLimit;
1257 unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1258 unsigned StartOfMacro = 0;
1259 for (unsigned i = 1, e = Changes.size(); i < e; ++i) {
1260 Change &C = Changes[i];
1261 if (C.NewlinesBefore == 0 && (!WithLastLine || C.Tok->isNot(tok::eof)))
1262 continue;
1263 const bool InPPDirective = C.ContinuesPPDirective;
1264 const auto BackslashColumn = C.PreviousEndOfTokenColumn + 2;
1265 if (InPPDirective ||
1266 (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {
1267 MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);
1268 }
1269 if (!InPPDirective) {
1270 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1271 MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1272 StartOfMacro = i;
1273 }
1274 }
1275 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1276}
1277
1278void WhitespaceManager::alignEscapedNewlines(unsigned Start, unsigned End,
1280 for (unsigned i = Start; i < End; ++i) {
1281 Change &C = Changes[i];
1282 if (C.NewlinesBefore > 0) {
1283 assert(C.ContinuesPPDirective);
1284 if (C.PreviousEndOfTokenColumn + 1 > Column)
1285 C.EscapedNewlineColumn = 0;
1286 else
1287 C.EscapedNewlineColumn = Column;
1288 }
1289 }
1290}
1291
1292void WhitespaceManager::alignArrayInitializers() {
1294 return;
1295
1296 for (unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1297 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1298 auto &C = Changes[ChangeIndex];
1299 if (C.Tok->IsArrayInitializer) {
1300 bool FoundComplete = false;
1301 for (unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1302 ++InsideIndex) {
1303 if (Changes[InsideIndex].Tok == C.Tok->MatchingParen) {
1304 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1305 ChangeIndex = InsideIndex + 1;
1306 FoundComplete = true;
1307 break;
1308 }
1309 }
1310 if (!FoundComplete)
1311 ChangeIndex = ChangeEnd;
1312 }
1313 }
1314}
1315
1316void WhitespaceManager::alignArrayInitializers(unsigned Start, unsigned End) {
1317
1319 alignArrayInitializersRightJustified(getCells(Start, End));
1321 alignArrayInitializersLeftJustified(getCells(Start, End));
1322}
1323
1324void WhitespaceManager::alignArrayInitializersRightJustified(
1325 CellDescriptions &&CellDescs) {
1326 if (!CellDescs.isRectangular())
1327 return;
1328
1329 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1330 auto &Cells = CellDescs.Cells;
1331
1332 auto *CellIter = Cells.begin();
1333 for (auto i = 0U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1334 unsigned NetWidth = 0U;
1335 if (isSplitCell(*CellIter))
1336 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1337 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1338
1339 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1340
1341
1342
1343 const auto *Next = CellIter;
1344 do {
1345 const FormatToken *Previous = Changes[Next->Index].Tok->Previous;
1347 Changes[Next->Index].Spaces = BracePadding;
1348 Changes[Next->Index].NewlinesBefore = 0;
1349 }
1350 Next = Next->NextColumnElement;
1351 } while (Next);
1352
1353
1354 if (CellIter != Cells.begin()) {
1355 auto ThisNetWidth =
1356 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1357 auto MaxNetWidth = getMaximumNetWidth(
1358 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1359 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1360 if (ThisNetWidth < MaxNetWidth)
1361 Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1362 auto RowCount = 1U;
1363 auto Offset = std::distance(Cells.begin(), CellIter);
1364 for (const auto *Next = CellIter->NextColumnElement; Next;
1365 Next = Next->NextColumnElement) {
1366 if (RowCount >= CellDescs.CellCounts.size())
1367 break;
1368 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1369 auto *End = Start + Offset;
1370 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1371 if (ThisNetWidth < MaxNetWidth)
1372 Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1373 ++RowCount;
1374 }
1375 }
1376 } else {
1377 auto ThisWidth =
1378 calculateCellWidth(CellIter->Index, CellIter->EndIndex, true) +
1379 NetWidth;
1380 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1381 Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1382 Changes[CellIter->Index].Spaces += (i > 0) ? 1 : BracePadding;
1383 }
1384 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1385 for (const auto *Next = CellIter->NextColumnElement; Next;
1386 Next = Next->NextColumnElement) {
1387 ThisWidth =
1388 calculateCellWidth(Next->Index, Next->EndIndex, true) + NetWidth;
1389 if (Changes[Next->Index].NewlinesBefore == 0) {
1390 Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
1391 Changes[Next->Index].Spaces += (i > 0) ? 1 : BracePadding;
1392 }
1393 alignToStartOfCell(Next->Index, Next->EndIndex);
1394 }
1395 }
1396 }
1397}
1398
1399void WhitespaceManager::alignArrayInitializersLeftJustified(
1400 CellDescriptions &&CellDescs) {
1401
1402 if (!CellDescs.isRectangular())
1403 return;
1404
1405 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1406 auto &Cells = CellDescs.Cells;
1407
1408 auto *CellIter = Cells.begin();
1409
1410 for (const auto *Next = CellIter; Next; Next = Next->NextColumnElement) {
1411 auto &Change = Changes[Next->Index];
1412 Change.Spaces =
1413 Change.NewlinesBefore == 0 ? BracePadding : CellDescs.InitialSpaces;
1414 }
1415 ++CellIter;
1416 for (auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1417 auto MaxNetWidth = getMaximumNetWidth(
1418 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1419 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1420 auto ThisNetWidth =
1421 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1422 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1423 Changes[CellIter->Index].Spaces =
1424 MaxNetWidth - ThisNetWidth +
1425 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1
1426 : BracePadding);
1427 }
1428 auto RowCount = 1U;
1429 auto Offset = std::distance(Cells.begin(), CellIter);
1430 for (const auto *Next = CellIter->NextColumnElement; Next;
1431 Next = Next->NextColumnElement) {
1432 if (RowCount >= CellDescs.CellCounts.size())
1433 break;
1434 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1435 auto *End = Start + Offset;
1436 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1437 if (Changes[Next->Index].NewlinesBefore == 0) {
1438 Changes[Next->Index].Spaces =
1439 MaxNetWidth - ThisNetWidth +
1440 (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : BracePadding);
1441 }
1442 ++RowCount;
1443 }
1444 }
1445}
1446
1447bool WhitespaceManager::isSplitCell(const CellDescription &Cell) {
1448 if (Cell.HasSplit)
1449 return true;
1450 for (const auto *Next = Cell.NextColumnElement; Next;
1451 Next = Next->NextColumnElement) {
1452 if (Next->HasSplit)
1453 return true;
1454 }
1455 return false;
1456}
1457
1458WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,
1459 unsigned End) {
1460
1461 unsigned Depth = 0;
1462 unsigned Cell = 0;
1463 SmallVector CellCounts;
1464 unsigned InitialSpaces = 0;
1465 unsigned InitialTokenLength = 0;
1466 unsigned EndSpaces = 0;
1467 SmallVector Cells;
1468 const FormatToken *MatchingParen = nullptr;
1469 for (unsigned i = Start; i < End; ++i) {
1470 auto &C = Changes[i];
1471 if (C.Tok->is(tok::l_brace))
1472 ++Depth;
1473 else if (C.Tok->is(tok::r_brace))
1474 --Depth;
1475 if (Depth == 2) {
1476 if (C.Tok->is(tok::l_brace)) {
1477 Cell = 0;
1478 MatchingParen = C.Tok->MatchingParen;
1479 if (InitialSpaces == 0) {
1480 InitialSpaces = C.Spaces + C.TokenLength;
1481 InitialTokenLength = C.TokenLength;
1482 auto j = i - 1;
1483 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1484 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1485 InitialTokenLength += Changes[j].TokenLength;
1486 }
1487 if (C.NewlinesBefore == 0) {
1488 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1489 InitialTokenLength += Changes[j].TokenLength;
1490 }
1491 }
1492 } else if (C.Tok->is(tok::comma)) {
1493 if (!Cells.empty())
1494 Cells.back().EndIndex = i;
1495 if (const auto *Next = C.Tok->getNextNonComment();
1496 Next && Next->isNot(tok::r_brace)) {
1497 ++Cell;
1498 }
1499 }
1500 } else if (Depth == 1) {
1501 if (C.Tok == MatchingParen) {
1502 if (!Cells.empty())
1503 Cells.back().EndIndex = i;
1504 Cells.push_back(CellDescription{i, ++Cell, i + 1, false, nullptr});
1505 CellCounts.push_back(C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1506 : Cell);
1507
1508 const auto *NextNonComment = C.Tok->getNextNonComment();
1509 while (NextNonComment && NextNonComment->is(tok::comma))
1510 NextNonComment = NextNonComment->getNextNonComment();
1511 auto j = i;
1512 while (j < End && Changes[j].Tok != NextNonComment)
1513 ++j;
1514 if (j < End && Changes[j].NewlinesBefore == 0 &&
1515 Changes[j].Tok->isNot(tok::r_brace)) {
1516 Changes[j].NewlinesBefore = 1;
1517
1518 Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1519 }
1520 } else if (C.Tok->is(tok::comment) && C.Tok->NewlinesBefore == 0) {
1521
1522 C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
1523 } else if (C.Tok->is(tok::l_brace)) {
1524
1525
1526 auto j = i - 1;
1527 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1528 ;
1529 EndSpaces = Changes[j].Spaces;
1530 }
1531 } else if (Depth == 0 && C.Tok->is(tok::r_brace)) {
1532 C.NewlinesBefore = 1;
1533 C.Spaces = EndSpaces;
1534 }
1535 if (C.Tok->StartsColumn) {
1536
1537
1538 bool HasSplit = false;
1539 if (Changes[i].NewlinesBefore > 0) {
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554 auto j = i - 1;
1555 if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
1556 Changes[j - 1].NewlinesBefore > 0) {
1557 --j;
1558 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1559 if (LineLimit < Style.ColumnLimit) {
1560 Changes[i].NewlinesBefore = 0;
1561 Changes[i].Spaces = 1;
1562 }
1563 }
1564 }
1565 while (Changes[i].NewlinesBefore > 0 && Changes[i].Tok == C.Tok) {
1566 Changes[i].Spaces = InitialSpaces;
1567 ++i;
1568 HasSplit = true;
1569 }
1570 if (Changes[i].Tok != C.Tok)
1571 --i;
1572 Cells.push_back(CellDescription{i, Cell, i, HasSplit, nullptr});
1573 }
1574 }
1575
1576 return linkCells({Cells, CellCounts, InitialSpaces});
1577}
1578
1579unsigned WhitespaceManager::calculateCellWidth(unsigned Start, unsigned End,
1580 bool WithSpaces) const {
1581 unsigned CellWidth = 0;
1582 for (auto i = Start; i < End; i++) {
1583 if (Changes[i].NewlinesBefore > 0)
1584 CellWidth = 0;
1585 CellWidth += Changes[i].TokenLength;
1586 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1587 }
1588 return CellWidth;
1589}
1590
1591void WhitespaceManager::alignToStartOfCell(unsigned Start, unsigned End) {
1592 if ((End - Start) <= 1)
1593 return;
1594
1595
1596 for (auto i = Start + 1; i < End; i++)
1597 if (Changes[i].NewlinesBefore > 0)
1598 Changes[i].Spaces = Changes[Start].Spaces;
1599}
1600
1601WhitespaceManager::CellDescriptions
1602WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1603 auto &Cells = CellDesc.Cells;
1604 for (auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1605 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {
1606 for (auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1607 if (NextIter->Cell == CellIter->Cell) {
1608 CellIter->NextColumnElement = &(*NextIter);
1609 break;
1610 }
1611 }
1612 }
1613 }
1614 return std::move(CellDesc);
1615}
1616
1617void WhitespaceManager::generateChanges() {
1618 for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
1619 const Change &C = Changes[i];
1620 if (i > 0) {
1621 auto Last = Changes[i - 1].OriginalWhitespaceRange;
1622 auto New = Changes[i].OriginalWhitespaceRange;
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664 if (Last.getBegin() == New.getBegin() &&
1665 (Last.getEnd() != Last.getBegin() ||
1666 New.getEnd() == New.getBegin())) {
1667 continue;
1668 }
1669 }
1670 if (C.CreateReplacement) {
1671 std::string ReplacementText = C.PreviousLinePostfix;
1672 if (C.ContinuesPPDirective) {
1673 appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,
1674 C.PreviousEndOfTokenColumn,
1675 C.EscapedNewlineColumn);
1676 } else {
1677 appendNewlineText(ReplacementText, C);
1678 }
1679
1680
1681 appendIndentText(
1682 ReplacementText, C.Tok->IndentLevel, std::max(0, C.Spaces),
1683 std::max((int)C.StartOfTokenColumn, C.Spaces) - std::max(0, C.Spaces),
1684 C.IsAligned);
1685 ReplacementText.append(C.CurrentLinePrefix);
1686 storeReplacement(C.OriginalWhitespaceRange, ReplacementText);
1687 }
1688 }
1689}
1690
1691void WhitespaceManager::storeReplacement(SourceRange Range, StringRef Text) {
1692 unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.getEnd()) -
1694
1696 WhitespaceLength) == Text) {
1697 return;
1698 }
1699 auto Err = Replaces.add(tooling::Replacement(
1701
1702
1703 if (Err) {
1704 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
1705 assert(false);
1706 }
1707}
1708
1709void WhitespaceManager::appendNewlineText(std::string &Text, const Change &C) {
1710 if (C.NewlinesBefore <= 0)
1711 return;
1712
1713 StringRef Newline = UseCRLF ? "\r\n" : "\n";
1714 Text.append(Newline);
1715
1716 if (C.Tok->HasFormFeedBefore)
1717 Text.append("\f");
1718
1719 for (unsigned I = 1; I < C.NewlinesBefore; ++I)
1720 Text.append(Newline);
1721}
1722
1723void WhitespaceManager::appendEscapedNewlineText(
1724 std::string &Text, unsigned Newlines, unsigned PreviousEndOfTokenColumn,
1725 unsigned EscapedNewlineColumn) {
1726 if (Newlines > 0) {
1727 unsigned Spaces =
1728 std::max(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1729 for (unsigned i = 0; i < Newlines; ++i) {
1730 Text.append(Spaces, ' ');
1731 Text.append(UseCRLF ? "\\\r\n" : "\\\n");
1732 Spaces = std::max(0, EscapedNewlineColumn - 1);
1733 }
1734 }
1735}
1736
1737void WhitespaceManager::appendIndentText(std::string &Text,
1738 unsigned IndentLevel, unsigned Spaces,
1739 unsigned WhitespaceStartColumn,
1740 bool IsAligned) {
1741 switch (Style.UseTab) {
1743 Text.append(Spaces, ' ');
1744 break;
1746 if (Style.TabWidth) {
1747 unsigned FirstTabWidth =
1748 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1749
1750
1751 if (Spaces < FirstTabWidth || Spaces == 1) {
1752 Text.append(Spaces, ' ');
1753 break;
1754 }
1755
1756 Spaces -= FirstTabWidth;
1757 Text.append("\t");
1758
1759 Text.append(Spaces / Style.TabWidth, '\t');
1760 Text.append(Spaces % Style.TabWidth, ' ');
1761 } else if (Spaces == 1) {
1762 Text.append(Spaces, ' ');
1763 }
1764 break;
1765 }
1767 if (WhitespaceStartColumn == 0) {
1768 unsigned Indentation = IndentLevel * Style.IndentWidth;
1769 Spaces = appendTabIndent(Text, Spaces, Indentation);
1770 }
1771 Text.append(Spaces, ' ');
1772 break;
1774 if (WhitespaceStartColumn == 0)
1775 Spaces = appendTabIndent(Text, Spaces, Spaces);
1776 Text.append(Spaces, ' ');
1777 break;
1779 if (WhitespaceStartColumn == 0) {
1780 unsigned Indentation =
1781 IsAligned ? IndentLevel * Style.IndentWidth : Spaces;
1782 Spaces = appendTabIndent(Text, Spaces, Indentation);
1783 }
1784 Text.append(Spaces, ' ');
1785 break;
1786 }
1787}
1788
1789unsigned WhitespaceManager::appendTabIndent(std::string &Text, unsigned Spaces,
1790 unsigned Indentation) {
1791
1792
1793 if (Indentation > Spaces)
1794 Indentation = Spaces;
1795 if (Style.TabWidth) {
1796 unsigned Tabs = Indentation / Style.TabWidth;
1797 Text.append(Tabs, '\t');
1798 Spaces -= Tabs * Style.TabWidth;
1799 }
1800 return Spaces;
1801}
1802
1803}
1804}
WhitespaceManager class manages whitespace around tokens and their replacements.
static CharSourceRange getCharRange(SourceRange R)
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Functor to sort changes in original source order.
bool operator()(const Change &C1, const Change &C2) const
void replaceWhitespaceInToken(const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars, StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective, unsigned Newlines, int Spaces)
Inserts or replaces whitespace in the middle of a token.
void addUntouchableToken(const FormatToken &Tok, bool InPPDirective)
Adds information about an unchangeable token's whitespace.
static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF)
Infers whether the input is using CRLF.
llvm::Error addReplacement(const tooling::Replacement &Replacement)
const tooling::Replacements & generateReplacements()
Returns all the Replacements created during formatting.
void replaceWhitespace(FormatToken &Tok, unsigned Newlines, unsigned Spaces, unsigned StartOfTokenColumn, bool IsAligned=false, bool InPPDirective=false)
Replaces the whitespace in front of Tok.
@ MR_ExpandedArg
The token was expanded from a macro argument when formatting the expanded token sequence.
static void AlignMatchingTokenSequence(unsigned &StartOfSequence, unsigned &EndOfSequence, unsigned &MinColumn, std::function< bool(const WhitespaceManager::Change &C)> Matches, SmallVector< WhitespaceManager::Change, 16 > &Changes)
static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, SmallVector< WhitespaceManager::Change, 16 > &Changes, unsigned StartAt, const FormatStyle::AlignConsecutiveStyle &ACS={}, bool RightJustify=false)
static void AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, unsigned Column, bool RightJustify, F &&Matches, SmallVector< WhitespaceManager::Change, 16 > &Changes)
TokenType
Determines the semantic type of a syntactic token, e.g.
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
for(const auto &A :T->param_types())
The FormatStyle is used to configure the formatting to follow specific guidelines.
@ UT_AlignWithSpaces
Use tabs for line continuation and indentation, and spaces for alignment.
@ UT_ForContinuationAndIndentation
Fill all leading whitespace with tabs, and use spaces for alignment that appears within a line (e....
@ UT_ForIndentation
Use tabs only for indentation.
@ UT_Always
Use tabs whenever we need to fill whitespace that spans at least from one tab stop to the next one.
@ TCAS_Never
Don't align trailing comments but other formatter applies.
@ TCAS_Leave
Leave trailing comments as they are.
@ TCAS_Always
Align trailing comments.
@ AIAS_Left
Align array column and left justify the columns e.g.:
@ AIAS_Right
Align array column and right justify the columns e.g.:
@ AIAS_None
Don't align array initializer columns.
@ ENAS_DontAlign
Don't align escaped newlines.
@ ENAS_Left
Align escaped newlines as far left as possible.
@ ENAS_LeftWithLastLine
Align escaped newlines as far left as possible, using the last line of the preprocessor directive as ...
@ PAS_Right
Align pointer to the right.
@ RAS_Right
Align reference to the right.
@ RAS_Pointer
Align reference like PointerAlignment.
A wrapper around a Token storing information about the whitespace characters preceding it.
unsigned OriginalColumn
The original 0-based column of this token, including expanded tabs.
SourceLocation getStartOfNonWhitespace() const
Returns actual token start location without leading escaped newlines and whitespace.
void setDecision(FormatDecision D)
unsigned Finalized
If true, this token has been fully formatted (indented and potentially re-formatted inside),...
std::optional< MacroExpansion > MacroCtx
unsigned NewlinesBefore
The number of newlines immediately before the Token.
unsigned IsFirst
Indicates that this is the first token of the file.
SourceRange WhitespaceRange
The range of the whitespace immediately preceding the Token.
Represents a change before a token, a break inside a token, or the layout of an unchanged token (or w...
Change(const FormatToken &Tok, bool CreateReplacement, SourceRange OriginalWhitespaceRange, int Spaces, unsigned StartOfTokenColumn, unsigned NewlinesBefore, StringRef PreviousLinePostfix, StringRef CurrentLinePrefix, bool IsAligned, bool ContinuesPPDirective, bool IsInsideToken)
Creates a Change.
const Change * StartOfBlockComment
SourceRange OriginalWhitespaceRange
std::string PreviousLinePostfix
std::string CurrentLinePrefix
unsigned StartOfTokenColumn
unsigned PreviousEndOfTokenColumn
unsigned EscapedNewlineColumn
bool ContinuesPPDirective