https://github.com/irymarchyk updated https://github.com/llvm/llvm-project/pull/134337
>From df25a8bbfd827085265c51a44bedbf38deebbab4 Mon Sep 17 00:00:00 2001 From: Ivan Rymarchyk <> Date: Sat, 29 Mar 2025 13:54:32 -0700 Subject: [PATCH 1/2] [clang-format]: Add `Custom` to `ShortFunctionStyle`; add new AllowShortFunctionsOnASingleLineOptions for granular setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current clang-format configuration option AllowShortFunctionsOnASingleLine uses a single enum (ShortFunctionStyle) to control when short function definitions can be merged onto a single line. This enum provides predefined combinations of conditions (e.g., None, Empty only, Inline only, Inline including Empty, All). This approach has limitations: 1. **Lack of Granularity:** Users cannot specify arbitrary combinations of conditions. For example, a user might want to allow merging for both empty functions and short top-level functions, but not for short functions defined within classes. This is not possible with the current enum options except by choosing All, which might merge more than desired. 2. **Inflexibility:** Adding new conditions for merging (e.g., distinguishing between member functions and constructors, handling lambdas specifically) would require adding many new combined enum values, leading to a combinatorial explosion and making the configuration complex. 3. **Implicit Behavior:** Some options imply others (e.g., Inline implies Empty), which might not always be intuitive or desired. The goal is to replace this single-choice enum with a more flexible mechanism allowing users to specify a set of conditions that must be met for a short function to be merged onto a single line. **Proposed Solution** 1. Introduce a new configuration option: AllowShortFunctionsOnSingleLineOptions. 2. This option will accept a list of strings, where each string represents a specific condition allowing merging. 3. **Backward Compatibility:** - If AllowShortFunctionsOnSingleLineOptions is present in the configuration, it takes precedence. - If AllowShortFunctionsOnSingleLineOptions is not present, but the old AllowShortFunctionsOnASingleLine is present, the old option should be parsed and mapped to the corresponding new semantics for compatibility. --- clang/docs/ClangFormatStyleOptions.rst | 64 +++++++++++ clang/include/clang/Format/Format.h | 70 ++++++++++++ clang/lib/Format/Format.cpp | 52 +++++++++ clang/lib/Format/TokenAnnotator.cpp | 7 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 9 +- clang/unittests/Format/ConfigParseTest.cpp | 6 ++ clang/unittests/Format/FormatTest.cpp | 111 ++++++++++++++++++++ 7 files changed, 310 insertions(+), 9 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 9ecac68ae72bf..167701cf6585d 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1959,6 +1959,70 @@ the configuration (without a prefix: ``Auto``). }; void f() { bar(); } + * ``SFS_Custom`` (in configuration: ``Custom``) + Configure merge behavior using AllowShortFunctionsOnASingleLineOptions + + + +.. _AllowShortFunctionsOnASingleLineOptions: + +**AllowShortFunctionsOnASingleLineOptions** (``ShortFunctionMergeFlags``) :versionbadge:`clang-format 21` :ref:`¶ <AllowShortFunctionsOnASingleLineOptions>` + Precise control over merging short functions + + If ``AllowShortFunctionsOnASingleLine`` is set to ``Custom``, use this to + specify behavior in different situations. + + .. code-block:: yaml + + # Example of usage: + AllowShortFunctionsOnASingleLine: Custom + AllowShortFunctionsOnASingleLineOptions: + Empty: false + Inline: true + All: false + + Nested configuration flags: + + Precise control over merging short functions + + .. code-block:: c++ + + # Should be declared this way: + AllowShortFunctionsOnASingleLine: Custom + AllowShortFunctionsOnASingleLineOptions: + Empty: false + Inline: true + All: false + + * ``bool Empty`` Only merge empty functions. + + .. code-block:: c++ + + void f() {} + void f2() { + bar2(); + } + + * ``bool Inline`` Only merge functions defined inside a class. + + .. code-block:: c++ + + class Foo { + void f() { foo(); } + }; + void f() { + foo(); + } + void f() {} + + * ``bool All`` Merge all functions fitting on a single line. + + .. code-block:: c++ + + class Foo { + void f() { foo(); } + }; + void f() { bar(); } .. _AllowShortIfStatementsOnASingleLine: diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index fec47a248abb4..96b1ecab04e63 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -871,6 +871,8 @@ struct FormatStyle { /// void f() { bar(); } /// \endcode SFS_All, + /// Configure merge behavior using AllowShortFunctionsOnASingleLineOptions + SFS_Custom, }; /// Dependent on the value, ``int f() { return 0; }`` can be put on a @@ -878,6 +880,72 @@ struct FormatStyle { /// \version 3.5 ShortFunctionStyle AllowShortFunctionsOnASingleLine; + /// Precise control over merging short functions + /// \code + /// # Should be declared this way: + /// AllowShortFunctionsOnASingleLine: Custom + /// AllowShortFunctionsOnASingleLineOptions: + /// Empty: false + /// Inline: true + /// All: false + /// \endcode + struct ShortFunctionMergeFlags { + /// Only merge empty functions. + /// \code + /// void f() {} + /// void f2() { + /// bar2(); + /// } + /// \endcode + bool Empty; + /// Only merge functions defined inside a class. + /// \code + /// class Foo { + /// void f() { foo(); } + /// }; + /// void f() { + /// foo(); + /// } + /// void f() {} + /// \endcode + bool Inline; + /// Merge all functions fitting on a single line. + /// \code + /// class Foo { + /// void f() { foo(); } + /// }; + /// void f() { bar(); } + /// \endcode + bool All; + + ShortFunctionMergeFlags() : Empty(false), Inline(false), All(false) {} + + ShortFunctionMergeFlags(bool Empty, bool Inline, bool All) + : Empty(Empty), Inline(Inline), All(All) {} + + bool operator==(const ShortFunctionMergeFlags &R) const { + return Empty == R.Empty && Inline == R.Inline && All == R.All; + } + bool operator!=(const ShortFunctionMergeFlags &R) const { + return !(*this == R); + } + }; + + /// Precise control over merging short functions + /// + /// If ``AllowShortFunctionsOnASingleLine`` is set to ``Custom``, use this to + /// specify behavior in different situations. + /// \code{.yaml} + /// # Example of usage: + /// AllowShortFunctionsOnASingleLine: Custom + /// AllowShortFunctionsOnASingleLineOptions: + /// Empty: false + /// Inline: true + /// All: false + /// \endcode + /// \version 21 + ShortFunctionMergeFlags AllowShortFunctionsOnASingleLineOptions; + /// Different styles for handling short if statements. enum ShortIfStyle : int8_t { /// Never put short ifs on the same line. @@ -5281,6 +5349,8 @@ struct FormatStyle { AllowShortEnumsOnASingleLine == R.AllowShortEnumsOnASingleLine && AllowShortFunctionsOnASingleLine == R.AllowShortFunctionsOnASingleLine && + AllowShortFunctionsOnASingleLineOptions == + R.AllowShortFunctionsOnASingleLineOptions && AllowShortIfStatementsOnASingleLine == R.AllowShortIfStatementsOnASingleLine && AllowShortLambdasOnASingleLine == R.AllowShortLambdasOnASingleLine && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 28aea86139e0d..21f896c6e9cf0 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -622,6 +622,15 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> { IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline); IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly); IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty); + IO.enumCase(Value, "Custom", FormatStyle::SFS_Custom); + } +}; + +template <> struct MappingTraits<FormatStyle::ShortFunctionMergeFlags> { + static void mapping(IO &IO, FormatStyle::ShortFunctionMergeFlags &Value) { + IO.mapOptional("Empty", Value.Empty); + IO.mapOptional("Inline", Value.Inline); + IO.mapOptional("All", Value.All); } }; @@ -982,6 +991,8 @@ template <> struct MappingTraits<FormatStyle> { Style.AllowShortEnumsOnASingleLine); IO.mapOptional("AllowShortFunctionsOnASingleLine", Style.AllowShortFunctionsOnASingleLine); + IO.mapOptional("AllowShortFunctionsOnASingleLineOptions", + Style.AllowShortFunctionsOnASingleLineOptions); IO.mapOptional("AllowShortIfStatementsOnASingleLine", Style.AllowShortIfStatementsOnASingleLine); IO.mapOptional("AllowShortLambdasOnASingleLine", @@ -1472,6 +1483,30 @@ static void expandPresetsSpacesInParens(FormatStyle &Expanded) { Expanded.SpacesInParensOptions = {}; } +static void expandPresetsShortFunctionsOnSingleLine(FormatStyle &Expanded) { + if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Custom) + return; + // Reset all flags + Expanded.AllowShortFunctionsOnASingleLineOptions = {}; + + if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None) + return; + + if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty || + Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline) { + Expanded.AllowShortFunctionsOnASingleLineOptions.Empty = true; + } + + if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline || + Expanded.AllowShortFunctionsOnASingleLine == + FormatStyle::SFS_InlineOnly) { + Expanded.AllowShortFunctionsOnASingleLineOptions.Inline = true; + } + + if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All) + Expanded.AllowShortFunctionsOnASingleLineOptions.All = true; +} + FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { FormatStyle LLVMStyle; LLVMStyle.AccessModifierOffset = -2; @@ -1501,6 +1536,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true; LLVMStyle.AllowShortEnumsOnASingleLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + LLVMStyle.AllowShortFunctionsOnASingleLineOptions = {}; + LLVMStyle.AllowShortFunctionsOnASingleLineOptions.All = true; LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; LLVMStyle.AllowShortLoopsOnASingleLine = false; @@ -1788,6 +1825,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.AlignTrailingComments = {}; GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {}; + GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true; GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; @@ -1798,6 +1837,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {}; + GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true; // TODO: still under discussion whether to switch to SLS_All. GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; @@ -1815,6 +1856,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.SpacesInContainerLiterals = false; } else if (Language == FormatStyle::LK_Proto) { GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {}; + GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; // This affects protocol buffer options specifications and text protos. // Text protos are currently mostly formatted inside C++ raw string literals @@ -1834,6 +1877,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { tooling::IncludeStyle::IBS_Preserve; } else if (Language == FormatStyle::LK_CSharp) { GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {}; + GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true; GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; GoogleStyle.BreakStringLiterals = false; GoogleStyle.ColumnLimit = 100; @@ -1893,6 +1938,8 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { } else { ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + ChromiumStyle.AllowShortFunctionsOnASingleLineOptions = {}; + ChromiumStyle.AllowShortFunctionsOnASingleLineOptions.Inline = true; ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; ChromiumStyle.AllowShortLoopsOnASingleLine = false; ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine; @@ -1907,6 +1954,8 @@ FormatStyle getMozillaStyle() { FormatStyle MozillaStyle = getLLVMStyle(); MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + MozillaStyle.AllowShortFunctionsOnASingleLineOptions = {}; + MozillaStyle.AllowShortFunctionsOnASingleLineOptions.Inline = true; MozillaStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_TopLevel; MozillaStyle.BinPackArguments = false; @@ -1989,6 +2038,7 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { Style.PenaltyReturnTypeOnItsOwnLine = 1000; Style.AllowShortEnumsOnASingleLine = false; Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLineOptions = {}; Style.AllowShortCaseLabelsOnASingleLine = false; Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; Style.AllowShortLoopsOnASingleLine = false; @@ -2160,6 +2210,7 @@ std::string configurationAsText(const FormatStyle &Style) { expandPresetsBraceWrapping(NonConstStyle); expandPresetsSpaceBeforeParens(NonConstStyle); expandPresetsSpacesInParens(NonConstStyle); + expandPresetsShortFunctionsOnSingleLine(NonConstStyle); Output << NonConstStyle; return Stream.str(); @@ -3722,6 +3773,7 @@ reformat(const FormatStyle &Style, StringRef Code, expandPresetsBraceWrapping(Expanded); expandPresetsSpaceBeforeParens(Expanded); expandPresetsSpacesInParens(Expanded); + expandPresetsShortFunctionsOnSingleLine(Expanded); Expanded.InsertBraces = false; Expanded.RemoveBracesLLVM = false; Expanded.RemoveParentheses = FormatStyle::RPS_Leave; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index d87b3a6088bd8..c058354918140 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5687,11 +5687,10 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && !Left.Children.empty()) { // Support AllowShortFunctionsOnASingleLine for JavaScript. - return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None || - Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty || + return (!Style.AllowShortFunctionsOnASingleLineOptions.Inline && + !Style.AllowShortFunctionsOnASingleLineOptions.All) || (Left.NestingLevel == 0 && Line.Level == 0 && - Style.AllowShortFunctionsOnASingleLine & - FormatStyle::SFS_InlineOnly); + Style.AllowShortFunctionsOnASingleLineOptions.Inline); } } else if (Style.Language == FormatStyle::LK_Java) { if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight && diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 000a5105ca407..5be28e895aab6 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -293,15 +293,14 @@ class LineJoiner { auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine, TheLine]() { - if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All) + if (Style.AllowShortFunctionsOnASingleLineOptions.All) return true; - if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && + if (Style.AllowShortFunctionsOnASingleLineOptions.Empty && NextLine.First->is(tok::r_brace)) { return true; } - if (Style.AllowShortFunctionsOnASingleLine & - FormatStyle::SFS_InlineOnly) { + if (Style.AllowShortFunctionsOnASingleLineOptions.Inline) { // Just checking TheLine->Level != 0 is not enough, because it // provokes treating functions inside indented namespaces as short. if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace)) @@ -551,7 +550,7 @@ class LineJoiner { unsigned MergedLines = 0; if (MergeShortFunctions || - (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && + (Style.AllowShortFunctionsOnASingleLineOptions.Empty && NextLine.First == NextLine.Last && I + 2 != E && I[2]->First->is(tok::r_brace))) { MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 287191d04d885..54e484fcbe4cd 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -256,6 +256,9 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InConditionalStatements); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InEmptyParentheses); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, Other); + CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Empty); + CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Inline); + CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, All); } #undef CHECK_PARSE_BOOL @@ -620,6 +623,9 @@ TEST(ConfigParseTest, ParsesConfiguration) { AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Empty); CHECK_PARSE("AllowShortFunctionsOnASingleLine: All", AllowShortFunctionsOnASingleLine, FormatStyle::SFS_All); + CHECK_PARSE("AllowShortFunctionsOnASingleLine: Custom", + AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Custom); + // For backward compatibility: CHECK_PARSE("AllowShortFunctionsOnASingleLine: false", AllowShortFunctionsOnASingleLine, FormatStyle::SFS_None); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 0b90bd360b758..868d4e375b953 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -15120,6 +15120,117 @@ TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) { MergeInlineOnly); } +TEST_F(FormatTest, CustomShortFunctionOptions) { + FormatStyle CustomEmpty = getLLVMStyle(); + CustomEmpty.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; + CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Empty = true; + CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Inline = false; + CustomEmpty.AllowShortFunctionsOnASingleLineOptions.All = false; + + // Empty functions should be on a single line + verifyFormat("int f() {}", CustomEmpty); + verifyFormat("class C {\n" + " int f() {}\n" + "};", + CustomEmpty); + + // Non-empty functions should be multi-line + verifyFormat("int f() {\n" + " return 42;\n" + "}", + CustomEmpty); + verifyFormat("class C {\n" + " int f() {\n" + " return 42;\n" + " }\n" + "};", + CustomEmpty); + + // Test with AfterFunction = true + CustomEmpty.BreakBeforeBraces = FormatStyle::BS_Custom; + CustomEmpty.BraceWrapping.AfterFunction = true; + verifyFormat("int f() {}", CustomEmpty); + verifyFormat("int g()\n" + "{\n" + " return 42;\n" + "}", + CustomEmpty); + + // Test with Inline = true, All = false + FormatStyle CustomInline = getLLVMStyle(); + CustomInline.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; + CustomInline.AllowShortFunctionsOnASingleLineOptions.Empty = false; + CustomInline.AllowShortFunctionsOnASingleLineOptions.Inline = true; + CustomInline.AllowShortFunctionsOnASingleLineOptions.All = false; + + verifyFormat("class C {\n" + " int f() {}\n" + "};", + CustomInline); + + // Non-empty inline functions should be single-line + verifyFormat("class C {\n" + " int f() { return 42; }\n" + "};", + CustomInline); + + // Non-inline functions should be multi-line + verifyFormat("int f() {\n" + " return 42;\n" + "}", + CustomInline); + verifyFormat("int g() {\n" + "}", + CustomInline); + + // Test with All = true + FormatStyle CustomAll = getLLVMStyle(); + CustomAll.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; + CustomAll.AllowShortFunctionsOnASingleLineOptions.Empty = false; + CustomAll.AllowShortFunctionsOnASingleLineOptions.Inline = false; + CustomAll.AllowShortFunctionsOnASingleLineOptions.All = true; + + // All functions should be on a single line if they fit + verifyFormat("int f() { return 42; }", CustomAll); + verifyFormat("int g() { return f() + h(); }", CustomAll); + verifyFormat("class C {\n" + " int f() { return 42; }\n" + "};", + CustomAll); + + verifyFormat("int f() {}", CustomAll); + verifyFormat("class C {\n" + " int f() {}\n" + "};", + CustomAll); + + // Test various combinations + FormatStyle CustomMixed = getLLVMStyle(); + CustomMixed.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; + CustomMixed.AllowShortFunctionsOnASingleLineOptions.Empty = true; + CustomMixed.AllowShortFunctionsOnASingleLineOptions.Inline = true; + CustomMixed.AllowShortFunctionsOnASingleLineOptions.All = false; + + // Empty functions should be on a single line + verifyFormat("int f() {}", CustomMixed); + verifyFormat("class C {\n" + " int f() {}\n" + "};", + CustomMixed); + + // Inline non-empty functions should be on a single line + verifyFormat("class C {\n" + " int f() { return 42; }\n" + "};", + CustomMixed); + + // Non-inline non-empty functions should be multi-line + verifyFormat("int f() {\n" + " return 42;\n" + "}", + CustomMixed); +} + TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) { FormatStyle MergeInlineOnly = getLLVMStyle(); MergeInlineOnly.AllowShortFunctionsOnASingleLine = >From e9e4e92afca915bfeba3fac0227930a99a5daa34 Mon Sep 17 00:00:00 2001 From: Ivan Rymarchyk <> Date: Fri, 4 Apr 2025 18:20:28 -0700 Subject: [PATCH 2/2] PR-134337: fixed PR comments --- clang/docs/ClangFormatStyleOptions.rst | 11 +++++++---- clang/include/clang/Format/Format.h | 17 ++++++++++------- clang/lib/Format/Format.cpp | 6 +++--- clang/lib/Format/TokenAnnotator.cpp | 2 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 2 +- clang/unittests/Format/ConfigParseTest.cpp | 2 +- clang/unittests/Format/FormatTest.cpp | 11 +++++++---- 7 files changed, 30 insertions(+), 21 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 167701cf6585d..c0529dd138f59 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1994,7 +1994,7 @@ the configuration (without a prefix: ``Auto``). Inline: true All: false - * ``bool Empty`` Only merge empty functions. + * ``bool Empty`` Merge top-level empty functions. .. code-block:: c++ @@ -2002,20 +2002,23 @@ the configuration (without a prefix: ``Auto``). void f2() { bar2(); } + void f3() { /* comment */ } - * ``bool Inline`` Only merge functions defined inside a class. + * ``bool Inline`` Merge functions defined inside a class. .. code-block:: c++ class Foo { void f() { foo(); } + void g() {} }; void f() { foo(); } - void f() {} + void f() { + } - * ``bool All`` Merge all functions fitting on a single line. + * ``bool Other`` Merge all functions fitting on a single line. .. code-block:: c++ diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 96b1ecab04e63..971b978adc2c7 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -890,23 +890,26 @@ struct FormatStyle { /// All: false /// \endcode struct ShortFunctionMergeFlags { - /// Only merge empty functions. + /// Merge top-level empty functions. /// \code /// void f() {} /// void f2() { /// bar2(); /// } + /// void f3() { /* comment */ } /// \endcode bool Empty; - /// Only merge functions defined inside a class. + /// Merge functions defined inside a class. /// \code /// class Foo { /// void f() { foo(); } + /// void g() {} /// }; /// void f() { /// foo(); /// } - /// void f() {} + /// void f() { + /// } /// \endcode bool Inline; /// Merge all functions fitting on a single line. @@ -916,15 +919,15 @@ struct FormatStyle { /// }; /// void f() { bar(); } /// \endcode - bool All; + bool Other; - ShortFunctionMergeFlags() : Empty(false), Inline(false), All(false) {} + ShortFunctionMergeFlags() : Empty(false), Inline(false), Other(false) {} ShortFunctionMergeFlags(bool Empty, bool Inline, bool All) - : Empty(Empty), Inline(Inline), All(All) {} + : Empty(Empty), Inline(Inline), Other(All) {} bool operator==(const ShortFunctionMergeFlags &R) const { - return Empty == R.Empty && Inline == R.Inline && All == R.All; + return Empty == R.Empty && Inline == R.Inline && Other == R.Other; } bool operator!=(const ShortFunctionMergeFlags &R) const { return !(*this == R); diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 21f896c6e9cf0..aff38f56f05e3 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -630,7 +630,7 @@ template <> struct MappingTraits<FormatStyle::ShortFunctionMergeFlags> { static void mapping(IO &IO, FormatStyle::ShortFunctionMergeFlags &Value) { IO.mapOptional("Empty", Value.Empty); IO.mapOptional("Inline", Value.Inline); - IO.mapOptional("All", Value.All); + IO.mapOptional("Other", Value.Other); } }; @@ -1504,7 +1504,7 @@ static void expandPresetsShortFunctionsOnSingleLine(FormatStyle &Expanded) { } if (Expanded.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All) - Expanded.AllowShortFunctionsOnASingleLineOptions.All = true; + Expanded.AllowShortFunctionsOnASingleLineOptions.Other = true; } FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { @@ -1537,7 +1537,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AllowShortEnumsOnASingleLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortFunctionsOnASingleLineOptions = {}; - LLVMStyle.AllowShortFunctionsOnASingleLineOptions.All = true; + LLVMStyle.AllowShortFunctionsOnASingleLineOptions.Other = true; LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; LLVMStyle.AllowShortLoopsOnASingleLine = false; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index c058354918140..cdf46f65e8b52 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5688,7 +5688,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, !Left.Children.empty()) { // Support AllowShortFunctionsOnASingleLine for JavaScript. return (!Style.AllowShortFunctionsOnASingleLineOptions.Inline && - !Style.AllowShortFunctionsOnASingleLineOptions.All) || + !Style.AllowShortFunctionsOnASingleLineOptions.Other) || (Left.NestingLevel == 0 && Line.Level == 0 && Style.AllowShortFunctionsOnASingleLineOptions.Inline); } diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 5be28e895aab6..6f30bbc8a9e5f 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -293,7 +293,7 @@ class LineJoiner { auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine, TheLine]() { - if (Style.AllowShortFunctionsOnASingleLineOptions.All) + if (Style.AllowShortFunctionsOnASingleLineOptions.Other) return true; if (Style.AllowShortFunctionsOnASingleLineOptions.Empty && NextLine.First->is(tok::r_brace)) { diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 54e484fcbe4cd..16ab406c9cade 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -258,7 +258,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, Other); CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Empty); CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Inline); - CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, All); + CHECK_PARSE_NESTED_BOOL(AllowShortFunctionsOnASingleLineOptions, Other); } #undef CHECK_PARSE_BOOL diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 868d4e375b953..79ee1230eb6a7 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -15125,7 +15125,7 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { CustomEmpty.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Empty = true; CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Inline = false; - CustomEmpty.AllowShortFunctionsOnASingleLineOptions.All = false; + CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Other = false; // Empty functions should be on a single line verifyFormat("int f() {}", CustomEmpty); @@ -15146,6 +15146,9 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { "};", CustomEmpty); + // test with comment + verifyFormat("void f3() { /* comment */ }", CustomEmpty); + // Test with AfterFunction = true CustomEmpty.BreakBeforeBraces = FormatStyle::BS_Custom; CustomEmpty.BraceWrapping.AfterFunction = true; @@ -15161,7 +15164,7 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { CustomInline.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; CustomInline.AllowShortFunctionsOnASingleLineOptions.Empty = false; CustomInline.AllowShortFunctionsOnASingleLineOptions.Inline = true; - CustomInline.AllowShortFunctionsOnASingleLineOptions.All = false; + CustomInline.AllowShortFunctionsOnASingleLineOptions.Other = false; verifyFormat("class C {\n" " int f() {}\n" @@ -15188,7 +15191,7 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { CustomAll.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; CustomAll.AllowShortFunctionsOnASingleLineOptions.Empty = false; CustomAll.AllowShortFunctionsOnASingleLineOptions.Inline = false; - CustomAll.AllowShortFunctionsOnASingleLineOptions.All = true; + CustomAll.AllowShortFunctionsOnASingleLineOptions.Other = true; // All functions should be on a single line if they fit verifyFormat("int f() { return 42; }", CustomAll); @@ -15209,7 +15212,7 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { CustomMixed.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; CustomMixed.AllowShortFunctionsOnASingleLineOptions.Empty = true; CustomMixed.AllowShortFunctionsOnASingleLineOptions.Inline = true; - CustomMixed.AllowShortFunctionsOnASingleLineOptions.All = false; + CustomMixed.AllowShortFunctionsOnASingleLineOptions.Other = false; // Empty functions should be on a single line verifyFormat("int f() {}", CustomMixed); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits