yusuke-kadowaki updated this revision to Diff 459292.
yusuke-kadowaki marked an inline comment as done.
yusuke-kadowaki added a comment.

Just updated the Style struct field definitions for review. Haven't implemented 
the logics.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132131/new/

https://reviews.llvm.org/D132131

Files:
  clang/docs/ClangFormatStyleOptions.rst
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/lib/Format/WhitespaceManager.cpp
  clang/unittests/Format/FormatTest.cpp
  clang/unittests/Format/FormatTestComments.cpp

Index: clang/unittests/Format/FormatTestComments.cpp
===================================================================
--- clang/unittests/Format/FormatTestComments.cpp
+++ clang/unittests/Format/FormatTestComments.cpp
@@ -2858,6 +2858,182 @@
                "int a; //\n");
 }
 
+TEST_F(FormatTestComments, AlignTrailingCommentsAcrossEmptyLines) {
+  FormatStyle Style = getLLVMStyle();
+  Style.AlignTrailingComments = FormatStyle::TCAS_AlignAcrossEmptyLines;
+  verifyFormat("#include \"a.h\"  // simple\n"
+               "\n"
+               "#include \"aa.h\" // example case\n",
+               Style);
+
+  verifyFormat("#include \"a.h\"   // align across\n"
+               "\n"
+               "#include \"aa.h\"  // two empty lines\n"
+               "\n"
+               "#include \"aaa.h\" // in a row\n",
+               Style);
+
+  verifyFormat("#include \"a.h\"      // align\n"
+               "#include \"aa.h\"     // comment\n"
+               "#include \"aaa.h\"    // blocks\n"
+               "\n"
+               "#include \"aaaa.h\"   // across\n"
+               "#include \"aaaaa.h\"  // one\n"
+               "#include \"aaaaaa.h\" // empty line\n",
+               Style);
+
+  verifyFormat("#include \"a.h\"  // align trailing comments\n"
+               "#include \"a.h\"\n"
+               "#include \"aa.h\" // across a line without comment\n",
+               Style);
+
+  verifyFormat("#include \"a.h\"   // align across\n"
+               "#include \"a.h\"\n"
+               "#include \"aa.h\"  // two lines without comment\n"
+               "#include \"a.h\"\n"
+               "#include \"aaa.h\" // in a row\n",
+               Style);
+
+  verifyFormat("#include \"a.h\"      // align\n"
+               "#include \"aa.h\"     // comment\n"
+               "#include \"aaa.h\"    // blocks\n"
+               "#include \"a.h\"\n"
+               "#include \"aaaa.h\"   // across\n"
+               "#include \"aaaaa.h\"  // a line without\n"
+               "#include \"aaaaaa.h\" // comment\n",
+               Style);
+
+  // Start of testing the combination with MaxEmptyLinesToKeep
+  Style.MaxEmptyLinesToKeep = 0;
+  verifyFormat("#include \"a.h\"  // comment\n"
+               "#include \"aa.h\" // comment\n",
+               Style);
+
+  Style.MaxEmptyLinesToKeep = 1;
+  verifyFormat("#include \"a.h\"  // comment\n"
+               "\n"
+               "#include \"aa.h\" // comment\n",
+               Style);
+
+  Style.MaxEmptyLinesToKeep = 2;
+  verifyFormat("#include \"a.h\"  // comment\n"
+               "\n"
+               "\n"
+               "#include \"aa.h\" // comment\n",
+               Style);
+
+  // Reset the setting
+  Style.MaxEmptyLinesToKeep = 1;
+  // End of testing the combination with MaxEmptyLinesToKeep
+
+  Style.ColumnLimit = 15;
+  EXPECT_EQ("int ab; // line\n"
+            "int a;  // long\n"
+            "        // long\n"
+            "\n"
+            "        // long",
+            format("int ab; // line\n"
+                   "int a; // long long\n"
+                   "\n"
+                   "// long",
+                   Style));
+
+  Style.ColumnLimit = 15;
+  EXPECT_EQ("int ab; // line\n"
+            "\n"
+            "int a;  // long\n"
+            "        // long\n",
+            format("int ab; // line\n"
+                   "\n"
+                   "int a; // long long\n",
+                   Style));
+
+  Style.ColumnLimit = 30;
+  EXPECT_EQ("int foo = 12345; // comment\n"
+            "int bar =\n"
+            "    1234;  // This is a very\n"
+            "           // long comment\n"
+            "           // which is wrapped\n"
+            "           // arround.\n"
+            "\n"
+            "int x = 2; // Is this still\n"
+            "           // aligned?\n",
+            format("int foo = 12345; // comment\n"
+                   "int bar = 1234; // This is a very long comment\n"
+                   "                // which is wrapped arround.\n"
+                   "\n"
+                   "int x = 2; // Is this still aligned?\n",
+                   Style));
+
+  Style.ColumnLimit = 35;
+  EXPECT_EQ("int foo = 12345; // comment\n"
+            "int bar =\n"
+            "    1234; // This is a very long\n"
+            "          // comment which is\n"
+            "          // wrapped arround.\n"
+            "\n"
+            "int x =\n"
+            "    2; // Is this still aligned?\n",
+            format("int foo = 12345; // comment\n"
+                   "int bar = 1234; // This is a very long comment\n"
+                   "                // which is wrapped arround.\n"
+                   "\n"
+                   "int x = 2; // Is this still aligned?\n",
+                   Style));
+
+  Style.ColumnLimit = 40;
+  EXPECT_EQ("int foo = 12345; // comment\n"
+            "int bar =\n"
+            "    1234; // This is a very long comment\n"
+            "          // which is wrapped arround.\n"
+            "\n"
+            "int x = 2; // Is this still aligned?\n",
+            format("int foo = 12345; // comment\n"
+                   "int bar = 1234; // This is a very long comment\n"
+                   "                // which is wrapped arround.\n"
+                   "\n"
+                   "int x = 2; // Is this still aligned?\n",
+                   Style));
+
+  Style.ColumnLimit = 45;
+  EXPECT_EQ("int foo = 12345; // comment\n"
+            "int bar =\n"
+            "    1234;  // This is a very long comment\n"
+            "           // which is wrapped arround.\n"
+            "\n"
+            "int x = 2; // Is this still aligned?\n",
+            format("int foo = 12345; // comment\n"
+                   "int bar = 1234; // This is a very long comment\n"
+                   "                // which is wrapped arround.\n"
+                   "\n"
+                   "int x = 2; // Is this still aligned?\n",
+                   Style));
+
+  Style.ColumnLimit = 80;
+  EXPECT_EQ("int a; // line about a\n"
+            "\n"
+            "// line about b\n"
+            "long b;",
+            format("int a; // line about a\n"
+                   "\n"
+                   "       // line about b\n"
+                   "       long b;",
+                   Style));
+
+  Style.ColumnLimit = 80;
+  EXPECT_EQ("int a; // line about a\n"
+            "\n"
+            "// line 1 about b\n"
+            "// line 2 about b\n"
+            "long b;",
+            format("int a; // line about a\n"
+                   "\n"
+                   "       // line 1 about b\n"
+                   "       // line 2 about b\n"
+                   "       long b;",
+                   Style));
+}
+
 TEST_F(FormatTestComments, AlignsBlockCommentDecorations) {
   EXPECT_EQ("/*\n"
             " */",
Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -20041,7 +20041,6 @@
 TEST_F(FormatTest, ParsesConfigurationBools) {
   FormatStyle Style = {};
   Style.Language = FormatStyle::LK_Cpp;
-  CHECK_PARSE_BOOL(AlignTrailingComments);
   CHECK_PARSE_BOOL(AllowAllArgumentsOnNextLine);
   CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine);
   CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine);
@@ -20365,6 +20364,19 @@
               FormatStyle::OAS_DontAlign);
   CHECK_PARSE("AlignOperands: true", AlignOperands, FormatStyle::OAS_Align);
 
+  Style.AlignTrailingComments = FormatStyle::TCAS_Align;
+  CHECK_PARSE("AlignTrailingComments: DontAlign", AlignTrailingComments,
+              FormatStyle::TCAS_DontAlign);
+  CHECK_PARSE("AlignTrailingComments: Align", AlignTrailingComments,
+              FormatStyle::TCAS_Align);
+  CHECK_PARSE("AlignTrailingComments: AlignAcrossEmptyLines",
+              AlignTrailingComments, FormatStyle::TCAS_AlignAcrossEmptyLines);
+  // For backwards compatibility
+  CHECK_PARSE("AlignTrailingComments: true", AlignTrailingComments,
+              FormatStyle::TCAS_Align);
+  CHECK_PARSE("AlignTrailingComments: false", AlignTrailingComments,
+              FormatStyle::TCAS_DontAlign);
+
   Style.UseTab = FormatStyle::UT_ForIndentation;
   CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never);
   CHECK_PARSE("UseTab: ForIndentation", UseTab, FormatStyle::UT_ForIndentation);
Index: clang/lib/Format/WhitespaceManager.cpp
===================================================================
--- clang/lib/Format/WhitespaceManager.cpp
+++ clang/lib/Format/WhitespaceManager.cpp
@@ -927,6 +927,11 @@
   unsigned StartOfSequence = 0;
   bool BreakBeforeNext = false;
   unsigned Newlines = 0;
+  unsigned int NewLineThreshold = 1;
+  if (Style.AlignTrailingComments == Style.TCAS_AlignAcrossEmptyLines) {
+    NewLineThreshold = Style.MaxEmptyLinesToKeep + 1;
+  }
+
   for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
     if (Changes[i].StartOfBlockComment)
       continue;
@@ -957,7 +962,7 @@
                                   Changes[i - 1].Tok->is(tok::r_brace) &&
                                   Changes[i - 1].StartOfTokenColumn == 0;
     bool WasAlignedWithStartOfNextLine = false;
-    if (Changes[i].NewlinesBefore == 1) { // A comment on its own line.
+    if (Changes[i].NewlinesBefore >= 1) { // A comment on its own line.
       unsigned CommentColumn = SourceMgr.getSpellingColumnNumber(
           Changes[i].OriginalWhitespaceRange.getEnd());
       for (unsigned j = i + 1; j != e; ++j) {
@@ -974,12 +979,13 @@
         break;
       }
     }
-    if (!Style.AlignTrailingComments || FollowsRBraceInColumn0) {
+    if (Style.AlignTrailingComments == FormatStyle::TCAS_DontAlign ||
+        FollowsRBraceInColumn0) {
       alignTrailingComments(StartOfSequence, i, MinColumn);
       MinColumn = ChangeMinColumn;
       MaxColumn = ChangeMinColumn;
       StartOfSequence = i;
-    } else if (BreakBeforeNext || Newlines > 1 ||
+    } else if (BreakBeforeNext || Newlines > NewLineThreshold ||
                (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
                // Break the comment sequence if the previous line did not end
                // in a trailing comment.
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -473,6 +473,21 @@
   }
 };
 
+template <>
+struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
+  static void enumeration(IO &IO,
+                          FormatStyle::TrailingCommentsAlignmentStyle &Value) {
+    IO.enumCase(Value, "DontAlign", FormatStyle::TCAS_DontAlign);
+    IO.enumCase(Value, "Align", FormatStyle::TCAS_Align);
+    IO.enumCase(Value, "AlignAcrossEmptyLines",
+                FormatStyle::TCAS_AlignAcrossEmptyLines);
+
+    // For backward compatibility.
+    IO.enumCase(Value, "true", FormatStyle::TCAS_Align);
+    IO.enumCase(Value, "false", FormatStyle::TCAS_DontAlign);
+  }
+};
+
 template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
   static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
     IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
@@ -1181,7 +1196,6 @@
   LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
   LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
   LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
-  LLVMStyle.AlignTrailingComments = true;
   LLVMStyle.AlignConsecutiveAssignments = {};
   LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
   LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
@@ -1191,6 +1205,7 @@
   LLVMStyle.AlignConsecutiveBitFields = {};
   LLVMStyle.AlignConsecutiveDeclarations = {};
   LLVMStyle.AlignConsecutiveMacros = {};
+  LLVMStyle.AlignTrailingComments = FormatStyle::TCAS_Align;
   LLVMStyle.AllowAllArgumentsOnNextLine = true;
   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
   LLVMStyle.AllowShortEnumsOnASingleLine = true;
@@ -1447,7 +1462,7 @@
   if (Language == FormatStyle::LK_Java) {
     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
-    GoogleStyle.AlignTrailingComments = false;
+    GoogleStyle.AlignTrailingComments = FormatStyle::TCAS_DontAlign;
     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
@@ -1595,7 +1610,7 @@
   Style.AccessModifierOffset = -4;
   Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
   Style.AlignOperands = FormatStyle::OAS_DontAlign;
-  Style.AlignTrailingComments = false;
+  Style.AlignTrailingComments = FormatStyle::TCAS_DontAlign;
   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
   Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -369,14 +369,83 @@
   /// \version 3.5
   OperandAlignmentStyle AlignOperands;
 
+  /// Different options for aligning trailing comments.
+  enum TrailingCommentsAlignmentKinds : int8_t {
+    /// Leave trailing comments as they are.
+    /// \code
+    ///   int a;    // comment
+    ///   int ab;       // comment
+    ///
+    ///   int abc;  // comment
+    ///   int abcd;     // comment
+    /// \endcode
+    TCAS_Leave,
+    /// Align trailing comments.
+    /// \code
+    ///   int a;  // comment
+    ///   int ab; // comment
+    ///
+    ///   int abc;  // comment
+    ///   int abcd; // comment
+    /// \endcode
+    TCAS_Always,
+    /// Don't align trailing comments but other formatter applies.
+    /// \code
+    ///   int a; // comment
+    ///   int ab; // comment
+    ///
+    ///   int abc; // comment
+    ///   int abcd; // comment
+    /// \endcode
+    TCAS_Never,
+  };
+
+  /// If specified, aligns trailing comments.
+  struct TrailingCommentsAlignmentStyle {
+    /// Specifies the way to align trailing comments
+    TrailingCommentsAlignmentKinds Kind;
+    /// How many empty lines to apply alignment
+    /// With ``MaxEmptyLinesToKeep`` is 2 and ``OverEmptyLines`` is 2,
+    /// \code
+    ///   int a;      // all these
+    ///
+    ///   int ab;     // comments are
+    ///
+    ///
+    ///   int abcdef; // aligned
+    /// \endcode
+    /// And with ``MaxEmptyLinesToKeep`` is 2 and ``OverEmptyLines`` is 1,
+    /// \code
+    ///   int a;  // these are
+    ///
+    ///   int ab; // aligned
+    ///
+    ///
+    ///   int abcdef; // but this isn't
+    /// \endcode
+    unsigned OverEmptyLines;
+
+    bool operator==(const TrailingCommentsAlignmentStyle &R) const {
+      return Kind == R.Kind && OverEmptyLines == R.OverEmptyLines;
+    }
+    bool operator!=(const TrailingCommentsAlignmentStyle &R) const {
+      return !(*this == R);
+    }
+  };
+
   /// If ``true``, aligns trailing comments.
+  ///
+  /// NOTE: As of clang-format 16 this option is not a bool but can be set
+  /// to the following enum values. Still ``true`` is parsed to ``Align`` and
+  /// ``false`` is parsed to ``DontAlign``.
+  ///
   /// \code
   ///   true:                                   false:
   ///   int a;     // My comment a      vs.     int a; // My comment a
   ///   int b = 2; // comment  b                int b = 2; // comment about b
   /// \endcode
   /// \version 3.7
-  bool AlignTrailingComments;
+  TrailingCommentsAlignmentStyle AlignTrailingComments;
 
   /// \brief If a function call or braced initializer list doesn't fit on a
   /// line, allow putting all arguments onto the next line, even if
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -846,15 +846,86 @@
 
 
 
-**AlignTrailingComments** (``Boolean``) :versionbadge:`clang-format 3.7`
+**AlignTrailingComments** (``TrailingCommentsAlignmentStyle``) :versionbadge:`clang-format 3.7`
   If ``true``, aligns trailing comments.
 
+  NOTE: As of clang-format 16 this option is not a bool but can be set
+  to the following enum values. Still ``true`` is parsed to ``Align`` and
+  ``false`` is parsed to ``DontAlign``.
+
+
   .. code-block:: c++
 
     true:                                   false:
     int a;     // My comment a      vs.     int a; // My comment a
     int b = 2; // comment  b                int b = 2; // comment about b
 
+  Nested configuration flags:
+
+  If specified, aligns trailing comments.
+
+  * ``TrailingCommentsAlignmentKinds Kind``
+    Specifies the way to align trailing comments
+
+    Possible values:
+
+    * ``TCAS_Leave`` (in configuration: ``Leave``)
+      Leave trailing comments as they are.
+
+      .. code-block:: c++
+
+        int a;    // comment
+        int ab;       // comment
+
+        int abc;  // comment
+        int abcd;     // comment
+
+    * ``TCAS_Always`` (in configuration: ``Always``)
+      Align trailing comments.
+
+      .. code-block:: c++
+
+        int a;  // comment
+        int ab; // comment
+
+        int abc;  // comment
+        int abcd; // comment
+
+    * ``TCAS_Never`` (in configuration: ``Never``)
+      Don't align trailing comments but other formatter applies.
+
+      .. code-block:: c++
+
+        int a; // comment
+        int ab; // comment
+
+        int abc; // comment
+        int abcd; // comment
+
+
+  * ``unsigned OverEmptyLines`` How many empty lines to apply alignment
+    With ``MaxEmptyLinesToKeep`` is 2 and ``OverEmptyLines`` is 2,
+
+    .. code-block:: c++
+
+      int a;      // all these
+
+      int ab;     // comments are
+
+
+      int abcdef; // aligned
+    And with ``MaxEmptyLinesToKeep`` is 2 and ``OverEmptyLines`` is 1,
+
+    .. code-block:: c++
+
+      int a;  // these are
+
+      int ab; // aligned
+
+
+      int abcdef; // but this isn't
+
+
 **AllowAllArgumentsOnNextLine** (``Boolean``) :versionbadge:`clang-format 9`
   If a function call or braced initializer list doesn't fit on a
   line, allow putting all arguments onto the next line, even if
@@ -3567,7 +3638,7 @@
 
     .. code-block:: yaml
 
-      QualifierOrder: ['inline', 'static', 'type', 'const']
+      QualifierOrder: ['inline', 'static' , 'type', 'const']
 
 
     .. code-block:: c++
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to