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