diff options
author | Alexander Kornienko <alexfh@google.com> | 2013-07-08 14:12:07 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2013-07-08 14:12:07 +0000 |
commit | 614d96a1f689ee126e974f8c8d15194a9d881075 (patch) | |
tree | 10f3d3fa71520ea51f421e5c1e022b96c2bbb6d2 /clang/lib/Format/BreakableToken.cpp | |
parent | ddd7b6a1c8dc21e700a20d05a12210e6c063a510 (diff) | |
download | bcm5719-llvm-614d96a1f689ee126e974f8c8d15194a9d881075.tar.gz bcm5719-llvm-614d96a1f689ee126e974f8c8d15194a9d881075.zip |
Fix for corner cases in code handling leading "* " decorations in block comments
Summary:
Fixes problems that lead to incorrect formatting of these and similar snippets:
/*
**
*/
/*
**/
/*
* */
/*
*test
*/
Clang-format used to think that all the cases above use "* " decoration, and
failed to calculate insertion position properly. It also used to remove leading
"* " in the last line.
Reviewers: klimek
Reviewed By: klimek
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1113
llvm-svn: 185818
Diffstat (limited to 'clang/lib/Format/BreakableToken.cpp')
-rw-r--r-- | clang/lib/Format/BreakableToken.cpp | 64 |
1 files changed, 36 insertions, 28 deletions
diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp index ace3baa660b..f01b481b844 100644 --- a/clang/lib/Format/BreakableToken.cpp +++ b/clang/lib/Format/BreakableToken.cpp @@ -225,50 +225,56 @@ BreakableBlockComment::BreakableBlockComment( TokenText.substr(2, TokenText.size() - 4).split(Lines, "\n"); int IndentDelta = StartColumn - OriginalStartColumn; - bool NeedsStar = true; LeadingWhitespace.resize(Lines.size()); StartOfLineColumn.resize(Lines.size()); + StartOfLineColumn[0] = StartColumn + 2; + for (size_t i = 1; i < Lines.size(); ++i) + adjustWhitespace(Style, 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. - NeedsStar = false; + Decoration = ""; } - 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] == '*'; + 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; + while (!Lines[i].startswith(Decoration)) + Decoration = Decoration.substr(0, Decoration.size() - 1); } - Decoration = NeedsStar ? "* " : ""; + + LastLineNeedsDecoration = true; 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. + 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; } - 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; - } + // The first line already excludes the star. + // For all other lines, adjust the line to exclude the star and + // (optionally) the first whitespace. + StartOfLineColumn[i] += Decoration.size(); + Lines[i] = Lines[i].substr(Decoration.size()); + LeadingWhitespace[i] += Decoration.size(); IndentAtLineBreak = std::min<int>(IndentAtLineBreak, 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"; @@ -365,9 +371,11 @@ BreakableBlockComment::replaceWhitespaceBefore(unsigned LineIndex, StringRef Prefix = Decoration; if (Lines[LineIndex].empty()) { if (LineIndex + 1 == Lines.size()) { - // If the last line is empty, we don't need a prefix, as the */ will line - // up with the decoration (if it exists). - Prefix = ""; + if (!LastLineNeedsDecoration) { + // If the last line was empty, we don't need a prefix, as the */ will + // line up with the decoration (if it exists). + Prefix = ""; + } } else if (!Decoration.empty()) { // For other empty lines, if we do have a decoration, adapt it to not // contain a trailing whitespace. @@ -375,7 +383,7 @@ BreakableBlockComment::replaceWhitespaceBefore(unsigned LineIndex, } } else { if (StartOfLineColumn[LineIndex] == 1) { - // This lines starts immediately after the decorating *. + // This line starts immediately after the decorating *. Prefix = Prefix.substr(0, 1); } } |