[clang-format] Fix breaking of comment sections in unwrapped lines containing newlines.
Summary:
The breaking of line comment sections was misaligning the case where the first comment line is on an unwrapped line containing newlines. In this case, the breaking column must be based on the source column of the last token that is preceded by a newline, not on the first token of the unwrapped line.
source:
```
enum A {
a, // line 1
// line 2
};
```
format before:
```
enum A {
a, // line 1
// line 2
};
```
format after:
```
enum A {
a, // line 1
// line 2
};
```
Reviewers: djasper
Reviewed By: djasper
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D29444
llvm-svn: 293891
diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp
index 09f17a3..e9dd253 100644
--- a/clang/lib/Format/BreakableToken.cpp
+++ b/clang/lib/Format/BreakableToken.cpp
@@ -695,7 +695,7 @@
Content[i] = Content[i].substr(0, EndOfLine);
}
LineTok = CurrentTok->Next;
- if (CurrentTok->Next && CurrentTok->Next->NewlinesBefore > 1) {
+ if (CurrentTok->Next && !CurrentTok->Next->ContinuesLineCommentSection) {
// A line comment section needs to broken by a line comment that is
// preceded by at least two newlines. Note that we put this break here
// instead of breaking at a previous stage during parsing, since that
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index c838cfb..d6a2ff2 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -261,6 +261,11 @@
/// Only set if \c Type == \c TT_StartOfName.
bool PartOfMultiVariableDeclStmt = false;
+ /// \brief Does this line comment continue a line comment section?
+ ///
+ /// Only set to true if \c Type == \c TT_LineComment.
+ bool ContinuesLineCommentSection = false;
+
/// \brief If this is a bracket, this points to the matching one.
FormatToken *MatchingParen = nullptr;
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index a96d4d9..2c7b87e 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2066,31 +2066,58 @@
// original start column of the min column token of the line.
//
// For example, the second line comment continues the first in these cases:
+ //
// // first line
// // second line
+ //
// and:
+ //
// // first line
// // second line
+ //
// and:
+ //
// int i; // first line
// // second line
+ //
// and:
+ //
// do { // first line
// // second line
// int i;
// } while (true);
//
+ // and:
+ //
+ // enum {
+ // a, // first line
+ // // second line
+ // b
+ // };
+ //
// The second line comment doesn't continue the first in these cases:
+ //
// // first line
// // second line
+ //
// and:
+ //
// int i; // first line
// // second line
+ //
// and:
+ //
// do { // first line
// // second line
// int i;
// } while (true);
+ //
+ // and:
+ //
+ // enum {
+ // a, // first line
+ // // second line
+ // };
const FormatToken *MinColumnToken = Line.Tokens.front().Tok;
// Scan for '{//'. If found, use the column of '{' as a min column for line
@@ -2103,6 +2130,11 @@
break;
}
PreviousToken = Node.Tok;
+
+ // Grab the last newline preceding a token in this unwrapped line.
+ if (Node.Tok->NewlinesBefore > 0) {
+ MinColumnToken = Node.Tok;
+ }
}
if (PreviousToken && PreviousToken->is(tok::l_brace)) {
MinColumnToken = PreviousToken;
@@ -2130,7 +2162,8 @@
//
// FIXME: Consider putting separate line comment sections as children to the
// unwrapped line instead.
- if (isOnNewLine(**I) && JustComments && !continuesLineComment(**I, *Line))
+ (*I)->ContinuesLineCommentSection = continuesLineComment(**I, *Line);
+ if (isOnNewLine(**I) && JustComments && !(*I)->ContinuesLineCommentSection)
addUnwrappedLine();
pushToken(*I);
}
@@ -2196,7 +2229,9 @@
if (!FormatTok->Tok.is(tok::comment))
return;
- if (!continuesLineComment(*FormatTok, *Line) &&
+ FormatTok->ContinuesLineCommentSection =
+ continuesLineComment(*FormatTok, *Line);
+ if (!FormatTok->ContinuesLineCommentSection &&
(isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
CommentsInCurrentLine = false;
}