16 #include "llvm/ADT/STLExtras.h" 36 : Tok(&Tok), CreateReplacement(CreateReplacement),
37 OriginalWhitespaceRange(OriginalWhitespaceRange),
38 StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
39 PreviousLinePostfix(PreviousLinePostfix),
40 CurrentLinePrefix(CurrentLinePrefix),
41 ContinuesPPDirective(ContinuesPPDirective), Spaces(Spaces),
54 Spaces, StartOfTokenColumn, Newlines,
"",
"",
63 Changes.push_back(
Change(Tok,
false,
72 return Replaces.add(Replacement);
77 StringRef PreviousPostfix, StringRef CurrentPrefix,
bool InPPDirective,
78 unsigned Newlines,
int Spaces) {
85 std::max(0, Spaces), Newlines, PreviousPostfix, CurrentPrefix,
86 InPPDirective && !Tok.
IsFirst,
true));
94 calculateLineBreakInformation();
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();
432 void WhitespaceManager::alignConsecutiveAssignments() {
439 if (C.NewlinesBefore > 0)
446 return C.Tok->is(tok::equal);
451 void WhitespaceManager::alignConsecutiveDeclarations() {
465 return C.Tok->is(TT_StartOfName) ||
466 C.Tok->is(TT_FunctionDeclarationName) ||
467 C.Tok->is(tok::kw_operator);
472 void WhitespaceManager::alignTrailingComments() {
473 unsigned MinColumn = 0;
475 unsigned StartOfSequence = 0;
476 bool BreakBeforeNext =
false;
477 unsigned Newlines = 0;
478 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
481 Newlines += Changes[i].NewlinesBefore;
485 unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
486 unsigned ChangeMaxColumn;
493 ChangeMaxColumn = ChangeMinColumn;
498 ChangeMaxColumn = ChangeMinColumn;
501 ChangeMaxColumn -= 2;
504 bool FollowsRBraceInColumn0 = i > 0 && Changes[i].NewlinesBefore == 0 &&
505 Changes[i - 1].Tok->is(tok::r_brace) &&
506 Changes[i - 1].StartOfTokenColumn == 0;
507 bool WasAlignedWithStartOfNextLine =
false;
509 unsigned CommentColumn = SourceMgr.getSpellingColumnNumber(
511 for (
unsigned j = i + 1; j != e; ++j) {
512 if (Changes[j].
Tok->
is(tok::comment))
515 unsigned NextColumn = SourceMgr.getSpellingColumnNumber(
519 WasAlignedWithStartOfNextLine =
520 CommentColumn == NextColumn ||
526 alignTrailingComments(StartOfSequence, i, MinColumn);
527 MinColumn = ChangeMinColumn;
528 MaxColumn = ChangeMinColumn;
530 }
else if (BreakBeforeNext || Newlines > 1 ||
531 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
535 !Changes[i - 1].IsTrailingComment) ||
536 WasAlignedWithStartOfNextLine) {
537 alignTrailingComments(StartOfSequence, i, MinColumn);
538 MinColumn = ChangeMinColumn;
539 MaxColumn = ChangeMaxColumn;
542 MinColumn =
std::max(MinColumn, ChangeMinColumn);
543 MaxColumn =
std::min(MaxColumn, ChangeMaxColumn);
549 (Changes[i].NewlinesBefore == 1 && StartOfSequence == i);
552 alignTrailingComments(StartOfSequence, Changes.size(), MinColumn);
555 void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
557 for (
unsigned i = Start; i !=
End; ++i) {
560 Shift = Column - Changes[i].StartOfTokenColumn;
563 Shift = Changes[i].IndentationOffset +
564 Changes[i].StartOfBlockComment->StartOfTokenColumn -
565 Changes[i].StartOfTokenColumn;
568 Changes[i].Spaces +=
Shift;
569 if (i + 1 != Changes.size())
571 Changes[i].StartOfTokenColumn +=
Shift;
575 void WhitespaceManager::alignEscapedNewlines() {
581 unsigned StartOfMacro = 0;
582 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
584 if (C.NewlinesBefore > 0) {
585 if (C.ContinuesPPDirective) {
586 MaxEndOfLine =
std::max(C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
588 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
594 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
597 void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
599 for (
unsigned i = Start; i <
End; ++i) {
601 if (C.NewlinesBefore > 0) {
602 assert(C.ContinuesPPDirective);
603 if (C.PreviousEndOfTokenColumn + 1 > Column)
604 C.EscapedNewlineColumn = 0;
606 C.EscapedNewlineColumn = Column;
611 void WhitespaceManager::generateChanges() {
612 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
613 const Change &C = Changes[i];
616 C.OriginalWhitespaceRange.getBegin() &&
617 "Generating two replacements for the same location");
619 if (C.CreateReplacement) {
620 std::string ReplacementText = C.PreviousLinePostfix;
621 if (C.ContinuesPPDirective)
622 appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,
623 C.PreviousEndOfTokenColumn,
624 C.EscapedNewlineColumn);
626 appendNewlineText(ReplacementText, C.NewlinesBefore);
627 appendIndentText(ReplacementText, C.Tok->IndentLevel,
629 C.StartOfTokenColumn -
std::max(0, C.Spaces));
630 ReplacementText.append(C.CurrentLinePrefix);
631 storeReplacement(C.OriginalWhitespaceRange, ReplacementText);
636 void WhitespaceManager::storeReplacement(
SourceRange Range, StringRef
Text) {
637 unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.
getEnd()) -
638 SourceMgr.getFileOffset(Range.
getBegin());
640 if (StringRef(SourceMgr.getCharacterData(Range.
getBegin()),
641 WhitespaceLength) ==
Text)
653 void WhitespaceManager::appendNewlineText(std::string &Text,
655 for (
unsigned i = 0; i < Newlines; ++i)
656 Text.append(UseCRLF ?
"\r\n" :
"\n");
659 void WhitespaceManager::appendEscapedNewlineText(
664 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
665 for (
unsigned i = 0; i < Newlines; ++i) {
666 Text.append(Spaces,
' ');
667 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
668 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
673 void WhitespaceManager::appendIndentText(std::string &Text,
674 unsigned IndentLevel,
unsigned Spaces,
675 unsigned WhitespaceStartColumn) {
678 Text.append(Spaces,
' ');
681 unsigned FirstTabWidth =
685 Spaces -= FirstTabWidth;
693 if (WhitespaceStartColumn == 0) {
697 if (Indentation > Spaces)
700 Text.append(Tabs,
'\t');
703 Text.append(Spaces,
' ');
706 if (WhitespaceStartColumn == 0) {
708 Text.append(Tabs,
'\t');
711 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.
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 max(int __a, int __b)
__DEVICE__ int min(int __a, int __b)
A trivial tuple used to represent a source range.
SourceLocation getBegin() const