[clang] 772eb24 - [clang-format] Add option to control the spaces in a line comment

Björn Schäpers via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 1 13:49:04 PST 2021


Author: Björn Schäpers
Date: 2021-02-01T22:48:50+01:00
New Revision: 772eb24e00629faaae0244aa0d6d6204542c579b

URL: https://github.com/llvm/llvm-project/commit/772eb24e00629faaae0244aa0d6d6204542c579b
DIFF: https://github.com/llvm/llvm-project/commit/772eb24e00629faaae0244aa0d6d6204542c579b.diff

LOG: [clang-format] Add option to control the spaces in a line comment

Differential Revision: https://reviews.llvm.org/D92257

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/Format.cpp
    clang/lib/Format/NamespaceEndCommentsFixer.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 3458575119e2..a28efa5dad04 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -3335,6 +3335,43 @@ the configuration (without a prefix: ``Auto``).
      var arr = [ 1, 2, 3 ];         vs.     var arr = [1, 2, 3];
      f({a : 1, b : 2, c : 3});              f({a: 1, b: 2, c: 3});
 
+**SpacesInLineCommentPrefix** (``SpacesInLineComment``)
+  How many spaces are allowed at the start of a line comment. To disable the
+  maximum set it to ``-1``, apart from that the maximum takes precedence
+  over the minimum.
+  Minimum = 1 Maximum = -1
+  // One space is forced
+
+  //  but more spaces are possible
+
+  Minimum = 0
+  Maximum = 0
+  //Forces to start every comment directly after the slashes
+
+  Note that in line comment sections the relative indent of the subsequent
+  lines is kept, that means the following:
+
+  .. code-block:: c++
+
+  before:                                   after:
+  Minimum: 1
+  //if (b) {                                // if (b) {
+  //  return true;                          //   return true;
+  //}                                       // }
+
+  Maximum: 0
+  /// List:                                 ///List:
+  ///  - Foo                                /// - Foo
+  ///    - Bar                              ///   - Bar
+
+  Nested configuration flags:
+
+
+  * ``unsigned Minimum`` The minimum number of spaces at the start of the comment.
+
+  * ``unsigned Maximum`` The maximum number of spaces at the start of the comment.
+
+
 **SpacesInParentheses** (``bool``)
   If ``true``, spaces will be inserted after ``(`` and before ``)``.
 

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 454355af4c41..6c5c993f98b1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -156,8 +156,8 @@ AST Matchers
 clang-format
 ------------
 
-- ...
-
+- Option ``SpacesInLineCommentPrefix`` has been added to control the
+  number of spaces in a line comments prefix.
 
 libclang
 --------

diff  --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 96c2a74e97db..269707fedaac 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2894,6 +2894,43 @@ struct FormatStyle {
   /// \endcode
   bool SpacesInCStyleCastParentheses;
 
+  /// Control of spaces within a single line comment
+  struct SpacesInLineComment {
+    /// The minimum number of spaces at the start of the comment.
+    unsigned Minimum;
+    /// The maximum number of spaces at the start of the comment.
+    unsigned Maximum;
+  };
+
+  /// How many spaces are allowed at the start of a line comment. To disable the
+  /// maximum set it to ``-1``, apart from that the maximum takes precedence
+  /// over the minimum.
+  /// \code Minimum = 1 Maximum = -1
+  /// // One space is forced
+  ///
+  /// //  but more spaces are possible
+  ///
+  /// Minimum = 0
+  /// Maximum = 0
+  /// //Forces to start every comment directly after the slashes
+  /// \endcode
+  ///
+  /// Note that in line comment sections the relative indent of the subsequent
+  /// lines is kept, that means the following:
+  /// \code
+  /// before:                                   after:
+  /// Minimum: 1
+  /// //if (b) {                                // if (b) {
+  /// //  return true;                          //   return true;
+  /// //}                                       // }
+  ///
+  /// Maximum: 0
+  /// /// List:                                 ///List:
+  /// ///  - Foo                                /// - Foo
+  /// ///    - Bar                              ///   - Bar
+  /// \endcode
+  SpacesInLineComment SpacesInLineCommentPrefix;
+
   /// If ``true``, spaces will be inserted after ``(`` and before ``)``.
   /// \code
   ///    true:                                  false:
@@ -3145,6 +3182,10 @@ struct FormatStyle {
            SpacesInConditionalStatement == R.SpacesInConditionalStatement &&
            SpacesInContainerLiterals == R.SpacesInContainerLiterals &&
            SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses &&
+           SpacesInLineCommentPrefix.Minimum ==
+               R.SpacesInLineCommentPrefix.Minimum &&
+           SpacesInLineCommentPrefix.Maximum ==
+               R.SpacesInLineCommentPrefix.Maximum &&
            SpacesInParentheses == R.SpacesInParentheses &&
            SpacesInSquareBrackets == R.SpacesInSquareBrackets &&
            SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets &&

diff  --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp
index f179ac64de17..4ac97ee2e45a 100644
--- a/clang/lib/Format/BreakableToken.cpp
+++ b/clang/lib/Format/BreakableToken.cpp
@@ -757,6 +757,9 @@ BreakableLineCommentSection::BreakableLineCommentSection(
   assert(Tok.is(TT_LineComment) &&
          "line comment section must start with a line comment");
   FormatToken *LineTok = nullptr;
+  // How many spaces we changed in the first line of the section, this will be
+  // applied in all following lines
+  int FirstLineSpaceChange = 0;
   for (const FormatToken *CurrentTok = &Tok;
        CurrentTok && CurrentTok->is(TT_LineComment);
        CurrentTok = CurrentTok->Next) {
@@ -768,44 +771,72 @@ BreakableLineCommentSection::BreakableLineCommentSection(
     TokenText.split(Lines, "\n");
     Content.resize(Lines.size());
     ContentColumn.resize(Lines.size());
-    OriginalContentColumn.resize(Lines.size());
+    PrefixSpaceChange.resize(Lines.size());
     Tokens.resize(Lines.size());
     Prefix.resize(Lines.size());
     OriginalPrefix.resize(Lines.size());
     for (size_t i = FirstLineIndex, e = Lines.size(); i < e; ++i) {
       Lines[i] = Lines[i].ltrim(Blanks);
       StringRef IndentPrefix = getLineCommentIndentPrefix(Lines[i], Style);
-      assert((TokenText.startswith("//") || TokenText.startswith("#")) &&
-             "unsupported line comment prefix, '//' and '#' are supported");
-      OriginalPrefix[i] = Prefix[i] = IndentPrefix;
-      if (Lines[i].size() > Prefix[i].size() &&
-          isAlphanumeric(Lines[i][Prefix[i].size()])) {
-        if (Prefix[i] == "//")
-          Prefix[i] = "// ";
-        else if (Prefix[i] == "///")
-          Prefix[i] = "/// ";
-        else if (Prefix[i] == "//!")
-          Prefix[i] = "//! ";
-        else if (Prefix[i] == "///<")
-          Prefix[i] = "///< ";
-        else if (Prefix[i] == "//!<")
-          Prefix[i] = "//!< ";
-        else if (Prefix[i] == "#")
-          Prefix[i] = "# ";
-        else if (Prefix[i] == "##")
-          Prefix[i] = "## ";
-        else if (Prefix[i] == "###")
-          Prefix[i] = "### ";
-        else if (Prefix[i] == "####")
-          Prefix[i] = "#### ";
+      OriginalPrefix[i] = IndentPrefix;
+      const unsigned SpacesInPrefix =
+          std::count(IndentPrefix.begin(), IndentPrefix.end(), ' ');
+
+      // On the first line of the comment section we calculate how many spaces
+      // are to be added or removed, all lines after that just get only the
+      // change and we will not look at the maximum anymore. Additionally to the
+      // actual first line, we calculate that when the non space Prefix changes,
+      // e.g. from "///" to "//".
+      if (i == 0 || OriginalPrefix[i].rtrim(Blanks) !=
+                        OriginalPrefix[i - 1].rtrim(Blanks)) {
+        if (SpacesInPrefix < Style.SpacesInLineCommentPrefix.Minimum &&
+            Lines[i].size() > IndentPrefix.size() &&
+            isAlphanumeric(Lines[i][IndentPrefix.size()])) {
+          FirstLineSpaceChange =
+              Style.SpacesInLineCommentPrefix.Minimum - SpacesInPrefix;
+        } else if (SpacesInPrefix > Style.SpacesInLineCommentPrefix.Maximum) {
+          FirstLineSpaceChange =
+              Style.SpacesInLineCommentPrefix.Maximum - SpacesInPrefix;
+        } else {
+          FirstLineSpaceChange = 0;
+        }
+      }
+
+      if (Lines[i].size() != IndentPrefix.size()) {
+        PrefixSpaceChange[i] = FirstLineSpaceChange;
+
+        if (SpacesInPrefix + PrefixSpaceChange[i] <
+            Style.SpacesInLineCommentPrefix.Minimum) {
+          PrefixSpaceChange[i] += Style.SpacesInLineCommentPrefix.Minimum -
+                                  (SpacesInPrefix + PrefixSpaceChange[i]);
+        }
+
+        assert(Lines[i].size() > IndentPrefix.size());
+        const auto FirstNonSpace = Lines[i][IndentPrefix.size()];
+        const auto AllowsSpaceChange =
+            SpacesInPrefix != 0 ||
+            (isAlphanumeric(FirstNonSpace) ||
+             (FirstNonSpace == '}' && FirstLineSpaceChange != 0));
+
+        if (PrefixSpaceChange[i] > 0 && AllowsSpaceChange) {
+          Prefix[i] = IndentPrefix.str();
+          Prefix[i].append(PrefixSpaceChange[i], ' ');
+        } else if (PrefixSpaceChange[i] < 0 && AllowsSpaceChange) {
+          Prefix[i] = IndentPrefix
+                          .drop_back(std::min<std::size_t>(
+                              -PrefixSpaceChange[i], SpacesInPrefix))
+                          .str();
+        } else {
+          Prefix[i] = IndentPrefix.str();
+        }
+      } else {
+        // If the IndentPrefix is the whole line, there is no content and we
+        // drop just all space
+        Prefix[i] = IndentPrefix.drop_back(SpacesInPrefix).str();
       }
 
       Tokens[i] = LineTok;
       Content[i] = Lines[i].substr(IndentPrefix.size());
-      OriginalContentColumn[i] =
-          StartColumn + encoding::columnWidthWithTabs(OriginalPrefix[i],
-                                                      StartColumn,
-                                                      Style.TabWidth, Encoding);
       ContentColumn[i] =
           StartColumn + encoding::columnWidthWithTabs(Prefix[i], StartColumn,
                                                       Style.TabWidth, Encoding);
@@ -848,10 +879,9 @@ BreakableLineCommentSection::getRangeLength(unsigned LineIndex, unsigned Offset,
       Encoding);
 }
 
-unsigned BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,
-                                                            bool Break) const {
-  if (Break)
-    return OriginalContentColumn[LineIndex];
+unsigned
+BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,
+                                                   bool /*Break*/) const {
   return ContentColumn[LineIndex];
 }
 
@@ -864,16 +894,10 @@ void BreakableLineCommentSection::insertBreak(
   unsigned BreakOffsetInToken =
       Text.data() - tokenAt(LineIndex).TokenText.data() + Split.first;
   unsigned CharsToRemove = Split.second;
-  // Compute the size of the new indent, including the size of the new prefix of
-  // the newly broken line.
-  unsigned IndentAtLineBreak = OriginalContentColumn[LineIndex] +
-                               Prefix[LineIndex].size() -
-                               OriginalPrefix[LineIndex].size();
-  assert(IndentAtLineBreak >= Prefix[LineIndex].size());
   Whitespaces.replaceWhitespaceInToken(
       tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "",
       Prefix[LineIndex], InPPDirective, /*Newlines=*/1,
-      /*Spaces=*/IndentAtLineBreak - Prefix[LineIndex].size());
+      /*Spaces=*/ContentColumn[LineIndex] - Prefix[LineIndex].size());
 }
 
 BreakableComment::Split BreakableLineCommentSection::getReflowSplit(
@@ -971,14 +995,12 @@ void BreakableLineCommentSection::adaptStartOfLine(
   }
   if (OriginalPrefix[LineIndex] != Prefix[LineIndex]) {
     // Adjust the prefix if necessary.
-
-    // Take care of the space possibly introduced after a decoration.
-    assert(Prefix[LineIndex] == (OriginalPrefix[LineIndex] + " ").str() &&
-           "Expecting a line comment prefix to 
diff er from original by at most "
-           "a space");
+    const auto SpacesToRemove = -std::min(PrefixSpaceChange[LineIndex], 0);
+    const auto SpacesToAdd = std::max(PrefixSpaceChange[LineIndex], 0);
     Whitespaces.replaceWhitespaceInToken(
-        tokenAt(LineIndex), OriginalPrefix[LineIndex].size(), 0, "", "",
-        /*InPPDirective=*/false, /*Newlines=*/0, /*Spaces=*/1);
+        tokenAt(LineIndex), OriginalPrefix[LineIndex].size() - SpacesToRemove,
+        /*ReplaceChars=*/SpacesToRemove, "", "", -/*InPPDirective=*/false,
+        /*Newlines=*/0, /*Spaces=*/SpacesToAdd);
   }
 }
 

diff  --git a/clang/lib/Format/BreakableToken.h b/clang/lib/Format/BreakableToken.h
index 41b19f82e9df..190144ad1be9 100644
--- a/clang/lib/Format/BreakableToken.h
+++ b/clang/lib/Format/BreakableToken.h
@@ -465,15 +465,23 @@ class BreakableLineCommentSection : public BreakableComment {
   // then the original prefix is "// ".
   SmallVector<StringRef, 16> OriginalPrefix;
 
-  // Prefix[i] contains the intended leading "//" with trailing spaces to
-  // account for the indentation of content within the comment at line i after
-  // formatting. It can be 
diff erent than the original prefix when the original
-  // line starts like this:
-  // //content
-  // Then the original prefix is "//", but the prefix is "// ".
-  SmallVector<StringRef, 16> Prefix;
-
-  SmallVector<unsigned, 16> OriginalContentColumn;
+  /// Prefix[i] + SpacesToAdd[i] contains the intended leading "//" with
+  /// trailing spaces to account for the indentation of content within the
+  /// comment at line i after formatting. It can be 
diff erent than the original
+  /// prefix.
+  /// When the original line starts like this:
+  /// //content
+  /// Then the OriginalPrefix[i] is "//", but the Prefix[i] is "// " in the LLVM
+  /// style.
+  /// When the line starts like:
+  /// // content
+  /// And we want to remove the spaces the OriginalPrefix[i] is "// " and
+  /// Prefix[i] is "//".
+  SmallVector<std::string, 16> Prefix;
+
+  /// How many spaces are added or removed from the OriginalPrefix to form
+  /// Prefix.
+  SmallVector<int, 16> PrefixSpaceChange;
 
   /// The token to which the last line of this breakable token belongs
   /// to; nullptr if that token is the initial token.

diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 5f5bb8585ac1..16a42f2d97c4 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -661,6 +661,8 @@ template <> struct MappingTraits<FormatStyle> {
                    Style.SpacesInContainerLiterals);
     IO.mapOptional("SpacesInCStyleCastParentheses",
                    Style.SpacesInCStyleCastParentheses);
+    IO.mapOptional("SpacesInLineCommentPrefix",
+                   Style.SpacesInLineCommentPrefix);
     IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
     IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
     IO.mapOptional("SpaceBeforeSquareBrackets",
@@ -710,6 +712,20 @@ template <> struct MappingTraits<FormatStyle::RawStringFormat> {
   }
 };
 
+template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
+  static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
+    // Transform the maximum to signed, to parse "-1" correctly
+    int signedMaximum = static_cast<int>(Space.Maximum);
+    IO.mapOptional("Minimum", Space.Minimum);
+    IO.mapOptional("Maximum", signedMaximum);
+    Space.Maximum = static_cast<unsigned>(signedMaximum);
+
+    if (Space.Maximum != -1u) {
+      Space.Minimum = std::min(Space.Minimum, Space.Maximum);
+    }
+  }
+};
+
 // Allows to read vector<FormatStyle> while keeping default values.
 // IO.getContext() should contain a pointer to the FormatStyle structure, that
 // will be used to get default values for missing keys.
@@ -986,6 +1002,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
   LLVMStyle.SpaceInEmptyParentheses = false;
   LLVMStyle.SpacesInContainerLiterals = true;
   LLVMStyle.SpacesInCStyleCastParentheses = false;
+  LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
   LLVMStyle.SpaceAfterCStyleCast = false;
   LLVMStyle.SpaceAfterLogicalNot = false;
   LLVMStyle.SpaceAfterTemplateKeyword = true;

diff  --git a/clang/lib/Format/NamespaceEndCommentsFixer.cpp b/clang/lib/Format/NamespaceEndCommentsFixer.cpp
index 97de45bd1965..c5bb6e9eab5d 100644
--- a/clang/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/clang/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -66,8 +66,10 @@ std::string computeName(const FormatToken *NamespaceTok) {
 }
 
 std::string computeEndCommentText(StringRef NamespaceName, bool AddNewline,
-                                  const FormatToken *NamespaceTok) {
-  std::string text = "// ";
+                                  const FormatToken *NamespaceTok,
+                                  unsigned SpacesToAdd) {
+  std::string text = "//";
+  text.append(SpacesToAdd, ' ');
   text += NamespaceTok->TokenText;
   if (NamespaceTok->is(TT_NamespaceMacro))
     text += "(";
@@ -278,7 +280,8 @@ std::pair<tooling::Replacements, unsigned> NamespaceEndCommentsFixer::analyze(
                       EndCommentNextTok->NewlinesBefore == 0 &&
                       EndCommentNextTok->isNot(tok::eof);
     const std::string EndCommentText =
-        computeEndCommentText(NamespaceName, AddNewline, NamespaceTok);
+        computeEndCommentText(NamespaceName, AddNewline, NamespaceTok,
+                              Style.SpacesInLineCommentPrefix.Minimum);
     if (!hasEndComment(EndCommentPrevTok)) {
       bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1;
       if (!isShort)

diff  --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index c1f88b9ae17a..1090f0ca8ee2 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -15994,6 +15994,26 @@ TEST_F(FormatTest, ParsesConfiguration) {
               "      - 'CPPEVAL'\n"
               "    CanonicalDelimiter: 'cc'",
               RawStringFormats, ExpectedRawStringFormats);
+
+  CHECK_PARSE("SpacesInLineCommentPrefix:\n"
+              "  Minimum: 0\n"
+              "  Maximum: 0",
+              SpacesInLineCommentPrefix.Minimum, 0u);
+  EXPECT_EQ(Style.SpacesInLineCommentPrefix.Maximum, 0u);
+  Style.SpacesInLineCommentPrefix.Minimum = 1;
+  CHECK_PARSE("SpacesInLineCommentPrefix:\n"
+              "  Minimum: 2",
+              SpacesInLineCommentPrefix.Minimum, 0u);
+  CHECK_PARSE("SpacesInLineCommentPrefix:\n"
+              "  Maximum: -1",
+              SpacesInLineCommentPrefix.Maximum, -1u);
+  CHECK_PARSE("SpacesInLineCommentPrefix:\n"
+              "  Minimum: 2",
+              SpacesInLineCommentPrefix.Minimum, 2u);
+  CHECK_PARSE("SpacesInLineCommentPrefix:\n"
+              "  Maximum: 1",
+              SpacesInLineCommentPrefix.Maximum, 1u);
+  EXPECT_EQ(Style.SpacesInLineCommentPrefix.Minimum, 1u);
 }
 
 TEST_F(FormatTest, ParsesConfigurationWithLanguages) {

diff  --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
index 457e7321ec75..108028e396a1 100644
--- a/clang/unittests/Format/FormatTestComments.cpp
+++ b/clang/unittests/Format/FormatTestComments.cpp
@@ -3144,7 +3144,7 @@ TEST_F(FormatTestComments, PythonStyleComments) {
             "      # commen6\n"
             "      # commen7",
             format("k:val#commen1 commen2\n"
-                   " # commen3\n"
+                   " #commen3\n"
                    "# commen4\n"
                    "a:1#commen5 commen6\n"
                    " #commen7",
@@ -3275,6 +3275,526 @@ TEST_F(FormatTestComments, IndentsLongJavadocAnnotatedLines) {
                    JSStyle20));
 }
 
+TEST_F(FormatTestComments, SpaceAtLineCommentBegin) {
+  FormatStyle Style = getLLVMStyle();
+  StringRef NoTextInComment = " //       \n"
+                              "\n"
+                              "void foo() {// \n"
+                              "// \n"
+                              "}";
+
+  EXPECT_EQ("//\n"
+            "\n"
+            "void foo() { //\n"
+            "  //\n"
+            "}",
+            format(NoTextInComment, Style));
+
+  Style.SpacesInLineCommentPrefix.Minimum = 0;
+  EXPECT_EQ("//\n"
+            "\n"
+            "void foo() { //\n"
+            "  //\n"
+            "}",
+            format(NoTextInComment, Style));
+
+  Style.SpacesInLineCommentPrefix.Minimum = 5;
+  EXPECT_EQ("//\n"
+            "\n"
+            "void foo() { //\n"
+            "  //\n"
+            "}",
+            format(NoTextInComment, Style));
+
+  Style = getLLVMStyle();
+  StringRef Code =
+      "//Free comment without space\n"
+      "\n"
+      "//   Free comment with 3 spaces\n"
+      "\n"
+      "///Free Doxygen without space\n"
+      "\n"
+      "///   Free Doxygen with 3 spaces\n"
+      "\n"
+      "/// A Doxygen Comment with a nested list:\n"
+      "/// - Foo\n"
+      "/// - Bar\n"
+      "///   - Baz\n"
+      "///   - End\n"
+      "///     of the inner list\n"
+      "///   .\n"
+      "/// .\n"
+      "\n"
+      "namespace Foo {\n"
+      "bool bar(bool b) {\n"
+      "  bool ret1 = true; ///<Doxygenstyle without space\n"
+      "  bool ret2 = true; ///<   Doxygenstyle with 3 spaces\n"
+      "  if (b) {\n"
+      "    //Foo\n"
+      "\n"
+      "    //   In function comment\n"
+      "    ret2 = false;\n"
+      "  } // End of if\n"
+      "\n"
+      "//  if (ret1) {\n" // Commented out at the beginning of the line
+      "//    return ret2;\n"
+      "//  }\n"
+      "\n"
+      "  //if (ret1) {\n" // Commtented out at the beginning of the content
+      "  //  return ret2;\n"
+      "  //}\n"
+      "\n"
+      "  return ret1 && ret2;\n"
+      "}\n"
+      "}\n"
+      "\n"
+      "namespace Bar {\n"
+      "int foo();\n"
+      "} //  namespace Bar\n"
+      "//@Nothing added because of the non ascii char\n"
+      "\n"
+      "//@      Nothing removed because of the non ascii char\n"
+      "\n"
+      "//  Comment to move to the left\n"
+      "//But not this?\n"
+      "//  @but this\n"
+      "\n"
+      "//Comment to move to the right\n"
+      "//@ this stays\n"
+      "\n"
+      "//} will not move\n"
+      "\n"
+      "//vv will only move\n"
+      "//} if the line above does\n";
+
+  EXPECT_EQ("// Free comment without space\n"
+            "\n"
+            "//   Free comment with 3 spaces\n"
+            "\n"
+            "/// Free Doxygen without space\n"
+            "\n"
+            "///   Free Doxygen with 3 spaces\n"
+            "\n"
+            "/// A Doxygen Comment with a nested list:\n"
+            "/// - Foo\n"
+            "/// - Bar\n"
+            "///   - Baz\n"
+            "///   - End\n"
+            "///     of the inner list\n"
+            "///   .\n"
+            "/// .\n"
+            "\n"
+            "namespace Foo {\n"
+            "bool bar(bool b) {\n"
+            "  bool ret1 = true; ///< Doxygenstyle without space\n"
+            "  bool ret2 = true; ///<   Doxygenstyle with 3 spaces\n"
+            "  if (b) {\n"
+            "    // Foo\n"
+            "\n"
+            "    //   In function comment\n"
+            "    ret2 = false;\n"
+            "  } // End of if\n"
+            "\n"
+            "  //  if (ret1) {\n"
+            "  //    return ret2;\n"
+            "  //  }\n"
+            "\n"
+            "  // if (ret1) {\n"
+            "  //   return ret2;\n"
+            "  // }\n"
+            "\n"
+            "  return ret1 && ret2;\n"
+            "}\n"
+            "} // namespace Foo\n"
+            "\n"
+            "namespace Bar {\n"
+            "int foo();\n"
+            "} //  namespace Bar\n"
+            "//@Nothing added because of the non ascii char\n"
+            "\n"
+            "//@      Nothing removed because of the non ascii char\n"
+            "\n"
+            "//  Comment to move to the left\n"
+            "// But not this?\n"
+            "//  @but this\n"
+            "\n"
+            "// Comment to move to the right\n"
+            "//@ this stays\n"
+            "\n"
+            "//} will not move\n"
+            "\n"
+            "// vv will only move\n"
+            "// } if the line above does\n",
+            format(Code, Style));
+
+  Style.SpacesInLineCommentPrefix = {0, 0};
+  EXPECT_EQ("//Free comment without space\n"
+            "\n"
+            "//Free comment with 3 spaces\n"
+            "\n"
+            "///Free Doxygen without space\n"
+            "\n"
+            "///Free Doxygen with 3 spaces\n"
+            "\n"
+            "///A Doxygen Comment with a nested list:\n"
+            "///- Foo\n"
+            "///- Bar\n"
+            "///  - Baz\n" // Here we keep the relative indentation
+            "///  - End\n"
+            "///    of the inner list\n"
+            "///  .\n"
+            "///.\n"
+            "\n"
+            "namespace Foo {\n"
+            "bool bar(bool b) {\n"
+            "  bool ret1 = true; ///<Doxygenstyle without space\n"
+            "  bool ret2 = true; ///<Doxygenstyle with 3 spaces\n"
+            "  if (b) {\n"
+            "    //Foo\n"
+            "\n"
+            "    //In function comment\n"
+            "    ret2 = false;\n"
+            "  } //End of if\n"
+            "\n"
+            "  //if (ret1) {\n"
+            "  //  return ret2;\n"
+            "  //}\n"
+            "\n"
+            "  //if (ret1) {\n"
+            "  //  return ret2;\n"
+            "  //}\n"
+            "\n"
+            "  return ret1 && ret2;\n"
+            "}\n"
+            "} //namespace Foo\n"
+            "\n"
+            "namespace Bar {\n"
+            "int foo();\n"
+            "} //namespace Bar\n"
+            "//@Nothing added because of the non ascii char\n"
+            "\n"
+            "//@      Nothing removed because of the non ascii char\n"
+            "\n"
+            "//Comment to move to the left\n"
+            "//But not this?\n"
+            "//@but this\n"
+            "\n"
+            "//Comment to move to the right\n"
+            "//@ this stays\n"
+            "\n"
+            "//} will not move\n"
+            "\n"
+            "//vv will only move\n"
+            "//} if the line above does\n",
+            format(Code, Style));
+
+  Style.SpacesInLineCommentPrefix = {2, -1u};
+  EXPECT_EQ("//  Free comment without space\n"
+            "\n"
+            "//   Free comment with 3 spaces\n"
+            "\n"
+            "///  Free Doxygen without space\n"
+            "\n"
+            "///   Free Doxygen with 3 spaces\n"
+            "\n"
+            "///  A Doxygen Comment with a nested list:\n"
+            "///  - Foo\n"
+            "///  - Bar\n"
+            "///    - Baz\n"
+            "///    - End\n"
+            "///      of the inner list\n"
+            "///    .\n"
+            "///  .\n"
+            "\n"
+            "namespace Foo {\n"
+            "bool bar(bool b) {\n"
+            "  bool ret1 = true; ///<  Doxygenstyle without space\n"
+            "  bool ret2 = true; ///<   Doxygenstyle with 3 spaces\n"
+            "  if (b) {\n"
+            "    //  Foo\n"
+            "\n"
+            "    //   In function comment\n"
+            "    ret2 = false;\n"
+            "  } //  End of if\n"
+            "\n"
+            "  //  if (ret1) {\n"
+            "  //    return ret2;\n"
+            "  //  }\n"
+            "\n"
+            "  //  if (ret1) {\n"
+            "  //    return ret2;\n"
+            "  //  }\n"
+            "\n"
+            "  return ret1 && ret2;\n"
+            "}\n"
+            "} //  namespace Foo\n"
+            "\n"
+            "namespace Bar {\n"
+            "int foo();\n"
+            "} //  namespace Bar\n"
+            "//@Nothing added because of the non ascii char\n"
+            "\n"
+            "//@      Nothing removed because of the non ascii char\n"
+            "\n"
+            "//  Comment to move to the left\n"
+            "//  But not this?\n"
+            "//  @but this\n"
+            "\n"
+            "//  Comment to move to the right\n"
+            "//@ this stays\n"
+            "\n"
+            "//} will not move\n"
+            "\n"
+            "//  vv will only move\n"
+            "//  } if the line above does\n",
+            format(Code, Style));
+
+  Style = getLLVMStyleWithColumns(20);
+  StringRef WrapCode = "//Lorem ipsum dolor sit amet\n"
+                       "\n"
+                       "//  Lorem   ipsum   dolor   sit   amet\n"
+                       "\n"
+                       "void f() {//Hello World\n"
+                       "}";
+
+  EXPECT_EQ("// Lorem ipsum dolor\n"
+            "// sit amet\n"
+            "\n"
+            "//  Lorem   ipsum\n"
+            "//  dolor   sit amet\n"
+            "\n"
+            "void f() { // Hello\n"
+            "           // World\n"
+            "}",
+            format(WrapCode, Style));
+
+  Style.SpacesInLineCommentPrefix = {0, 0};
+  EXPECT_EQ("//Lorem ipsum dolor\n"
+            "//sit amet\n"
+            "\n"
+            "//Lorem   ipsum\n"
+            "//dolor   sit   amet\n"
+            "\n"
+            "void f() { //Hello\n"
+            "           //World\n"
+            "}",
+            format(WrapCode, Style));
+
+  Style.SpacesInLineCommentPrefix = {1, 1};
+  EXPECT_EQ("// Lorem ipsum dolor\n"
+            "// sit amet\n"
+            "\n"
+            "// Lorem   ipsum\n"
+            "// dolor   sit amet\n"
+            "\n"
+            "void f() { // Hello\n"
+            "           // World\n"
+            "}",
+            format(WrapCode, Style));
+
+  Style.SpacesInLineCommentPrefix = {3, 3};
+  EXPECT_EQ("//   Lorem ipsum\n"
+            "//   dolor sit amet\n"
+            "\n"
+            "//   Lorem   ipsum\n"
+            "//   dolor   sit\n"
+            "//   amet\n"
+            "\n"
+            "void f() { //   Hello\n"
+            "           //   World\n"
+            "}",
+            format(WrapCode, Style));
+
+  Style = getLLVMStyleWithColumns(20);
+  StringRef AShitloadOfSpaces = "//                      This are more spaces "
+                                "than the ColumnLimit, what now?\n"
+                                "\n"
+                                "//   Comment\n"
+                                "\n"
+                                "// This is a text to split in multiple "
+                                "lines, please. Thank you very much!\n"
+                                "\n"
+                                "// A comment with\n"
+                                "//   some indentation that has to be split.\n"
+                                "// And now without";
+  EXPECT_EQ("//                      This are more spaces "
+            "than the ColumnLimit, what now?\n"
+            "\n"
+            "//   Comment\n"
+            "\n"
+            "// This is a text to\n"
+            "// split in multiple\n"
+            "// lines, please.\n"
+            "// Thank you very\n"
+            "// much!\n"
+            "\n"
+            "// A comment with\n"
+            "//   some\n"
+            "//   indentation\n"
+            "//   that has to be\n"
+            "//   split.\n"
+            "// And now without",
+            format(AShitloadOfSpaces, Style));
+
+  Style.SpacesInLineCommentPrefix = {0, 0};
+  EXPECT_EQ("//This are more\n"
+            "//spaces than the\n"
+            "//ColumnLimit, what\n"
+            "//now?\n"
+            "\n"
+            "//Comment\n"
+            "\n"
+            "//This is a text to\n"
+            "//split in multiple\n"
+            "//lines, please.\n"
+            "//Thank you very\n"
+            "//much!\n"
+            "\n"
+            "//A comment with\n"
+            "//  some indentation\n"
+            "//  that has to be\n"
+            "//  split.\n"
+            "//And now without",
+            format(AShitloadOfSpaces, Style));
+
+  Style.SpacesInLineCommentPrefix = {3, 3};
+  EXPECT_EQ("//   This are more\n"
+            "//   spaces than the\n"
+            "//   ColumnLimit,\n"
+            "//   what now?\n"
+            "\n"
+            "//   Comment\n"
+            "\n"
+            "//   This is a text\n"
+            "//   to split in\n"
+            "//   multiple lines,\n"
+            "//   please. Thank\n"
+            "//   you very much!\n"
+            "\n"
+            "//   A comment with\n"
+            "//     some\n"
+            "//     indentation\n"
+            "//     that has to\n"
+            "//     be split.\n"
+            "//   And now without",
+            format(AShitloadOfSpaces, Style));
+
+  Style.SpacesInLineCommentPrefix = {30, -1u};
+  EXPECT_EQ("//                              This are more spaces than the "
+            "ColumnLimit, what now?\n"
+            "\n"
+            "//                              Comment\n"
+            "\n"
+            "//                              This is a text to split in "
+            "multiple lines, please. Thank you very much!\n"
+            "\n"
+            "//                              A comment with\n"
+            "//                                some indentation that has to be "
+            "split.\n"
+            "//                              And now without",
+            format(AShitloadOfSpaces, Style));
+
+  Style.SpacesInLineCommentPrefix = {2, 4};
+  EXPECT_EQ("//  A Comment to be\n"
+            "//  moved\n"
+            "//   with indent\n"
+            "\n"
+            "//  A Comment to be\n"
+            "//  moved\n"
+            "//   with indent\n"
+            "\n"
+            "//  A Comment to be\n"
+            "//  moved\n"
+            "//   with indent\n"
+            "\n"
+            "//   A Comment to be\n"
+            "//   moved\n"
+            "//    with indent\n"
+            "\n"
+            "//    A Comment to\n"
+            "//    be moved\n"
+            "//     with indent\n"
+            "\n"
+            "//    A Comment to\n"
+            "//    be moved\n"
+            "//     with indent\n"
+            "\n"
+            "//    A Comment to\n"
+            "//    be moved\n"
+            "//     with indent\n",
+            format("//A Comment to be moved\n"
+                   "// with indent\n"
+                   "\n"
+                   "// A Comment to be moved\n"
+                   "//  with indent\n"
+                   "\n"
+                   "//  A Comment to be moved\n"
+                   "//   with indent\n"
+                   "\n"
+                   "//   A Comment to be moved\n"
+                   "//    with indent\n"
+                   "\n"
+                   "//    A Comment to be moved\n"
+                   "//     with indent\n"
+                   "\n"
+                   "//     A Comment to be moved\n"
+                   "//      with indent\n"
+                   "\n"
+                   "//      A Comment to be moved\n"
+                   "//       with indent\n",
+                   Style));
+
+  Style.ColumnLimit = 30;
+  EXPECT_EQ("int i; //  A Comment to be\n"
+            "       //  moved\n"
+            "       //   with indent\n"
+            "\n"
+            "int i; //  A Comment to be\n"
+            "       //  moved\n"
+            "       //   with indent\n"
+            "\n"
+            "int i; //  A Comment to be\n"
+            "       //  moved\n"
+            "       //   with indent\n"
+            "\n"
+            "int i; //   A Comment to be\n"
+            "       //   moved\n"
+            "       //    with indent\n"
+            "\n"
+            "int i; //    A Comment to be\n"
+            "       //    moved\n"
+            "       //     with indent\n"
+            "\n"
+            "int i; //    A Comment to be\n"
+            "       //    moved\n"
+            "       //     with indent\n"
+            "\n"
+            "int i; //    A Comment to be\n"
+            "       //    moved\n"
+            "       //     with indent\n",
+            format("int i;//A Comment to be moved\n"
+                   "      // with indent\n"
+                   "\n"
+                   "int i;// A Comment to be moved\n"
+                   "      //  with indent\n"
+                   "\n"
+                   "int i;//  A Comment to be moved\n"
+                   "      //   with indent\n"
+                   "\n"
+                   "int i;//   A Comment to be moved\n"
+                   "      //    with indent\n"
+                   "\n"
+                   "int i;//    A Comment to be moved\n"
+                   "      //     with indent\n"
+                   "\n"
+                   "int i;//     A Comment to be moved\n"
+                   "      //      with indent\n"
+                   "\n"
+                   "int i;//      A Comment to be moved\n"
+                   "      //       with indent\n",
+                   Style));
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang


        


More information about the cfe-commits mailing list