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