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