15 #include "llvm/ADT/STLExtras.h" 35 : Tok(&Tok), CreateReplacement(CreateReplacement),
36 OriginalWhitespaceRange(OriginalWhitespaceRange),
37 StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
38 PreviousLinePostfix(PreviousLinePostfix),
39 CurrentLinePrefix(CurrentLinePrefix),
40 ContinuesPPDirective(ContinuesPPDirective), Spaces(Spaces),
53 Spaces, StartOfTokenColumn, Newlines,
"",
"",
62 Changes.push_back(
Change(Tok,
false,
71 return Replaces.add(Replacement);
76 StringRef PreviousPostfix, StringRef CurrentPrefix,
bool InPPDirective,
77 unsigned Newlines,
int Spaces) {
84 std::max(0, Spaces), Newlines, PreviousPostfix, CurrentPrefix,
85 InPPDirective && !Tok.
IsFirst,
true));
93 calculateLineBreakInformation();
94 alignConsecutiveMacros();
95 alignConsecutiveDeclarations();
96 alignConsecutiveAssignments();
97 alignTrailingComments();
98 alignEscapedNewlines();
104 void WhitespaceManager::calculateLineBreakInformation() {
105 Changes[0].PreviousEndOfTokenColumn = 0;
106 Change *LastOutsideTokenChange = &Changes[0];
107 for (
unsigned i = 1, e = Changes.size(); i != e; ++i) {
109 Changes[i].OriginalWhitespaceRange.getBegin();
111 Changes[i - 1].OriginalWhitespaceRange.getEnd();
112 unsigned OriginalWhitespaceStartOffset =
113 SourceMgr.getFileOffset(OriginalWhitespaceStart);
114 unsigned PreviousOriginalWhitespaceEndOffset =
115 SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);
116 assert(PreviousOriginalWhitespaceEndOffset <=
117 OriginalWhitespaceStartOffset);
118 const char *
const PreviousOriginalWhitespaceEndData =
119 SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd);
120 StringRef
Text(PreviousOriginalWhitespaceEndData,
121 SourceMgr.getCharacterData(OriginalWhitespaceStart) -
122 PreviousOriginalWhitespaceEndData);
144 auto NewlinePos =
Text.find_first_of(
'\n');
145 if (NewlinePos == StringRef::npos) {
146 Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset -
147 PreviousOriginalWhitespaceEndOffset +
148 Changes[i].PreviousLinePostfix.size() +
149 Changes[i - 1].CurrentLinePrefix.size();
151 Changes[i - 1].TokenLength =
152 NewlinePos + Changes[i - 1].CurrentLinePrefix.size();
159 Changes[i - 1].TokenLength + Changes[i - 1].Spaces;
161 LastOutsideTokenChange = &Changes[i - 1];
164 Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength;
166 Changes[i - 1].IsTrailingComment =
167 (Changes[i].NewlinesBefore > 0 || Changes[i].Tok->is(
tok::eof) ||
168 (Changes[i].IsInsideToken && Changes[i].Tok->is(tok::comment))) &&
169 Changes[i - 1].Tok->is(tok::comment) &&
200 OriginalWhitespaceStart != PreviousOriginalWhitespaceEnd;
204 Changes.back().TokenLength = 0;
205 Changes.back().IsTrailingComment = Changes.back().Tok->is(tok::comment);
208 for (
auto &
Change : Changes) {
218 LastBlockComment = &
Change;
226 LastBlockComment =
nullptr;
232 template <
typename F>
236 bool FoundMatchOnLine =
false;
252 for (
unsigned i = Start; i !=
End; ++i) {
253 if (ScopeStack.size() != 0 &&
254 Changes[i].indentAndNestingLevel() <
255 Changes[ScopeStack.back()].indentAndNestingLevel())
256 ScopeStack.pop_back();
260 unsigned PreviousNonComment = i - 1;
261 while (PreviousNonComment > Start &&
262 Changes[PreviousNonComment].
Tok->
is(tok::comment))
263 PreviousNonComment--;
265 Changes[PreviousNonComment].indentAndNestingLevel())
266 ScopeStack.push_back(i);
268 bool InsideNestedScope = ScopeStack.size() != 0;
272 FoundMatchOnLine =
false;
278 if (!FoundMatchOnLine && !InsideNestedScope && Matches(Changes[i])) {
279 FoundMatchOnLine =
true;
280 Shift = Column - Changes[i].StartOfTokenColumn;
281 Changes[i].Spaces +=
Shift;
287 unsigned ScopeStart = ScopeStack.back();
288 if (Changes[ScopeStart - 1].
Tok->
is(TT_FunctionDeclarationName) ||
289 (ScopeStart > Start + 1 &&
290 Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)))
291 Changes[i].Spaces +=
Shift;
295 Changes[i].StartOfTokenColumn +=
Shift;
296 if (i + 1 != Changes.size())
328 template <
typename F>
332 unsigned MinColumn = 0;
336 unsigned StartOfSequence = 0;
337 unsigned EndOfSequence = 0;
341 auto IndentAndNestingLevel = StartAt < Changes.size()
342 ? Changes[StartAt].indentAndNestingLevel()
343 : std::pair<unsigned, unsigned>(0, 0);
348 unsigned CommasBeforeLastMatch = 0;
349 unsigned CommasBeforeMatch = 0;
352 bool FoundMatchOnLine =
false;
361 auto AlignCurrentSequence = [&] {
362 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
371 unsigned i = StartAt;
372 for (
unsigned e = Changes.size(); i != e; ++i) {
377 CommasBeforeMatch = 0;
382 AlignCurrentSequence();
384 FoundMatchOnLine =
false;
387 if (Changes[i].
Tok->
is(tok::comma)) {
391 unsigned StoppedAt =
AlignTokens(Style, Matches, Changes, i);
396 if (!Matches(Changes[i]))
401 if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
402 AlignCurrentSequence();
404 CommasBeforeLastMatch = CommasBeforeMatch;
405 FoundMatchOnLine =
true;
407 if (StartOfSequence == 0)
410 unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
411 int LineLengthAfter = -Changes[i].Spaces;
412 for (
unsigned j = i; j != e && Changes[j].NewlinesBefore == 0; ++j)
414 unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
417 if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
418 CommasBeforeLastMatch != CommasBeforeMatch) {
419 AlignCurrentSequence();
423 MinColumn =
std::max(MinColumn, ChangeMinColumn);
424 MaxColumn =
std::min(MaxColumn, ChangeMaxColumn);
428 AlignCurrentSequence();
440 unsigned &StartOfSequence,
unsigned &EndOfSequence,
unsigned &MinColumn,
441 unsigned &MaxColumn,
bool &FoundMatchOnLine,
444 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
446 FoundMatchOnLine =
false;
449 for (
unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
452 FoundMatchOnLine =
false;
458 if (!FoundMatchOnLine && AlignMacrosMatches(Changes[I])) {
459 FoundMatchOnLine =
true;
460 Shift = MinColumn - Changes[I].StartOfTokenColumn;
461 Changes[I].Spaces +=
Shift;
465 Changes[I].StartOfTokenColumn +=
Shift;
466 if (I + 1 != Changes.size())
477 void WhitespaceManager::alignConsecutiveMacros() {
481 auto AlignMacrosMatches = [](
const Change &C) {
483 unsigned SpacesRequiredBefore = 1;
494 SpacesRequiredBefore = 0;
497 if (!Current || !Current->
is(tok::identifier))
510 unsigned MinColumn = 0;
514 unsigned StartOfSequence = 0;
515 unsigned EndOfSequence = 0;
518 bool FoundMatchOnLine =
false;
521 for (
unsigned E = Changes.size(); I != E; ++I) {
528 FoundMatchOnLine, AlignMacrosMatches, Changes);
530 FoundMatchOnLine =
false;
533 if (!AlignMacrosMatches(Changes[I]))
536 FoundMatchOnLine =
true;
538 if (StartOfSequence == 0)
541 unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn;
542 int LineLengthAfter = -Changes[I].Spaces;
543 for (
unsigned j = I; j != E && Changes[j].NewlinesBefore == 0; ++j)
545 unsigned ChangeMaxColumn =
Style.ColumnLimit - LineLengthAfter;
547 MinColumn =
std::max(MinColumn, ChangeMinColumn);
548 MaxColumn =
std::min(MaxColumn, ChangeMaxColumn);
553 FoundMatchOnLine, AlignMacrosMatches, Changes);
556 void WhitespaceManager::alignConsecutiveAssignments() {
564 if (C.NewlinesBefore > 0)
571 return C.Tok->is(tok::equal);
576 void WhitespaceManager::alignConsecutiveDeclarations() {
591 if (C.Tok->isOneOf(TT_FunctionDeclarationName, tok::kw_operator))
593 if (C.Tok->isNot(TT_StartOfName))
596 for (
FormatToken *Next = C.Tok->Next; Next; Next = Next->Next) {
597 if (Next->is(tok::comment))
599 if (!Next->Tok.getIdentifierInfo())
601 if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
610 void WhitespaceManager::alignTrailingComments() {
611 unsigned MinColumn = 0;
613 unsigned StartOfSequence = 0;
614 bool BreakBeforeNext =
false;
615 unsigned Newlines = 0;
616 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
619 Newlines += Changes[i].NewlinesBefore;
623 unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
624 unsigned ChangeMaxColumn;
626 if (
Style.ColumnLimit == 0)
628 else if (
Style.ColumnLimit >= Changes[i].TokenLength)
629 ChangeMaxColumn =
Style.ColumnLimit - Changes[i].TokenLength;
631 ChangeMaxColumn = ChangeMinColumn;
636 ChangeMaxColumn = ChangeMinColumn;
639 ChangeMaxColumn -= 2;
642 bool FollowsRBraceInColumn0 = i > 0 && Changes[i].NewlinesBefore == 0 &&
643 Changes[i - 1].Tok->is(tok::r_brace) &&
644 Changes[i - 1].StartOfTokenColumn == 0;
645 bool WasAlignedWithStartOfNextLine =
false;
647 unsigned CommentColumn = SourceMgr.getSpellingColumnNumber(
649 for (
unsigned j = i + 1; j != e; ++j) {
650 if (Changes[j].
Tok->
is(tok::comment))
653 unsigned NextColumn = SourceMgr.getSpellingColumnNumber(
657 WasAlignedWithStartOfNextLine =
658 CommentColumn == NextColumn ||
659 CommentColumn == NextColumn +
Style.IndentWidth;
664 alignTrailingComments(StartOfSequence, i, MinColumn);
665 MinColumn = ChangeMinColumn;
666 MaxColumn = ChangeMinColumn;
668 }
else if (BreakBeforeNext || Newlines > 1 ||
669 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
673 !Changes[i - 1].IsTrailingComment) ||
674 WasAlignedWithStartOfNextLine) {
675 alignTrailingComments(StartOfSequence, i, MinColumn);
676 MinColumn = ChangeMinColumn;
677 MaxColumn = ChangeMaxColumn;
680 MinColumn =
std::max(MinColumn, ChangeMinColumn);
681 MaxColumn =
std::min(MaxColumn, ChangeMaxColumn);
686 (Changes[i].NewlinesBefore == 1 && StartOfSequence == i);
689 alignTrailingComments(StartOfSequence, Changes.size(), MinColumn);
692 void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
694 for (
unsigned i = Start; i !=
End; ++i) {
697 Shift = Column - Changes[i].StartOfTokenColumn;
700 Shift = Changes[i].IndentationOffset +
701 Changes[i].StartOfBlockComment->StartOfTokenColumn -
702 Changes[i].StartOfTokenColumn;
705 Changes[i].Spaces +=
Shift;
706 if (i + 1 != Changes.size())
708 Changes[i].StartOfTokenColumn +=
Shift;
712 void WhitespaceManager::alignEscapedNewlines() {
717 unsigned MaxEndOfLine = AlignLeft ? 0 :
Style.ColumnLimit;
718 unsigned StartOfMacro = 0;
719 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
721 if (C.NewlinesBefore > 0) {
722 if (C.ContinuesPPDirective) {
723 MaxEndOfLine =
std::max(C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
725 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
726 MaxEndOfLine = AlignLeft ? 0 :
Style.ColumnLimit;
731 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
734 void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
736 for (
unsigned i = Start; i <
End; ++i) {
738 if (C.NewlinesBefore > 0) {
739 assert(C.ContinuesPPDirective);
740 if (C.PreviousEndOfTokenColumn + 1 > Column)
741 C.EscapedNewlineColumn = 0;
743 C.EscapedNewlineColumn = Column;
748 void WhitespaceManager::generateChanges() {
749 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
750 const Change &C = Changes[i];
753 C.OriginalWhitespaceRange.getBegin() &&
754 "Generating two replacements for the same location");
756 if (C.CreateReplacement) {
757 std::string ReplacementText = C.PreviousLinePostfix;
758 if (C.ContinuesPPDirective)
759 appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,
760 C.PreviousEndOfTokenColumn,
761 C.EscapedNewlineColumn);
763 appendNewlineText(ReplacementText, C.NewlinesBefore);
764 appendIndentText(ReplacementText, C.Tok->IndentLevel,
766 C.StartOfTokenColumn -
std::max(0, C.Spaces));
767 ReplacementText.append(C.CurrentLinePrefix);
768 storeReplacement(C.OriginalWhitespaceRange, ReplacementText);
773 void WhitespaceManager::storeReplacement(
SourceRange Range, StringRef
Text) {
774 unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.
getEnd()) -
775 SourceMgr.getFileOffset(Range.
getBegin());
777 if (StringRef(SourceMgr.getCharacterData(Range.
getBegin()),
778 WhitespaceLength) ==
Text)
790 void WhitespaceManager::appendNewlineText(std::string &Text,
792 for (
unsigned i = 0; i < Newlines; ++i)
793 Text.append(UseCRLF ?
"\r\n" :
"\n");
796 void WhitespaceManager::appendEscapedNewlineText(
801 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
802 for (
unsigned i = 0; i < Newlines; ++i) {
803 Text.append(Spaces,
' ');
804 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
805 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
810 void WhitespaceManager::appendIndentText(std::string &Text,
811 unsigned IndentLevel,
unsigned Spaces,
812 unsigned WhitespaceStartColumn) {
813 switch (
Style.UseTab) {
814 case FormatStyle::UT_Never:
815 Text.append(Spaces,
' ');
817 case FormatStyle::UT_Always: {
818 if (
Style.TabWidth) {
819 unsigned FirstTabWidth =
820 Style.TabWidth - WhitespaceStartColumn %
Style.TabWidth;
823 if (Spaces < FirstTabWidth || Spaces == 1) {
824 Text.append(Spaces,
' ');
828 Spaces -= FirstTabWidth;
831 Text.append(Spaces /
Style.TabWidth,
'\t');
832 Text.append(Spaces %
Style.TabWidth,
' ');
833 }
else if (Spaces == 1) {
834 Text.append(Spaces,
' ');
838 case FormatStyle::UT_ForIndentation:
839 if (WhitespaceStartColumn == 0) {
840 unsigned Indentation = IndentLevel *
Style.IndentWidth;
843 if (Indentation > Spaces)
845 if (
Style.TabWidth) {
846 unsigned Tabs = Indentation /
Style.TabWidth;
847 Text.append(Tabs,
'\t');
848 Spaces -= Tabs *
Style.TabWidth;
851 Text.append(Spaces,
' ');
853 case FormatStyle::UT_ForContinuationAndIndentation:
854 if (WhitespaceStartColumn == 0 &&
Style.TabWidth) {
855 unsigned Tabs = Spaces /
Style.TabWidth;
856 Text.append(Tabs,
'\t');
857 Spaces -= Tabs *
Style.TabWidth;
859 Text.append(Spaces,
' ');
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
__DEVICE__ int max(int __a, int __b)
WhitespaceManager class manages whitespace around tokens and their replacements.
SourceLocation getEnd() const
static CharSourceRange getCharRange(SourceRange R)
Encodes a location in the source.
Dataflow Directional Tag Classes.
__DEVICE__ int min(int __a, int __b)
A trivial tuple used to represent a source range.
SourceLocation getBegin() const