Skip to content

Commit 4c6b2fb

Browse files
committed
[clang-format] Introduce "ReflowComments: IndentOnly" to re-indent comments without breaking internal structure (think Doxygen).
* Convert `ReflowComments` from boolean into a new `enum` which can take on the value `RCS_Never`, `RCS_IndentOnly`, or `RCS_Always`. The first one is equivalent to the old `false`, the third one is `true`, and the middle one means that multiline comments should only have their indentation corrected, which is what Doxygen users will want. * Preserve backward compatibility while parsing `ReflowComments`.
1 parent 637b7f8 commit 4c6b2fb

File tree

8 files changed

+78
-26
lines changed

8 files changed

+78
-26
lines changed

clang/include/clang/Format/Format.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3749,23 +3749,34 @@ struct FormatStyle {
37493749
/// \version 13
37503750
ReferenceAlignmentStyle ReferenceAlignment;
37513751

3752+
enum ReflowCommentsStyle : int8_t { RCS_Never, RCS_IndentOnly, RCS_Always };
37523753
// clang-format off
37533754
/// If ``true``, clang-format will attempt to re-flow comments. That is it
37543755
/// will touch a comment and *reflow* long comments into new lines, trying to
37553756
/// obey the ``ColumnLimit``.
37563757
/// \code
3757-
/// false:
3758+
/// RCS_Never:
37583759
/// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
37593760
/// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
3761+
/// /* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
3762+
/// * and a misaligned second line */
37603763
///
3761-
/// true:
3764+
/// RCS_IndentOnly:
3765+
/// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
3766+
/// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
3767+
/// /* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
3768+
/// * and a misaligned second line */
3769+
///
3770+
/// RCS_Always:
37623771
/// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
37633772
/// // information
37643773
/// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
37653774
/// * information */
3775+
/// /* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
3776+
/// * information and a misaligned second line */
37663777
/// \endcode
37673778
/// \version 3.8
3768-
bool ReflowComments;
3779+
ReflowCommentsStyle ReflowComments;
37693780
// clang-format on
37703781

37713782
/// Remove optional braces of control statements (``if``, ``else``, ``for``,

clang/lib/Format/BreakableToken.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,10 @@ BreakableComment::getSplit(unsigned LineIndex, unsigned TailOffset,
420420
unsigned ColumnLimit, unsigned ContentStartColumn,
421421
const llvm::Regex &CommentPragmasRegex) const {
422422
// Don't break lines matching the comment pragmas regex.
423-
if (CommentPragmasRegex.match(Content[LineIndex]))
423+
if (Style.ReflowComments != FormatStyle::RCS_Always ||
424+
CommentPragmasRegex.match(Content[LineIndex])) {
424425
return Split(StringRef::npos, 0);
426+
}
425427
return getCommentSplit(Content[LineIndex].substr(TailOffset),
426428
ContentStartColumn, ColumnLimit, Style.TabWidth,
427429
Encoding, Style);
@@ -608,8 +610,10 @@ BreakableToken::Split BreakableBlockComment::getSplit(
608610
unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
609611
unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const {
610612
// Don't break lines matching the comment pragmas regex.
611-
if (CommentPragmasRegex.match(Content[LineIndex]))
613+
if (Style.ReflowComments != FormatStyle::RCS_Always ||
614+
CommentPragmasRegex.match(Content[LineIndex])) {
612615
return Split(StringRef::npos, 0);
616+
}
613617
return getCommentSplit(Content[LineIndex].substr(TailOffset),
614618
ContentStartColumn, ColumnLimit, Style.TabWidth,
615619
Encoding, Style, Decoration.ends_with("*"));
@@ -855,7 +859,8 @@ bool BreakableBlockComment::mayReflow(
855859
StringRef IndentContent = Content[LineIndex];
856860
if (Lines[LineIndex].ltrim(Blanks).starts_with("*"))
857861
IndentContent = Lines[LineIndex].ltrim(Blanks).substr(1);
858-
return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) &&
862+
return LineIndex > 0 && Style.ReflowComments == FormatStyle::RCS_Always &&
863+
!CommentPragmasRegex.match(IndentContent) &&
859864
mayReflowContent(Content[LineIndex]) && !Tok.Finalized &&
860865
!switchesFormatting(tokenAt(LineIndex));
861866
}
@@ -1160,7 +1165,8 @@ bool BreakableLineCommentSection::mayReflow(
11601165
// // text that protrudes
11611166
// // into text with different indent
11621167
// We do reflow in that case in block comments.
1163-
return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) &&
1168+
return LineIndex > 0 && Style.ReflowComments == FormatStyle::RCS_Always &&
1169+
!CommentPragmasRegex.match(IndentContent) &&
11641170
mayReflowContent(Content[LineIndex]) && !Tok.Finalized &&
11651171
!switchesFormatting(tokenAt(LineIndex)) &&
11661172
OriginalPrefix[LineIndex] == OriginalPrefix[LineIndex - 1];

clang/lib/Format/ContinuationIndenter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,7 +2400,7 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
24002400
State.Line->InPPDirective, Encoding, Style);
24012401
}
24022402
} else if (Current.is(TT_BlockComment)) {
2403-
if (!Style.ReflowComments ||
2403+
if (Style.ReflowComments == FormatStyle::RCS_Never ||
24042404
// If a comment token switches formatting, like
24052405
// /* clang-format on */, we don't want to break it further,
24062406
// but we may still want to adjust its indentation.
@@ -2421,7 +2421,7 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
24212421
}
24222422
return true;
24232423
}();
2424-
if (!Style.ReflowComments ||
2424+
if (Style.ReflowComments == FormatStyle::RCS_Never ||
24252425
CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
24262426
switchesFormatting(Current) || !RegularComments) {
24272427
return nullptr;

clang/lib/Format/Format.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,16 @@ template <> struct MappingTraits<FormatStyle::RawStringFormat> {
497497
}
498498
};
499499

500+
template <> struct ScalarEnumerationTraits<FormatStyle::ReflowCommentsStyle> {
501+
static void enumeration(IO &IO, FormatStyle::ReflowCommentsStyle &Value) {
502+
IO.enumCase(Value, "Never", FormatStyle::RCS_Never);
503+
IO.enumCase(Value, "IndentOnly", FormatStyle::RCS_IndentOnly);
504+
IO.enumCase(Value, "Always", FormatStyle::RCS_Always);
505+
IO.enumCase(Value, "false", FormatStyle::RCS_Never);
506+
IO.enumCase(Value, "true", FormatStyle::RCS_Always);
507+
}
508+
};
509+
500510
template <>
501511
struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
502512
static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
@@ -1534,7 +1544,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
15341544
LLVMStyle.PPIndentWidth = -1;
15351545
LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
15361546
LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
1537-
LLVMStyle.ReflowComments = true;
1547+
LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
15381548
LLVMStyle.RemoveBracesLLVM = false;
15391549
LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave;
15401550
LLVMStyle.RemoveSemicolon = false;

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4588,11 +4588,11 @@ bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
45884588

45894589
// Checks if \p FormatTok is a line comment that continues the line comment
45904590
// section on \p Line.
4591-
static bool
4592-
continuesLineCommentSection(const FormatToken &FormatTok,
4593-
const UnwrappedLine &Line,
4594-
const llvm::Regex &CommentPragmasRegex) {
4595-
if (Line.Tokens.empty())
4591+
static bool continuesLineCommentSection(
4592+
const FormatToken &FormatTok, const UnwrappedLine &Line,
4593+
const FormatStyle::ReflowCommentsStyle ReflowCommentsStyle,
4594+
const llvm::Regex &CommentPragmasRegex) {
4595+
if (Line.Tokens.empty() || ReflowCommentsStyle != FormatStyle::RCS_Always)
45964596
return false;
45974597

45984598
StringRef IndentContent = FormatTok.TokenText;
@@ -4704,8 +4704,8 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
47044704
//
47054705
// FIXME: Consider putting separate line comment sections as children to the
47064706
// unwrapped line instead.
4707-
Tok->ContinuesLineCommentSection =
4708-
continuesLineCommentSection(*Tok, *Line, CommentPragmasRegex);
4707+
Tok->ContinuesLineCommentSection = continuesLineCommentSection(
4708+
*Tok, *Line, Style.ReflowComments, CommentPragmasRegex);
47094709
if (isOnNewLine(*Tok) && JustComments && !Tok->ContinuesLineCommentSection)
47104710
addUnwrappedLine();
47114711
pushToken(Tok);
@@ -4778,8 +4778,8 @@ void UnwrappedLineParser::distributeComments(
47784778
if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
47794779
FormatTok->ContinuesLineCommentSection = false;
47804780
} else {
4781-
FormatTok->ContinuesLineCommentSection =
4782-
continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex);
4781+
FormatTok->ContinuesLineCommentSection = continuesLineCommentSection(
4782+
*FormatTok, *Line, Style.ReflowComments, CommentPragmasRegex);
47834783
}
47844784
if (!FormatTok->ContinuesLineCommentSection &&
47854785
(isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {

clang/unittests/Format/ConfigParseTest.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
183183
CHECK_PARSE_BOOL(ObjCSpaceAfterProperty);
184184
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
185185
CHECK_PARSE_BOOL(Cpp11BracedListStyle);
186-
CHECK_PARSE_BOOL(ReflowComments);
187186
CHECK_PARSE_BOOL(RemoveBracesLLVM);
188187
CHECK_PARSE_BOOL(RemoveSemicolon);
189188
CHECK_PARSE_BOOL(SkipMacroDefinitionBody);
@@ -372,6 +371,16 @@ TEST(ConfigParseTest, ParsesConfiguration) {
372371
CHECK_PARSE("PointerBindsToType: Middle", PointerAlignment,
373372
FormatStyle::PAS_Middle);
374373

374+
Style.ReflowComments = FormatStyle::RCS_Always;
375+
CHECK_PARSE("ReflowComments: Never", ReflowComments, FormatStyle::RCS_Never);
376+
CHECK_PARSE("ReflowComments: IndentOnly", ReflowComments,
377+
FormatStyle::RCS_IndentOnly);
378+
CHECK_PARSE("ReflowComments: Always", ReflowComments,
379+
FormatStyle::RCS_Always);
380+
// For backward compatibility:
381+
CHECK_PARSE("ReflowComments: false", ReflowComments, FormatStyle::RCS_Never);
382+
CHECK_PARSE("ReflowComments: true", ReflowComments, FormatStyle::RCS_Always);
383+
375384
Style.Standard = FormatStyle::LS_Auto;
376385
CHECK_PARSE("Standard: c++03", Standard, FormatStyle::LS_Cpp03);
377386
CHECK_PARSE("Standard: c++11", Standard, FormatStyle::LS_Cpp11);

clang/unittests/Format/FormatTest.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17851,7 +17851,7 @@ TEST_F(FormatTest, AlignConsecutiveMacros) {
1785117851

1785217852
// Test across comments
1785317853
Style.MaxEmptyLinesToKeep = 10;
17854-
Style.ReflowComments = false;
17854+
Style.ReflowComments = FormatStyle::RCS_Never;
1785517855
Style.AlignConsecutiveMacros.AcrossComments = true;
1785617856
verifyFormat("#define a 3\n"
1785717857
"// line comment\n"
@@ -18598,7 +18598,7 @@ TEST_F(FormatTest, AlignConsecutiveAssignmentsAcrossEmptyLinesAndComments) {
1859818598
"y = 1;",
1859918599
Alignment);
1860018600

18601-
Alignment.ReflowComments = true;
18601+
Alignment.ReflowComments = FormatStyle::RCS_Always;
1860218602
Alignment.ColumnLimit = 50;
1860318603
verifyFormat("int x = 0;\n"
1860418604
"int yy = 1; /// specificlennospace\n"
@@ -18996,7 +18996,7 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
1899618996
"y = 1;",
1899718997
Alignment);
1899818998

18999-
EXPECT_EQ(Alignment.ReflowComments, true);
18999+
EXPECT_EQ(Alignment.ReflowComments, FormatStyle::RCS_Always);
1900019000
Alignment.ColumnLimit = 50;
1900119001
verifyFormat("int x = 0;\n"
1900219002
"int yy = 1; /// specificlennospace\n"

clang/unittests/Format/FormatTestComments.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,25 @@ TEST_F(FormatTestComments, AlignsBlockComments) {
493493

494494
TEST_F(FormatTestComments, CommentReflowingCanBeTurnedOff) {
495495
FormatStyle Style = getLLVMStyleWithColumns(20);
496-
Style.ReflowComments = false;
497-
verifyFormat("// aaaaaaaaa aaaaaaaaaa aaaaaaaaaa", Style);
498-
verifyFormat("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa */", Style);
496+
Style.ReflowComments = FormatStyle::RCS_Never;
497+
verifyNoChange("// aaaaaaaaa aaaaaaaaaa aaaaaaaaaa", Style);
498+
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa */", Style);
499+
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\naaaaaaaaa*/", Style);
500+
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n aaaaaaaaa*/", Style);
501+
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n * aaaaaaaaa*/",
502+
Style);
503+
}
504+
505+
TEST_F(FormatTestComments, CommentReflowingCanApplyOnlyToIndents) {
506+
FormatStyle Style = getLLVMStyleWithColumns(20);
507+
Style.ReflowComments = FormatStyle::RCS_IndentOnly;
508+
verifyNoChange("// aaaaaaaaa aaaaaaaaaa aaaaaaaaaa", Style);
509+
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa */", Style);
510+
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\naaaaaaaaa*/", Style);
511+
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n aaaaaaaaa*/", Style);
512+
verifyFormat("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n * aaaaaaaaa*/",
513+
"/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n * aaaaaaaaa*/",
514+
Style);
499515
}
500516

501517
TEST_F(FormatTestComments, CorrectlyHandlesLengthOfBlockComments) {

0 commit comments

Comments
 (0)