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  const FormatStyle &Style) {
45  static const char *const KnownCStylePrefixes[] = {"///<", "//!<", "///", "//",
46  "//!"};
47  static const char *const KnownTextProtoPrefixes[] = {"//", "#"};
48  ArrayRef<const char *> KnownPrefixes(KnownCStylePrefixes);
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,
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);
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 
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 
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(),
196 }
197 
199  const FormatToken &Tok, unsigned StartColumn, StringRef Prefix,
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 
210  const FormatToken &Tok, unsigned StartColumn, StringRef Prefix,
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,
231 }
232 
234  unsigned StartColumn, bool InPPDirective,
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
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,
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,
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 
344  const FormatToken &Token, unsigned StartColumn,
345  unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
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] +
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] =
501  IndentDelta;
502 }
503 
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 
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 +
578  Content, StartColumn, Style.TabWidth, Encoding) +
579  PostfixLength;
580  return ReflownColumn;
581 }
582 
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 
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
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 
729  const FormatToken &Token, unsigned StartColumn,
730  unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
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] == "#" &&
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 
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 
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 
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 
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,
870  }
871 }
872 
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 
943  if (LastLineTok) {
944  State.NextToken = LastLineTok->Next;
945  }
946 }
947 
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
unsigned getLineCount() const override
bool switchesFormatting(const FormatToken &Token)
Checks if Token switches formatting, like /* clang-format off.
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
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:283
static StringRef getLineCommentIndentPrefix(StringRef Comment, const FormatStyle &Style)
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:1168
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
Split getSplitAfterLastLine(unsigned TailOffset, unsigned ColumnLimit) const override
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:840
The current state when indenting a unwrapped line.
SmallVector< StringRef, 16 > Content
Should be used for JavaScript.
Definition: Format.h:1170
const AnnotatedLine * Line
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:120
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
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
bool introducesBreakBefore(unsigned LineIndex) const override
#define false
Definition: stdbool.h:33
bool is(tok::TokenKind Kind) const
Definition: FormatToken.h:297
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.
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, WhitespaceManager &Whitespaces) override
StringRef TokenText
The raw text of the token.
Definition: FormatToken.h:168
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:1185
unsigned getLineLengthAfterSplitBefore(unsigned LineIndex, unsigned TailOffset, unsigned PreviousEndColumn, unsigned ColumnLimit, Split SplitBefore) const override
Dataflow Directional Tag Classes.
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:295
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:1548
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
LLVM_READONLY bool isPunctuation(unsigned char c)
Return true if this character is an ASCII punctuation character.
Definition: CharInfo.h:132
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
Should be used for Protocol Buffer messages in text format (https://developers.google.com/protocol-buffers/).
Definition: Format.h:1180
BreakableToken(const FormatToken &Tok, bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)
StringRef Text
Definition: Format.cpp:1336
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