[clang-format] Align block comment decorations

Summary:
This patch implements block comment decoration alignment.

source:
```
/* line 1
* line 2
*/
```

result before:
```
/* line 1
* line 2
*/
```

result after:
```
/* line 1
 * line 2
 */
```

Reviewers: djasper, bkramer, klimek

Reviewed By: klimek

Subscribers: mprobst, cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D29943

llvm-svn: 295312
This commit is contained in:
Krasimir Georgiev 2017-02-16 12:39:31 +00:00
parent 58984e7087
commit bb99a36dc0
4 changed files with 224 additions and 10 deletions

View File

@ -344,6 +344,20 @@ BreakableBlockComment::BreakableBlockComment(
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,
@ -373,6 +387,10 @@ BreakableBlockComment::BreakableBlockComment(
// 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.
@ -382,12 +400,15 @@ BreakableBlockComment::BreakableBlockComment(
}
// 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();
ContentColumn[i] += DecorationSize;
if (DecorationSize) {
ContentColumn[i] = DecorationColumn + DecorationSize;
}
Content[i] = Content[i].substr(DecorationSize);
if (!Decoration.startswith(Content[i]))
IndentAtLineBreak =
@ -400,7 +421,8 @@ BreakableBlockComment::BreakableBlockComment(
llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n";
for (size_t i = 0; i < Lines.size(); ++i) {
llvm::dbgs() << i << " |" << Content[i] << "| "
<< (Content[i].data() - Lines[i].data()) << "\n";
<< "CC=" << ContentColumn[i] << "| "
<< "IN=" << (Content[i].data() - Lines[i].data()) << "\n";
}
});
}

View File

@ -358,6 +358,10 @@ private:
// Either "* " if all lines begin with a "*", or empty.
StringRef Decoration;
// If this block comment has decorations, this is the column of the start of
// the decorations.
unsigned DecorationColumn;
};
class BreakableLineCommentSection : public BreakableComment {

View File

@ -1966,7 +1966,7 @@ TEST_F(FormatTest, EscapedNewlines) {
format("#define A \\\nint i;\\\n int j;", getLLVMStyleWithColumns(11)));
EXPECT_EQ("#define A\n\nint i;", format("#define A \\\n\n int i;"));
EXPECT_EQ("template <class T> f();", format("\\\ntemplate <class T> f();"));
EXPECT_EQ("/* \\ \\ \\\n*/", format("\\\n/* \\ \\ \\\n*/"));
EXPECT_EQ("/* \\ \\ \\\n */", format("\\\n/* \\ \\ \\\n */"));
EXPECT_EQ("<a\n\\\\\n>", format("<a\n\\\\\n>"));
}

View File

@ -937,11 +937,11 @@ TEST_F(FormatTestComments, SplitsLongLinesInComments) {
getLLVMStyleWithColumns(20)));
EXPECT_EQ("/* some comment\n"
" * a comment\n"
"* that we break\n"
" * another comment\n"
"* we have to break\n"
"* a left comment\n"
" * a comment that\n"
" * we break another\n"
" * comment we have\n"
" * to break a left\n"
" * comment\n"
" */",
format(" /* some comment\n"
" * a comment that we break\n"
@ -1856,10 +1856,10 @@ TEST_F(FormatTestComments, BlockComments) {
getLLVMStyleWithColumns(15)));
EXPECT_EQ("/*\n**\n*/", format("/*\n**\n*/"));
EXPECT_EQ("/*\n"
"*\n"
" *\n"
" * aaaaaa\n"
" * aaaaaa\n"
"*/",
" */",
format("/*\n"
"*\n"
" * aaaaaa aaaaaa\n"
@ -2164,6 +2164,194 @@ TEST_F(FormatTestComments, AlignTrailingComments) {
" long b;",
getLLVMStyleWithColumns(80)));
}
TEST_F(FormatTestComments, AlignsBlockCommentDecorations) {
EXPECT_EQ("/*\n"
" */",
format("/*\n"
"*/", getLLVMStyle()));
EXPECT_EQ("/*\n"
" */",
format("/*\n"
" */", getLLVMStyle()));
EXPECT_EQ("/*\n"
" */",
format("/*\n"
" */", getLLVMStyle()));
// Align a single line.
EXPECT_EQ("/*\n"
" * line */",
format("/*\n"
"* line */",
getLLVMStyle()));
EXPECT_EQ("/*\n"
" * line */",
format("/*\n"
" * line */",
getLLVMStyle()));
EXPECT_EQ("/*\n"
" * line */",
format("/*\n"
" * line */",
getLLVMStyle()));
EXPECT_EQ("/*\n"
" * line */",
format("/*\n"
" * line */",
getLLVMStyle()));
EXPECT_EQ("/**\n"
" * line */",
format("/**\n"
"* line */",
getLLVMStyle()));
EXPECT_EQ("/**\n"
" * line */",
format("/**\n"
" * line */",
getLLVMStyle()));
EXPECT_EQ("/**\n"
" * line */",
format("/**\n"
" * line */",
getLLVMStyle()));
EXPECT_EQ("/**\n"
" * line */",
format("/**\n"
" * line */",
getLLVMStyle()));
EXPECT_EQ("/**\n"
" * line */",
format("/**\n"
" * line */",
getLLVMStyle()));
// Align the end '*/' after a line.
EXPECT_EQ("/*\n"
" * line\n"
" */",
format("/*\n"
"* line\n"
"*/", getLLVMStyle()));
EXPECT_EQ("/*\n"
" * line\n"
" */",
format("/*\n"
" * line\n"
" */", getLLVMStyle()));
EXPECT_EQ("/*\n"
" * line\n"
" */",
format("/*\n"
" * line\n"
" */", getLLVMStyle()));
// Align two lines.
EXPECT_EQ("/* line 1\n"
" * line 2 */",
format("/* line 1\n"
" * line 2 */",
getLLVMStyle()));
EXPECT_EQ("/* line 1\n"
" * line 2 */",
format("/* line 1\n"
"* line 2 */",
getLLVMStyle()));
EXPECT_EQ("/* line 1\n"
" * line 2 */",
format("/* line 1\n"
" * line 2 */",
getLLVMStyle()));
EXPECT_EQ("/* line 1\n"
" * line 2 */",
format("/* line 1\n"
" * line 2 */",
getLLVMStyle()));
EXPECT_EQ("/* line 1\n"
" * line 2 */",
format("/* line 1\n"
" * line 2 */",
getLLVMStyle()));
EXPECT_EQ("int i; /* line 1\n"
" * line 2 */",
format("int i; /* line 1\n"
"* line 2 */",
getLLVMStyle()));
EXPECT_EQ("int i; /* line 1\n"
" * line 2 */",
format("int i; /* line 1\n"
" * line 2 */",
getLLVMStyle()));
EXPECT_EQ("int i; /* line 1\n"
" * line 2 */",
format("int i; /* line 1\n"
" * line 2 */",
getLLVMStyle()));
// Align several lines.
EXPECT_EQ("/* line 1\n"
" * line 2\n"
" * line 3 */",
format("/* line 1\n"
" * line 2\n"
"* line 3 */",
getLLVMStyle()));
EXPECT_EQ("/* line 1\n"
" * line 2\n"
" * line 3 */",
format("/* line 1\n"
" * line 2\n"
"* line 3 */",
getLLVMStyle()));
EXPECT_EQ("/*\n"
"** line 1\n"
"** line 2\n"
"*/",
format("/*\n"
"** line 1\n"
" ** line 2\n"
"*/",
getLLVMStyle()));
// Align with different indent after the decorations.
EXPECT_EQ("/*\n"
" * line 1\n"
" * line 2\n"
" * line 3\n"
" * line 4\n"
" */",
format("/*\n"
"* line 1\n"
" * line 2\n"
" * line 3\n"
"* line 4\n"
"*/", getLLVMStyle()));
// Align empty or blank lines.
EXPECT_EQ("/**\n"
" *\n"
" *\n"
" *\n"
" */",
format("/**\n"
"* \n"
" * \n"
" *\n"
"*/", getLLVMStyle()));
// Align while breaking and reflowing.
EXPECT_EQ("/*\n"
" * long long long\n"
" * long long\n"
" *\n"
" * long */",
format("/*\n"
" * long long long long\n"
" * long\n"
" *\n"
"* long */",
getLLVMStyleWithColumns(20)));
}
} // end namespace
} // end namespace format
} // end namespace clang