Skip to content

Commit

Permalink
[clang-format] Keep level of comment before an empty line
Browse files Browse the repository at this point in the history
Summary:
This patch fixes bug https://bugs.llvm.org/show_bug.cgi?id=3313: a comment line
was aligned with the next #ifdef even in the presence of an empty line between
them.

Reviewers: djasper, klimek

Reviewed By: djasper

Subscribers: klimek, cfe-commits

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

llvm-svn: 307795
  • Loading branch information
krasimirgg committed Jul 12, 2017
1 parent 8c804d9 commit e092634
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 5 deletions.
17 changes: 13 additions & 4 deletions clang/lib/Format/TokenAnnotator.cpp
Expand Up @@ -1694,17 +1694,26 @@ void TokenAnnotator::setCommentLineLevels(
for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(),
E = Lines.rend();
I != E; ++I) {
bool CommentLine = (*I)->First;
bool CommentLine = true;
for (const FormatToken *Tok = (*I)->First; Tok; Tok = Tok->Next) {
if (!Tok->is(tok::comment)) {
CommentLine = false;
break;
}
}
if (NextNonCommentLine && CommentLine)
(*I)->Level = NextNonCommentLine->Level;
else

if (NextNonCommentLine && CommentLine) {
// If the comment is currently aligned with the line immediately following
// it, that's probably intentional and we should keep it.
bool AlignedWithNextLine =
NextNonCommentLine->First->NewlinesBefore <= 1 &&
NextNonCommentLine->First->OriginalColumn ==
(*I)->First->OriginalColumn;
if (AlignedWithNextLine)
(*I)->Level = NextNonCommentLine->Level;
} else {
NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : nullptr;
}

setCommentLineLevels((*I)->Children);
}
Expand Down
25 changes: 24 additions & 1 deletion clang/unittests/Format/FormatTest.cpp
Expand Up @@ -825,12 +825,35 @@ TEST_F(FormatTest, FormatsSwitchStatement) {
" case A:\n"
" f();\n"
" break;\n"
" // On B:\n"
" // fallthrough\n"
" case B:\n"
" g();\n"
" break;\n"
" }\n"
"});");
EXPECT_EQ("DEBUG({\n"
" switch (x) {\n"
" case A:\n"
" f();\n"
" break;\n"
" // On B:\n"
" case B:\n"
" g();\n"
" break;\n"
" }\n"
"});",
format("DEBUG({\n"
" switch (x) {\n"
" case A:\n"
" f();\n"
" break;\n"
" // On B:\n"
" case B:\n"
" g();\n"
" break;\n"
" }\n"
"});",
getLLVMStyle()));
verifyFormat("switch (a) {\n"
"case (b):\n"
" return;\n"
Expand Down
64 changes: 64 additions & 0 deletions clang/unittests/Format/FormatTestComments.cpp
Expand Up @@ -805,6 +805,70 @@ TEST_F(FormatTestComments, ParsesCommentsAdjacentToPPDirectives) {
format("namespace {}\n /* Test */ #define A"));
}

TEST_F(FormatTestComments, KeepsLevelOfCommentBeforePPDirective) {
// Keep the current level if the comment was originally not aligned with
// the preprocessor directive.
EXPECT_EQ("void f() {\n"
" int i;\n"
" /* comment */\n"
"#ifdef A\n"
" int j;\n"
"}",
format("void f() {\n"
" int i;\n"
" /* comment */\n"
"#ifdef A\n"
" int j;\n"
"}"));

EXPECT_EQ("void f() {\n"
" int i;\n"
" /* comment */\n"
"\n"
"#ifdef A\n"
" int j;\n"
"}",
format("void f() {\n"
" int i;\n"
" /* comment */\n"
"\n"
"#ifdef A\n"
" int j;\n"
"}"));

// Keep the current level if there is an empty line between the comment and
// the preprocessor directive.
EXPECT_EQ("void f() {\n"
" int i;\n"
" /* comment */\n"
"\n"
"#ifdef A\n"
" int j;\n"
"}",
format("void f() {\n"
" int i;\n"
"/* comment */\n"
"\n"
"#ifdef A\n"
" int j;\n"
"}"));

// Align with the preprocessor directive if the comment was originally aligned
// with the preprocessor directive.
EXPECT_EQ("void f() {\n"
" int i;\n"
"/* comment */\n"
"#ifdef A\n"
" int j;\n"
"}",
format("void f() {\n"
" int i;\n"
"/* comment */\n"
"#ifdef A\n"
" int j;\n"
"}"));
}

TEST_F(FormatTestComments, SplitsLongLinesInComments) {
EXPECT_EQ("/* This is a long\n"
" * comment that\n"
Expand Down

0 comments on commit e092634

Please sign in to comment.