[llvm-branch-commits] [clang] 39e9a64 - [clang-format] Fix DefSeparator empty line issues

Tom Stellard via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Feb 8 10:29:55 PST 2022


Author: ksyx
Date: 2022-02-08T10:29:18-08:00
New Revision: 39e9a64cf5847935c2ba0099f4bf39945d8ee19b

URL: https://github.com/llvm/llvm-project/commit/39e9a64cf5847935c2ba0099f4bf39945d8ee19b
DIFF: https://github.com/llvm/llvm-project/commit/39e9a64cf5847935c2ba0099f4bf39945d8ee19b.diff

LOG: [clang-format] Fix DefSeparator empty line issues

- Add or remove empty lines surrounding union blocks.
- Fixes https://github.com/llvm/llvm-project/issues/53229, in which
  keywords like class and struct in a line ending with left brace or
  whose next line is left brace only, will be falsely recognized as
  definition line, causing extra empty lines inserted surrounding blocks
  with no need to be formatted.

Reviewed By: MyDeveloperDay, curdeius, HazardyKnusperkeks, owenpan
Differential Revision: https://reviews.llvm.org/D119067

(cherry picked from commit a70549ae43dfa551f3eacdfa7a7f2c0df073be8e)

Added: 
    

Modified: 
    clang/lib/Format/DefinitionBlockSeparator.cpp
    clang/unittests/Format/DefinitionBlockSeparatorTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Format/DefinitionBlockSeparator.cpp b/clang/lib/Format/DefinitionBlockSeparator.cpp
index 827564357f788..cfb019a471dce 100644
--- a/clang/lib/Format/DefinitionBlockSeparator.cpp
+++ b/clang/lib/Format/DefinitionBlockSeparator.cpp
@@ -35,19 +35,31 @@ void DefinitionBlockSeparator::separateBlocks(
   const bool IsNeverStyle =
       Style.SeparateDefinitionBlocks == FormatStyle::SDS_Never;
   const AdditionalKeywords &ExtraKeywords = Tokens.getKeywords();
-  auto LikelyDefinition = [this, ExtraKeywords](const AnnotatedLine *Line,
-                                                bool ExcludeEnum = false) {
+  auto GetBracketLevelChange = [](const FormatToken *Tok) {
+    if (Tok->isOneOf(tok::l_brace, tok::l_paren, tok::l_square))
+      return 1;
+    if (Tok->isOneOf(tok::r_brace, tok::r_paren, tok::r_square))
+      return -1;
+    return 0;
+  };
+  auto LikelyDefinition = [&](const AnnotatedLine *Line,
+                              bool ExcludeEnum = false) {
     if ((Line->MightBeFunctionDecl && Line->mightBeFunctionDefinition()) ||
         Line->startsWithNamespace())
       return true;
-    FormatToken *CurrentToken = Line->First;
-    while (CurrentToken) {
-      if (CurrentToken->isOneOf(tok::kw_class, tok::kw_struct) ||
-          (Style.isJavaScript() && CurrentToken->is(ExtraKeywords.kw_function)))
-        return true;
-      if (!ExcludeEnum && CurrentToken->is(tok::kw_enum))
-        return true;
-      CurrentToken = CurrentToken->Next;
+    int BracketLevel = 0;
+    for (const FormatToken *CurrentToken = Line->First; CurrentToken;
+         CurrentToken = CurrentToken->Next) {
+      if (BracketLevel == 0) {
+        if ((CurrentToken->isOneOf(tok::kw_class, tok::kw_struct,
+                                   tok::kw_union) ||
+             (Style.isJavaScript() &&
+              CurrentToken->is(ExtraKeywords.kw_function))))
+          return true;
+        if (!ExcludeEnum && CurrentToken->is(tok::kw_enum))
+          return true;
+      }
+      BracketLevel += GetBracketLevelChange(CurrentToken);
     }
     return false;
   };
@@ -102,14 +114,17 @@ void DefinitionBlockSeparator::separateBlocks(
              IsPPConditional(OpeningLineIndex - 1);
     };
     const auto HasEnumOnLine = [&]() {
-      FormatToken *CurrentToken = CurrentLine->First;
       bool FoundEnumKeyword = false;
-      while (CurrentToken) {
-        if (CurrentToken->is(tok::kw_enum))
-          FoundEnumKeyword = true;
-        else if (FoundEnumKeyword && CurrentToken->is(tok::l_brace))
-          return true;
-        CurrentToken = CurrentToken->Next;
+      int BracketLevel = 0;
+      for (const FormatToken *CurrentToken = CurrentLine->First; CurrentToken;
+           CurrentToken = CurrentToken->Next) {
+        if (BracketLevel == 0) {
+          if (CurrentToken->is(tok::kw_enum))
+            FoundEnumKeyword = true;
+          else if (FoundEnumKeyword && CurrentToken->is(tok::l_brace))
+            return true;
+        }
+        BracketLevel += GetBracketLevelChange(CurrentToken);
       }
       return FoundEnumKeyword && I + 1 < Lines.size() &&
              Lines[I + 1]->First->is(tok::l_brace);

diff  --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
index 4cbae0f55b036..582b62e445df9 100644
--- a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
+++ b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
@@ -109,6 +109,15 @@ TEST_F(DefinitionBlockSeparatorTest, Basic) {
                "};",
                Style);
 
+  verifyFormat("union foo {\n"
+               "  int i, j;\n"
+               "};\n"
+               "\n"
+               "union bar {\n"
+               "  int j, k;\n"
+               "};",
+               Style);
+
   verifyFormat("class foo {\n"
                "  int i, j;\n"
                "};\n"
@@ -311,6 +320,9 @@ TEST_F(DefinitionBlockSeparatorTest, Always) {
                       "int bar3(int j, int k, const enum Bar b) {\n"
                       "  // A comment\n"
                       "  int r = j % k;\n"
+                      "  if (struct S = getS()) {\n"
+                      "    // if condition\n"
+                      "  }\n"
                       "  return r;\n"
                       "}\n";
   std::string Postfix = "\n"
@@ -364,6 +376,9 @@ TEST_F(DefinitionBlockSeparatorTest, Never) {
                         "int bar3(int j, int k, const enum Bar b) {\n"
                         "  // A comment\n"
                         "  int r = j % k;\n"
+                        "  if (struct S = getS()) {\n"
+                        "    // if condition\n"
+                        "  }\n"
                         "  return r;\n"
                         "}\n"
                         "} // namespace";
@@ -425,6 +440,10 @@ TEST_F(DefinitionBlockSeparatorTest, OpeningBracketOwnsLine) {
                "{\n"
                "  // A comment\n"
                "  int r = j % k;\n"
+               "  if (struct S = getS())\n"
+               "  {\n"
+               "    // if condition\n"
+               "  }\n"
                "  return r;\n"
                "}\n"
                "} // namespace NS",
@@ -473,6 +492,9 @@ TEST_F(DefinitionBlockSeparatorTest, Leave) {
                         "int bar3(int j, int k, const enum Bar b) {\n"
                         "  // A comment\n"
                         "  int r = j % k;\n"
+                        "  if (struct S = getS()) {\n"
+                        "    // if condition\n"
+                        "  }\n"
                         "  return r;\n"
                         "}\n"
                         "} // namespace";


        


More information about the llvm-branch-commits mailing list