[clang] [clang-format] Option to ignore PP directives (PR #70338)

via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 13 01:58:45 PST 2023


https://github.com/tomekpaszek updated https://github.com/llvm/llvm-project/pull/70338

>From b5ba0b3fde2c6662e19dfdf96a787621ec767460 Mon Sep 17 00:00:00 2001
From: Tomek Paszek <tomek at unity3d.com>
Date: Sat, 11 Nov 2023 19:38:00 +0100
Subject: [PATCH 1/4] Added an option to ignore macro definitions.

---
 clang/include/clang/Format/Format.h         |  5 +++++
 clang/lib/Format/Format.cpp                 |  2 ++
 clang/lib/Format/UnwrappedLineFormatter.cpp |  2 ++
 clang/unittests/Format/ConfigParseTest.cpp  |  3 ++-
 clang/unittests/Format/FormatTest.cpp       | 16 ++++++++++++++++
 5 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 3e9d1915badd87f..3af7241441c8b13 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2442,6 +2442,10 @@ struct FormatStyle {
   /// <https://github.com/capnproto/capnproto/blob/master/kjdoc/tour.md#maybes>`_
   /// \version 13
   std::vector<std::string> IfMacros;
+      
+  /// Ignore formatting in preprocessor definitions.
+  /// \version 18
+  bool IgnorePPDefinitions;
 
   /// Specify whether access modifiers should have their own indentation level.
   ///
@@ -4719,6 +4723,7 @@ struct FormatStyle {
                R.IncludeStyle.IncludeIsMainRegex &&
            IncludeStyle.IncludeIsMainSourceRegex ==
                R.IncludeStyle.IncludeIsMainSourceRegex &&
+           IgnorePPDefinitions == R.IgnorePPDefinitions &&
            IndentAccessModifiers == R.IndentAccessModifiers &&
            IndentCaseBlocks == R.IndentCaseBlocks &&
            IndentCaseLabels == R.IndentCaseLabels &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index edb33f4af4defef..6e5ec754dfdcdd9 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1000,6 +1000,7 @@ template <> struct MappingTraits<FormatStyle> {
     IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
     IO.mapOptional("ForEachMacros", Style.ForEachMacros);
     IO.mapOptional("IfMacros", Style.IfMacros);
+    IO.mapOptional("IgnorePPDefinitions", Style.IgnorePPDefinitions);
     IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
     IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
     IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
@@ -1504,6 +1505,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
   LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
   LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
   LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
+  LLVMStyle.IgnorePPDefinitions = false;
   LLVMStyle.IncludeStyle.IncludeCategories = {
       {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
       {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 280485d9a90d1bf..bbf6383ff7673f6 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -1355,6 +1355,8 @@ unsigned UnwrappedLineFormatter::format(
     bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
                           Indent != TheLine.First->OriginalColumn;
     bool ShouldFormat = TheLine.Affected || FixIndentation;
+    if (Style.IgnorePPDefinitions && TheLine.Type == LT_PreprocessorDirective)
+      ShouldFormat = false;
     // We cannot format this line; if the reason is that the line had a
     // parsing error, remember that.
     if (ShouldFormat && TheLine.Type == LT_Invalid && Status) {
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index f90ed178d99c286..110df624d44573c 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -166,6 +166,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_BOOL(DerivePointerAlignment);
   CHECK_PARSE_BOOL_FIELD(DerivePointerAlignment, "DerivePointerBinding");
   CHECK_PARSE_BOOL(DisableFormat);
+  CHECK_PARSE_BOOL(IgnorePPDefinitions);
   CHECK_PARSE_BOOL(IndentAccessModifiers);
   CHECK_PARSE_BOOL(IndentCaseLabels);
   CHECK_PARSE_BOOL(IndentCaseBlocks);
@@ -198,7 +199,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_BOOL(SpaceBeforeRangeBasedForLoopColon);
   CHECK_PARSE_BOOL(SpaceBeforeSquareBrackets);
   CHECK_PARSE_BOOL(VerilogBreakBetweenInstancePorts);
-
+  
   CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements, Enabled);
   CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements,
                           AcrossEmptyLines);
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index b2d84f2ee389551..659132dcb9c3970 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -24153,6 +24153,22 @@ TEST_F(FormatTest, WhitespaceSensitiveMacros) {
   verifyNoChange("FOO(String-ized&Messy+But: :Still=Intentional);", Style);
 }
 
+TEST_F(FormatTest, IgnorePPDefinitions) {
+  FormatStyle Style = getLLVMStyle();
+  Style.IgnorePPDefinitions = true;
+
+  verifyNoChange("#define  A", Style);
+  verifyNoChange("#define A   b", Style);
+  verifyNoChange("#define A  (  args   )", Style);
+  verifyNoChange("#define A  (  args   )  =  func  (  args  )", Style);
+  verifyNoChange("#define TEXT Text . With periods.", Style);
+  verifyNoChange("#define TEXT \\\nLine  number  one .  \\\nNumber  two .",
+                 Style);
+
+  // TODO
+  // verifyNoChange("/* comment */ #define A  (  args   )", Style);
+}
+
 TEST_F(FormatTest, VeryLongNamespaceCommentSplit) {
   // These tests are not in NamespaceEndCommentsFixerTest because that doesn't
   // test its interaction with line wrapping

>From aa62209c0181232339d24c2cb767795dcfa2b2c1 Mon Sep 17 00:00:00 2001
From: Tomek Paszek <tomek at unity3d.com>
Date: Fri, 27 Oct 2023 13:57:50 +0200
Subject: [PATCH 2/4] Added edge cases to the test and code that fixes handling
 them

---
 clang/lib/Format/UnwrappedLineParser.cpp | 8 ++++++++
 clang/unittests/Format/FormatTest.cpp    | 3 ++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 488d8dc07b1eae3..07cf966a08ff5e5 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1134,6 +1134,14 @@ void UnwrappedLineParser::parsePPDefine() {
     return;
   }
 
+  if (Style.IgnorePPDefinitions) {
+    do {
+      nextToken();
+    } while (!eof());
+    addUnwrappedLine();
+    return;
+  }
+
   if (IncludeGuard == IG_IfNdefed &&
       IncludeGuardToken->TokenText == FormatTok->TokenText) {
     IncludeGuard = IG_Defined;
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 659132dcb9c3970..a1f8961c3e5edb6 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -24161,9 +24161,10 @@ TEST_F(FormatTest, IgnorePPDefinitions) {
   verifyNoChange("#define A   b", Style);
   verifyNoChange("#define A  (  args   )", Style);
   verifyNoChange("#define A  (  args   )  =  func  (  args  )", Style);
-  verifyNoChange("#define TEXT Text . With periods.", Style);
   verifyNoChange("#define TEXT \\\nLine  number  one .  \\\nNumber  two .",
                  Style);
+  verifyNoChange("#define A x:", Style);
+  verifyNoChange("#define A a. b", Style);
 
   // TODO
   // verifyNoChange("/* comment */ #define A  (  args   )", Style);

>From 9575b8f6c24435a0f6bed2593276ccbe10c8070b Mon Sep 17 00:00:00 2001
From: Tomek Paszek <tomek at unity3d.com>
Date: Sat, 11 Nov 2023 19:28:25 +0100
Subject: [PATCH 3/4] Added more tests

---
 clang/unittests/Format/ConfigParseTest.cpp |  2 +-
 clang/unittests/Format/FormatTest.cpp      | 40 +++++++++++++++++++---
 2 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 110df624d44573c..7ce9ae26b36fbb9 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -199,7 +199,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_BOOL(SpaceBeforeRangeBasedForLoopColon);
   CHECK_PARSE_BOOL(SpaceBeforeSquareBrackets);
   CHECK_PARSE_BOOL(VerilogBreakBetweenInstancePorts);
-  
+
   CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements, Enabled);
   CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements,
                           AcrossEmptyLines);
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index a1f8961c3e5edb6..19cf521107c604b 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -24161,13 +24161,43 @@ TEST_F(FormatTest, IgnorePPDefinitions) {
   verifyNoChange("#define A   b", Style);
   verifyNoChange("#define A  (  args   )", Style);
   verifyNoChange("#define A  (  args   )  =  func  (  args  )", Style);
-  verifyNoChange("#define TEXT \\\nLine  number  one .  \\\nNumber  two .",
-                 Style);
+
   verifyNoChange("#define A x:", Style);
   verifyNoChange("#define A a. b", Style);
-
-  // TODO
-  // verifyNoChange("/* comment */ #define A  (  args   )", Style);
+    
+  // Surrounded with formatted code
+  verifyFormat("int a;\n"
+               "#define  A  a\n"
+               "int a;",
+               "int  a ;\n"
+               "#define  A  a\n"
+               "int  a ;",
+               Style);
+    
+  // Columns are not broken when a limit is set
+  Style.ColumnLimit = 10;
+  verifyNoChange("#define A a a a a", Style);
+  Style.ColumnLimit = 0;
+    
+  // Multiline definition
+  verifyNoChange("#define A \\\n"
+                 "Line one with spaces  .  \\\n"
+                 " Line two.",
+                   Style);
+  verifyNoChange("#define A \\\n"
+                 "a a \\\n"
+                 "a        \\\na",
+                 Style);
+  Style.AlignEscapedNewlines = FormatStyle::ENAS_Left;
+  verifyNoChange("#define A \\\n"
+                 "a a \\\n"
+                 "a        \\\na",
+                 Style);
+  Style.AlignEscapedNewlines = FormatStyle::ENAS_Right;
+  verifyNoChange("#define A \\\n"
+                 "a a \\\n"
+                 "a        \\\na", 
+                 Style);
 }
 
 TEST_F(FormatTest, VeryLongNamespaceCommentSplit) {

>From c5da2c40065bb5394a9d85fb0b82ad0a1b00757a Mon Sep 17 00:00:00 2001
From: Tomek Paszek <tomek at unity3d.com>
Date: Mon, 13 Nov 2023 10:58:12 +0100
Subject: [PATCH 4/4] Updated documentation files

---
 clang/docs/ClangFormatStyleOptions.rst | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 21342e1b89ea866..80565620d8f24bf 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -3160,6 +3160,11 @@ the configuration (without a prefix: ``Auto``).
   For example: `KJ_IF_MAYBE
   <https://github.com/capnproto/capnproto/blob/master/kjdoc/tour.md#maybes>`_
 
+.. _IgnorePPDefinitions:
+
+**IgnorePPDefinitions** (``Boolean``) :versionbadge:`clang-format 18` :ref:`¶ <IgnorePPDefinitions>`
+  Ignore formatting in preprocessor definitions.
+
 .. _IncludeBlocks:
 
 **IncludeBlocks** (``IncludeBlocksStyle``) :versionbadge:`clang-format 6` :ref:`¶ <IncludeBlocks>`



More information about the cfe-commits mailing list