Skip to content
Merged
50 changes: 37 additions & 13 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5272,22 +5272,46 @@ the configuration (without a prefix: ``Auto``).

.. _ReflowComments:

**ReflowComments** (``Boolean``) :versionbadge:`clang-format 3.8` :ref:`¶ <ReflowComments>`
If ``true``, clang-format will attempt to re-flow comments. That is it
will touch a comment and *reflow* long comments into new lines, trying to
obey the ``ColumnLimit``.
**ReflowComments** (``ReflowCommentsStyle``) :versionbadge:`clang-format 3.8` :ref:`¶ <ReflowComments>`
Comment reformatting style.

.. code-block:: c++
Possible values:

* ``RCS_Never`` (in configuration: ``Never``)
Leave comments untouched.

.. code-block:: c++

// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
/* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
* and a misaligned second line */

* ``RCS_IndentOnly`` (in configuration: ``IndentOnly``)
Only apply indentation rules, moving comments left or right, without
changing formatting inside the comments.

.. code-block:: c++

// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
/* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
* and a misaligned second line */

* ``RCS_Always`` (in configuration: ``Always``)
Apply indentation rules and reflow long comments into new lines, trying
to obey the ``ColumnLimit``.

.. code-block:: c++

// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
// information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
* information */
/* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
* information and a misaligned second line */

false:
// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */

true:
// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
// information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
* information */

.. _RemoveBracesLLVM:

Expand Down
51 changes: 35 additions & 16 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -3814,24 +3814,43 @@ struct FormatStyle {
ReferenceAlignmentStyle ReferenceAlignment;

// clang-format off
/// If ``true``, clang-format will attempt to re-flow comments. That is it
/// will touch a comment and *reflow* long comments into new lines, trying to
/// obey the ``ColumnLimit``.
/// \code
/// false:
/// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
///
/// true:
/// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
/// // information
/// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
/// * information */
/// \endcode
/// \version 3.8
bool ReflowComments;
/// \brief Types of comment reflow style.
enum ReflowCommentsStyle : int8_t {
/// Leave comments untouched.
/// \code
/// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
/// /* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/// * and a misaligned second line */
/// \endcode
RCS_Never,
/// Only apply indentation rules, moving comments left or right, without
/// changing formatting inside the comments.
/// \code
/// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
/// /* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/// * and a misaligned second line */
/// \endcode
RCS_IndentOnly,
/// Apply indentation rules and reflow long comments into new lines, trying
/// to obey the ``ColumnLimit``.
/// \code
/// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
/// // information
/// /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
/// * information */
/// /* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
/// * information and a misaligned second line */
/// \endcode
RCS_Always
};
// clang-format on

/// \brief Comment reformatting style.
/// \version 3.8
ReflowCommentsStyle ReflowComments;

/// Remove optional braces of control statements (``if``, ``else``, ``for``,
/// and ``while``) in C++ according to the LLVM coding style.
/// \warning
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Format/BreakableToken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ BreakableComment::getSplit(unsigned LineIndex, unsigned TailOffset,
unsigned ColumnLimit, unsigned ContentStartColumn,
const llvm::Regex &CommentPragmasRegex) const {
// Don't break lines matching the comment pragmas regex.
if (CommentPragmasRegex.match(Content[LineIndex]))
if (!AlwaysReflow || CommentPragmasRegex.match(Content[LineIndex]))
return Split(StringRef::npos, 0);
return getCommentSplit(Content[LineIndex].substr(TailOffset),
ContentStartColumn, ColumnLimit, Style.TabWidth,
Expand Down Expand Up @@ -608,7 +608,7 @@ BreakableToken::Split BreakableBlockComment::getSplit(
unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const {
// Don't break lines matching the comment pragmas regex.
if (CommentPragmasRegex.match(Content[LineIndex]))
if (!AlwaysReflow || CommentPragmasRegex.match(Content[LineIndex]))
return Split(StringRef::npos, 0);
return getCommentSplit(Content[LineIndex].substr(TailOffset),
ContentStartColumn, ColumnLimit, Style.TabWidth,
Expand Down Expand Up @@ -855,7 +855,8 @@ bool BreakableBlockComment::mayReflow(
StringRef IndentContent = Content[LineIndex];
if (Lines[LineIndex].ltrim(Blanks).starts_with("*"))
IndentContent = Lines[LineIndex].ltrim(Blanks).substr(1);
return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) &&
return LineIndex > 0 && AlwaysReflow &&
!CommentPragmasRegex.match(IndentContent) &&
mayReflowContent(Content[LineIndex]) && !Tok.Finalized &&
!switchesFormatting(tokenAt(LineIndex));
}
Expand Down Expand Up @@ -1160,7 +1161,8 @@ bool BreakableLineCommentSection::mayReflow(
// // text that protrudes
// // into text with different indent
// We do reflow in that case in block comments.
return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) &&
return LineIndex > 0 && AlwaysReflow &&
!CommentPragmasRegex.match(IndentContent) &&
mayReflowContent(Content[LineIndex]) && !Tok.Finalized &&
!switchesFormatting(tokenAt(LineIndex)) &&
OriginalPrefix[LineIndex] == OriginalPrefix[LineIndex - 1];
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Format/BreakableToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@ class BreakableComment : public BreakableToken {
// The intended start column of the first line of text from this section.
unsigned StartColumn;

const bool AlwaysReflow = Style.ReflowComments == FormatStyle::RCS_Always;

// The prefix to use in front a line that has been reflown up.
// For example, when reflowing the second line after the first here:
// // comment 1
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Format/ContinuationIndenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2464,7 +2464,7 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
State.Line->InPPDirective, Encoding, Style);
}
} else if (Current.is(TT_BlockComment)) {
if (!Style.ReflowComments ||
if (Style.ReflowComments == FormatStyle::RCS_Never ||
// If a comment token switches formatting, like
// /* clang-format on */, we don't want to break it further,
// but we may still want to adjust its indentation.
Expand All @@ -2485,7 +2485,7 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
}
return true;
}();
if (!Style.ReflowComments ||
if (Style.ReflowComments == FormatStyle::RCS_Never ||
CommentPragmasRegex.match(Current.TokenText.substr(2)) ||
switchesFormatting(Current) || !RegularComments) {
return nullptr;
Expand Down
13 changes: 12 additions & 1 deletion clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,17 @@ template <> struct MappingTraits<FormatStyle::RawStringFormat> {
}
};

template <> struct ScalarEnumerationTraits<FormatStyle::ReflowCommentsStyle> {
static void enumeration(IO &IO, FormatStyle::ReflowCommentsStyle &Value) {
IO.enumCase(Value, "Never", FormatStyle::RCS_Never);
IO.enumCase(Value, "IndentOnly", FormatStyle::RCS_IndentOnly);
IO.enumCase(Value, "Always", FormatStyle::RCS_Always);
// For backward compatibility:
IO.enumCase(Value, "false", FormatStyle::RCS_Never);
IO.enumCase(Value, "true", FormatStyle::RCS_Always);
}
};

template <>
struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
Expand Down Expand Up @@ -1559,7 +1570,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.PPIndentWidth = -1;
LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
LLVMStyle.ReflowComments = true;
LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
LLVMStyle.RemoveBracesLLVM = false;
LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave;
LLVMStyle.RemoveSemicolon = false;
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4607,9 +4607,9 @@ bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
// section on \p Line.
static bool
continuesLineCommentSection(const FormatToken &FormatTok,
const UnwrappedLine &Line,
const UnwrappedLine &Line, const FormatStyle &Style,
const llvm::Regex &CommentPragmasRegex) {
if (Line.Tokens.empty())
if (Line.Tokens.empty() || Style.ReflowComments != FormatStyle::RCS_Always)
return false;

StringRef IndentContent = FormatTok.TokenText;
Expand Down Expand Up @@ -4722,7 +4722,7 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
// FIXME: Consider putting separate line comment sections as children to the
// unwrapped line instead.
Tok->ContinuesLineCommentSection =
continuesLineCommentSection(*Tok, *Line, CommentPragmasRegex);
continuesLineCommentSection(*Tok, *Line, Style, CommentPragmasRegex);
if (isOnNewLine(*Tok) && JustComments && !Tok->ContinuesLineCommentSection)
addUnwrappedLine();
pushToken(Tok);
Expand Down Expand Up @@ -4795,8 +4795,8 @@ void UnwrappedLineParser::distributeComments(
if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
FormatTok->ContinuesLineCommentSection = false;
} else {
FormatTok->ContinuesLineCommentSection =
continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex);
FormatTok->ContinuesLineCommentSection = continuesLineCommentSection(
*FormatTok, *Line, Style, CommentPragmasRegex);
}
if (!FormatTok->ContinuesLineCommentSection &&
(isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
Expand Down
11 changes: 10 additions & 1 deletion clang/unittests/Format/ConfigParseTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(ObjCSpaceAfterProperty);
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
CHECK_PARSE_BOOL(Cpp11BracedListStyle);
CHECK_PARSE_BOOL(ReflowComments);
CHECK_PARSE_BOOL(RemoveBracesLLVM);
CHECK_PARSE_BOOL(RemoveSemicolon);
CHECK_PARSE_BOOL(SkipMacroDefinitionBody);
Expand Down Expand Up @@ -377,6 +376,16 @@ TEST(ConfigParseTest, ParsesConfiguration) {
CHECK_PARSE("PointerBindsToType: Middle", PointerAlignment,
FormatStyle::PAS_Middle);

Style.ReflowComments = FormatStyle::RCS_Always;
CHECK_PARSE("ReflowComments: Never", ReflowComments, FormatStyle::RCS_Never);
CHECK_PARSE("ReflowComments: IndentOnly", ReflowComments,
FormatStyle::RCS_IndentOnly);
CHECK_PARSE("ReflowComments: Always", ReflowComments,
FormatStyle::RCS_Always);
// For backward compatibility:
CHECK_PARSE("ReflowComments: false", ReflowComments, FormatStyle::RCS_Never);
CHECK_PARSE("ReflowComments: true", ReflowComments, FormatStyle::RCS_Always);

Style.Standard = FormatStyle::LS_Auto;
CHECK_PARSE("Standard: c++03", Standard, FormatStyle::LS_Cpp03);
CHECK_PARSE("Standard: c++11", Standard, FormatStyle::LS_Cpp11);
Expand Down
6 changes: 3 additions & 3 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17991,7 +17991,7 @@ TEST_F(FormatTest, AlignConsecutiveMacros) {

// Test across comments
Style.MaxEmptyLinesToKeep = 10;
Style.ReflowComments = false;
Style.ReflowComments = FormatStyle::RCS_Never;
Style.AlignConsecutiveMacros.AcrossComments = true;
verifyFormat("#define a 3\n"
"// line comment\n"
Expand Down Expand Up @@ -18738,7 +18738,7 @@ TEST_F(FormatTest, AlignConsecutiveAssignmentsAcrossEmptyLinesAndComments) {
"y = 1;",
Alignment);

Alignment.ReflowComments = true;
Alignment.ReflowComments = FormatStyle::RCS_Always;
Alignment.ColumnLimit = 50;
verifyFormat("int x = 0;\n"
"int yy = 1; /// specificlennospace\n"
Expand Down Expand Up @@ -19136,7 +19136,7 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
"y = 1;",
Alignment);

EXPECT_EQ(Alignment.ReflowComments, true);
EXPECT_EQ(Alignment.ReflowComments, FormatStyle::RCS_Always);
Alignment.ColumnLimit = 50;
verifyFormat("int x = 0;\n"
"int yy = 1; /// specificlennospace\n"
Expand Down
29 changes: 28 additions & 1 deletion clang/unittests/Format/FormatTestComments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,9 +493,36 @@ TEST_F(FormatTestComments, AlignsBlockComments) {

TEST_F(FormatTestComments, CommentReflowingCanBeTurnedOff) {
FormatStyle Style = getLLVMStyleWithColumns(20);
Style.ReflowComments = false;
Style.ReflowComments = FormatStyle::RCS_Never;
verifyFormat("// aaaaaaaaa aaaaaaaaaa aaaaaaaaaa", Style);
verifyFormat("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa */", Style);
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n"
"aaaaaaaaa*/",
Style);
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n"
" aaaaaaaaa*/",
Style);
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n"
" * aaaaaaaaa*/",
Style);
}

TEST_F(FormatTestComments, CommentReflowingCanApplyOnlyToIndents) {
FormatStyle Style = getLLVMStyleWithColumns(20);
Style.ReflowComments = FormatStyle::RCS_IndentOnly;
verifyFormat("// aaaaaaaaa aaaaaaaaaa aaaaaaaaaa", Style);
verifyFormat("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa */", Style);
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n"
"aaaaaaaaa*/",
Style);
verifyNoChange("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n"
" aaaaaaaaa*/",
Style);
verifyFormat("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n"
" * aaaaaaaaa*/",
"/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa\n"
" * aaaaaaaaa*/",
Style);
}

TEST_F(FormatTestComments, CorrectlyHandlesLengthOfBlockComments) {
Expand Down