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,
"",
"",
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;
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();
152 NewlinePos +
Changes[i - 1].CurrentLinePrefix.size();
161 LastOutsideTokenChange = &
Changes[i - 1];
163 Changes[i].PreviousEndOfTokenColumn =
166 Changes[i - 1].IsTrailingComment =
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);
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 ScopeStack.push_back(i);
262 bool InsideNestedScope = ScopeStack.size() != 0;
266 FoundMatchOnLine =
false;
272 if (!FoundMatchOnLine && !InsideNestedScope && Matches(Changes[i])) {
273 FoundMatchOnLine =
true;
274 Shift = Column - Changes[i].StartOfTokenColumn;
275 Changes[i].Spaces +=
Shift;
281 unsigned ScopeStart = ScopeStack.back();
282 if (Changes[ScopeStart - 1].
Tok->
is(TT_FunctionDeclarationName) ||
283 (ScopeStart > Start + 1 &&
284 Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)))
285 Changes[i].Spaces +=
Shift;
289 Changes[i].StartOfTokenColumn +=
Shift;
290 if (i + 1 != Changes.size())
322 template <
typename F>
326 unsigned MinColumn = 0;
330 unsigned StartOfSequence = 0;
331 unsigned EndOfSequence = 0;
335 auto IndentAndNestingLevel = StartAt < Changes.size()
336 ? Changes[StartAt].indentAndNestingLevel()
337 : std::pair<unsigned, unsigned>(0, 0);
342 unsigned CommasBeforeLastMatch = 0;
343 unsigned CommasBeforeMatch = 0;
346 bool FoundMatchOnLine =
false;
355 auto AlignCurrentSequence = [&] {
356 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
365 unsigned i = StartAt;
366 for (
unsigned e = Changes.size(); i != e; ++i) {
371 CommasBeforeMatch = 0;
376 AlignCurrentSequence();
378 FoundMatchOnLine =
false;
381 if (Changes[i].
Tok->
is(tok::comma)) {
385 unsigned StoppedAt =
AlignTokens(Style, Matches, Changes, i);
390 if (!Matches(Changes[i]))
395 if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
396 AlignCurrentSequence();
398 CommasBeforeLastMatch = CommasBeforeMatch;
399 FoundMatchOnLine =
true;
401 if (StartOfSequence == 0)
404 unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
405 int LineLengthAfter = -Changes[i].Spaces;
406 for (
unsigned j = i; j != e && Changes[j].NewlinesBefore == 0; ++j)
408 unsigned ChangeMaxColumn = Style.
ColumnLimit - LineLengthAfter;
411 if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
412 CommasBeforeLastMatch != CommasBeforeMatch) {
413 AlignCurrentSequence();
417 MinColumn =
std::max(MinColumn, ChangeMinColumn);
418 MaxColumn =
std::min(MaxColumn, ChangeMaxColumn);
422 AlignCurrentSequence();
426 void WhitespaceManager::alignConsecutiveAssignments() {
433 if (C.NewlinesBefore > 0)
440 return C.Tok->is(tok::equal);
445 void WhitespaceManager::alignConsecutiveDeclarations() {
459 return C.Tok->is(TT_StartOfName) ||
460 C.Tok->is(TT_FunctionDeclarationName) ||
461 C.Tok->is(tok::kw_operator);
466 void WhitespaceManager::alignTrailingComments() {
467 unsigned MinColumn = 0;
469 unsigned StartOfSequence = 0;
470 bool BreakBeforeNext =
false;
471 unsigned Newlines = 0;
472 for (
unsigned i = 0, e =
Changes.size(); i != e; ++i) {
475 Newlines +=
Changes[i].NewlinesBefore;
479 unsigned ChangeMinColumn =
Changes[i].StartOfTokenColumn;
480 unsigned ChangeMaxColumn;
487 ChangeMaxColumn = ChangeMinColumn;
492 ChangeMaxColumn = ChangeMinColumn;
495 ChangeMaxColumn -= 2;
498 bool FollowsRBraceInColumn0 = i > 0 &&
Changes[i].NewlinesBefore == 0 &&
499 Changes[i - 1].Tok->is(tok::r_brace) &&
500 Changes[i - 1].StartOfTokenColumn == 0;
501 bool WasAlignedWithStartOfNextLine =
false;
503 unsigned CommentColumn = SourceMgr.getSpellingColumnNumber(
505 for (
unsigned j = i + 1; j != e; ++j) {
509 unsigned NextColumn = SourceMgr.getSpellingColumnNumber(
513 WasAlignedWithStartOfNextLine =
514 CommentColumn == NextColumn ||
520 alignTrailingComments(StartOfSequence, i, MinColumn);
521 MinColumn = ChangeMinColumn;
522 MaxColumn = ChangeMinColumn;
524 }
else if (BreakBeforeNext || Newlines > 1 ||
525 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
529 !
Changes[i - 1].IsTrailingComment) ||
530 WasAlignedWithStartOfNextLine) {
531 alignTrailingComments(StartOfSequence, i, MinColumn);
532 MinColumn = ChangeMinColumn;
533 MaxColumn = ChangeMaxColumn;
536 MinColumn =
std::max(MinColumn, ChangeMinColumn);
537 MaxColumn =
std::min(MaxColumn, ChangeMaxColumn);
543 (
Changes[i].NewlinesBefore == 1 && StartOfSequence == i);
546 alignTrailingComments(StartOfSequence,
Changes.size(), MinColumn);
549 void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
551 for (
unsigned i = Start; i !=
End; ++i) {
554 Shift = Column -
Changes[i].StartOfTokenColumn;
557 Shift =
Changes[i].IndentationOffset +
558 Changes[i].StartOfBlockComment->StartOfTokenColumn -
569 void WhitespaceManager::alignEscapedNewlines() {
575 unsigned StartOfMacro = 0;
576 for (
unsigned i = 1, e =
Changes.size(); i < e; ++i) {
578 if (C.NewlinesBefore > 0) {
579 if (C.ContinuesPPDirective) {
580 MaxEndOfLine =
std::max(C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
582 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
588 alignEscapedNewlines(StartOfMacro + 1,
Changes.size(), MaxEndOfLine);
591 void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
593 for (
unsigned i = Start; i <
End; ++i) {
595 if (C.NewlinesBefore > 0) {
596 assert(C.ContinuesPPDirective);
597 if (C.PreviousEndOfTokenColumn + 1 > Column)
598 C.EscapedNewlineColumn = 0;
600 C.EscapedNewlineColumn = Column;
605 void WhitespaceManager::generateChanges() {
606 for (
unsigned i = 0, e =
Changes.size(); i != e; ++i) {
610 C.OriginalWhitespaceRange.getBegin() &&
611 "Generating two replacements for the same location");
613 if (C.CreateReplacement) {
614 std::string ReplacementText = C.PreviousLinePostfix;
615 if (C.ContinuesPPDirective)
616 appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,
617 C.PreviousEndOfTokenColumn,
618 C.EscapedNewlineColumn);
620 appendNewlineText(ReplacementText, C.NewlinesBefore);
621 appendIndentText(ReplacementText, C.Tok->IndentLevel,
623 C.StartOfTokenColumn -
std::max(0, C.Spaces));
624 ReplacementText.append(C.CurrentLinePrefix);
625 storeReplacement(C.OriginalWhitespaceRange, ReplacementText);
630 void WhitespaceManager::storeReplacement(
SourceRange Range, StringRef
Text) {
631 unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.
getEnd()) -
632 SourceMgr.getFileOffset(Range.
getBegin());
634 if (StringRef(SourceMgr.getCharacterData(Range.
getBegin()),
635 WhitespaceLength) ==
Text)
647 void WhitespaceManager::appendNewlineText(std::string &Text,
649 for (
unsigned i = 0; i < Newlines; ++i)
650 Text.append(UseCRLF ?
"\r\n" :
"\n");
653 void WhitespaceManager::appendEscapedNewlineText(
658 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
659 for (
unsigned i = 0; i < Newlines; ++i) {
660 Text.append(Spaces,
' ');
661 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
662 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
667 void WhitespaceManager::appendIndentText(std::string &Text,
668 unsigned IndentLevel,
unsigned Spaces,
669 unsigned WhitespaceStartColumn) {
672 Text.append(Spaces,
' ');
675 unsigned FirstTabWidth =
679 Spaces -= FirstTabWidth;
687 if (WhitespaceStartColumn == 0) {
691 if (Indentation > Spaces)
694 Text.append(Tabs,
'\t');
697 Text.append(Spaces,
' ');
700 if (WhitespaceStartColumn == 0) {
702 Text.append(Tabs,
'\t');
705 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.
AvailabilityChange Changes[NumAvailabilitySlots]
WhitespaceManager class manages whitespace around tokens and their replacements.
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
SourceLocation getEnd() const
static CharSourceRange getCharRange(SourceRange R)
Encodes a location in the source.
Dataflow Directional Tag Classes.
std::string toString(const til::SExpr *E)
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const