[clang] [clang-format] Don't align comments over scopes (PR #68743)

Björn Schäpers via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 17 04:07:37 PDT 2023


https://github.com/HazardyKnusperkeks updated https://github.com/llvm/llvm-project/pull/68743

>From 84ebaa789588605c924708a98392bd014c63f373 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= <bjoern at hazardy.de>
Date: Tue, 10 Oct 2023 22:50:43 +0200
Subject: [PATCH] [clang-format] Don't align comments over scopes

We now stop aligning trailing comments on all closing braces, for
classes etc. we even check for the semicolon between the comment and the
brace.

Fixes #67906.
---
 clang/lib/Format/WhitespaceManager.cpp        |  40 ++++--
 clang/unittests/Format/FormatTestComments.cpp | 136 +++++++++++++++++-
 2 files changed, 162 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index dc81060671c1712..f37301a0a81c829 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -1048,6 +1048,9 @@ void WhitespaceManager::alignChainedConditionals() {
 }
 
 void WhitespaceManager::alignTrailingComments() {
+  if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Never)
+    return;
+
   const int Size = Changes.size();
   int MinColumn = 0;
   int StartOfSequence = 0;
@@ -1118,16 +1121,35 @@ void WhitespaceManager::alignTrailingComments() {
       }
     }
 
-    // We don't want to align namespace end comments.
-    const bool DontAlignThisComment =
-        I > 0 && C.NewlinesBefore == 0 &&
-        Changes[I - 1].Tok->is(TT_NamespaceRBrace);
-    if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Never ||
-        DontAlignThisComment) {
+    // We don't want to align comments which end a scope, which are here
+    // identified by most closing braces.
+    const bool DontAlignThisComment = [&] {
+      if (I == 0 || C.NewlinesBefore > 0)
+        return false;
+      const auto *Tok = Changes[I - 1].Tok;
+      if (Tok->is(tok::semi)) {
+        Tok = Tok->Previous;
+        if (!Tok)
+          return false;
+      }
+      if (Tok->isNot(tok::r_brace))
+        return false;
+      auto LastBrace = Tok;
+      while (Tok->Previous && Tok->Previous->is(tok::r_brace))
+        Tok = Tok->Previous;
+      return Tok->NewlinesBefore > 0 ||
+             LastBrace->isOneOf(TT_ClassRBrace, TT_EnumRBrace,
+                                TT_NamespaceRBrace, TT_StructRBrace,
+                                TT_UnionRBrace);
+    }();
+
+    if (DontAlignThisComment) {
       alignTrailingComments(StartOfSequence, I, MinColumn);
-      MinColumn = ChangeMinColumn;
-      MaxColumn = ChangeMinColumn;
-      StartOfSequence = I;
+      // Reset to initial values, but skip this change for the next alignment
+      // pass.
+      MinColumn = 0;
+      MaxColumn = INT_MAX;
+      StartOfSequence = I + 1;
     } else if (BreakBeforeNext || Newlines > NewLineThreshold ||
                (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
                // Break the comment sequence if the previous line did not end
diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
index 1198329b7b5a8f0..6b36e7d997b3799 100644
--- a/clang/unittests/Format/FormatTestComments.cpp
+++ b/clang/unittests/Format/FormatTestComments.cpp
@@ -182,7 +182,7 @@ TEST_F(FormatTestComments, UnderstandsSingleLineComments) {
                    "int   a;     // This is unrelated"));
   EXPECT_EQ("class C {\n"
             "  void f() { // This does something ..\n"
-            "  }          // awesome..\n"
+            "  } // awesome..\n"
             "\n"
             "  int a; // This is unrelated\n"
             "};",
@@ -3191,20 +3191,146 @@ TEST_F(FormatTestComments, DontAlignNamespaceComments) {
           "}\n"
           "// Comment";
 
-#if 0
-  // FIXME: The following comment is aligned with the namespace comment.
   verifyFormat("namespace A {\n"
                "  int Foo;\n"
                "  int Bar;\n"
                "} // namespace A\n"
-               " // Comment",
+               "// Comment",
                Input, Style);
-#endif
 
   Style.FixNamespaceComments = false;
   verifyFormat(Input, Style);
 }
 
+TEST_F(FormatTestComments, DontAlignOverScope) {
+  verifyFormat("if (foo) {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "} // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("if (foo) {\n"
+               "  // something\n"
+               "} else {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "} // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("if (foo) {\n"
+               "  // something\n"
+               "} else if (foo) {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "} // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("while (foo) {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "} // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("for (;;) {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "} // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+#if 0
+  // FIXME: Skip do-while
+  verifyFormat("do {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "} while (foo); // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("do\n"
+               "  int aLongVariable; // with comment\n"
+               "while (foo); // not aigned"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+#endif
+
+  verifyFormat("switch (foo) {\n"
+               "case 7: {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "} // case not aligned\n"
+               "} // switch also not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("switch (foo) {\n"
+               "default: {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "} // case not aligned\n"
+               "} // switch also not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("class C {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "}; // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("struct S {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "}; // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("union U {\n"
+               "  int aLongVariable; // with comment\n"
+               "  int f;             // aligned\n"
+               "}; // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("enum E {\n"
+               "  aLongVariable, // with comment\n"
+               "  f              // aligned\n"
+               "}; // not aligned\n"
+               "int bar;    // new align\n"
+               "int foobar; // group");
+
+  verifyFormat("void foo() {\n"
+               "  {\n"
+               "    int aLongVariable; // with comment\n"
+               "    int f;             // aligned\n"
+               "  } // not aligned\n"
+               "  int bar;    // new align\n"
+               "  int foobar; // group\n"
+               "}");
+
+  verifyFormat("auto longLambda = [] { // comment\n"
+               "  int aLongVariable;   // with comment\n"
+               "  int f;               // aligned\n"
+               "}; // not aligned\n"
+               "int bar;                             // new align\n"
+               "int foobar;                          // group\n"
+               "auto shortLambda = [] { return 5; }; // aligned");
+
+  // Short Elements
+  verifyFormat("namespace NS {} // namespace NS\n"
+               "class C {}; // Comments\n"
+               "struct S {}; // are\n"
+               "union {}; // not\n"
+               "enum E {}; // aligned\n"
+               "int x;   // evenwhen the braces have no new\n"
+               "int foo; // line in front of them");
+}
+
 TEST_F(FormatTestComments, AlignsBlockCommentDecorations) {
   EXPECT_EQ("/*\n"
             " */",



More information about the cfe-commits mailing list