Skip to content

Commit cb52efb

Browse files
authored
[clang-format] Split line comments separated by backslashes (#147648)
Fixes #147341
1 parent 7704f81 commit cb52efb

File tree

5 files changed

+33
-25
lines changed

5 files changed

+33
-25
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,9 +1554,9 @@ the configuration (without a prefix: ``Auto``).
15541554

15551555
.. code-block:: c++
15561556

1557-
#define A \
1558-
int aaaa; \
1559-
int b; \
1557+
#define A \
1558+
int aaaa; \
1559+
int b; \
15601560
int dddddddddd;
15611561

15621562

clang/include/clang/Format/Format.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,9 +513,9 @@ struct FormatStyle {
513513
ENAS_LeftWithLastLine,
514514
/// Align escaped newlines in the right-most column.
515515
/// \code
516-
/// #define A \
517-
/// int aaaa; \
518-
/// int b; \
516+
/// #define A \
517+
/// int aaaa; \
518+
/// int b; \
519519
/// int dddddddddd;
520520
/// \endcode
521521
ENAS_Right,

clang/lib/Format/FormatTokenLexer.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,23 +1329,26 @@ FormatToken *FormatTokenLexer::getNextToken() {
13291329
if (FormatTok->is(tok::unknown))
13301330
FormatTok->setType(TT_ImplicitStringLiteral);
13311331

1332+
const bool IsCpp = Style.isCpp();
1333+
13321334
// JavaScript and Java do not allow to escape the end of the line with a
13331335
// backslash. Backslashes are syntax errors in plain source, but can occur in
13341336
// comments. When a single line comment ends with a \, it'll cause the next
13351337
// line of code to be lexed as a comment, breaking formatting. The code below
13361338
// finds comments that contain a backslash followed by a line break, truncates
13371339
// the comment token at the backslash, and resets the lexer to restart behind
13381340
// the backslash.
1339-
if ((Style.isJavaScript() || Style.isJava()) && FormatTok->is(tok::comment) &&
1340-
FormatTok->TokenText.starts_with("//")) {
1341-
size_t BackslashPos = FormatTok->TokenText.find('\\');
1342-
while (BackslashPos != StringRef::npos) {
1343-
if (BackslashPos + 1 < FormatTok->TokenText.size() &&
1344-
FormatTok->TokenText[BackslashPos + 1] == '\n') {
1345-
truncateToken(BackslashPos + 1);
1341+
if (const auto Text = FormatTok->TokenText;
1342+
Text.starts_with("//") &&
1343+
(IsCpp || Style.isJavaScript() || Style.isJava())) {
1344+
assert(FormatTok->is(tok::comment));
1345+
for (auto Pos = Text.find('\\'); Pos++ != StringRef::npos;
1346+
Pos = Text.find('\\', Pos)) {
1347+
if (Pos < Text.size() && Text[Pos] == '\n' &&
1348+
(!IsCpp || Text.substr(Pos + 1).ltrim().starts_with("//"))) {
1349+
truncateToken(Pos);
13461350
break;
13471351
}
1348-
BackslashPos = FormatTok->TokenText.find('\\', BackslashPos + 1);
13491352
}
13501353
}
13511354

@@ -1450,7 +1453,7 @@ FormatToken *FormatTokenLexer::getNextToken() {
14501453
Column = FormatTok->LastLineColumnWidth;
14511454
}
14521455

1453-
if (Style.isCpp()) {
1456+
if (IsCpp) {
14541457
auto *Identifier = FormatTok->Tok.getIdentifierInfo();
14551458
auto it = Macros.find(Identifier);
14561459
if ((Tokens.empty() || !Tokens.back()->Tok.getIdentifierInfo() ||

clang/unittests/Format/FormatTestComments.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -747,16 +747,14 @@ TEST_F(FormatTestComments, DontSplitLineCommentsWithEscapedNewlines) {
747747
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
748748
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
749749
getLLVMStyleWithColumns(50)));
750-
// FIXME: One day we might want to implement adjustment of leading whitespace
751-
// of the consecutive lines in this kind of comment:
752-
EXPECT_EQ("double\n"
753-
" a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
754-
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
755-
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
756-
format("double a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
757-
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
758-
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
759-
getLLVMStyleWithColumns(49)));
750+
verifyFormat("double\n"
751+
" a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
752+
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
753+
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
754+
"double a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
755+
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
756+
" // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
757+
getLLVMStyleWithColumns(49));
760758
}
761759

762760
TEST_F(FormatTestComments, DontIntroduceMultilineComments) {

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4126,6 +4126,13 @@ TEST_F(TokenAnnotatorTest, JsonCodeInRawString) {
41264126
EXPECT_TOKEN(Tokens[6], tok::colon, TT_DictLiteral);
41274127
}
41284128

4129+
TEST_F(TokenAnnotatorTest, LineCommentTrailingBackslash) {
4130+
auto Tokens = annotate("// a \\\n"
4131+
"// b");
4132+
ASSERT_EQ(Tokens.size(), 3u) << Tokens;
4133+
EXPECT_TOKEN(Tokens[1], tok::comment, TT_LineComment);
4134+
}
4135+
41294136
} // namespace
41304137
} // namespace format
41314138
} // namespace clang

0 commit comments

Comments
 (0)