Author: Iuri Chaer Date: 2024-10-11T19:14:09-07:00 New Revision: 0fba8381d2a71ff440fdf0ae30d59a0bf07fea75
URL: https://github.com/llvm/llvm-project/commit/0fba8381d2a71ff440fdf0ae30d59a0bf07fea75 DIFF: https://github.com/llvm/llvm-project/commit/0fba8381d2a71ff440fdf0ae30d59a0bf07fea75.diff LOG: [clang-format] Introduce "ReflowComments: IndentOnly" to re-indent comments without breaking internal structure (think Doxygen). (#96804) * 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`. Added: Modified: clang/docs/ClangFormatStyleOptions.rst clang/docs/ReleaseNotes.rst clang/include/clang/Format/Format.h clang/lib/Format/BreakableToken.cpp clang/lib/Format/BreakableToken.h clang/lib/Format/ContinuationIndenter.cpp clang/lib/Format/Format.cpp clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/ConfigParseTest.cpp clang/unittests/Format/FormatTest.cpp clang/unittests/Format/FormatTestComments.cpp Removed: ################################################################################ diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index a9bfb4c4a0fcb2..8add0a53e5be13 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -5406,22 +5406,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: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 69f02fb0910177..337e3fc10bf49d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -663,6 +663,8 @@ clang-format - Adds ``BreakBinaryOperations`` option. - Adds ``TemplateNames`` option. - Adds ``AlignFunctionDeclarations`` option to ``AlignConsecutiveDeclarations``. +- Adds ``IndentOnly`` suboption to ``ReflowComments`` to fix the indentation of multi-line comments + without touching their contents, renames ``false`` to ``Never``, and ``true`` to ``Always``. libclang -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 3d3e4330902a30..a0762b088b68ef 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -3847,24 +3847,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 diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp index 75304908dc6506..bde77578769906 100644 --- a/clang/lib/Format/BreakableToken.cpp +++ b/clang/lib/Format/BreakableToken.cpp @@ -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, @@ -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, @@ -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)); } @@ -1160,7 +1161,8 @@ bool BreakableLineCommentSection::mayReflow( // // text that protrudes // // into text with diff erent 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]; diff --git a/clang/lib/Format/BreakableToken.h b/clang/lib/Format/BreakableToken.h index 8b9360a3335ef4..45c00b35fd01ed 100644 --- a/clang/lib/Format/BreakableToken.h +++ b/clang/lib/Format/BreakableToken.h @@ -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 diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 4df8dc89be459f..fd53969e4b3b33 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -2471,7 +2471,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. @@ -2492,7 +2492,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; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index f97127f09d2096..148270795c562f 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -527,6 +527,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) { @@ -1569,7 +1580,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; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 9c4a065fd93b96..c9625c39e527b4 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -4623,9 +4623,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; @@ -4738,7 +4738,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); @@ -4811,8 +4811,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)) { diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 9abb8a110bf8ee..318f08c04759b9 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -183,7 +183,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); @@ -381,6 +380,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); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 2c5e5857445c35..43513f18321bc0 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -18108,7 +18108,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" @@ -18855,7 +18855,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" @@ -19253,7 +19253,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" diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp index 4eea14282c3256..5eefd767706a3e 100644 --- a/clang/unittests/Format/FormatTestComments.cpp +++ b/clang/unittests/Format/FormatTestComments.cpp @@ -520,9 +520,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) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits