170ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko//===--- BreakableToken.cpp - Format C++ code -----------------------------===//
270ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko//
370ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko//                     The LLVM Compiler Infrastructure
470ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko//
570ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko// This file is distributed under the University of Illinois Open Source
670ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko// License. See LICENSE.TXT for details.
770ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko//
870ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko//===----------------------------------------------------------------------===//
970ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko///
1070ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko/// \file
1170ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko/// \brief Contains implementation of BreakableToken class and classes derived
1270ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko/// from it.
1370ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko///
1470ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko//===----------------------------------------------------------------------===//
1570ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
1670ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko#include "BreakableToken.h"
172b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko#include "clang/Basic/CharInfo.h"
18de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek#include "clang/Format/Format.h"
19919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko#include "llvm/ADT/STLExtras.h"
20de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek#include "llvm/Support/Debug.h"
2170ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko#include <algorithm>
2270ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#define DEBUG_TYPE "format-token-breaker"
246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2570ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienkonamespace clang {
2670ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienkonamespace format {
27de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek
2874b7363bcfc502dec34092af434da787cf9d5b9fDaniel Jasperstatic const char *const Blanks = " \t\v\f\r";
298afa39b271d94969891dba014e0fc545b4873479Alexander Kornienkostatic bool IsBlank(char C) {
308afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko  switch (C) {
312a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper  case ' ':
322a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper  case '\t':
332a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper  case '\v':
342a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper  case '\f':
3574b7363bcfc502dec34092af434da787cf9d5b9fDaniel Jasper  case '\r':
362a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper    return true;
372a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper  default:
382a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper    return false;
398afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko  }
408afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko}
418afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko
42b8f716464b9f7eaae62aa9d646e7eca7f566990fCraig Topperstatic BreakableToken::Split getCommentSplit(StringRef Text,
43b8f716464b9f7eaae62aa9d646e7eca7f566990fCraig Topper                                             unsigned ContentStartColumn,
44b8f716464b9f7eaae62aa9d646e7eca7f566990fCraig Topper                                             unsigned ColumnLimit,
450b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko                                             unsigned TabWidth,
46b8f716464b9f7eaae62aa9d646e7eca7f566990fCraig Topper                                             encoding::Encoding Encoding) {
47919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko  if (ColumnLimit <= ContentStartColumn + 1)
48de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    return BreakableToken::Split(StringRef::npos, 0);
49919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko
50919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko  unsigned MaxSplit = ColumnLimit - ContentStartColumn + 1;
5100895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  unsigned MaxSplitBytes = 0;
5200895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko
5300895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  for (unsigned NumChars = 0;
540b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko       NumChars < MaxSplit && MaxSplitBytes < Text.size();) {
550b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko    unsigned BytesInChar =
5600895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko        encoding::getCodePointNumBytes(Text[MaxSplitBytes], Encoding);
570b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko    NumChars +=
580b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko        encoding::columnWidthWithTabs(Text.substr(MaxSplitBytes, BytesInChar),
590b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko                                      ContentStartColumn, TabWidth, Encoding);
600b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko    MaxSplitBytes += BytesInChar;
610b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko  }
6200895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko
638afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko  StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);
64919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko  if (SpaceOffset == StringRef::npos ||
65de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek      // Don't break at leading whitespace.
668afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko      Text.find_last_not_of(Blanks, SpaceOffset) == StringRef::npos) {
67be9ed776e57fe606b5826a0d37a5a2dbfb927e63Manuel Klimek    // Make sure that we don't break at leading whitespace that
68be9ed776e57fe606b5826a0d37a5a2dbfb927e63Manuel Klimek    // reaches past MaxSplit.
698afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko    StringRef::size_type FirstNonWhitespace = Text.find_first_not_of(Blanks);
70be9ed776e57fe606b5826a0d37a5a2dbfb927e63Manuel Klimek    if (FirstNonWhitespace == StringRef::npos)
71be9ed776e57fe606b5826a0d37a5a2dbfb927e63Manuel Klimek      // If the comment is only whitespace, we cannot split.
72be9ed776e57fe606b5826a0d37a5a2dbfb927e63Manuel Klimek      return BreakableToken::Split(StringRef::npos, 0);
738afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko    SpaceOffset = Text.find_first_of(
748afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko        Blanks, std::max<unsigned>(MaxSplitBytes, FirstNonWhitespace));
75be9ed776e57fe606b5826a0d37a5a2dbfb927e63Manuel Klimek  }
76919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko  if (SpaceOffset != StringRef::npos && SpaceOffset != 0) {
778afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko    StringRef BeforeCut = Text.substr(0, SpaceOffset).rtrim(Blanks);
788afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko    StringRef AfterCut = Text.substr(SpaceOffset).ltrim(Blanks);
79919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko    return BreakableToken::Split(BeforeCut.size(),
80919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko                                 AfterCut.begin() - BeforeCut.end());
81919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko  }
82919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko  return BreakableToken::Split(StringRef::npos, 0);
83919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko}
84919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko
856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic BreakableToken::Split
866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesgetStringSplit(StringRef Text, unsigned UsedColumns, unsigned ColumnLimit,
876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               unsigned TabWidth, encoding::Encoding Encoding) {
88de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  // FIXME: Reduce unit test case.
89de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  if (Text.empty())
90de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    return BreakableToken::Split(StringRef::npos, 0);
912c2f729d10cb10324bf2e7871867f7bbc19ad358Alexander Kornienko  if (ColumnLimit <= UsedColumns)
9200895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko    return BreakableToken::Split(StringRef::npos, 0);
93651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned MaxSplit = ColumnLimit - UsedColumns;
9400895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  StringRef::size_type SpaceOffset = 0;
9500895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  StringRef::size_type SlashOffset = 0;
96f2b2c7da1f3bfed9b0bb194ff00d6e1e43d68d5cAlexander Kornienko  StringRef::size_type WordStartOffset = 0;
9700895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  StringRef::size_type SplitPoint = 0;
9800895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  for (unsigned Chars = 0;;) {
9900895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko    unsigned Advance;
10000895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko    if (Text[0] == '\\') {
10100895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko      Advance = encoding::getEscapeSequenceLength(Text);
10200895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko      Chars += Advance;
10300895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko    } else {
10400895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko      Advance = encoding::getCodePointNumBytes(Text[0], Encoding);
1052c2f729d10cb10324bf2e7871867f7bbc19ad358Alexander Kornienko      Chars += encoding::columnWidthWithTabs(
1062c2f729d10cb10324bf2e7871867f7bbc19ad358Alexander Kornienko          Text.substr(0, Advance), UsedColumns + Chars, TabWidth, Encoding);
10700895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko    }
10800895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko
109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (Chars > MaxSplit || Text.size() == Advance)
11000895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko      break;
11100895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko
1128afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko    if (IsBlank(Text[0]))
11300895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko      SpaceOffset = SplitPoint;
11400895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko    if (Text[0] == '/')
11500895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko      SlashOffset = SplitPoint;
1168afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko    if (Advance == 1 && !isAlphanumeric(Text[0]))
117f2b2c7da1f3bfed9b0bb194ff00d6e1e43d68d5cAlexander Kornienko      WordStartOffset = SplitPoint;
11800895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko
11900895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko    SplitPoint += Advance;
12000895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko    Text = Text.substr(Advance);
12100895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  }
12200895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko
12300895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  if (SpaceOffset != 0)
124de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    return BreakableToken::Split(SpaceOffset + 1, 0);
12500895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  if (SlashOffset != 0)
126de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    return BreakableToken::Split(SlashOffset + 1, 0);
127f2b2c7da1f3bfed9b0bb194ff00d6e1e43d68d5cAlexander Kornienko  if (WordStartOffset != 0)
128f2b2c7da1f3bfed9b0bb194ff00d6e1e43d68d5cAlexander Kornienko    return BreakableToken::Split(WordStartOffset + 1, 0);
12900895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  if (SplitPoint != 0)
13000895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko    return BreakableToken::Split(SplitPoint, 0);
13100895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  return BreakableToken::Split(StringRef::npos, 0);
132919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko}
133919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko
134de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimekunsigned BreakableSingleLineToken::getLineCount() const { return 1; }
135de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek
1362785b9aabcb2c3fd6f7dd8b63d3cd3d4b9bca284Alexander Kornienkounsigned BreakableSingleLineToken::getLineLengthAfterSplit(
1372785b9aabcb2c3fd6f7dd8b63d3cd3d4b9bca284Alexander Kornienko    unsigned LineIndex, unsigned Offset, StringRef::size_type Length) const {
13800895106f9ed602af67984ec4d225a0cdc8c12afAlexander Kornienko  return StartColumn + Prefix.size() + Postfix.size() +
1390b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko         encoding::columnWidthWithTabs(Line.substr(Offset, Length),
1400b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko                                       StartColumn + Prefix.size(),
1410b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko                                       Style.TabWidth, Encoding);
142de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek}
143de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek
14416a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander KornienkoBreakableSingleLineToken::BreakableSingleLineToken(
1453d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    const FormatToken &Tok, unsigned IndentLevel, unsigned StartColumn,
1463d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    StringRef Prefix, StringRef Postfix, bool InPPDirective,
1473d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    encoding::Encoding Encoding, const FormatStyle &Style)
1483d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    : BreakableToken(Tok, IndentLevel, InPPDirective, Encoding, Style),
1490b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko      StartColumn(StartColumn), Prefix(Prefix), Postfix(Postfix) {
150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(Tok.TokenText.endswith(Postfix));
151de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  Line = Tok.TokenText.substr(
152de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek      Prefix.size(), Tok.TokenText.size() - Prefix.size() - Postfix.size());
153de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek}
154de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek
1552c2f729d10cb10324bf2e7871867f7bbc19ad358Alexander KornienkoBreakableStringLiteral::BreakableStringLiteral(
1563d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    const FormatToken &Tok, unsigned IndentLevel, unsigned StartColumn,
1573d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    StringRef Prefix, StringRef Postfix, bool InPPDirective,
1583d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    encoding::Encoding Encoding, const FormatStyle &Style)
1593d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    : BreakableSingleLineToken(Tok, IndentLevel, StartColumn, Prefix, Postfix,
1603d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko                               InPPDirective, Encoding, Style) {}
16170ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
162de008c0f3bf66103185fc9f7f49995fa431451a6Manuel KlimekBreakableToken::Split
163de008c0f3bf66103185fc9f7f49995fa431451a6Manuel KlimekBreakableStringLiteral::getSplit(unsigned LineIndex, unsigned TailOffset,
164de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek                                 unsigned ColumnLimit) const {
1652c2f729d10cb10324bf2e7871867f7bbc19ad358Alexander Kornienko  return getStringSplit(Line.substr(TailOffset),
1662c2f729d10cb10324bf2e7871867f7bbc19ad358Alexander Kornienko                        StartColumn + Prefix.size() + Postfix.size(),
1672c2f729d10cb10324bf2e7871867f7bbc19ad358Alexander Kornienko                        ColumnLimit, Style.TabWidth, Encoding);
168de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek}
16970ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
1702b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienkovoid BreakableStringLiteral::insertBreak(unsigned LineIndex,
1712b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko                                         unsigned TailOffset, Split Split,
1722b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko                                         WhitespaceManager &Whitespaces) {
173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned LeadingSpaces = StartColumn;
174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // The '@' of an ObjC string literal (@"Test") does not become part of the
175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // string token.
176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // FIXME: It might be a cleaner solution to merge the tokens as a
177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // precomputation step.
178651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Prefix.startswith("@"))
179651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    --LeadingSpaces;
1802b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko  Whitespaces.replaceWhitespaceInToken(
1812b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko      Tok, Prefix.size() + TailOffset + Split.first, Split.second, Postfix,
182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Prefix, InPPDirective, 1, IndentLevel, LeadingSpaces);
1832b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko}
1842b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko
185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic StringRef getLineCommentIndentPrefix(StringRef Comment) {
186651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  static const char *const KnownPrefixes[] = { "///", "//" };
187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StringRef LongestPrefix;
188651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (StringRef KnownPrefix : KnownPrefixes) {
189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (Comment.startswith(KnownPrefix)) {
190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      size_t PrefixLength = KnownPrefix.size();
191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      while (PrefixLength < Comment.size() && Comment[PrefixLength] == ' ')
192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ++PrefixLength;
193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (PrefixLength > LongestPrefix.size())
194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        LongestPrefix = Comment.substr(0, PrefixLength);
195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return LongestPrefix;
198de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek}
199de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek
2003d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander KornienkoBreakableLineComment::BreakableLineComment(
2013d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    const FormatToken &Token, unsigned IndentLevel, unsigned StartColumn,
2023d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)
2033d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    : BreakableSingleLineToken(Token, IndentLevel, StartColumn,
204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                               getLineCommentIndentPrefix(Token.TokenText), "",
2050b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko                               InPPDirective, Encoding, Style) {
2062b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko  OriginalPrefix = Prefix;
2072b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko  if (Token.TokenText.size() > Prefix.size() &&
2082b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko      isAlphanumeric(Token.TokenText[Prefix.size()])) {
2092b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko    if (Prefix == "//")
2102b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko      Prefix = "// ";
2112b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko    else if (Prefix == "///")
2122b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko      Prefix = "/// ";
2132b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko  }
2142b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko}
215de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek
216de008c0f3bf66103185fc9f7f49995fa431451a6Manuel KlimekBreakableToken::Split
217de008c0f3bf66103185fc9f7f49995fa431451a6Manuel KlimekBreakableLineComment::getSplit(unsigned LineIndex, unsigned TailOffset,
218de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek                               unsigned ColumnLimit) const {
219de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  return getCommentSplit(Line.substr(TailOffset), StartColumn + Prefix.size(),
2200b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko                         ColumnLimit, Style.TabWidth, Encoding);
221de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek}
222de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek
2232b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienkovoid BreakableLineComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
22416a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko                                       Split Split,
2252b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko                                       WhitespaceManager &Whitespaces) {
2262b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko  Whitespaces.replaceWhitespaceInToken(
2272b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko      Tok, OriginalPrefix.size() + TailOffset + Split.first, Split.second,
228a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko      Postfix, Prefix, InPPDirective, /*Newlines=*/1, IndentLevel, StartColumn);
229a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko}
230a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko
231a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienkovoid BreakableLineComment::replaceWhitespace(unsigned LineIndex,
232a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko                                             unsigned TailOffset, Split Split,
233a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko                                             WhitespaceManager &Whitespaces) {
234a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko  Whitespaces.replaceWhitespaceInToken(
235a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko      Tok, OriginalPrefix.size() + TailOffset + Split.first, Split.second, "",
236a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko      "", /*InPPDirective=*/false, /*Newlines=*/0, /*IndentLevel=*/0,
237a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko      /*Spaces=*/1);
2382b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko}
2392b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko
2402b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienkovoid
2412b2faa53ecd32e823c55430d0889c11ea91b582cAlexander KornienkoBreakableLineComment::replaceWhitespaceBefore(unsigned LineIndex,
2422b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko                                              WhitespaceManager &Whitespaces) {
2432b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko  if (OriginalPrefix != Prefix) {
2442b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko    Whitespaces.replaceWhitespaceInToken(Tok, OriginalPrefix.size(), 0, "", "",
245a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko                                         /*InPPDirective=*/false,
246a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko                                         /*Newlines=*/0, /*IndentLevel=*/0,
247a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko                                         /*Spaces=*/1);
2482b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko  }
2492b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko}
2502b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko
25100895106f9ed602af67984ec4d225a0cdc8c12afAlexander KornienkoBreakableBlockComment::BreakableBlockComment(
2523d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    const FormatToken &Token, unsigned IndentLevel, unsigned StartColumn,
25316a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko    unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
2540b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko    encoding::Encoding Encoding, const FormatStyle &Style)
2553d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko    : BreakableToken(Token, IndentLevel, InPPDirective, Encoding, Style) {
256de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  StringRef TokenText(Token.TokenText);
257de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  assert(TokenText.startswith("/*") && TokenText.endswith("*/"));
25870ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko  TokenText.substr(2, TokenText.size() - 4).split(Lines, "\n");
25970ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
260de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  int IndentDelta = StartColumn - OriginalStartColumn;
261de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  LeadingWhitespace.resize(Lines.size());
262de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  StartOfLineColumn.resize(Lines.size());
2631659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko  StartOfLineColumn[0] = StartColumn + 2;
2641659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko  for (size_t i = 1; i < Lines.size(); ++i)
2650b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko    adjustWhitespace(i, IndentDelta);
2661659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko
2671659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko  Decoration = "* ";
268de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  if (Lines.size() == 1 && !FirstInLine) {
269de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    // Comments for which FirstInLine is false can start on arbitrary column,
270de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    // and available horizontal space can be too small to align consecutive
271de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    // lines with the first one.
272de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    // FIXME: We could, probably, align them to current indentation level, but
273de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    // now we just wrap them without stars.
2741659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    Decoration = "";
275de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  }
2761659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko  for (size_t i = 1, e = Lines.size(); i < e && !Decoration.empty(); ++i) {
2771659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    // If the last line is empty, the closing "*/" will have a star.
2781659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    if (i + 1 == e && Lines[i].empty())
2791659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko      break;
2801659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    while (!Lines[i].startswith(Decoration))
2811659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko      Decoration = Decoration.substr(0, Decoration.size() - 1);
282de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  }
2831659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko
2841659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko  LastLineNeedsDecoration = true;
285de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  IndentAtLineBreak = StartOfLineColumn[0] + 1;
286de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  for (size_t i = 1; i < Lines.size(); ++i) {
287de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    if (Lines[i].empty()) {
2881659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko      if (i + 1 == Lines.size()) {
2891659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko        // Empty last line means that we already have a star as a part of the
2901659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko        // trailing */. We also need to preserve whitespace, so that */ is
2911659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko        // correctly indented.
2921659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko        LastLineNeedsDecoration = false;
2931659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko      } else if (Decoration.empty()) {
2941659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko        // For all other lines, set the start column to 0 if they're empty, so
2951659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko        // we do not insert trailing whitespace anywhere.
296de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek        StartOfLineColumn[i] = 0;
2971659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko      }
298de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek      continue;
29970ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko    }
3001659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    // The first line already excludes the star.
3011659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    // For all other lines, adjust the line to exclude the star and
3021659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    // (optionally) the first whitespace.
3031659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    StartOfLineColumn[i] += Decoration.size();
3041659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    Lines[i] = Lines[i].substr(Decoration.size());
3051659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    LeadingWhitespace[i] += Decoration.size();
306de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    IndentAtLineBreak = std::min<int>(IndentAtLineBreak, StartOfLineColumn[i]);
30770ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko  }
308cb4b40b86e284151d6ca14181f949655a9ceccd8Daniel Jasper  IndentAtLineBreak = std::max<unsigned>(IndentAtLineBreak, Decoration.size());
309de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  DEBUG({
3101659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko    llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n";
311de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    for (size_t i = 0; i < Lines.size(); ++i) {
312de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek      llvm::dbgs() << i << " |" << Lines[i] << "| " << LeadingWhitespace[i]
313de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek                   << "\n";
314de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    }
315de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  });
316de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek}
31770ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
3180b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienkovoid BreakableBlockComment::adjustWhitespace(unsigned LineIndex,
319de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek                                             int IndentDelta) {
32016a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko  // When in a preprocessor directive, the trailing backslash in a block comment
32116a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko  // is not needed, but can serve a purpose of uniformity with necessary escaped
32216a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko  // newlines outside the comment. In this case we remove it here before
32316a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko  // trimming the trailing whitespace. The backslash will be re-added later when
32416a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko  // inserting a line break.
32516a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko  size_t EndOfPreviousLine = Lines[LineIndex - 1].size();
32616a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko  if (InPPDirective && Lines[LineIndex - 1].endswith("\\"))
32716a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko    --EndOfPreviousLine;
32816a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko
329de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  // Calculate the end of the non-whitespace text in the previous line.
33016a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko  EndOfPreviousLine =
3318afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko      Lines[LineIndex - 1].find_last_not_of(Blanks, EndOfPreviousLine);
332de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  if (EndOfPreviousLine == StringRef::npos)
333de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    EndOfPreviousLine = 0;
334de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  else
335de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    ++EndOfPreviousLine;
336de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  // Calculate the start of the non-whitespace text in the current line.
3378afa39b271d94969891dba014e0fc545b4873479Alexander Kornienko  size_t StartOfLine = Lines[LineIndex].find_first_not_of(Blanks);
338de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  if (StartOfLine == StringRef::npos)
339de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    StartOfLine = Lines[LineIndex].size();
340919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko
3410b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko  StringRef Whitespace = Lines[LineIndex].substr(0, StartOfLine);
342de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  // Adjust Lines to only contain relevant text.
343de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  Lines[LineIndex - 1] = Lines[LineIndex - 1].substr(0, EndOfPreviousLine);
344de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  Lines[LineIndex] = Lines[LineIndex].substr(StartOfLine);
345de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  // Adjust LeadingWhitespace to account all whitespace between the lines
346de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  // to the current line.
347de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  LeadingWhitespace[LineIndex] =
348de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek      Lines[LineIndex].begin() - Lines[LineIndex - 1].end();
349d63312b1484a4642225c97e1dd013fe520b2b9a4Manuel Klimek
350651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Adjust the start column uniformly across all lines.
3516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  StartOfLineColumn[LineIndex] =
35283a7dcdf5fce1bdf74ce985419d77a41a51abfa2Alexander Kornienko      encoding::columnWidthWithTabs(Whitespace, 0, Style.TabWidth, Encoding) +
3536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      IndentDelta;
35470ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko}
35570ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
356de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimekunsigned BreakableBlockComment::getLineCount() const { return Lines.size(); }
35770ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
3582785b9aabcb2c3fd6f7dd8b63d3cd3d4b9bca284Alexander Kornienkounsigned BreakableBlockComment::getLineLengthAfterSplit(
3592785b9aabcb2c3fd6f7dd8b63d3cd3d4b9bca284Alexander Kornienko    unsigned LineIndex, unsigned Offset, StringRef::size_type Length) const {
3600b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko  unsigned ContentStartColumn = getContentStartColumn(LineIndex, Offset);
3610b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko  return ContentStartColumn +
3620b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko         encoding::columnWidthWithTabs(Lines[LineIndex].substr(Offset, Length),
3630b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko                                       ContentStartColumn, Style.TabWidth,
3640b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko                                       Encoding) +
365de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek         // The last line gets a "*/" postfix.
366de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek         (LineIndex + 1 == Lines.size() ? 2 : 0);
36770ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko}
36870ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
369de008c0f3bf66103185fc9f7f49995fa431451a6Manuel KlimekBreakableToken::Split
370de008c0f3bf66103185fc9f7f49995fa431451a6Manuel KlimekBreakableBlockComment::getSplit(unsigned LineIndex, unsigned TailOffset,
371de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek                                unsigned ColumnLimit) const {
372de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  return getCommentSplit(Lines[LineIndex].substr(TailOffset),
373de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek                         getContentStartColumn(LineIndex, TailOffset),
3740b62cc30c9aa462184de0435dc083d944a41d67fAlexander Kornienko                         ColumnLimit, Style.TabWidth, Encoding);
375de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek}
376de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek
377de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimekvoid BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
37816a0ec60507a4eec275a5c3a86d4501b1b7b817bAlexander Kornienko                                        Split Split,
379de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek                                        WhitespaceManager &Whitespaces) {
38070ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko  StringRef Text = Lines[LineIndex].substr(TailOffset);
381de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  StringRef Prefix = Decoration;
382de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  if (LineIndex + 1 == Lines.size() &&
383de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek      Text.size() == Split.first + Split.second) {
384de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    // For the last line we need to break before "*/", but not to add "* ".
385de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    Prefix = "";
386de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  }
387e573c3f7fc40e813559ab4ff1e7eec4f66f1a50fManuel Klimek
388de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  unsigned BreakOffsetInToken =
389de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek      Text.data() - Tok.TokenText.data() + Split.first;
390de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  unsigned CharsToRemove = Split.second;
391b6dba337ba87c2f47a402ecccf4089ab86bbe70cManuel Klimek  assert(IndentAtLineBreak >= Decoration.size());
3923d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko  Whitespaces.replaceWhitespaceInToken(
3933d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko      Tok, BreakOffsetInToken, CharsToRemove, "", Prefix, InPPDirective, 1,
3943d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko      IndentLevel, IndentAtLineBreak - Decoration.size());
395de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek}
396de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek
397a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienkovoid BreakableBlockComment::replaceWhitespace(unsigned LineIndex,
398a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko                                              unsigned TailOffset, Split Split,
399a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko                                              WhitespaceManager &Whitespaces) {
400a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko  StringRef Text = Lines[LineIndex].substr(TailOffset);
401a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko  unsigned BreakOffsetInToken =
402a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko      Text.data() - Tok.TokenText.data() + Split.first;
403a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko  unsigned CharsToRemove = Split.second;
404a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko  Whitespaces.replaceWhitespaceInToken(
405a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko      Tok, BreakOffsetInToken, CharsToRemove, "", "", /*InPPDirective=*/false,
406a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko      /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1);
407a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko}
408a7462b8ce22a3f754bf51eeeb01adafc42b32ceaAlexander Kornienko
409de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimekvoid
410de008c0f3bf66103185fc9f7f49995fa431451a6Manuel KlimekBreakableBlockComment::replaceWhitespaceBefore(unsigned LineIndex,
411de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek                                               WhitespaceManager &Whitespaces) {
412de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  if (LineIndex == 0)
41370ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko    return;
414de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  StringRef Prefix = Decoration;
415c5cc4bf2699b0542f352738f84eee373cfcf670fManuel Klimek  if (Lines[LineIndex].empty()) {
416c5cc4bf2699b0542f352738f84eee373cfcf670fManuel Klimek    if (LineIndex + 1 == Lines.size()) {
4171659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko      if (!LastLineNeedsDecoration) {
4181659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko        // If the last line was empty, we don't need a prefix, as the */ will
4191659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko        // line up with the decoration (if it exists).
4201659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko        Prefix = "";
4211659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko      }
422c5cc4bf2699b0542f352738f84eee373cfcf670fManuel Klimek    } else if (!Decoration.empty()) {
423c5cc4bf2699b0542f352738f84eee373cfcf670fManuel Klimek      // For other empty lines, if we do have a decoration, adapt it to not
424c5cc4bf2699b0542f352738f84eee373cfcf670fManuel Klimek      // contain a trailing whitespace.
425c5cc4bf2699b0542f352738f84eee373cfcf670fManuel Klimek      Prefix = Prefix.substr(0, 1);
426c5cc4bf2699b0542f352738f84eee373cfcf670fManuel Klimek    }
427e2c482f3720261dea180400816d4572d1986f423Daniel Jasper  } else {
428e2c482f3720261dea180400816d4572d1986f423Daniel Jasper    if (StartOfLineColumn[LineIndex] == 1) {
4291659dedac63858de50ee60175a88c42ff974e61bAlexander Kornienko      // This line starts immediately after the decorating *.
430e2c482f3720261dea180400816d4572d1986f423Daniel Jasper      Prefix = Prefix.substr(0, 1);
431e2c482f3720261dea180400816d4572d1986f423Daniel Jasper    }
432c5cc4bf2699b0542f352738f84eee373cfcf670fManuel Klimek  }
43370ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko
4342a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper  unsigned WhitespaceOffsetInToken = Lines[LineIndex].data() -
4352a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper                                     Tok.TokenText.data() -
4362a409b62126d8f0b8f5749d5ed435ad2b394b526Daniel Jasper                                     LeadingWhitespace[LineIndex];
4372b2faa53ecd32e823c55430d0889c11ea91b582cAlexander Kornienko  Whitespaces.replaceWhitespaceInToken(
438de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek      Tok, WhitespaceOffsetInToken, LeadingWhitespace[LineIndex], "", Prefix,
4393d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko      InPPDirective, 1, IndentLevel,
4403d9ffcf3aa0ed84fa297e3c461bb84e48221aa2dAlexander Kornienko      StartOfLineColumn[LineIndex] - Prefix.size());
441919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko}
442919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko
443de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimekunsigned
444de008c0f3bf66103185fc9f7f49995fa431451a6Manuel KlimekBreakableBlockComment::getContentStartColumn(unsigned LineIndex,
445de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek                                             unsigned TailOffset) const {
446de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  // If we break, we always break at the predefined indent.
447de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek  if (TailOffset != 0)
448de008c0f3bf66103185fc9f7f49995fa431451a6Manuel Klimek    return IndentAtLineBreak;
4496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return std::max(0, StartOfLineColumn[LineIndex]);
450919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko}
451919398bb40d5d643f38b6595f5e8eac641e89d50Alexander Kornienko
45270ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko} // namespace format
45370ce7881fc30a39b795b2873f008e7eca72ba669Alexander Kornienko} // namespace clang
454