BreakableBlockComment::BreakableBlockComment( const FormatStyle &Style, const FormatToken &Token, unsigned StartColumn, unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective, encoding::Encoding Encoding) : BreakableToken(Token, InPPDirective, Encoding) { StringRef TokenText(Token.TokenText); assert(TokenText.startswith("/*") && TokenText.endswith("*/")); TokenText.substr(2, TokenText.size() - 4).split(Lines, "\n"); int IndentDelta = StartColumn - OriginalStartColumn; bool NeedsStar = true; LeadingWhitespace.resize(Lines.size()); StartOfLineColumn.resize(Lines.size()); if (Lines.size() == 1 && !FirstInLine) { // Comments for which FirstInLine is false can start on arbitrary column, // and available horizontal space can be too small to align consecutive // lines with the first one. // FIXME: We could, probably, align them to current indentation level, but // now we just wrap them without stars. NeedsStar = false; } StartOfLineColumn[0] = StartColumn + 2; for (size_t i = 1; i < Lines.size(); ++i) { adjustWhitespace(Style, i, IndentDelta); if (Lines[i].empty()) // If the last line is empty, the closing "*/" will have a star. NeedsStar = NeedsStar && i + 1 == Lines.size(); else NeedsStar = NeedsStar && Lines[i][0] == '*'; } Decoration = NeedsStar ? "* " : ""; IndentAtLineBreak = StartOfLineColumn[0] + 1; for (size_t i = 1; i < Lines.size(); ++i) { if (Lines[i].empty()) { if (!NeedsStar && i + 1 != Lines.size()) // For all but the last line (which always ends in */), set the // start column to 0 if they're empty, so we do not insert // trailing whitespace anywhere. StartOfLineColumn[i] = 0; continue; } if (NeedsStar) { // The first line already excludes the star. // For all other lines, adjust the line to exclude the star and // (optionally) the first whitespace. int Offset = Lines[i].startswith("* ") ? 2 : 1; StartOfLineColumn[i] += Offset; Lines[i] = Lines[i].substr(Offset); LeadingWhitespace[i] += Offset; } IndentAtLineBreak = std::min<int>(IndentAtLineBreak, StartOfLineColumn[i]); } IndentAtLineBreak = std::max<unsigned>(IndentAtLineBreak, Decoration.size()); DEBUG({ for (size_t i = 0; i < Lines.size(); ++i) { llvm::dbgs() << i << " |" << Lines[i] << "| " << LeadingWhitespace[i] << "\n"; } });
BreakableBlockComment::BreakableBlockComment( const FormatToken &Token, unsigned IndentLevel, unsigned StartColumn, unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style) : BreakableToken(Token, IndentLevel, InPPDirective, Encoding, Style) { StringRef TokenText(Token.TokenText); assert(TokenText.startswith("/*") && TokenText.endswith("*/")); TokenText.substr(2, TokenText.size() - 4).split(Lines, "\n"); int IndentDelta = StartColumn - OriginalStartColumn; WrappedLines.resize(Lines.size()); LeadingWhitespace.resize(Lines.size()); StartOfLineColumn.resize(Lines.size()); StartOfLineColumn[0] = StartColumn + 2; for (size_t i = 1; i < Lines.size(); ++i) adjustWhitespace(i, IndentDelta); Decoration = "* "; if (Lines.size() == 1 && !FirstInLine) { // Comments for which FirstInLine is false can start on arbitrary column, // and available horizontal space can be too small to align consecutive // lines with the first one. // FIXME: We could, probably, align them to current indentation level, but // now we just wrap them without stars. Decoration = ""; } for (size_t i = 1, e = Lines.size(); i < e && !Decoration.empty(); ++i) { // If the last line is empty, the closing "*/" will have a star. if (i + 1 == e && Lines[i].empty()) break; if (!Lines[i].empty() && i + 1 != e && Decoration.startswith(Lines[i])) continue; while (!Lines[i].startswith(Decoration)) Decoration = Decoration.substr(0, Decoration.size() - 1); } LastLineNeedsDecoration = true; IndentAtLineBreak = StartOfLineColumn[0] + 1; for (size_t i = 1; i < Lines.size(); ++i) { if (Lines[i].empty()) { if (i + 1 == Lines.size()) { // Empty last line means that we already have a star as a part of the // trailing */. We also need to preserve whitespace, so that */ is // correctly indented. LastLineNeedsDecoration = false; } else if (Decoration.empty()) { // For all other lines, set the start column to 0 if they're empty, so // we do not insert trailing whitespace anywhere. StartOfLineColumn[i] = 0; } continue; } // The first line already excludes the star. // For all other lines, adjust the line to exclude the star and // (optionally) the first whitespace. unsigned DecorationSize = Decoration.startswith(Lines[i]) ? Lines[i].size() : Decoration.size(); StartOfLineColumn[i] += DecorationSize; Lines[i] = Lines[i].substr(DecorationSize); LeadingWhitespace[i] += DecorationSize; if (!Decoration.startswith(Lines[i])) IndentAtLineBreak = std::min<int>(IndentAtLineBreak, std::max(0, StartOfLineColumn[i])); } IndentAtLineBreak = std::max<unsigned>(IndentAtLineBreak, Decoration.size()); DEBUG({ llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n"; for (size_t i = 0; i < Lines.size(); ++i) { llvm::dbgs() << i << " |" << Lines[i] << "| " << LeadingWhitespace[i] << "\n"; } });
BreakableBlockComment::BreakableBlockComment( const FormatToken &Token, unsigned StartColumn, unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style) : BreakableComment(Token, StartColumn, InPPDirective, Encoding, Style) { assert(Tok.is(TT_BlockComment) && "block comment section must start with a block comment"); StringRef TokenText(Tok.TokenText); assert(TokenText.startswith("/*") && TokenText.endswith("*/")); TokenText.substr(2, TokenText.size() - 4).split(Lines, "\n"); int IndentDelta = StartColumn - OriginalStartColumn; Content.resize(Lines.size()); Content[0] = Lines[0]; ContentColumn.resize(Lines.size()); // Account for the initial '/*'. ContentColumn[0] = StartColumn + 2; Tokens.resize(Lines.size()); for (size_t i = 1; i < Lines.size(); ++i) adjustWhitespace(i, IndentDelta); // Align decorations with the column of the star on the first line, // that is one column after the start "/*". DecorationColumn = StartColumn + 1; // Account for comment decoration patterns like this: // // /* // ** blah blah blah // */ if (Lines.size() >= 2 && Content[1].startswith("**") && static_cast<unsigned>(ContentColumn[1]) == StartColumn) { DecorationColumn = StartColumn; } Decoration = "* "; if (Lines.size() == 1 && !FirstInLine) { // Comments for which FirstInLine is false can start on arbitrary column, // and available horizontal space can be too small to align consecutive // lines with the first one. // FIXME: We could, probably, align them to current indentation level, but // now we just wrap them without stars. Decoration = ""; } for (size_t i = 1, e = Lines.size(); i < e && !Decoration.empty(); ++i) { // If the last line is empty, the closing "*/" will have a star. if (i + 1 == e && Content[i].empty()) break; if (!Content[i].empty() && i + 1 != e && Decoration.startswith(Content[i])) continue; while (!Content[i].startswith(Decoration)) Decoration = Decoration.substr(0, Decoration.size() - 1); } LastLineNeedsDecoration = true; IndentAtLineBreak = ContentColumn[0] + 1; for (size_t i = 1, e = Lines.size(); i < e; ++i) { if (Content[i].empty()) { if (i + 1 == e) { // Empty last line means that we already have a star as a part of the // trailing */. We also need to preserve whitespace, so that */ is // correctly indented. LastLineNeedsDecoration = false; // Align the star in the last '*/' with the stars on the previous lines. if (e >= 2 && !Decoration.empty()) { ContentColumn[i] = DecorationColumn; } } else if (Decoration.empty()) { // For all other lines, set the start column to 0 if they're empty, so // we do not insert trailing whitespace anywhere. ContentColumn[i] = 0; } continue; } // The first line already excludes the star. // The last line excludes the star if LastLineNeedsDecoration is false. // For all other lines, adjust the line to exclude the star and // (optionally) the first whitespace. unsigned DecorationSize = Decoration.startswith(Content[i]) ? Content[i].size() : Decoration.size(); if (DecorationSize) { ContentColumn[i] = DecorationColumn + DecorationSize; } Content[i] = Content[i].substr(DecorationSize); if (!Decoration.startswith(Content[i])) IndentAtLineBreak = std::min<int>(IndentAtLineBreak, std::max(0, ContentColumn[i])); } IndentAtLineBreak = std::max<unsigned>(IndentAtLineBreak, Decoration.size()); DEBUG({ llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n"; for (size_t i = 0; i < Lines.size(); ++i) { llvm::dbgs() << i << " |" << Content[i] << "| " << "CC=" << ContentColumn[i] << "| " << "IN=" << (Content[i].data() - Lines[i].data()) << "\n"; } });