clang: lib/Format/BreakableToken.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/Support/Debug.h"
21#include
22
23#define DEBUG_TYPE "format-token-breaker"
24
26namespace format {
27
28static constexpr StringRef Blanks(" \t\v\f\r");
29
31 const FormatStyle &Style) {
32 static constexpr StringRef KnownCStylePrefixes[] = {"///<", "//!<", "///",
33 "//!", "//:", "//"};
34 static constexpr StringRef KnownTextProtoPrefixes[] = {"####", "###", "##",
35 "//", "#"};
37 if (Style.isTextProto())
38 KnownPrefixes = KnownTextProtoPrefixes;
39
40 assert(
41 llvm::is_sorted(KnownPrefixes, [](StringRef Lhs, StringRef Rhs) noexcept {
42 return Lhs.size() > Rhs.size();
43 }));
44
45 for (StringRef KnownPrefix : KnownPrefixes) {
46 if (Comment.starts_with(KnownPrefix)) {
47 const auto PrefixLength =
48 Comment.find_first_not_of(' ', KnownPrefix.size());
49 return Comment.substr(0, PrefixLength);
50 }
51 }
52 return {};
53}
54
57 unsigned ColumnLimit, unsigned TabWidth,
59 bool DecorationEndsWithStar = false) {
60 LLVM_DEBUG(llvm::dbgs() << "Comment split: \"" << Text
61 << "\", Column limit: " << ColumnLimit
62 << ", Content start: " << ContentStartColumn << "\n");
63 if (ColumnLimit <= ContentStartColumn + 1)
65
66 unsigned MaxSplit = ColumnLimit - ContentStartColumn + 1;
67 unsigned MaxSplitBytes = 0;
68
69 for (unsigned NumChars = 0;
70 NumChars < MaxSplit && MaxSplitBytes < Text.size();) {
71 unsigned BytesInChar =
74 Text.substr(MaxSplitBytes, BytesInChar), ContentStartColumn + NumChars,
76 MaxSplitBytes += BytesInChar;
77 }
78
79
80
81
82 if (Style.isJavaScript()) {
83 StringRef::size_type SpaceOffset =
84 Text.find_first_of(Blanks, MaxSplitBytes);
85 if (SpaceOffset != StringRef::npos && SpaceOffset + 1 < Text.size() &&
86 Text[SpaceOffset + 1] == '{') {
87 MaxSplitBytes = SpaceOffset + 1;
88 }
89 }
90
91 StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);
92
93 static const auto kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\.");
94
95 while (SpaceOffset != StringRef::npos) {
96
97
98
99
100
101 if (Style.isCpp()) {
102 StringRef::size_type LastNonBlank =
103 Text.find_last_not_of(Blanks, SpaceOffset);
104 if (LastNonBlank != StringRef::npos && Text[LastNonBlank] == '\\') {
105 SpaceOffset = Text.find_last_of(Blanks, LastNonBlank);
106 continue;
107 }
108 }
109
110
111
112 if (kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks))) {
113 SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
114 continue;
115 }
116
117
118 if (Style.isJavaScript() && SpaceOffset + 1 < Text.size() &&
119 (Text[SpaceOffset + 1] == '{' || Text[SpaceOffset + 1] == '@')) {
120 SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
121 continue;
122 }
123
124 break;
125 }
126
127 if (SpaceOffset == StringRef::npos ||
128
129 Text.find_last_not_of(Blanks, SpaceOffset) == StringRef::npos) {
130
131
132 StringRef::size_type FirstNonWhitespace = Text.find_first_not_of(Blanks);
133 if (FirstNonWhitespace == StringRef::npos) {
134
136 }
137 SpaceOffset = Text.find_first_of(
138 Blanks, std::max(MaxSplitBytes, FirstNonWhitespace));
139 }
140 if (SpaceOffset != StringRef::npos && SpaceOffset != 0) {
141
142
143
144
145 if (SpaceOffset == 1 && Text[SpaceOffset - 1] == '*')
147 StringRef BeforeCut = Text.substr(0, SpaceOffset).rtrim(Blanks);
148 StringRef AfterCut = Text.substr(SpaceOffset);
149 if (!DecorationEndsWithStar)
150 AfterCut = AfterCut.ltrim(Blanks);
152 AfterCut.begin() - BeforeCut.end());
153 }
155}
156
160
161 if (Text.empty())
163 if (ColumnLimit <= UsedColumns)
165 unsigned MaxSplit = ColumnLimit - UsedColumns;
166 StringRef::size_type SpaceOffset = 0;
167 StringRef::size_type SlashOffset = 0;
168 StringRef::size_type WordStartOffset = 0;
169 StringRef::size_type SplitPoint = 0;
170 for (unsigned Chars = 0;;) {
171 unsigned Advance;
172 if (Text[0] == '\\') {
174 Chars += Advance;
175 } else {
178 Text.substr(0, Advance), UsedColumns + Chars, TabWidth, Encoding);
179 }
180
181 if (Chars > MaxSplit || Text.size() <= Advance)
182 break;
183
185 SpaceOffset = SplitPoint;
186 if (Text[0] == '/')
187 SlashOffset = SplitPoint;
189 WordStartOffset = SplitPoint;
190
191 SplitPoint += Advance;
193 }
194
195 if (SpaceOffset != 0)
197 if (SlashOffset != 0)
199 if (WordStartOffset != 0)
201 if (SplitPoint != 0)
204}
205
207 assert((Token.is(TT_BlockComment) || Token.is(TT_LineComment)) &&
208 "formatting regions are switched by comment tokens");
209 StringRef Content = Token.TokenText.substr(2).ltrim();
210 return Content.starts_with("clang-format on") ||
211 Content.starts_with("clang-format off");
212}
213
214unsigned
217
218
219
220
221
222
223
224
225
226
227
228 return RemainingTokenColumns + 1 - Split.second;
229}
230
232
234 unsigned Offset,
235 StringRef::size_type Length,
237 llvm_unreachable("Getting the length of a part of the string literal "
238 "indicates that the code tries to reflow it.");
239}
240
241unsigned
248
250 bool Break) const {
252}
253
265
267 unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
268 unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const {
271}
272
275 unsigned ContentIndent,
280}
281
289 : "\"",
294
295
296
297
298
299
300
301 bool SignOnNewLine =
302 .isJavaScript() &&
303 Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;
304
306
307
308 assert(QuoteStyle == DoubleQuotes);
309 LeftBraceQuote =
310 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? "{\"" : "{ \"";
311 RightBraceQuote =
312 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? "\"}" : "\" }";
313 Postfix = "\",";
314 Prefix = "\"";
315 } else {
316
317
318 if (QuoteStyle == SingleQuotes) {
319 LeftBraceQuote = Style.SpacesInParensOptions.Other ? "( '" : "('";
320 RightBraceQuote = Style.SpacesInParensOptions.Other ? "' )" : "')";
321 Postfix = SignOnNewLine ? "'" : "' +";
322 Prefix = SignOnNewLine ? "+ '" : "'";
323 } else {
324 if (QuoteStyle == AtDoubleQuotes) {
325 LeftBraceQuote = Style.SpacesInParensOptions.Other ? "( @" : "(@";
326 Prefix = SignOnNewLine ? "+ @\"" : "@\"";
327 } else {
328 LeftBraceQuote = Style.SpacesInParensOptions.Other ? "( \"" : "(\"";
329 Prefix = SignOnNewLine ? "+ \"" : "\"";
330 }
332 Postfix = SignOnNewLine ? "\"" : "\" +";
333 }
334 }
335
336
337 ContinuationIndent = BracesNeeded ? LeftBraceQuote.size() - 1 : 0;
338
339
340 if (!Style.isVerilog() && SignOnNewLine && !BracesNeeded && UnindentPlus &&
341 Style.AlignOperands == FormatStyle::OAS_AlignAfterOperator) {
342 ContinuationIndent -= 2;
343 }
344}
345
347 unsigned LineIndex, unsigned Offset, unsigned StartColumn) const {
351}
352
353unsigned
355 bool Break) const {
356 return std::max(
357 0,
361 : 0) +
363}
364
376
379
381 return;
382
383
384
385
386
387
389 Tok, 0, 1, "",
391 0);
393 Tok, Tok.TokenText.size() - 1, 1,
395 "", InPPDirective, 0, 0);
396}
397
401 const FormatStyle &Style)
404
406
409 unsigned ColumnLimit, unsigned ContentStartColumn,
410 const llvm::Regex &CommentPragmasRegex) const {
411
413 return Split(StringRef::npos, 0);
415 ContentStartColumn, ColumnLimit, Style.TabWidth,
417}
418
420 unsigned LineIndex, unsigned TailOffset, Split Split,
422 StringRef Text = Content[LineIndex].substr(TailOffset);
423
424
425
426
427 unsigned BreakOffsetInToken =
429 unsigned CharsToRemove = Split.second;
431 tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "", "",
432 false, 0, 1);
433}
434
438
440 Content = Content.trim(Blanks);
441
442
443 bool hasSpecialMeaningPrefix = false;
444 for (StringRef Prefix :
445 {"@", "\\", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "}) {
446 if (Content.starts_with(Prefix)) {
447 hasSpecialMeaningPrefix = true;
448 break;
449 }
450 }
451
452
453
454
455 static const auto kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\. ");
456 hasSpecialMeaningPrefix =
457 hasSpecialMeaningPrefix || kNumberedListRegexp.match(Content);
458
459
460
461
462 return Content.size() >= 2 && !hasSpecialMeaningPrefix &&
463 !Content.ends_with("\\") &&
464
465
467}
468
471 unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
474 DelimitersOnNewline(false),
475 UnbreakableTailLength(Token.UnbreakableTailLength) {
476 assert(Tok.is(TT_BlockComment) &&
477 "block comment section must start with a block comment");
478
482 .split(Lines, UseCRLF ? "\r\n" : "\n");
483
484 int IndentDelta = StartColumn - OriginalStartColumn;
488
491 for (size_t i = 1; i < Lines.size(); ++i)
492 adjustWhitespace(i, IndentDelta);
493
494
495
497
498
499
500
501
502
503 if (Lines.size() >= 2 && Content[1].starts_with("**") &&
506 }
507
508 Decoration = "* ";
509 if (Lines.size() == 1 && !FirstInLine) {
510
511
512
513
514
515 Decoration = "";
516 }
517 for (size_t i = 1, e = Content.size(); i < e && !Decoration.empty(); ++i) {
519 if (i + 1 == e) {
520
521 if (Text.empty())
522 break;
523 } else if (.empty() && Decoration.starts_with(Text)) {
524 continue;
525 }
526 while (.starts_with(Decoration))
527 Decoration = Decoration.drop_back(1);
528 }
529
530 LastLineNeedsDecoration = true;
532 for (size_t i = 1, e = Lines.size(); i < e; ++i) {
533 if (Content[i].empty()) {
534 if (i + 1 == e) {
535
536
537
538 LastLineNeedsDecoration = false;
539
540 if (e >= 2 && !Decoration.empty())
542 } else if (Decoration.empty()) {
543
544
546 }
547 continue;
548 }
549
550
551
552
553
554 unsigned DecorationSize = Decoration.starts_with(Content[i])
556 : Decoration.size();
557 if (DecorationSize)
558 ContentColumn[i] = DecorationColumn + DecorationSize;
560 if (!Decoration.starts_with(Content[i])) {
561 IndentAtLineBreak =
562 std::min(IndentAtLineBreak, std::max(0, ContentColumn[i]));
563 }
564 }
565 IndentAtLineBreak = std::max(IndentAtLineBreak, Decoration.size());
566
567
568 if (Style.isJavaScript() || Style.isJava()) {
569 if ((Lines[0] == "*" || Lines[0].starts_with("* ")) && Lines.size() > 1) {
570
571 DelimitersOnNewline = true;
572 } else if (Lines[0].starts_with("* ") && Lines.size() == 1) {
573
574
575
576 unsigned EndColumn =
580 2;
581 DelimitersOnNewline = EndColumn > Style.ColumnLimit;
582 }
583 }
584
585 LLVM_DEBUG({
586 llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n";
587 llvm::dbgs() << "DelimitersOnNewline " << DelimitersOnNewline << "\n";
588 for (size_t i = 0; i < Lines.size(); ++i) {
589 llvm::dbgs() << i << " |" << Content[i] << "| "
591 << "IN=" << (Content[i].data() - Lines[i].data()) << "\n";
592 }
593 });
594}
595
597 unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
598 unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const {
599
601 return Split(StringRef::npos, 0);
603 ContentStartColumn, ColumnLimit, Style.TabWidth,
605}
606
607void BreakableBlockComment::adjustWhitespace(unsigned LineIndex,
608 int IndentDelta) {
609
610
611
612
613
614 size_t EndOfPreviousLine = Lines[LineIndex - 1].size();
616 --EndOfPreviousLine;
617
618
619 EndOfPreviousLine =
620 Lines[LineIndex - 1].find_last_not_of(Blanks, EndOfPreviousLine);
621 if (EndOfPreviousLine == StringRef::npos)
622 EndOfPreviousLine = 0;
623 else
624 ++EndOfPreviousLine;
625
626 size_t StartOfLine = Lines[LineIndex].find_first_not_of(Blanks);
627 if (StartOfLine == StringRef::npos)
628 StartOfLine = Lines[LineIndex].size();
629
630 StringRef Whitespace = Lines[LineIndex].substr(0, StartOfLine);
631
632 size_t PreviousContentOffset =
633 Content[LineIndex - 1].data() - Lines[LineIndex - 1].data();
634 Content[LineIndex - 1] = Lines[LineIndex - 1].substr(
635 PreviousContentOffset, EndOfPreviousLine - PreviousContentOffset);
636 Content[LineIndex] = Lines[LineIndex].substr(StartOfLine);
637
638
641 IndentDelta;
642}
643
645 unsigned Offset,
646 StringRef::size_type Length,
651}
652
654 unsigned Offset,
656 unsigned LineLength =
657 UnbreakableTailLength +
659 if (LineIndex + 1 == Lines.size()) {
660 LineLength += 2;
661
662 bool HasRemainingText = Offset < Content[LineIndex].size();
663 if (!HasRemainingText) {
664 bool HasDecoration = Lines[LineIndex].ltrim().starts_with(Decoration);
665 if (HasDecoration)
666 LineLength -= Decoration.size();
667 }
668 }
669 return LineLength;
670}
671
673 bool Break) const {
674 if (Break)
675 return IndentAtLineBreak;
677}
678
679const llvm::StringSet<>
681 "@param", "@return", "@returns", "@throws", "@type", "@template",
682 "@see", "@deprecated", "@define", "@exports", "@mods", "@private",
683};
684
686 if (.isJava() &&
.isJavaScript())
687 return 0;
688
689
690
691 StringRef ContentWithNoDecoration = Content[LineIndex];
692 if (LineIndex == 0 && ContentWithNoDecoration.starts_with("*"))
693 ContentWithNoDecoration = ContentWithNoDecoration.substr(1).ltrim(Blanks);
694 StringRef FirstWord = ContentWithNoDecoration.substr(
695 0, ContentWithNoDecoration.find_first_of(Blanks));
697 return Style.ContinuationIndentWidth;
698 return 0;
699}
700
704 StringRef Text = Content[LineIndex].substr(TailOffset);
705 StringRef Prefix = Decoration;
706
707
708
709 unsigned LocalIndentAtLineBreak = IndentAtLineBreak;
710 if (LineIndex + 1 == Lines.size() &&
712
713 Prefix = "";
714 if (LocalIndentAtLineBreak >= 2)
715 LocalIndentAtLineBreak -= 2;
716 }
717
718
719 unsigned BreakOffsetInToken =
721 unsigned CharsToRemove = Split.second;
722 assert(LocalIndentAtLineBreak >= Prefix.size());
723 std::string PrefixWithTrailingIndent = std::string(Prefix);
724 PrefixWithTrailingIndent.append(ContentIndent, ' ');
726 tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "",
727 PrefixWithTrailingIndent, InPPDirective, 1,
728 LocalIndentAtLineBreak + ContentIndent -
729 PrefixWithTrailingIndent.size());
730}
731
733 unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {
734 if ((LineIndex, CommentPragmasRegex))
735 return Split(StringRef::npos, 0);
736
737
738
739 size_t Trimmed = Content[LineIndex].find_first_not_of(Blanks);
740 if (LineIndex) {
741 unsigned PreviousContentIndent = getContentIndent(LineIndex - 1);
742 if (PreviousContentIndent && Trimmed != StringRef::npos &&
743 Trimmed != PreviousContentIndent) {
744 return Split(StringRef::npos, 0);
745 }
746 }
747
748 return Split(0, Trimmed != StringRef::npos ? Trimmed : 0);
749}
750
752
753 return DelimitersOnNewline &&
754 Lines[0].substr(1).find_first_not_of(Blanks) != StringRef::npos;
755}
756
759 StringRef TrimmedContent = Content[LineIndex].ltrim(Blanks);
760
761 assert(Tokens[LineIndex - 1] == Tokens[LineIndex] &&
762 "Reflowing whitespace within a token");
763
764
765 unsigned WhitespaceOffsetInToken = Content[LineIndex - 1].data() +
766 Content[LineIndex - 1].size() -
768 unsigned WhitespaceLength = TrimmedContent.data() -
770 WhitespaceOffsetInToken;
772 tokenAt(LineIndex), WhitespaceOffsetInToken,
773 WhitespaceLength, "",
775 0);
776}
777
780 if (LineIndex == 0) {
781 if (DelimitersOnNewline) {
782
783
784
785
786 size_t BreakLength = Lines[0].substr(1).find_first_not_of(Blanks);
787 if (BreakLength != StringRef::npos) {
788 insertBreak(LineIndex, 0, Split(1, BreakLength), 0,
789 Whitespaces);
790 }
791 }
792 return;
793 }
794
795
796 StringRef Prefix = Decoration;
797 if (Content[LineIndex].empty()) {
798 if (LineIndex + 1 == Lines.size()) {
799 if (!LastLineNeedsDecoration) {
800
801
802 Prefix = "";
803 }
804 } else if (!Decoration.empty()) {
805
806
807 Prefix = Prefix.substr(0, 1);
808 }
810
811 Prefix = Prefix.substr(0, 1);
812 }
813
814
815 unsigned WhitespaceOffsetInToken = Content[LineIndex - 1].data() +
816 Content[LineIndex - 1].size() -
818 unsigned WhitespaceLength = Content[LineIndex].data() -
820 WhitespaceOffsetInToken;
822 tokenAt(LineIndex), WhitespaceOffsetInToken, WhitespaceLength, "", Prefix,
824}
825
828 if (DelimitersOnNewline) {
829
830
831
832 StringRef Line = Content.back().substr(TailOffset);
833 StringRef TrimmedLine = Line.rtrim(Blanks);
834 if (!TrimmedLine.empty())
835 return Split(TrimmedLine.size(), Line.size() - TrimmedLine.size());
836 }
837 return Split(StringRef::npos, 0);
838}
839
841 unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {
842
843
844 StringRef IndentContent = Content[LineIndex];
845 if (Lines[LineIndex].ltrim(Blanks).starts_with("*"))
846 IndentContent = Lines[LineIndex].ltrim(Blanks).substr(1);
848 !CommentPragmasRegex.match(IndentContent) &&
851}
852
857 assert(Tok.is(TT_LineComment) &&
858 "line comment section must start with a line comment");
860 const int Minimum = Style.SpacesInLineCommentPrefix.Minimum;
861
862
863 int FirstLineSpaceChange = 0;
865 CurrentTok && CurrentTok->is(TT_LineComment);
866 CurrentTok = CurrentTok->Next) {
867 LastLineTok = LineTok;
868 StringRef TokenText(CurrentTok->TokenText);
869 assert((TokenText.starts_with("//") || TokenText.starts_with("#")) &&
870 "unsupported line comment prefix, '//' and '#' are supported");
871 size_t FirstLineIndex = Lines.size();
875 PrefixSpaceChange.resize(Lines.size());
877 Prefix.resize(Lines.size());
878 OriginalPrefix.resize(Lines.size());
879 for (size_t i = FirstLineIndex, e = Lines.size(); i < e; ++i) {
882 OriginalPrefix[i] = IndentPrefix;
883 const int SpacesInPrefix = llvm::count(IndentPrefix, ' ');
884
885
886
887 const auto NoSpaceBeforeFirstCommentChar = [&]() {
888 assert(Lines[i].size() > IndentPrefix.size());
889 const char FirstCommentChar = Lines[i][IndentPrefix.size()];
890 const unsigned FirstCharByteSize =
893 Lines[i].substr(IndentPrefix.size(), FirstCharByteSize),
895 return false;
896 }
897
898
899
900
901
902
903
904
905
906 if (FirstCommentChar == '#' && .starts_with("#"))
907 return false;
908 return FirstCommentChar == '\\' || isPunctuation(FirstCommentChar) ||
910 };
911
912
913
914
915
916
917 if (i == 0 || OriginalPrefix[i].rtrim(Blanks) !=
918 OriginalPrefix[i - 1].rtrim(Blanks)) {
919 if (SpacesInPrefix < Minimum && Lines[i].size() > IndentPrefix.size() &&
920 !NoSpaceBeforeFirstCommentChar()) {
921 FirstLineSpaceChange = Minimum - SpacesInPrefix;
922 } else if (static_cast<unsigned>(SpacesInPrefix) >
923 Style.SpacesInLineCommentPrefix.Maximum) {
924 FirstLineSpaceChange =
925 Style.SpacesInLineCommentPrefix.Maximum - SpacesInPrefix;
926 } else {
927 FirstLineSpaceChange = 0;
928 }
929 }
930
931 if (Lines[i].size() != IndentPrefix.size()) {
932 assert(Lines[i].size() > IndentPrefix.size());
933
934 PrefixSpaceChange[i] = SpacesInPrefix + FirstLineSpaceChange < Minimum
935 ? Minimum - SpacesInPrefix
936 : FirstLineSpaceChange;
937
938 const auto FirstNonSpace = Lines[i][IndentPrefix.size()];
939 const bool IsFormatComment = LineTok && switchesFormatting(*LineTok);
940 const bool LineRequiresLeadingSpace =
941 !NoSpaceBeforeFirstCommentChar() ||
942 (FirstNonSpace == '}' && FirstLineSpaceChange != 0);
943 const bool AllowsSpaceChange =
944 !IsFormatComment &&
945 (SpacesInPrefix != 0 || LineRequiresLeadingSpace);
946
947 if (PrefixSpaceChange[i] > 0 && AllowsSpaceChange) {
948 Prefix[i] = IndentPrefix.str();
949 Prefix[i].append(PrefixSpaceChange[i], ' ');
950 } else if (PrefixSpaceChange[i] < 0 && AllowsSpaceChange) {
951 Prefix[i] = IndentPrefix
952 .drop_back(std::minstd::size\_t(
953 -PrefixSpaceChange[i], SpacesInPrefix))
954 .str();
955 } else {
956 Prefix[i] = IndentPrefix.str();
957 }
958 } else {
959
960
961 Prefix[i] = IndentPrefix.drop_back(SpacesInPrefix).str();
962 }
963
965 Content[i] = Lines[i].substr(IndentPrefix.size());
969
970
971 size_t EndOfLine = Content[i].find_last_not_of(Blanks);
972 if (EndOfLine == StringRef::npos)
973 EndOfLine = Content[i].size();
974 else
975 ++EndOfLine;
977 }
978 LineTok = CurrentTok->Next;
979 if (CurrentTok->Next && !CurrentTok->Next->ContinuesLineCommentSection) {
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994 break;
995 }
996 }
997}
998
999unsigned
1001 StringRef::size_type Length,
1006}
1007
1008unsigned
1010 bool ) const {
1012}
1013
1015 unsigned LineIndex, unsigned TailOffset, Split Split,
1017 StringRef Text = Content[LineIndex].substr(TailOffset);
1018
1019
1020 unsigned BreakOffsetInToken =
1022 unsigned CharsToRemove = Split.second;
1024 tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "",
1025 Prefix[LineIndex], InPPDirective, 1,
1026 ContentColumn[LineIndex] - Prefix[LineIndex].size());
1027}
1028
1030 unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {
1031 if ((LineIndex, CommentPragmasRegex))
1032 return Split(StringRef::npos, 0);
1033
1034 size_t Trimmed = Content[LineIndex].find_first_not_of(Blanks);
1035
1036
1037
1038
1039
1040 return Split(0, Trimmed != StringRef::npos ? Trimmed : 0);
1041}
1042
1045 if (LineIndex > 0 && Tokens[LineIndex] != Tokens[LineIndex - 1]) {
1046
1047
1049 *Tokens[LineIndex], 0, 0,
1050 StartColumn, true,
1051 false);
1052 } else if (LineIndex > 0) {
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063 unsigned Offset = Lines[LineIndex - 1].data() +
1064 Lines[LineIndex - 1].size() -
1066
1067
1068 unsigned WhitespaceLength =
1071 WhitespaceLength,
1072 "",
1073 "",
1074 false,
1075 0,
1076 0);
1077 }
1078
1079 unsigned Offset =
1081 unsigned WhitespaceLength =
1082 Content[LineIndex].data() - Lines[LineIndex].data();
1084 WhitespaceLength,
1085 "",
1087 false,
1088 0,
1089 0);
1090}
1091
1094
1095
1096
1097
1098
1099
1100 if (LineIndex > 0 && Tokens[LineIndex] != Tokens[LineIndex - 1]) {
1101
1102
1103
1104
1105
1106 unsigned LineColumn =
1108 (Content[LineIndex].data() - Lines[LineIndex].data()) +
1109 (OriginalPrefix[LineIndex].size() - Prefix[LineIndex].size());
1110
1111
1112
1113
1114
1116 1,
1117 LineColumn,
1118 LineColumn,
1119 true,
1120 false);
1121 }
1122 if (OriginalPrefix[LineIndex] != Prefix[LineIndex]) {
1123
1124 const auto SpacesToRemove = -std::min(PrefixSpaceChange[LineIndex], 0);
1125 const auto SpacesToAdd = std::max(PrefixSpaceChange[LineIndex], 0);
1127 tokenAt(LineIndex), OriginalPrefix[LineIndex].size() - SpacesToRemove,
1128 SpacesToRemove, "", "", false,
1129 0, SpacesToAdd);
1130 }
1131}
1132
1134 if (LastLineTok)
1135 State.NextToken = LastLineTok->Next;
1136}
1137
1139 unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {
1140
1141
1142 StringRef IndentContent = Content[LineIndex];
1143 if (Lines[LineIndex].starts_with("//"))
1144 IndentContent = Lines[LineIndex].substr(2);
1145
1146
1147
1148
1149
1150
1152 !CommentPragmasRegex.match(IndentContent) &&
1155 OriginalPrefix[LineIndex] == OriginalPrefix[LineIndex - 1];
1156}
1157
1158}
1159}
Declares BreakableToken, BreakableStringLiteral, BreakableComment, BreakableBlockComment and Breakabl...
This file implements an indenter that manages the indentation of continuations.
StringRef TokenText
The raw text of the token.
Various functions to configurably format source code.
Token - This structure provides full information about a lexed token.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
BreakableStringLiteralUsingOperators(const FormatToken &Tok, QuoteStyleType QuoteStyle, bool UnindentPlus, unsigned StartColumn, unsigned UnbreakableTailLength, bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)
Creates a breakable token for a single line string literal for C#, Java, JavaScript,...
Definition BreakableToken.cpp:282
QuoteStyleType QuoteStyle
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, unsigned ContentIndent, WhitespaceManager &Whitespaces) const override
Emits the previously retrieved Split via Whitespaces.
Definition BreakableToken.cpp:365
StringRef RightBraceQuote
unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override
Returns the column at which content in line LineIndex starts, assuming no reflow.
Definition BreakableToken.cpp:354
void updateAfterBroken(WhitespaceManager &Whitespaces) const override
Adds replacements that are needed when the token is broken.
Definition BreakableToken.cpp:377
unsigned getRemainingLength(unsigned LineIndex, unsigned Offset, unsigned StartColumn) const override
Returns the number of columns required to format the text following the byte Offset in the line LineI...
Definition BreakableToken.cpp:346
Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit, unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const override
Returns a range (offset, length) at which to break the line at LineIndex, if previously broken at Tai...
Definition BreakableToken.cpp:266
unsigned UnbreakableTailLength
unsigned getRangeLength(unsigned LineIndex, unsigned Offset, StringRef::size_type Length, unsigned StartColumn) const override
Returns the number of columns required to format the text in the byte range [Offset,...
Definition BreakableToken.cpp:233
unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override
Returns the column at which content in line LineIndex starts, assuming no reflow.
Definition BreakableToken.cpp:249
unsigned getLineCount() const override
Returns the number of lines in this token in the original code.
Definition BreakableToken.cpp:231
unsigned getRemainingLength(unsigned LineIndex, unsigned Offset, unsigned StartColumn) const override
Returns the number of columns required to format the text following the byte Offset in the line LineI...
Definition BreakableToken.cpp:242
BreakableStringLiteral(const FormatToken &Tok, unsigned StartColumn, StringRef Prefix, StringRef Postfix, unsigned UnbreakableTailLength, bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)
Creates a breakable token for a single line string literal.
Definition BreakableToken.cpp:254
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, unsigned ContentIndent, WhitespaceManager &Whitespaces) const override
Emits the previously retrieved Split via Whitespaces.
Definition BreakableToken.cpp:273
std::pair< StringRef::size_type, unsigned > Split
Contains starting character index and length of split.
const FormatStyle & Style
unsigned getLengthAfterCompression(unsigned RemainingTokenColumns, Split Split) const
Returns the number of columns needed to format RemainingTokenColumns, assuming that Split is within t...
Definition BreakableToken.cpp:215
BreakableToken(const FormatToken &Tok, bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)
const encoding::Encoding Encoding
Manages the whitespaces around tokens and their replacements.
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 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.
unsigned columnWidthWithTabs(StringRef Text, unsigned StartColumn, unsigned TabWidth, Encoding Encoding)
Returns the number of columns required to display the Text, starting from the StartColumn on a termin...
unsigned getEscapeSequenceLength(StringRef Text)
Gets the length of an escape sequence inside a C++ string literal.
unsigned getCodePointNumBytes(char FirstChar, Encoding Encoding)
Gets the number of bytes in a sequence representing a single codepoint and starting with FirstChar in...
unsigned columnWidth(StringRef Text, Encoding Encoding)
Returns the number of columns required to display the Text on a generic Unicode-capable terminal.
bool switchesFormatting(const FormatToken &Token)
Checks if Token switches formatting, like /* clang-format off */.
Definition BreakableToken.cpp:206
static BreakableToken::Split getStringSplit(StringRef Text, unsigned UsedColumns, unsigned ColumnLimit, unsigned TabWidth, encoding::Encoding Encoding)
Definition BreakableToken.cpp:158
static StringRef getLineCommentIndentPrefix(StringRef Comment, const FormatStyle &Style)
Definition BreakableToken.cpp:30
static bool mayReflowContent(StringRef Content)
Definition BreakableToken.cpp:439
static constexpr StringRef Blanks(" \t\v\f\r")
static BreakableToken::Split getCommentSplit(StringRef Text, unsigned ContentStartColumn, unsigned ColumnLimit, unsigned TabWidth, encoding::Encoding Encoding, const FormatStyle &Style, bool DecorationEndsWithStar=false)
Definition BreakableToken.cpp:56
The JSON file list parser is used to communicate input to InstallAPI.
unsigned TabWidth
The number of columns used for tab stops.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
LLVM_READONLY bool isHorizontalWhitespace(unsigned char c)
Returns true if this character is horizontal ASCII whitespace: ' ', '\t', '\f', '\v'.
LLVM_READONLY bool isPunctuation(unsigned char c)
Return true if this character is an ASCII punctuation character.
A wrapper around a Token storing information about the whitespace characters preceding it.
StringRef TokenText
The raw text of the token.
FormatToken * Next
The next token in the unwrapped line.
The current state when indenting a unwrapped line.