ksyx created this revision.
ksyx added reviewers: MyDeveloperDay, curdeius, HazardyKnusperkeks.
ksyx added a project: clang-format.
ksyx requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This commit 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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119067

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

Index: clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
===================================================================
--- clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
+++ clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
@@ -302,6 +302,9 @@
                       "\n"
                       "int bar2(int j, int k) {\n"
                       "  int r = j / k;\n"
+                      "  if (struct S = getS()) {\n"
+                      "    // if condition\n"
+                      "  }\n"
                       "  return r;\n"
                       "}\n"
                       "\n"
@@ -355,6 +358,9 @@
                         "\n"
                         "int bar2(int j, int k) {\n"
                         "  int r = j / k;\n"
+                        "  if (struct S = getS()) {\n"
+                        "    // if condition\n"
+                        "  }\n"
                         "  return r;\n"
                         "}\n"
                         "\n"
@@ -412,6 +418,10 @@
                "int bar2(int j, int k)\n"
                "{\n"
                "  int r = j / k;\n"
+               "  if (struct S = getS())\n"
+               "  {\n"
+               "    // if condition\n"
+               "  }\n"
                "  return r;\n"
                "}\n"
                "\n"
@@ -465,6 +475,9 @@
                         "\n"
                         "int bar2(int j, int k) {\n"
                         "  int r = j / k;\n"
+                        "  if (struct S = getS()) {\n"
+                        "    // if condition\n"
+                        "  }\n"
                         "  return r;\n"
                         "}\n"
                         "\n"
Index: clang/lib/Format/DefinitionBlockSeparator.cpp
===================================================================
--- clang/lib/Format/DefinitionBlockSeparator.cpp
+++ clang/lib/Format/DefinitionBlockSeparator.cpp
@@ -35,18 +35,31 @@
   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;
+    else if (Tok->isOneOf(tok::r_brace, tok::r_paren, tok::r_square))
+      return -1;
+    else
+      return 0;
+  };
+  auto LikelyDefinition = [&](const AnnotatedLine *Line,
+                              bool ExcludeEnum = false) {
     if ((Line->MightBeFunctionDecl && Line->mightBeFunctionDefinition()) ||
         Line->startsWithNamespace())
       return true;
     FormatToken *CurrentToken = Line->First;
+    int BracketLevel = 0;
     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;
+      if (BracketLevel == 0) {
+        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;
+      }
+      BracketLevel += GetBracketLevelChange(CurrentToken);
       CurrentToken = CurrentToken->Next;
     }
     return false;
@@ -104,11 +117,15 @@
     const auto HasEnumOnLine = [&]() {
       FormatToken *CurrentToken = CurrentLine->First;
       bool FoundEnumKeyword = false;
+      int BracketLevel = 0;
       while (CurrentToken) {
-        if (CurrentToken->is(tok::kw_enum))
-          FoundEnumKeyword = true;
-        else if (FoundEnumKeyword && CurrentToken->is(tok::l_brace))
-          return true;
+        if (BracketLevel == 0) {
+          if (CurrentToken->is(tok::kw_enum))
+            FoundEnumKeyword = true;
+          else if (FoundEnumKeyword && CurrentToken->is(tok::l_brace))
+            return true;
+        }
+        BracketLevel += GetBracketLevelChange(CurrentToken);
         CurrentToken = CurrentToken->Next;
       }
       return FoundEnumKeyword && I + 1 < Lines.size() &&
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to