Skip to content

[clang-format][NFC] Upgrade IndentBraces option to a struct #143663

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

rmarker
Copy link
Contributor

@rmarker rmarker commented Jun 11, 2025

This allows for more suboptions to be added in the future to give more control of brace indenting.

This allows for more suboptions to provide fine grained control of the
brace indenting to be added.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang-format labels Jun 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 11, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-format

Author: None (rmarker)

Changes

This allows for more suboptions to be added to give more control of brace indenting.


Full diff: https://github.com/llvm/llvm-project/pull/143663.diff

6 Files Affected:

  • (modified) clang/docs/ClangFormatStyleOptions.rst (+1-1)
  • (modified) clang/include/clang/Format/Format.h (+14-2)
  • (modified) clang/lib/Format/ContinuationIndenter.cpp (+3-2)
  • (modified) clang/lib/Format/Format.cpp (+17-3)
  • (modified) clang/lib/Format/UnwrappedLineParser.cpp (+4-4)
  • (modified) clang/unittests/Format/ConfigParseTest.cpp (+17-1)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 83716cc049ee3..053b840ae897a 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -2539,7 +2539,7 @@ the configuration (without a prefix: ``Auto``).
         foo();
       } while (1);
 
-  * ``bool IndentBraces`` Indent the wrapped braces themselves.
+  * ``IndentBracesOptions IndentBraces`` Controls indenting of wrapped braces.
 
   * ``bool SplitEmptyFunction`` If ``false``, empty function body can be put on a single line.
     This option is used only if the opening brace of the function has
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 127b1d08919de..1fab1547ad17c 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -1355,6 +1355,18 @@ struct FormatStyle {
     BWACS_Always
   };
 
+  /// Options for indenting wrapped braces.
+  struct IndentBracesOptions {
+    /// Indent wrapped braces.
+    bool Enabled;
+    bool operator==(const IndentBracesOptions &R) const {
+      return Enabled == R.Enabled;
+    }
+    bool operator!=(const IndentBracesOptions &R) const {
+      return !(*this == R);
+    }
+  };
+
   /// Precise control over the wrapping of braces.
   /// \code
   ///   # Should be declared this way:
@@ -1545,8 +1557,8 @@ struct FormatStyle {
     ///   } while (1);
     /// \endcode
     bool BeforeWhile;
-    /// Indent the wrapped braces themselves.
-    bool IndentBraces;
+    /// Controls indenting of wrapped braces.
+    IndentBracesOptions IndentBraces;
     /// If ``false``, empty function body can be put on a single line.
     /// This option is used only if the opening brace of the function has
     /// already been wrapped, i.e. the ``AfterFunction`` brace wrapping mode is
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 424b6dbc0da79..1193eb660791e 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -1335,7 +1335,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
   }
 
   if (Style.BraceWrapping.BeforeLambdaBody &&
-      Style.BraceWrapping.IndentBraces && Current.is(TT_LambdaLBrace)) {
+      Style.BraceWrapping.IndentBraces.Enabled && Current.is(TT_LambdaLBrace)) {
     const auto From = Style.LambdaBodyIndentation == FormatStyle::LBI_Signature
                           ? CurrentState.Indent
                           : State.FirstIndent;
@@ -2123,7 +2123,8 @@ void ContinuationIndenter::moveStateToNewBlock(LineState &State, bool NewLine) {
   if (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope &&
       State.NextToken->is(TT_LambdaLBrace) &&
       !State.Line->MightBeFunctionDecl) {
-    const auto Indent = Style.IndentWidth * Style.BraceWrapping.IndentBraces;
+    const auto Indent =
+        Style.IndentWidth * Style.BraceWrapping.IndentBraces.Enabled;
     State.Stack.back().NestedBlockIndent = State.FirstIndent + Indent;
   }
   unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index bdaf264e9adce..6825fbfb89479 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -231,6 +231,20 @@ struct ScalarEnumerationTraits<
   }
 };
 
+template <> struct MappingTraits<FormatStyle::IndentBracesOptions> {
+  static void enumInput(IO &IO, FormatStyle::IndentBracesOptions &Value) {
+    // For backward compatibility.
+    IO.enumCase(Value, "false",
+                FormatStyle::IndentBracesOptions({/*Enabled=*/false}));
+    IO.enumCase(Value, "true",
+                FormatStyle::IndentBracesOptions({/*Enabled=*/true}));
+  }
+
+  static void mapping(IO &IO, FormatStyle::IndentBracesOptions &Value) {
+    IO.mapOptional("Enabled", Value.Enabled);
+  }
+};
+
 template <>
 struct ScalarEnumerationTraits<
     FormatStyle::BreakBeforeConceptDeclarationsStyle> {
@@ -1381,7 +1395,7 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
                             /*BeforeElse=*/false,
                             /*BeforeLambdaBody=*/false,
                             /*BeforeWhile=*/false,
-                            /*IndentBraces=*/false,
+                            /*IndentBraces=*/{/*Enabled=*/false},
                             /*SplitEmptyFunction=*/true,
                             /*SplitEmptyRecord=*/true,
                             /*SplitEmptyNamespace=*/true};
@@ -1451,7 +1465,7 @@ static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
         /*BeforeElse=*/true,
         /*BeforeLambdaBody=*/true,
         /*BeforeWhile=*/true,
-        /*IndentBraces=*/true,
+        /*IndentBraces=*/{/*Enabled=*/true},
         /*SplitEmptyFunction=*/true,
         /*SplitEmptyRecord=*/true,
         /*SplitEmptyNamespace=*/true};
@@ -1551,7 +1565,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
                              /*BeforeElse=*/false,
                              /*BeforeLambdaBody=*/false,
                              /*BeforeWhile=*/false,
-                             /*IndentBraces=*/false,
+                             /*IndentBraces=*/{/*Enabled=*/false},
                              /*SplitEmptyFunction=*/true,
                              /*SplitEmptyRecord=*/true,
                              /*SplitEmptyNamespace=*/true};
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 61b84126fe1b9..a1452acabb330 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -135,7 +135,7 @@ class CompoundStatementIndenter {
       : CompoundStatementIndenter(Parser, LineLevel,
                                   Style.BraceWrapping.AfterControlStatement ==
                                       FormatStyle::BWACS_Always,
-                                  Style.BraceWrapping.IndentBraces) {}
+                                  Style.BraceWrapping.IndentBraces.Enabled) {}
   CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel,
                             bool WrapBrace, bool IndentBrace)
       : LineLevel(LineLevel), OldLineLevel(LineLevel) {
@@ -3349,9 +3349,9 @@ void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
   if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
       FormatTok->is(tok::l_brace)) {
 
-    CompoundStatementIndenter Indenter(this, Line->Level,
-                                       Style.BraceWrapping.AfterCaseLabel,
-                                       Style.BraceWrapping.IndentBraces);
+    CompoundStatementIndenter Indenter(
+        this, Line->Level, Style.BraceWrapping.AfterCaseLabel,
+        Style.BraceWrapping.IndentBraces.Enabled);
     parseBlock();
     if (FormatTok->is(tok::kw_break)) {
       if (Style.BraceWrapping.AfterControlStatement ==
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index aedfdd151d6d3..901ae689e6cf3 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -235,7 +235,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse);
   CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeLambdaBody);
   CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeWhile);
-  CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces);
   CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunction);
   CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyRecord);
   CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyNamespace);
@@ -757,6 +756,23 @@ TEST(ConfigParseTest, ParsesConfiguration) {
               "  AfterControlStatement: false",
               BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Never);
 
+  Style.BraceWrapping.IndentBraces.Enabled = false;
+  CHECK_PARSE("BraceWrapping:\n"
+              "  IndentBraces:\n"
+              "    Enabled: true",
+              BraceWrapping.IndentBraces.Enabled, true);
+  CHECK_PARSE("BraceWrapping:\n"
+              "  IndentBraces:\n"
+              "    Enabled: false",
+              BraceWrapping.IndentBraces.Enabled, false);
+  // For backward compatibility:
+  CHECK_PARSE("BraceWrapping:\n"
+              "  IndentBraces: true",
+              BraceWrapping.IndentBraces.Enabled, true);
+  CHECK_PARSE("BraceWrapping:\n"
+              "  IndentBraces: false",
+              BraceWrapping.IndentBraces.Enabled, false);
+
   Style.BreakAfterReturnType = FormatStyle::RTBS_All;
   CHECK_PARSE("BreakAfterReturnType: None", BreakAfterReturnType,
               FormatStyle::RTBS_None);

Copy link
Contributor

@mydeveloperday mydeveloperday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this fix, it needs tests to show what you are doing

@rmarker
Copy link
Contributor Author

rmarker commented Jun 15, 2025

I don't understand this fix, it needs tests to show what you are doing

This doesn't fix anything. Rather, it is upgrading IndentBraces to be a struct so that more options to control the indentation can be added to it in a subsequent PR. For example #143249 as a possibility.

The tests didn't end up being touched as the IndentBraces option currently isn't used in the tests and therefore didn't need to be updated. I imagine this is because, at the moment, its functionality is covered by the GNU brace wrapping tests, which use IndentBraces under the hood. New tests for the option would need to be added when extra options for indenting are added.
Though, if you think it is worthwhile, I could add initial tests to this PR based on the GNU brace wrapping tests? They would then act as a base for any subsequent PRs to build upon.

@owenca
Copy link
Contributor

owenca commented Jun 16, 2025

I don't understand this fix, it needs tests to show what you are doing

See #143249 (comment) and #143249 (comment). IMO, the current BraceWrapping.IndentBraces boolean is easy to understand: Indent (or not) the wrapped braces. I don't know if it makes sense to change it to an enum or struct, move it out of BraceWrapping, or add an IndentLambdaBraces to accommodate a very specific style in #143248.

@rmarker
Copy link
Contributor Author

rmarker commented Jun 16, 2025

Probably not a big deal, the one ambiguity with the current IndentBraces is that it only indents the wrapped braces associated with GNU. It doesn't indent all braces that have the option of being wrapped, such as namespace, class or functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category clang-format
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants