1 //===--- BreakableToken.cpp - Format C++ code -----------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Contains implementation of BreakableToken class and classes derived
12 /// from it.
13 ///
14 //===----------------------------------------------------------------------===//
15 
16 #include "BreakableToken.h"
17 #include "ContinuationIndenter.h"
18 #include "clang/Basic/CharInfo.h"
19 #include "clang/Format/Format.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/Support/Debug.h"
22 #include <algorithm>
23 
24 #define DEBUG_TYPE "format-token-breaker"
25 
26 namespace clang {
27 namespace format {
28 
29 static const char *const Blanks = " \t\v\f\r";
30 static bool IsBlank(char C) {
31   switch (C) {
32   case ' ':
33   case '\t':
34   case '\v':
35   case '\f':
36   case '\r':
37     return true;
38   default:
39     return false;
40   }
41 }
42 
43 static StringRef getLineCommentIndentPrefix(StringRef Comment,
44                                             const FormatStyle &Style) {
45   static const char *const KnownCStylePrefixes[] = {"///<", "//!<", "///", "//",
46                                                     "//!"};
47   static const char *const KnownTextProtoPrefixes[] = {"//", "#"};
48   ArrayRef<const char *> KnownPrefixes(KnownCStylePrefixes);
49   if (Style.Language == FormatStyle::LK_TextProto)
50     KnownPrefixes = KnownTextProtoPrefixes;
51 
52   StringRef LongestPrefix;
53   for (StringRef KnownPrefix : KnownPrefixes) {
54     if (Comment.startswith(KnownPrefix)) {
55       size_t PrefixLength = KnownPrefix.size();
56       while (PrefixLength < Comment.size() && Comment[PrefixLength] == ' ')
57         ++PrefixLength;
58       if (PrefixLength > LongestPrefix.size())
59         LongestPrefix = Comment.substr(0, PrefixLength);
60     }
61   }
62   return LongestPrefix;
63 }
64 
65 static BreakableToken::Split getCommentSplit(StringRef Text,
66                                              unsigned ContentStartColumn,
67                                              unsigned ColumnLimit,
68                                              unsigned TabWidth,
69                                              encoding::Encoding Encoding) {
70   if (ColumnLimit <= ContentStartColumn + 1)
71     return BreakableToken::Split(StringRef::npos, 0);
72 
73   unsigned MaxSplit = ColumnLimit - ContentStartColumn + 1;
74   unsigned MaxSplitBytes = 0;
75 
76   for (unsigned NumChars = 0;
77        NumChars < MaxSplit && MaxSplitBytes < Text.size();) {
78     unsigned BytesInChar =
79         encoding::getCodePointNumBytes(Text[MaxSplitBytes], Encoding);
80     NumChars +=
81         encoding::columnWidthWithTabs(Text.substr(MaxSplitBytes, BytesInChar),
82                                       ContentStartColumn, TabWidth, Encoding);
83     MaxSplitBytes += BytesInChar;
84   }
85 
86   StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);
87 
88   // Do not split before a number followed by a dot: this would be interpreted
89   // as a numbered list, which would prevent re-flowing in subsequent passes.
90   static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\.");
91   if (SpaceOffset != StringRef::npos &&
92       kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks)))
93     SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
94 
95   if (SpaceOffset == StringRef::npos ||
96       // Don't break at leading whitespace.
97       Text.find_last_not_of(Blanks, SpaceOffset) == StringRef::npos) {
98     // Make sure that we don't break at leading whitespace that
99     // reaches past MaxSplit.
100     StringRef::size_type FirstNonWhitespace = Text.find_first_not_of(Blanks);
101     if (FirstNonWhitespace == StringRef::npos)
102       // If the comment is only whitespace, we cannot split.
103       return BreakableToken::Split(StringRef::npos, 0);
104     SpaceOffset = Text.find_first_of(
105         Blanks, std::max<unsigned>(MaxSplitBytes, FirstNonWhitespace));
106   }
107   if (SpaceOffset != StringRef::npos && SpaceOffset != 0) {
108     StringRef BeforeCut = Text.substr(0, SpaceOffset).rtrim(Blanks);
109     StringRef AfterCut = Text.substr(SpaceOffset).ltrim(Blanks);
110     return BreakableToken::Split(BeforeCut.size(),
111                                  AfterCut.begin() - BeforeCut.end());
112   }
113   return BreakableToken::Split(StringRef::npos, 0);
114 }
115 
116 static BreakableToken::Split
117 getStringSplit(StringRef Text, unsigned UsedColumns, unsigned ColumnLimit,
118                unsigned TabWidth, encoding::Encoding Encoding) {
119   // FIXME: Reduce unit test case.
120   if (Text.empty())
121     return BreakableToken::Split(StringRef::npos, 0);
122   if (ColumnLimit <= UsedColumns)
123     return BreakableToken::Split(StringRef::npos, 0);
124   unsigned MaxSplit = ColumnLimit - UsedColumns;
125   StringRef::size_type SpaceOffset = 0;
126   StringRef::size_type SlashOffset = 0;
127   StringRef::size_type WordStartOffset = 0;
128   StringRef::size_type SplitPoint = 0;
129   for (unsigned Chars = 0;;) {
130     unsigned Advance;
131     if (Text[0] == '\\') {
132       Advance = encoding::getEscapeSequenceLength(Text);
133       Chars += Advance;
134     } else {
135       Advance = encoding::getCodePointNumBytes(Text[0], Encoding);
136       Chars += encoding::columnWidthWithTabs(
137           Text.substr(0, Advance), UsedColumns + Chars, TabWidth, Encoding);
138     }
139 
140     if (Chars > MaxSplit || Text.size() <= Advance)
141       break;
142 
143     if (IsBlank(Text[0]))
144       SpaceOffset = SplitPoint;
145     if (Text[0] == '/')
146       SlashOffset = SplitPoint;
147     if (Advance == 1 && !isAlphanumeric(Text[0]))
148       WordStartOffset = SplitPoint;
149 
150     SplitPoint += Advance;
151     Text = Text.substr(Advance);
152   }
153 
154   if (SpaceOffset != 0)
155     return BreakableToken::Split(SpaceOffset + 1, 0);
156   if (SlashOffset != 0)
157     return BreakableToken::Split(SlashOffset + 1, 0);
158   if (WordStartOffset != 0)
159     return BreakableToken::Split(WordStartOffset + 1, 0);
160   if (SplitPoint != 0)
161     return BreakableToken::Split(SplitPoint, 0);
162   return BreakableToken::Split(StringRef::npos, 0);
163 }
164 
165 bool switchesFormatting(const FormatToken &Token) {
166   assert((Token.is(TT_BlockComment) || Token.is(TT_LineComment)) &&
167          "formatting regions are switched by comment tokens");
168   StringRef Content = Token.TokenText.substr(2).ltrim();
169   return Content.startswith("clang-format on") ||
170          Content.startswith("clang-format off");
171 }
172 
173 unsigned
174 BreakableToken::getLineLengthAfterCompression(unsigned RemainingTokenColumns,
175                                               Split Split) const {
176   // Example: consider the content
177   // lala  lala
178   // - RemainingTokenColumns is the original number of columns, 10;
179   // - Split is (4, 2), denoting the two spaces between the two words;
180   //
181   // We compute the number of columns when the split is compressed into a single
182   // space, like:
183   // lala lala
184   return RemainingTokenColumns + 1 - Split.second;
185 }
186 
187 unsigned BreakableSingleLineToken::getLineCount() const { return 1; }
188 
189 unsigned BreakableSingleLineToken::getLineLengthAfterSplit(
190     unsigned LineIndex, unsigned TailOffset,
191     StringRef::size_type Length) const {
192   return StartColumn + Prefix.size() + Postfix.size() +
193          encoding::columnWidthWithTabs(Line.substr(TailOffset, Length),
194                                        StartColumn + Prefix.size(),
195                                        Style.TabWidth, Encoding);
196 }
197 
198 BreakableSingleLineToken::BreakableSingleLineToken(
199     const FormatToken &Tok, unsigned StartColumn, StringRef Prefix,
200     StringRef Postfix, bool InPPDirective, encoding::Encoding Encoding,
201     const FormatStyle &Style)
202     : BreakableToken(Tok, InPPDirective, Encoding, Style),
203       StartColumn(StartColumn), Prefix(Prefix), Postfix(Postfix) {
204   assert(Tok.TokenText.startswith(Prefix) && Tok.TokenText.endswith(Postfix));
205   Line = Tok.TokenText.substr(
206       Prefix.size(), Tok.TokenText.size() - Prefix.size() - Postfix.size());
207 }
208 
209 BreakableStringLiteral::BreakableStringLiteral(
210     const FormatToken &Tok, unsigned StartColumn, StringRef Prefix,
211     StringRef Postfix, bool InPPDirective, encoding::Encoding Encoding,
212     const FormatStyle &Style)
213     : BreakableSingleLineToken(Tok, StartColumn, Prefix, Postfix, InPPDirective,
214                                Encoding, Style) {}
215 
216 BreakableToken::Split
217 BreakableStringLiteral::getSplit(unsigned LineIndex, unsigned TailOffset,
218                                  unsigned ColumnLimit,
219                                  llvm::Regex &CommentPragmasRegex) const {
220   return getStringSplit(Line.substr(TailOffset),
221                         StartColumn + Prefix.size() + Postfix.size(),
222                         ColumnLimit, Style.TabWidth, Encoding);
223 }
224 
225 void BreakableStringLiteral::insertBreak(unsigned LineIndex,
226                                          unsigned TailOffset, Split Split,
227                                          WhitespaceManager &Whitespaces) {
228   Whitespaces.replaceWhitespaceInToken(
229       Tok, Prefix.size() + TailOffset + Split.first, Split.second, Postfix,
230       Prefix, InPPDirective, 1, StartColumn);
231 }
232 
233 BreakableComment::BreakableComment(const FormatToken &Token,
234                                    unsigned StartColumn, bool InPPDirective,
235                                    encoding::Encoding Encoding,
236                                    const FormatStyle &Style)
237     : BreakableToken(Token, InPPDirective, Encoding, Style),
238       StartColumn(StartColumn) {}
239 
240 unsigned BreakableComment::getLineCount() const { return Lines.size(); }
241 
242 BreakableToken::Split
243 BreakableComment::getSplit(unsigned LineIndex, unsigned TailOffset,
244                            unsigned ColumnLimit,
245                            llvm::Regex &CommentPragmasRegex) const {
246   // Don't break lines matching the comment pragmas regex.
247   if (CommentPragmasRegex.match(Content[LineIndex]))
248     return Split(StringRef::npos, 0);
249   return getCommentSplit(Content[LineIndex].substr(TailOffset),
250                          getContentStartColumn(LineIndex, TailOffset),
251                          ColumnLimit, Style.TabWidth, Encoding);
252 }
253 
254 void BreakableComment::compressWhitespace(unsigned LineIndex,
255                                           unsigned TailOffset, Split Split,
256                                           WhitespaceManager &Whitespaces) {
257   StringRef Text = Content[LineIndex].substr(TailOffset);
258   // Text is relative to the content line, but Whitespaces operates relative to
259   // the start of the corresponding token, so compute the start of the Split
260   // that needs to be compressed into a single space relative to the start of
261   // its token.
262   unsigned BreakOffsetInToken =
263       Text.data() - tokenAt(LineIndex).TokenText.data() + Split.first;
264   unsigned CharsToRemove = Split.second;
265   Whitespaces.replaceWhitespaceInToken(
266       tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "", "",
267       /*InPPDirective=*/false, /*Newlines=*/0, /*Spaces=*/1);
268 }
269 
270 BreakableToken::Split
271 BreakableComment::getReflowSplit(StringRef Text, StringRef ReflowPrefix,
272                                  unsigned PreviousEndColumn,
273                                  unsigned ColumnLimit) const {
274   unsigned ReflowStartColumn = PreviousEndColumn + ReflowPrefix.size();
275   StringRef TrimmedText = Text.rtrim(Blanks);
276   // This is the width of the resulting line in case the full line of Text gets
277   // reflown up starting at ReflowStartColumn.
278   unsigned FullWidth = ReflowStartColumn + encoding::columnWidthWithTabs(
279                                                TrimmedText, ReflowStartColumn,
280                                                Style.TabWidth, Encoding);
281   // If the full line fits up, we return a reflow split after it,
282   // otherwise we compute the largest piece of text that fits after
283   // ReflowStartColumn.
284   Split ReflowSplit =
285       FullWidth <= ColumnLimit
286           ? Split(TrimmedText.size(), Text.size() - TrimmedText.size())
287           : getCommentSplit(Text, ReflowStartColumn, ColumnLimit,
288                             Style.TabWidth, Encoding);
289 
290   // We need to be extra careful here, because while it's OK to keep a long line
291   // if it can't be broken into smaller pieces (like when the first word of a
292   // long line is longer than the column limit), it's not OK to reflow that long
293   // word up. So we recompute the size of the previous line after reflowing and
294   // only return the reflow split if that's under the line limit.
295   if (ReflowSplit.first != StringRef::npos &&
296       // Check if the width of the newly reflown line is under the limit.
297       PreviousEndColumn + ReflowPrefix.size() +
298               encoding::columnWidthWithTabs(Text.substr(0, ReflowSplit.first),
299                                             PreviousEndColumn +
300                                                 ReflowPrefix.size(),
301                                             Style.TabWidth, Encoding) <=
302           ColumnLimit) {
303     return ReflowSplit;
304   }
305   return Split(StringRef::npos, 0);
306 }
307 
308 const FormatToken &BreakableComment::tokenAt(unsigned LineIndex) const {
309   return Tokens[LineIndex] ? *Tokens[LineIndex] : Tok;
310 }
311 
312 static bool mayReflowContent(StringRef Content) {
313   Content = Content.trim(Blanks);
314   // Lines starting with '@' commonly have special meaning.
315   // Lines starting with '-', '-#', '+' or '*' are bulleted/numbered lists.
316   static const SmallVector<StringRef, 8> kSpecialMeaningPrefixes = {
317       "@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "};
318   bool hasSpecialMeaningPrefix = false;
319   for (StringRef Prefix : kSpecialMeaningPrefixes) {
320     if (Content.startswith(Prefix)) {
321       hasSpecialMeaningPrefix = true;
322       break;
323     }
324   }
325 
326   // Numbered lists may also start with a number followed by '.'
327   // To avoid issues if a line starts with a number which is actually the end
328   // of a previous line, we only consider numbers with up to 2 digits.
329   static llvm::Regex kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\. ");
330   hasSpecialMeaningPrefix =
331       hasSpecialMeaningPrefix || kNumberedListRegexp.match(Content);
332 
333   // Simple heuristic for what to reflow: content should contain at least two
334   // characters and either the first or second character must be
335   // non-punctuation.
336   return Content.size() >= 2 && !hasSpecialMeaningPrefix &&
337          !Content.endswith("\\") &&
338          // Note that this is UTF-8 safe, since if isPunctuation(Content[0]) is
339          // true, then the first code point must be 1 byte long.
340          (!isPunctuation(Content[0]) || !isPunctuation(Content[1]));
341 }
342 
343 BreakableBlockComment::BreakableBlockComment(
344     const FormatToken &Token, unsigned StartColumn,
345     unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
346     encoding::Encoding Encoding, const FormatStyle &Style)
347     : BreakableComment(Token, StartColumn, InPPDirective, Encoding, Style),
348       DelimitersOnNewline(false) {
349   assert(Tok.is(TT_BlockComment) &&
350          "block comment section must start with a block comment");
351 
352   StringRef TokenText(Tok.TokenText);
353   assert(TokenText.startswith("/*") && TokenText.endswith("*/"));
354   TokenText.substr(2, TokenText.size() - 4).split(Lines, "\n");
355 
356   int IndentDelta = StartColumn - OriginalStartColumn;
357   Content.resize(Lines.size());
358   Content[0] = Lines[0];
359   ContentColumn.resize(Lines.size());
360   // Account for the initial '/*'.
361   ContentColumn[0] = StartColumn + 2;
362   Tokens.resize(Lines.size());
363   for (size_t i = 1; i < Lines.size(); ++i)
364     adjustWhitespace(i, IndentDelta);
365 
366   // Align decorations with the column of the star on the first line,
367   // that is one column after the start "/*".
368   DecorationColumn = StartColumn + 1;
369 
370   // Account for comment decoration patterns like this:
371   //
372   // /*
373   // ** blah blah blah
374   // */
375   if (Lines.size() >= 2 && Content[1].startswith("**") &&
376       static_cast<unsigned>(ContentColumn[1]) == StartColumn) {
377     DecorationColumn = StartColumn;
378   }
379 
380   Decoration = "* ";
381   if (Lines.size() == 1 && !FirstInLine) {
382     // Comments for which FirstInLine is false can start on arbitrary column,
383     // and available horizontal space can be too small to align consecutive
384     // lines with the first one.
385     // FIXME: We could, probably, align them to current indentation level, but
386     // now we just wrap them without stars.
387     Decoration = "";
388   }
389   for (size_t i = 1, e = Lines.size(); i < e && !Decoration.empty(); ++i) {
390     // If the last line is empty, the closing "*/" will have a star.
391     if (i + 1 == e && Content[i].empty())
392       break;
393     if (!Content[i].empty() && i + 1 != e && Decoration.startswith(Content[i]))
394       continue;
395     while (!Content[i].startswith(Decoration))
396       Decoration = Decoration.substr(0, Decoration.size() - 1);
397   }
398 
399   LastLineNeedsDecoration = true;
400   IndentAtLineBreak = ContentColumn[0] + 1;
401   for (size_t i = 1, e = Lines.size(); i < e; ++i) {
402     if (Content[i].empty()) {
403       if (i + 1 == e) {
404         // Empty last line means that we already have a star as a part of the
405         // trailing */. We also need to preserve whitespace, so that */ is
406         // correctly indented.
407         LastLineNeedsDecoration = false;
408         // Align the star in the last '*/' with the stars on the previous lines.
409         if (e >= 2 && !Decoration.empty()) {
410           ContentColumn[i] = DecorationColumn;
411         }
412       } else if (Decoration.empty()) {
413         // For all other lines, set the start column to 0 if they're empty, so
414         // we do not insert trailing whitespace anywhere.
415         ContentColumn[i] = 0;
416       }
417       continue;
418     }
419 
420     // The first line already excludes the star.
421     // The last line excludes the star if LastLineNeedsDecoration is false.
422     // For all other lines, adjust the line to exclude the star and
423     // (optionally) the first whitespace.
424     unsigned DecorationSize = Decoration.startswith(Content[i])
425                                   ? Content[i].size()
426                                   : Decoration.size();
427     if (DecorationSize) {
428       ContentColumn[i] = DecorationColumn + DecorationSize;
429     }
430     Content[i] = Content[i].substr(DecorationSize);
431     if (!Decoration.startswith(Content[i]))
432       IndentAtLineBreak =
433           std::min<int>(IndentAtLineBreak, std::max(0, ContentColumn[i]));
434   }
435   IndentAtLineBreak = std::max<unsigned>(IndentAtLineBreak, Decoration.size());
436 
437   // Detect a multiline jsdoc comment and set DelimitersOnNewline in that case.
438   if (Style.Language == FormatStyle::LK_JavaScript ||
439       Style.Language == FormatStyle::LK_Java) {
440     if ((Lines[0] == "*" || Lines[0].startswith("* ")) && Lines.size() > 1) {
441       // This is a multiline jsdoc comment.
442       DelimitersOnNewline = true;
443     } else if (Lines[0].startswith("* ") && Lines.size() == 1) {
444       // Detect a long single-line comment, like:
445       // /** long long long */
446       // Below, '2' is the width of '*/'.
447       unsigned EndColumn =
448           ContentColumn[0] +
449           encoding::columnWidthWithTabs(Lines[0], ContentColumn[0],
450                                         Style.TabWidth, Encoding) +
451           2;
452       DelimitersOnNewline = EndColumn > Style.ColumnLimit;
453     }
454   }
455 
456   DEBUG({
457     llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n";
458     llvm::dbgs() << "DelimitersOnNewline " << DelimitersOnNewline << "\n";
459     for (size_t i = 0; i < Lines.size(); ++i) {
460       llvm::dbgs() << i << " |" << Content[i] << "| "
461                    << "CC=" << ContentColumn[i] << "| "
462                    << "IN=" << (Content[i].data() - Lines[i].data()) << "\n";
463     }
464   });
465 }
466 
467 void BreakableBlockComment::adjustWhitespace(unsigned LineIndex,
468                                              int IndentDelta) {
469   // When in a preprocessor directive, the trailing backslash in a block comment
470   // is not needed, but can serve a purpose of uniformity with necessary escaped
471   // newlines outside the comment. In this case we remove it here before
472   // trimming the trailing whitespace. The backslash will be re-added later when
473   // inserting a line break.
474   size_t EndOfPreviousLine = Lines[LineIndex - 1].size();
475   if (InPPDirective && Lines[LineIndex - 1].endswith("\\"))
476     --EndOfPreviousLine;
477 
478   // Calculate the end of the non-whitespace text in the previous line.
479   EndOfPreviousLine =
480       Lines[LineIndex - 1].find_last_not_of(Blanks, EndOfPreviousLine);
481   if (EndOfPreviousLine == StringRef::npos)
482     EndOfPreviousLine = 0;
483   else
484     ++EndOfPreviousLine;
485   // Calculate the start of the non-whitespace text in the current line.
486   size_t StartOfLine = Lines[LineIndex].find_first_not_of(Blanks);
487   if (StartOfLine == StringRef::npos)
488     StartOfLine = Lines[LineIndex].rtrim("\r\n").size();
489 
490   StringRef Whitespace = Lines[LineIndex].substr(0, StartOfLine);
491   // Adjust Lines to only contain relevant text.
492   size_t PreviousContentOffset =
493       Content[LineIndex - 1].data() - Lines[LineIndex - 1].data();
494   Content[LineIndex - 1] = Lines[LineIndex - 1].substr(
495       PreviousContentOffset, EndOfPreviousLine - PreviousContentOffset);
496   Content[LineIndex] = Lines[LineIndex].substr(StartOfLine);
497 
498   // Adjust the start column uniformly across all lines.
499   ContentColumn[LineIndex] =
500       encoding::columnWidthWithTabs(Whitespace, 0, Style.TabWidth, Encoding) +
501       IndentDelta;
502 }
503 
504 unsigned BreakableBlockComment::getLineLengthAfterSplit(
505     unsigned LineIndex, unsigned TailOffset,
506     StringRef::size_type Length) const {
507   unsigned ContentStartColumn = getContentStartColumn(LineIndex, TailOffset);
508   unsigned LineLength =
509       ContentStartColumn + encoding::columnWidthWithTabs(
510                                Content[LineIndex].substr(TailOffset, Length),
511                                ContentStartColumn, Style.TabWidth, Encoding);
512   // The last line gets a "*/" postfix.
513   if (LineIndex + 1 == Lines.size()) {
514     LineLength += 2;
515     // We never need a decoration when breaking just the trailing "*/" postfix.
516     // Note that checking that Length == 0 is not enough, since Length could
517     // also be StringRef::npos.
518     if (Content[LineIndex].substr(TailOffset, Length).empty()) {
519       LineLength -= Decoration.size();
520     }
521   }
522   return LineLength;
523 }
524 
525 void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
526                                         Split Split,
527                                         WhitespaceManager &Whitespaces) {
528   StringRef Text = Content[LineIndex].substr(TailOffset);
529   StringRef Prefix = Decoration;
530   // We need this to account for the case when we have a decoration "* " for all
531   // the lines except for the last one, where the star in "*/" acts as a
532   // decoration.
533   unsigned LocalIndentAtLineBreak = IndentAtLineBreak;
534   if (LineIndex + 1 == Lines.size() &&
535       Text.size() == Split.first + Split.second) {
536     // For the last line we need to break before "*/", but not to add "* ".
537     Prefix = "";
538     if (LocalIndentAtLineBreak >= 2)
539       LocalIndentAtLineBreak -= 2;
540   }
541   // The split offset is from the beginning of the line. Convert it to an offset
542   // from the beginning of the token text.
543   unsigned BreakOffsetInToken =
544       Text.data() - tokenAt(LineIndex).TokenText.data() + Split.first;
545   unsigned CharsToRemove = Split.second;
546   assert(LocalIndentAtLineBreak >= Prefix.size());
547   Whitespaces.replaceWhitespaceInToken(
548       tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "", Prefix,
549       InPPDirective, /*Newlines=*/1,
550       /*Spaces=*/LocalIndentAtLineBreak - Prefix.size());
551 }
552 
553 BreakableToken::Split BreakableBlockComment::getSplitBefore(
554     unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit,
555     llvm::Regex &CommentPragmasRegex) const {
556   if (!mayReflow(LineIndex, CommentPragmasRegex))
557     return Split(StringRef::npos, 0);
558   StringRef TrimmedContent = Content[LineIndex].ltrim(Blanks);
559   Split Result = getReflowSplit(TrimmedContent, ReflowPrefix, PreviousEndColumn,
560                                 ColumnLimit);
561   // Result is relative to TrimmedContent. Adapt it relative to
562   // Content[LineIndex].
563   if (Result.first != StringRef::npos)
564     Result.first += Content[LineIndex].size() - TrimmedContent.size();
565   return Result;
566 }
567 
568 unsigned
569 BreakableBlockComment::getReflownColumn(StringRef Content, unsigned LineIndex,
570                                         unsigned PreviousEndColumn) const {
571   unsigned StartColumn = PreviousEndColumn + ReflowPrefix.size();
572   // If this is the last line, it will carry around its '*/' postfix.
573   unsigned PostfixLength = (LineIndex + 1 == Lines.size() ? 2 : 0);
574   // The line is composed of previous text, reflow prefix, reflown text and
575   // postfix.
576   unsigned ReflownColumn = StartColumn +
577                            encoding::columnWidthWithTabs(
578                                Content, StartColumn, Style.TabWidth, Encoding) +
579                            PostfixLength;
580   return ReflownColumn;
581 }
582 
583 unsigned BreakableBlockComment::getLineLengthAfterSplitBefore(
584     unsigned LineIndex, unsigned TailOffset, unsigned PreviousEndColumn,
585     unsigned ColumnLimit, Split SplitBefore) const {
586   if (SplitBefore.first == StringRef::npos ||
587       // Block comment line contents contain the trailing whitespace after the
588       // decoration, so the need of left trim. Note that this behavior is
589       // consistent with the breaking of block comments where the indentation of
590       // a broken line is uniform across all the lines of the block comment.
591       SplitBefore.first + SplitBefore.second <
592           Content[LineIndex].ltrim().size()) {
593     // A piece of line, not the whole, gets reflown.
594     return getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
595   } else {
596     // The whole line gets reflown, need to check if we need to insert a break
597     // for the postfix or not.
598     StringRef TrimmedContent = Content[LineIndex].ltrim(Blanks);
599     unsigned ReflownColumn =
600         getReflownColumn(TrimmedContent, LineIndex, PreviousEndColumn);
601     if (ReflownColumn <= ColumnLimit) {
602       return ReflownColumn;
603     }
604     return getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
605   }
606 }
607 
608 bool BreakableBlockComment::introducesBreakBefore(unsigned LineIndex) const {
609   // A break is introduced when we want delimiters on newline.
610   return LineIndex == 0 && DelimitersOnNewline &&
611          Lines[0].substr(1).find_first_not_of(Blanks) != StringRef::npos;
612 }
613 
614 void BreakableBlockComment::replaceWhitespaceBefore(
615     unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit,
616     Split SplitBefore, WhitespaceManager &Whitespaces) {
617   if (LineIndex == 0) {
618     if (DelimitersOnNewline) {
619       // Since we're breaking af index 1 below, the break position and the
620       // break length are the same.
621       size_t BreakLength = Lines[0].substr(1).find_first_not_of(Blanks);
622       if (BreakLength != StringRef::npos) {
623         insertBreak(LineIndex, 0, Split(1, BreakLength), Whitespaces);
624         DelimitersOnNewline = true;
625       }
626     }
627     return;
628   }
629   StringRef TrimmedContent = Content[LineIndex].ltrim(Blanks);
630   if (SplitBefore.first != StringRef::npos) {
631     // Here we need to reflow.
632     assert(Tokens[LineIndex - 1] == Tokens[LineIndex] &&
633            "Reflowing whitespace within a token");
634     // This is the offset of the end of the last line relative to the start of
635     // the token text in the token.
636     unsigned WhitespaceOffsetInToken = Content[LineIndex - 1].data() +
637                                        Content[LineIndex - 1].size() -
638                                        tokenAt(LineIndex).TokenText.data();
639     unsigned WhitespaceLength = TrimmedContent.data() -
640                                 tokenAt(LineIndex).TokenText.data() -
641                                 WhitespaceOffsetInToken;
642     Whitespaces.replaceWhitespaceInToken(
643         tokenAt(LineIndex), WhitespaceOffsetInToken,
644         /*ReplaceChars=*/WhitespaceLength, /*PreviousPostfix=*/"",
645         /*CurrentPrefix=*/ReflowPrefix, InPPDirective, /*Newlines=*/0,
646         /*Spaces=*/0);
647     // Check if we need to also insert a break at the whitespace range.
648     // Note that we don't need a penalty for this break, since it doesn't change
649     // the total number of lines.
650     unsigned ReflownColumn =
651         getReflownColumn(TrimmedContent, LineIndex, PreviousEndColumn);
652     if (ReflownColumn > ColumnLimit)
653       insertBreak(LineIndex, 0, SplitBefore, Whitespaces);
654     return;
655   }
656 
657   // Here no reflow with the previous line will happen.
658   // Fix the decoration of the line at LineIndex.
659   StringRef Prefix = Decoration;
660   if (Content[LineIndex].empty()) {
661     if (LineIndex + 1 == Lines.size()) {
662       if (!LastLineNeedsDecoration) {
663         // If the last line was empty, we don't need a prefix, as the */ will
664         // line up with the decoration (if it exists).
665         Prefix = "";
666       }
667     } else if (!Decoration.empty()) {
668       // For other empty lines, if we do have a decoration, adapt it to not
669       // contain a trailing whitespace.
670       Prefix = Prefix.substr(0, 1);
671     }
672   } else {
673     if (ContentColumn[LineIndex] == 1) {
674       // This line starts immediately after the decorating *.
675       Prefix = Prefix.substr(0, 1);
676     }
677   }
678   // This is the offset of the end of the last line relative to the start of the
679   // token text in the token.
680   unsigned WhitespaceOffsetInToken = Content[LineIndex - 1].data() +
681                                      Content[LineIndex - 1].size() -
682                                      tokenAt(LineIndex).TokenText.data();
683   unsigned WhitespaceLength = Content[LineIndex].data() -
684                               tokenAt(LineIndex).TokenText.data() -
685                               WhitespaceOffsetInToken;
686   Whitespaces.replaceWhitespaceInToken(
687       tokenAt(LineIndex), WhitespaceOffsetInToken, WhitespaceLength, "", Prefix,
688       InPPDirective, /*Newlines=*/1, ContentColumn[LineIndex] - Prefix.size());
689 }
690 
691 BreakableToken::Split
692 BreakableBlockComment::getSplitAfterLastLine(unsigned TailOffset,
693                                              unsigned ColumnLimit) const {
694   if (DelimitersOnNewline) {
695     // Replace the trailing whitespace of the last line with a newline.
696     // In case the last line is empty, the ending '*/' is already on its own
697     // line.
698     StringRef Line = Content.back().substr(TailOffset);
699     StringRef TrimmedLine = Line.rtrim(Blanks);
700     if (!TrimmedLine.empty())
701       return Split(TrimmedLine.size(), Line.size() - TrimmedLine.size());
702   }
703   return Split(StringRef::npos, 0);
704 }
705 
706 bool BreakableBlockComment::mayReflow(unsigned LineIndex,
707                                       llvm::Regex &CommentPragmasRegex) const {
708   // Content[LineIndex] may exclude the indent after the '*' decoration. In that
709   // case, we compute the start of the comment pragma manually.
710   StringRef IndentContent = Content[LineIndex];
711   if (Lines[LineIndex].ltrim(Blanks).startswith("*")) {
712     IndentContent = Lines[LineIndex].ltrim(Blanks).substr(1);
713   }
714   return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) &&
715          mayReflowContent(Content[LineIndex]) && !Tok.Finalized &&
716          !switchesFormatting(tokenAt(LineIndex));
717 }
718 
719 unsigned
720 BreakableBlockComment::getContentStartColumn(unsigned LineIndex,
721                                              unsigned TailOffset) const {
722   // If we break, we always break at the predefined indent.
723   if (TailOffset != 0)
724     return IndentAtLineBreak;
725   return std::max(0, ContentColumn[LineIndex]);
726 }
727 
728 BreakableLineCommentSection::BreakableLineCommentSection(
729     const FormatToken &Token, unsigned StartColumn,
730     unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
731     encoding::Encoding Encoding, const FormatStyle &Style)
732     : BreakableComment(Token, StartColumn, InPPDirective, Encoding, Style) {
733   assert(Tok.is(TT_LineComment) &&
734          "line comment section must start with a line comment");
735   FormatToken *LineTok = nullptr;
736   for (const FormatToken *CurrentTok = &Tok;
737        CurrentTok && CurrentTok->is(TT_LineComment);
738        CurrentTok = CurrentTok->Next) {
739     LastLineTok = LineTok;
740     StringRef TokenText(CurrentTok->TokenText);
741     assert((TokenText.startswith("//") || TokenText.startswith("#")) &&
742            "unsupported line comment prefix, '//' and '#' are supported");
743     size_t FirstLineIndex = Lines.size();
744     TokenText.split(Lines, "\n");
745     Content.resize(Lines.size());
746     ContentColumn.resize(Lines.size());
747     OriginalContentColumn.resize(Lines.size());
748     Tokens.resize(Lines.size());
749     Prefix.resize(Lines.size());
750     OriginalPrefix.resize(Lines.size());
751     for (size_t i = FirstLineIndex, e = Lines.size(); i < e; ++i) {
752       Lines[i] = Lines[i].ltrim(Blanks);
753       // We need to trim the blanks in case this is not the first line in a
754       // multiline comment. Then the indent is included in Lines[i].
755       StringRef IndentPrefix =
756           getLineCommentIndentPrefix(Lines[i].ltrim(Blanks), Style);
757       assert((TokenText.startswith("//") || TokenText.startswith("#")) &&
758              "unsupported line comment prefix, '//' and '#' are supported");
759       OriginalPrefix[i] = Prefix[i] = IndentPrefix;
760       if (Lines[i].size() > Prefix[i].size() &&
761           isAlphanumeric(Lines[i][Prefix[i].size()])) {
762         if (Prefix[i] == "//")
763           Prefix[i] = "// ";
764         else if (Prefix[i] == "///")
765           Prefix[i] = "/// ";
766         else if (Prefix[i] == "//!")
767           Prefix[i] = "//! ";
768         else if (Prefix[i] == "///<")
769           Prefix[i] = "///< ";
770         else if (Prefix[i] == "//!<")
771           Prefix[i] = "//!< ";
772         else if (Prefix[i] == "#" &&
773                  Style.Language == FormatStyle::LK_TextProto)
774           Prefix[i] = "# ";
775       }
776 
777       Tokens[i] = LineTok;
778       Content[i] = Lines[i].substr(IndentPrefix.size());
779       OriginalContentColumn[i] =
780           StartColumn + encoding::columnWidthWithTabs(OriginalPrefix[i],
781                                                       StartColumn,
782                                                       Style.TabWidth, Encoding);
783       ContentColumn[i] =
784           StartColumn + encoding::columnWidthWithTabs(Prefix[i], StartColumn,
785                                                       Style.TabWidth, Encoding);
786 
787       // Calculate the end of the non-whitespace text in this line.
788       size_t EndOfLine = Content[i].find_last_not_of(Blanks);
789       if (EndOfLine == StringRef::npos)
790         EndOfLine = Content[i].size();
791       else
792         ++EndOfLine;
793       Content[i] = Content[i].substr(0, EndOfLine);
794     }
795     LineTok = CurrentTok->Next;
796     if (CurrentTok->Next && !CurrentTok->Next->ContinuesLineCommentSection) {
797       // A line comment section needs to broken by a line comment that is
798       // preceded by at least two newlines. Note that we put this break here
799       // instead of breaking at a previous stage during parsing, since that
800       // would split the contents of the enum into two unwrapped lines in this
801       // example, which is undesirable:
802       // enum A {
803       //   a, // comment about a
804       //
805       //   // comment about b
806       //   b
807       // };
808       //
809       // FIXME: Consider putting separate line comment sections as children to
810       // the unwrapped line instead.
811       break;
812     }
813   }
814 }
815 
816 unsigned BreakableLineCommentSection::getLineLengthAfterSplit(
817     unsigned LineIndex, unsigned TailOffset,
818     StringRef::size_type Length) const {
819   unsigned ContentStartColumn =
820       (TailOffset == 0 ? ContentColumn[LineIndex]
821                        : OriginalContentColumn[LineIndex]);
822   return ContentStartColumn + encoding::columnWidthWithTabs(
823                                   Content[LineIndex].substr(TailOffset, Length),
824                                   ContentStartColumn, Style.TabWidth, Encoding);
825 }
826 
827 void BreakableLineCommentSection::insertBreak(unsigned LineIndex,
828                                               unsigned TailOffset, Split Split,
829                                               WhitespaceManager &Whitespaces) {
830   StringRef Text = Content[LineIndex].substr(TailOffset);
831   // Compute the offset of the split relative to the beginning of the token
832   // text.
833   unsigned BreakOffsetInToken =
834       Text.data() - tokenAt(LineIndex).TokenText.data() + Split.first;
835   unsigned CharsToRemove = Split.second;
836   // Compute the size of the new indent, including the size of the new prefix of
837   // the newly broken line.
838   unsigned IndentAtLineBreak = OriginalContentColumn[LineIndex] +
839                                Prefix[LineIndex].size() -
840                                OriginalPrefix[LineIndex].size();
841   assert(IndentAtLineBreak >= Prefix[LineIndex].size());
842   Whitespaces.replaceWhitespaceInToken(
843       tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "",
844       Prefix[LineIndex], InPPDirective, /*Newlines=*/1,
845       /*Spaces=*/IndentAtLineBreak - Prefix[LineIndex].size());
846 }
847 
848 BreakableComment::Split BreakableLineCommentSection::getSplitBefore(
849     unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit,
850     llvm::Regex &CommentPragmasRegex) const {
851   if (!mayReflow(LineIndex, CommentPragmasRegex))
852     return Split(StringRef::npos, 0);
853   return getReflowSplit(Content[LineIndex], ReflowPrefix, PreviousEndColumn,
854                         ColumnLimit);
855 }
856 
857 unsigned BreakableLineCommentSection::getLineLengthAfterSplitBefore(
858     unsigned LineIndex, unsigned TailOffset, unsigned PreviousEndColumn,
859     unsigned ColumnLimit, Split SplitBefore) const {
860   if (SplitBefore.first == StringRef::npos ||
861       SplitBefore.first + SplitBefore.second < Content[LineIndex].size()) {
862     // A piece of line, not the whole line, gets reflown.
863     return getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
864   } else {
865     // The whole line gets reflown.
866     unsigned StartColumn = PreviousEndColumn + ReflowPrefix.size();
867     return StartColumn +
868            encoding::columnWidthWithTabs(Content[LineIndex], StartColumn,
869                                          Style.TabWidth, Encoding);
870   }
871 }
872 
873 void BreakableLineCommentSection::replaceWhitespaceBefore(
874     unsigned LineIndex, unsigned PreviousEndColumn, unsigned ColumnLimit,
875     Split SplitBefore, WhitespaceManager &Whitespaces) {
876   // If this is the first line of a token, we need to inform Whitespace Manager
877   // about it: either adapt the whitespace range preceding it, or mark it as an
878   // untouchable token.
879   // This happens for instance here:
880   // // line 1 \
881   // // line 2
882   if (LineIndex > 0 && Tokens[LineIndex] != Tokens[LineIndex - 1]) {
883     if (SplitBefore.first != StringRef::npos) {
884       // Reflow happens between tokens. Replace the whitespace between the
885       // tokens by the empty string.
886       Whitespaces.replaceWhitespace(
887           *Tokens[LineIndex], /*Newlines=*/0, /*Spaces=*/0,
888           /*StartOfTokenColumn=*/StartColumn, /*InPPDirective=*/false);
889       // Replace the indent and prefix of the token with the reflow prefix.
890       unsigned WhitespaceLength =
891           Content[LineIndex].data() - tokenAt(LineIndex).TokenText.data();
892       Whitespaces.replaceWhitespaceInToken(*Tokens[LineIndex],
893                                            /*Offset=*/0,
894                                            /*ReplaceChars=*/WhitespaceLength,
895                                            /*PreviousPostfix=*/"",
896                                            /*CurrentPrefix=*/ReflowPrefix,
897                                            /*InPPDirective=*/false,
898                                            /*Newlines=*/0,
899                                            /*Spaces=*/0);
900     } else {
901       // This is the first line for the current token, but no reflow with the
902       // previous token is necessary. However, we still may need to adjust the
903       // start column. Note that ContentColumn[LineIndex] is the expected
904       // content column after a possible update to the prefix, hence the prefix
905       // length change is included.
906       unsigned LineColumn =
907           ContentColumn[LineIndex] -
908           (Content[LineIndex].data() - Lines[LineIndex].data()) +
909           (OriginalPrefix[LineIndex].size() - Prefix[LineIndex].size());
910 
911       // We always want to create a replacement instead of adding an untouchable
912       // token, even if LineColumn is the same as the original column of the
913       // token. This is because WhitespaceManager doesn't align trailing
914       // comments if they are untouchable.
915       Whitespaces.replaceWhitespace(*Tokens[LineIndex],
916                                     /*Newlines=*/1,
917                                     /*Spaces=*/LineColumn,
918                                     /*StartOfTokenColumn=*/LineColumn,
919                                     /*InPPDirective=*/false);
920     }
921   }
922   if (OriginalPrefix[LineIndex] != Prefix[LineIndex]) {
923     // Adjust the prefix if necessary.
924 
925     // Take care of the space possibly introduced after a decoration.
926     assert(Prefix[LineIndex] == (OriginalPrefix[LineIndex] + " ").str() &&
927            "Expecting a line comment prefix to differ from original by at most "
928            "a space");
929     Whitespaces.replaceWhitespaceInToken(
930         tokenAt(LineIndex), OriginalPrefix[LineIndex].size(), 0, "", "",
931         /*InPPDirective=*/false, /*Newlines=*/0, /*Spaces=*/1);
932   }
933   // Add a break after a reflow split has been introduced, if necessary.
934   // Note that this break doesn't need to be penalized, since it doesn't change
935   // the number of lines.
936   if (SplitBefore.first != StringRef::npos &&
937       SplitBefore.first + SplitBefore.second < Content[LineIndex].size()) {
938     insertBreak(LineIndex, 0, SplitBefore, Whitespaces);
939   }
940 }
941 
942 void BreakableLineCommentSection::updateNextToken(LineState &State) const {
943   if (LastLineTok) {
944     State.NextToken = LastLineTok->Next;
945   }
946 }
947 
948 bool BreakableLineCommentSection::mayReflow(
949     unsigned LineIndex, llvm::Regex &CommentPragmasRegex) const {
950   // Line comments have the indent as part of the prefix, so we need to
951   // recompute the start of the line.
952   StringRef IndentContent = Content[LineIndex];
953   if (Lines[LineIndex].startswith("//")) {
954     IndentContent = Lines[LineIndex].substr(2);
955   }
956   return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) &&
957          mayReflowContent(Content[LineIndex]) && !Tok.Finalized &&
958          !switchesFormatting(tokenAt(LineIndex)) &&
959          OriginalPrefix[LineIndex] == OriginalPrefix[LineIndex - 1];
960 }
961 
962 unsigned
963 BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,
964                                                    unsigned TailOffset) const {
965   if (TailOffset != 0) {
966     return OriginalContentColumn[LineIndex];
967   }
968   return ContentColumn[LineIndex];
969 }
970 
971 } // namespace format
972 } // namespace clang
973