[PATCH] Split long lines in multi-line comments.
Alexander Kornienko
alexfh at google.com
Fri Mar 15 12:09:16 PDT 2013
Hi djasper, klimek,
This is implementation for /* */ comments only.
http://llvm-reviews.chandlerc.com/D547
Files:
lib/Format/Format.cpp
unittests/Format/FormatTest.cpp
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -146,7 +146,7 @@
alignComments();
if (Tok.Type == TT_BlockComment)
- indentBlockComment(Tok.FormatTok, Spaces);
+ indentBlockComment(Tok.FormatTok, Spaces, Style);
storeReplacement(Tok.FormatTok, getNewLineText(NewLines, Spaces));
}
@@ -193,33 +193,89 @@
}
private:
- void indentBlockComment(const FormatToken &Tok, int Indent) {
+ StringRef findCommonPrefix(ArrayRef<StringRef> Lines) {
+ if (Lines.size() < 3)
+ return "";
+ StringRef Prefix(Lines[1].data(), Lines[1].find_first_not_of(" *"));
+ for (size_t i = 2; i < Lines.size(); ++i) {
+ for (size_t j = 0; j < Prefix.size() && j < Lines[i].size(); ++j)
+ if (Prefix[j] != Lines[i][j]) {
+ Prefix = Prefix.substr(0, j);
+ break;
+ }
+ }
+ return Prefix;
+ }
+
+ bool safeToSplitLine(StringRef Line) {
+ return Line.find_first_of("/\\:<>()[]{}*&%") == StringRef::npos;
+ }
+
+ void indentBlockComment(const FormatToken &Tok, int Indent,
+ const FormatStyle &Style) {
SourceLocation TokenLoc = Tok.Tok.getLocation();
- int IndentDelta = Indent - SourceMgr.getSpellingColumnNumber(TokenLoc) + 1;
- const char *Start = SourceMgr.getCharacterData(TokenLoc);
- const char *Current = Start;
- const char *TokEnd = Current + Tok.TokenLength;
- llvm::SmallVector<SourceLocation, 16> LineStarts;
- while (Current < TokEnd) {
- if (*Current == '\n') {
- ++Current;
- LineStarts.push_back(TokenLoc.getLocWithOffset(Current - Start));
- // If we need to outdent the line, check that it's indented enough.
- for (int i = 0; i < -IndentDelta; ++i, ++Current)
- if (Current >= TokEnd || *Current != ' ')
- return;
- } else {
- ++Current;
+ int TokenIndent = SourceMgr.getSpellingColumnNumber(TokenLoc) - 1;
+ int IndentDelta = Indent - TokenIndent;
+ StringRef Text(SourceMgr.getCharacterData(TokenLoc), Tok.TokenLength);
+ SmallVector<StringRef, 16> Lines;
+ Text.split(Lines, "\n");
+
+ if (IndentDelta > 0) {
+ std::string WhiteSpace(IndentDelta, ' ');
+ for (size_t i = 1; i < Lines.size(); ++i) {
+ Replaces.insert(tooling::Replacement(
+ SourceMgr, TokenLoc.getLocWithOffset(Lines[i].data() - Text.data()),
+ 0, WhiteSpace));
+ }
+ } else if (IndentDelta < 0) {
+ std::string WhiteSpace(-IndentDelta, ' ');
+ // Check that the line is indented enough.
+ for (size_t i = 1; i < Lines.size(); ++i) {
+ if (!Lines[i].startswith(WhiteSpace))
+ return;
+ }
+ for (size_t i = 1; i < Lines.size(); ++i) {
+ Replaces.insert(tooling::Replacement(
+ SourceMgr, TokenLoc.getLocWithOffset(Lines[i].data() - Text.data()),
+ -IndentDelta, ""));
}
}
- for (size_t i = 0; i < LineStarts.size(); ++i) {
- if (IndentDelta > 0)
- Replaces.insert(tooling::Replacement(SourceMgr, LineStarts[i], 0,
- std::string(IndentDelta, ' ')));
- else if (IndentDelta < 0)
- Replaces.insert(
- tooling::Replacement(SourceMgr, LineStarts[i], -IndentDelta, ""));
+ // Split long lines in comments.
+ StringRef Prefix = findCommonPrefix(Lines);
+ size_t ColumnLimit = Style.ColumnLimit - Prefix.size() - IndentDelta;
+ std::string NewLine("\n");
+ if (IndentDelta < 0)
+ NewLine += Prefix.substr(-IndentDelta).str();
+ else
+ NewLine += std::string(IndentDelta, ' ') + Prefix.str();
+
+ if (Prefix.endswith("*")) {
+ NewLine += " ";
+ --ColumnLimit;
+ }
+
+ for (size_t i = 1; i < Lines.size(); ++i) {
+ StringRef Line = Lines[i].substr(Prefix.size());
+ if (Line.size() <= ColumnLimit || !safeToSplitLine(Line))
+ continue;
+ while (Line.size() > ColumnLimit) {
+ size_t SpacePos = Line.find_last_of(" ", ColumnLimit + 1);
+ if (SpacePos == StringRef::npos)
+ break;
+ size_t BreakPos = Line.find_last_not_of(" ", SpacePos);
+ if (BreakPos == StringRef::npos)
+ break;
+
+ ++BreakPos;
+
+ Replaces.insert(tooling::Replacement(
+ SourceMgr,
+ TokenLoc.getLocWithOffset(Line.data() + BreakPos - Text.data()),
+ SpacePos - BreakPos + 1, NewLine));
+
+ Line = Line.substr(SpacePos).ltrim();
+ }
}
}
Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -651,6 +651,63 @@
" */"));
}
+TEST_F(FormatTest, SplitsLongLinesInComments) {
+ EXPECT_EQ("/*\n"
+ "This is a long\n"
+ "comment that doesn't\n"
+ "fit on one line. \n"
+ "*/",
+ format("/*\n"
+ "This is a long "
+ "comment that doesn't "
+ "fit on one line. \n"
+ "*/", getLLVMStyleWithColumns(20)));
+ EXPECT_EQ("/*\n"
+ " * This is a long\n"
+ " * comment that\n"
+ " * doesn't fit on\n"
+ " * one line.\n"
+ " */",
+ format("/*\n"
+ " * This is a long comment that doesn't fit on one line.\n"
+ " */", getLLVMStyleWithColumns(20)));
+ EXPECT_EQ("{\n"
+ " /*\n"
+ " This is another\n"
+ " long comment that\n"
+ " doesn't fit on one\n"
+ " line\n"
+ " */\n"
+ "}",
+ format("{\n"
+ "/*\n"
+ "This is another long comment that doesn't fit on one line\n"
+ "*/\n"
+ "}", getLLVMStyleWithColumns(20)));
+ EXPECT_EQ("{\n"
+ " /*\n"
+ " * This is\n"
+ " * another comment\n"
+ " * that doesn't\n"
+ " * fit on one line\n"
+ " */\n"
+ "}",
+ format("{\n"
+ "/*\n"
+ " * This is another comment that doesn't fit on one line\n"
+ " */\n"
+ "}", getLLVMStyleWithColumns(20)));
+ EXPECT_EQ("/*\n"
+ " * This is a long\n"
+ " * comment that\n"
+ " * doesn't fit on\n"
+ " * one line\n"
+ " */",
+ format(" /*\n"
+ " * This is a long comment that doesn't fit on one line\n"
+ " */", getLLVMStyleWithColumns(20)));
+}
+
TEST_F(FormatTest, CommentsInStaticInitializers) {
EXPECT_EQ(
"static SomeType type = { aaaaaaaaaaaaaaaaaaaa, /* comment */\n"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D547.1.patch
Type: text/x-patch
Size: 6935 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130315/cf538bbe/attachment.bin>
More information about the cfe-commits
mailing list