]> granicus.if.org Git - clang/commitdiff
[clang-format] Fix breaking of comment sections in unwrapped lines containing newlines.
authorKrasimir Georgiev <krasimir@google.com>
Thu, 2 Feb 2017 14:36:50 +0000 (14:36 +0000)
committerKrasimir Georgiev <krasimir@google.com>
Thu, 2 Feb 2017 14:36:50 +0000 (14:36 +0000)
Summary:
The breaking of line comment sections was misaligning the case where the first comment line is on an unwrapped line containing newlines. In this case, the breaking column must be based on the source column of the last token that is preceded by a newline, not on the first token of the unwrapped line.

source:
```
enum A {
  a, // line 1
  // line 2
};
```
format before:
```
enum A {
  a, // line 1
     // line 2
};
```
format after:
```
enum A {
  a, // line 1
  // line 2
};
```

Reviewers: djasper

Reviewed By: djasper

Subscribers: cfe-commits, klimek

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@293891 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Format/BreakableToken.cpp
lib/Format/FormatToken.h
lib/Format/UnwrappedLineParser.cpp
unittests/Format/FormatTest.cpp

index 09f17a35d07a01dff14bfb86bb1642a4c8295a89..e9dd253f3ec12f8c512b2e3e3bcb9b835a84c943 100644 (file)
@@ -695,7 +695,7 @@ BreakableLineCommentSection::BreakableLineCommentSection(
       Content[i] = Content[i].substr(0, EndOfLine);
     }
     LineTok = CurrentTok->Next;
-    if (CurrentTok->Next && CurrentTok->Next->NewlinesBefore > 1) {
+    if (CurrentTok->Next && !CurrentTok->Next->ContinuesLineCommentSection) {
       // A line comment section needs to broken by a line comment that is
       // preceded by at least two newlines. Note that we put this break here
       // instead of breaking at a previous stage during parsing, since that
index c838cfbe1daba3a988bdc284b0d97d0760361a34..d6a2ff286aeaa22aa403a34505d2c7acf4c7cdbd 100644 (file)
@@ -261,6 +261,11 @@ struct FormatToken {
   /// Only set if \c Type == \c TT_StartOfName.
   bool PartOfMultiVariableDeclStmt = false;
 
+  /// \brief Does this line comment continue a line comment section?
+  ///
+  /// Only set to true if \c Type == \c TT_LineComment.
+  bool ContinuesLineCommentSection = false;
+
   /// \brief If this is a bracket, this points to the matching one.
   FormatToken *MatchingParen = nullptr;
 
index a96d4d9be3e7bf3387487b95bfb5446df101eab5..2c7b87ee014a91813a64d974dff3b30f62e06892 100644 (file)
@@ -2066,31 +2066,58 @@ static bool continuesLineComment(const FormatToken &FormatTok,
   // original start column of the min column token of the line.
   //
   // For example, the second line comment continues the first in these cases:
+  //
   // // first line
   // // second line
+  //
   // and:
+  //
   // // first line
   //  // second line
+  //
   // and:
+  //
   // int i; // first line
   //  // second line
+  //
   // and:
+  //
   // do { // first line
   //      // second line
   //   int i;
   // } while (true);
   //
+  // and:
+  //
+  // enum {
+  //   a, // first line
+  //    // second line
+  //   b
+  // };
+  //
   // The second line comment doesn't continue the first in these cases:
+  //
   //   // first line
   //  // second line
+  //
   // and:
+  //
   // int i; // first line
   // // second line
+  //
   // and:
+  //
   // do { // first line
   //   // second line
   //   int i;
   // } while (true);
+  //
+  // and:
+  //
+  // enum {
+  //   a, // first line
+  //   // second line
+  // };
   const FormatToken *MinColumnToken = Line.Tokens.front().Tok;
 
   // Scan for '{//'. If found, use the column of '{' as a min column for line
@@ -2103,6 +2130,11 @@ static bool continuesLineComment(const FormatToken &FormatTok,
       break;
     }
     PreviousToken = Node.Tok;
+
+    // Grab the last newline preceding a token in this unwrapped line.
+    if (Node.Tok->NewlinesBefore > 0) {
+      MinColumnToken = Node.Tok;
+    }
   }
   if (PreviousToken && PreviousToken->is(tok::l_brace)) {
     MinColumnToken = PreviousToken;
@@ -2130,7 +2162,8 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
     //
     // FIXME: Consider putting separate line comment sections as children to the
     // unwrapped line instead.
-    if (isOnNewLine(**I) && JustComments && !continuesLineComment(**I, *Line))
+    (*I)->ContinuesLineCommentSection = continuesLineComment(**I, *Line);
+    if (isOnNewLine(**I) && JustComments && !(*I)->ContinuesLineCommentSection)
       addUnwrappedLine();
     pushToken(*I);
   }
@@ -2196,7 +2229,9 @@ void UnwrappedLineParser::readToken() {
 
     if (!FormatTok->Tok.is(tok::comment))
       return;
-    if (!continuesLineComment(*FormatTok, *Line) &&
+    FormatTok->ContinuesLineCommentSection =
+        continuesLineComment(*FormatTok, *Line);
+    if (!FormatTok->ContinuesLineCommentSection &&
         (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
       CommentsInCurrentLine = false;
     }
index 497015bb09581f6c873f60ead868ac45f029d6ba..1f81f5fbd2f086880ab1fe5acd53a907b50580e1 100644 (file)
@@ -951,7 +951,46 @@ TEST_F(FormatTest, UnderstandsSingleLineComments) {
                    "  c\n"
                    "};",
                    getLLVMStyleWithColumns(20)));
-
+  EXPECT_EQ("enum A {\n"
+            "  a, // line 1\n"
+            "  // line 2\n"
+            "};",
+            format("enum A {\n"
+                   "  a, // line 1\n"
+                   "  // line 2\n"
+                   "};",
+                   getLLVMStyleWithColumns(20)));
+  EXPECT_EQ("enum A {\n"
+            "  a, // line 1\n"
+            "     // line 2\n"
+            "};",
+            format("enum A {\n"
+                   "  a, // line 1\n"
+                   "   // line 2\n"
+                   "};",
+                   getLLVMStyleWithColumns(20)));
+  EXPECT_EQ("enum A {\n"
+            "  a, // line 1\n"
+            "  // line 2\n"
+            "  b\n"
+            "};",
+            format("enum A {\n"
+                   "  a, // line 1\n"
+                   "  // line 2\n"
+                   "  b\n"
+                   "};",
+                   getLLVMStyleWithColumns(20)));
+  EXPECT_EQ("enum A {\n"
+            "  a, // line 1\n"
+            "     // line 2\n"
+            "  b\n"
+            "};",
+            format("enum A {\n"
+                   "  a, // line 1\n"
+                   "   // line 2\n"
+                   "  b\n"
+                   "};",
+                   getLLVMStyleWithColumns(20)));
   verifyFormat(
       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =\n"
       "    bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; // Trailing comment");