Skip to content

Commit

Permalink
[clang-format] Keep trailing preprocessor line comments separate from…
Browse files Browse the repository at this point in the history
… the following section comments

Summary:
r303415 changed the way a sequence of line comments following a preprocessor
macro is handled, which has the unfortunate effect of aligning a trailing
preprocessor line comment and following unrelated section comments, so:
```
#ifdef A // comment about A
// section comment
#endif
```
gets turned into:
```
#ifdef A // comment about A
         // section comment
#endif
```
This patch fixes this by additionally checking the original start columns of
the line comments.

Reviewers: djasper

Reviewed By: djasper

Subscribers: klimek, cfe-commits

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

llvm-svn: 303541
  • Loading branch information
krasimirgg committed May 22, 2017
1 parent 6110be9 commit ea222a7
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 14 deletions.
39 changes: 25 additions & 14 deletions clang/lib/Format/UnwrappedLineParser.cpp
Expand Up @@ -60,6 +60,21 @@ static bool isLineComment(const FormatToken &FormatTok) {
FormatTok.TokenText.startswith("//");
}

// Checks if \p FormatTok is a line comment that continues the line comment
// \p Previous. The original column of \p MinColumnToken is used to determine
// whether \p FormatTok is indented enough to the right to continue \p Previous.
static bool continuesLineComment(const FormatToken &FormatTok,
const FormatToken *Previous,
const FormatToken *MinColumnToken) {
if (!Previous || !MinColumnToken)
return false;
unsigned MinContinueColumn =
MinColumnToken->OriginalColumn + (isLineComment(*MinColumnToken) ? 0 : 1);
return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 &&
isLineComment(*Previous) &&
FormatTok.OriginalColumn >= MinContinueColumn;
}

class ScopedMacroState : public FormatTokenSource {
public:
ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
Expand Down Expand Up @@ -101,8 +116,8 @@ class ScopedMacroState : public FormatTokenSource {
private:
bool eof() {
return Token && Token->HasUnescapedNewline &&
!(PreviousToken && isLineComment(*PreviousToken) &&
isLineComment(*Token) && Token->NewlinesBefore == 1);
!continuesLineComment(*Token, PreviousToken,
/*MinColumnToken=*/PreviousToken);
}

FormatToken *getFakeEOF() {
Expand Down Expand Up @@ -2106,9 +2121,9 @@ bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {

// Checks if \p FormatTok is a line comment that continues the line comment
// section on \p Line.
static bool continuesLineComment(const FormatToken &FormatTok,
const UnwrappedLine &Line,
llvm::Regex &CommentPragmasRegex) {
static bool continuesLineCommentSection(const FormatToken &FormatTok,
const UnwrappedLine &Line,
llvm::Regex &CommentPragmasRegex) {
if (Line.Tokens.empty())
return false;

Expand Down Expand Up @@ -2207,12 +2222,8 @@ static bool continuesLineComment(const FormatToken &FormatTok,
MinColumnToken = PreviousToken;
}

unsigned MinContinueColumn =
MinColumnToken->OriginalColumn +
(isLineComment(*MinColumnToken) ? 0 : 1);
return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 &&
isLineComment(*(Line.Tokens.back().Tok)) &&
FormatTok.OriginalColumn >= MinContinueColumn;
return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok,
MinColumnToken);
}

void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
Expand All @@ -2230,7 +2241,7 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
// FIXME: Consider putting separate line comment sections as children to the
// unwrapped line instead.
(*I)->ContinuesLineCommentSection =
continuesLineComment(**I, *Line, CommentPragmasRegex);
continuesLineCommentSection(**I, *Line, CommentPragmasRegex);
if (isOnNewLine(**I) && JustComments && !(*I)->ContinuesLineCommentSection)
addUnwrappedLine();
pushToken(*I);
Expand Down Expand Up @@ -2263,7 +2274,7 @@ void UnwrappedLineParser::distributeComments(
const SmallVectorImpl<FormatToken *> &Comments,
const FormatToken *NextTok) {
// Whether or not a line comment token continues a line is controlled by
// the method continuesLineComment, with the following caveat:
// the method continuesLineCommentSection, with the following caveat:
//
// Define a trail of Comments to be a nonempty proper postfix of Comments such
// that each comment line from the trail is aligned with the next token, if
Expand Down Expand Up @@ -2301,7 +2312,7 @@ void UnwrappedLineParser::distributeComments(
FormatTok->ContinuesLineCommentSection = false;
} else {
FormatTok->ContinuesLineCommentSection =
continuesLineComment(*FormatTok, *Line, CommentPragmasRegex);
continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex);
}
if (!FormatTok->ContinuesLineCommentSection &&
(isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
Expand Down
32 changes: 32 additions & 0 deletions clang/unittests/Format/FormatTestComments.cpp
Expand Up @@ -1020,6 +1020,38 @@ TEST_F(FormatTestComments, SplitsLongLinesInCommentsInPreprocessor) {
getLLVMStyleWithColumns(20)));
}

TEST_F(FormatTestComments, KeepsTrailingPPCommentsAndSectionCommentsSeparate) {
verifyFormat("#ifdef A // line about A\n"
"// section comment\n"
"#endif",
getLLVMStyleWithColumns(80));
verifyFormat("#ifdef A // line 1 about A\n"
" // line 2 about A\n"
"// section comment\n"
"#endif",
getLLVMStyleWithColumns(80));
EXPECT_EQ("#ifdef A // line 1 about A\n"
" // line 2 about A\n"
"// section comment\n"
"#endif",
format("#ifdef A // line 1 about A\n"
" // line 2 about A\n"
"// section comment\n"
"#endif",
getLLVMStyleWithColumns(80)));
verifyFormat("int f() {\n"
" int i;\n"
"#ifdef A // comment about A\n"
" // section comment 1\n"
" // section comment 2\n"
" i = 2;\n"
"#else // comment about #else\n"
" // section comment 3\n"
" i = 4;\n"
"#endif\n"
"}", getLLVMStyleWithColumns(80));
}

TEST_F(FormatTestComments, CommentsInStaticInitializers) {
EXPECT_EQ(
"static SomeType type = {aaaaaaaaaaaaaaaaaaaa, /* comment */\n"
Expand Down

0 comments on commit ea222a7

Please sign in to comment.