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/8] [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/8] 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); >From b1fd41217c49400248780ba6fb7a2ac0a355937c Mon Sep 17 00:00:00 2001 From: Ivan Rymarchyk <> Date: Mon, 7 Apr 2025 21:05:17 -0700 Subject: [PATCH 3/8] Updated configuration with new suggestion - reuse existing option --- clang/docs/ClangFormatStyleOptions.rst | 51 ++---- clang/include/clang/Format/Format.h | 152 ++++++++---------- clang/lib/Format/Format.cpp | 120 +++++++------- clang/lib/Format/TokenAnnotator.cpp | 7 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 8 +- clang/unittests/Format/ConfigParseTest.cpp | 38 +++-- .../Format/DefinitionBlockSeparatorTest.cpp | 4 +- clang/unittests/Format/FormatTest.cpp | 124 +++++++++----- clang/unittests/Format/FormatTestCSharp.cpp | 5 +- clang/unittests/Format/FormatTestJS.cpp | 27 +++- clang/unittests/Format/FormatTestJava.cpp | 5 +- 11 files changed, 289 insertions(+), 252 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index c0529dd138f59..6f3b9f798093f 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1905,12 +1905,16 @@ the configuration (without a prefix: ``Auto``). Dependent on the value, ``int f() { return 0; }`` can be put on a single line. - Possible values: + Nested configuration flags: + + Different styles for merging short functions containing at most one + statement. - * ``SFS_None`` (in configuration: ``None``) + They can be read as a whole for compatibility. The choices are: + * ``None`` Never merge functions into a single line. - * ``SFS_InlineOnly`` (in configuration: ``InlineOnly``) + * ``InlineOnly`` Only merge functions defined inside a class. Same as ``inline``, except it does not implies ``empty``: i.e. top level empty functions are not merged either. @@ -1926,7 +1930,7 @@ the configuration (without a prefix: ``Auto``). void f() { } - * ``SFS_Empty`` (in configuration: ``Empty``) + * ``Empty`` Only merge empty functions. .. code-block:: c++ @@ -1936,7 +1940,7 @@ the configuration (without a prefix: ``Auto``). bar2(); } - * ``SFS_Inline`` (in configuration: ``Inline``) + * ``Inline`` Only merge functions defined inside a class. Implies ``empty``. .. code-block:: c++ @@ -1949,7 +1953,7 @@ the configuration (without a prefix: ``Auto``). } void f() {} - * ``SFS_All`` (in configuration: ``All``) + * ``All`` Merge all functions fitting on a single line. .. code-block:: c++ @@ -1959,37 +1963,15 @@ the configuration (without a prefix: ``Auto``). }; void f() { bar(); } - * ``SFS_Custom`` (in configuration: ``Custom``) - Configure merge behavior using AllowShortFunctionsOnASingleLineOptions - + Also can be specified as a nested configuration flag: - -.. _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 + .. code-block:: c++ # Example of usage: - AllowShortFunctionsOnASingleLine: Custom - AllowShortFunctionsOnASingleLineOptions: - Empty: false - Inline: true - All: false - - Nested configuration flags: - - Precise control over merging short functions + AllowShortFunctionsOnASingleLine: InlineOnly - .. code-block:: c++ - - # Should be declared this way: - AllowShortFunctionsOnASingleLine: Custom - AllowShortFunctionsOnASingleLineOptions: + # or more granular control: + AllowShortFunctionsOnASingleLine: Empty: false Inline: true All: false @@ -2018,7 +2000,8 @@ the configuration (without a prefix: ``Auto``). void f() { } - * ``bool Other`` Merge all functions fitting on a single line. + * ``bool Other`` Merge all functions fitting on a single line. Please note that this + control does not include Empty .. code-block:: c++ diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 971b978adc2c7..2278bf3966296 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -827,69 +827,68 @@ struct FormatStyle { /// Different styles for merging short functions containing at most one /// statement. - enum ShortFunctionStyle : int8_t { - /// Never merge functions into a single line. - SFS_None, - /// Only merge functions defined inside a class. Same as ``inline``, - /// except it does not implies ``empty``: i.e. top level empty functions - /// are not merged either. - /// \code - /// class Foo { - /// void f() { foo(); } - /// }; - /// void f() { - /// foo(); - /// } - /// void f() { - /// } - /// \endcode - SFS_InlineOnly, - /// Only merge empty functions. - /// \code - /// void f() {} - /// void f2() { - /// bar2(); - /// } - /// \endcode - SFS_Empty, - /// Only merge functions defined inside a class. Implies ``empty``. - /// \code - /// class Foo { - /// void f() { foo(); } - /// }; - /// void f() { - /// foo(); - /// } - /// void f() {} - /// \endcode - SFS_Inline, - /// Merge all functions fitting on a single line. - /// \code - /// class Foo { - /// void f() { foo(); } - /// }; - /// 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 - /// single line. - /// \version 3.5 - ShortFunctionStyle AllowShortFunctionsOnASingleLine; - - /// Precise control over merging short functions + /// + /// They can be read as a whole for compatibility. The choices are: + /// * ``None`` + /// Never merge functions into a single line. + /// + /// * ``InlineOnly`` + /// Only merge functions defined inside a class. Same as ``inline``, + /// except it does not implies ``empty``: i.e. top level empty functions + /// are not merged either. + /// \code + /// class Foo { + /// void f() { foo(); } + /// }; + /// void f() { + /// foo(); + /// } + /// void f() { + /// } + /// \endcode + /// + /// * ``Empty`` + /// Only merge empty functions. + /// \code + /// void f() {} + /// void f2() { + /// bar2(); + /// } + /// \endcode + /// + /// * ``Inline`` + /// Only merge functions defined inside a class. Implies ``empty``. + /// \code + /// class Foo { + /// void f() { foo(); } + /// }; + /// void f() { + /// foo(); + /// } + /// void f() {} + /// \endcode + /// + /// * ``All`` + /// Merge all functions fitting on a single line. + /// \code + /// class Foo { + /// void f() { foo(); } + /// }; + /// void f() { bar(); } + /// \endcode + /// + /// Also can be specified as a nested configuration flag: /// \code - /// # Should be declared this way: - /// AllowShortFunctionsOnASingleLine: Custom - /// AllowShortFunctionsOnASingleLineOptions: + /// # Example of usage: + /// AllowShortFunctionsOnASingleLine: InlineOnly + /// + /// # or more granular control: + /// AllowShortFunctionsOnASingleLine: /// Empty: false /// Inline: true /// All: false /// \endcode - struct ShortFunctionMergeFlags { + struct ShortFunctionStyle { /// Merge top-level empty functions. /// \code /// void f() {} @@ -912,7 +911,8 @@ struct FormatStyle { /// } /// \endcode bool Inline; - /// Merge all functions fitting on a single line. + /// Merge all functions fitting on a single line. Please note that this + /// control does not include Empty /// \code /// class Foo { /// void f() { foo(); } @@ -921,33 +921,19 @@ struct FormatStyle { /// \endcode bool Other; - ShortFunctionMergeFlags() : Empty(false), Inline(false), Other(false) {} - - ShortFunctionMergeFlags(bool Empty, bool Inline, bool All) - : Empty(Empty), Inline(Inline), Other(All) {} - - bool operator==(const ShortFunctionMergeFlags &R) const { + bool operator==(const ShortFunctionStyle &R) const { return Empty == R.Empty && Inline == R.Inline && Other == R.Other; } - bool operator!=(const ShortFunctionMergeFlags &R) const { - return !(*this == R); - } + bool operator!=(const ShortFunctionStyle &R) const { return !(*this == R); } + ShortFunctionStyle() : Empty(false), Inline(false), Other(false) {} + ShortFunctionStyle(bool Empty, bool Inline, bool Other) + : Empty(Empty), Inline(Inline), Other(Other) {} }; - /// 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; + /// Dependent on the value, ``int f() { return 0; }`` can be put on a + /// single line. + /// \version 3.5 + ShortFunctionStyle AllowShortFunctionsOnASingleLine; /// Different styles for handling short if statements. enum ShortIfStyle : int8_t { @@ -5352,8 +5338,6 @@ 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 aff38f56f05e3..c1a7a0a034a22 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -613,21 +613,35 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> { } }; -template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> { - static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { - IO.enumCase(Value, "None", FormatStyle::SFS_None); - IO.enumCase(Value, "false", FormatStyle::SFS_None); - IO.enumCase(Value, "All", FormatStyle::SFS_All); - IO.enumCase(Value, "true", FormatStyle::SFS_All); - 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::ShortFunctionStyle> { + static void enumInput(IO &IO, FormatStyle::ShortFunctionStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::ShortFunctionStyle({})); + IO.enumCase(Value, "Empty", + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false})); + IO.enumCase(Value, "Inline", + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false})); + IO.enumCase(Value, "InlineOnly", + FormatStyle::ShortFunctionStyle({/*Empty=*/false, + /*Inline=*/true, + /*Other=*/false})); + IO.enumCase(Value, "All", + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true})); + + // For backward compatibility. + IO.enumCase(Value, "true", + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true})); + IO.enumCase(Value, "false", FormatStyle::ShortFunctionStyle({})); } -}; -template <> struct MappingTraits<FormatStyle::ShortFunctionMergeFlags> { - static void mapping(IO &IO, FormatStyle::ShortFunctionMergeFlags &Value) { + static void mapping(IO &IO, FormatStyle::ShortFunctionStyle &Value) { IO.mapOptional("Empty", Value.Empty); IO.mapOptional("Inline", Value.Inline); IO.mapOptional("Other", Value.Other); @@ -991,8 +1005,6 @@ template <> struct MappingTraits<FormatStyle> { Style.AllowShortEnumsOnASingleLine); IO.mapOptional("AllowShortFunctionsOnASingleLine", Style.AllowShortFunctionsOnASingleLine); - IO.mapOptional("AllowShortFunctionsOnASingleLineOptions", - Style.AllowShortFunctionsOnASingleLineOptions); IO.mapOptional("AllowShortIfStatementsOnASingleLine", Style.AllowShortIfStatementsOnASingleLine); IO.mapOptional("AllowShortLambdasOnASingleLine", @@ -1483,30 +1495,6 @@ 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.Other = true; -} - FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { FormatStyle LLVMStyle; LLVMStyle.AccessModifierOffset = -2; @@ -1535,9 +1523,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true; LLVMStyle.AllowShortEnumsOnASingleLine = true; - LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; - LLVMStyle.AllowShortFunctionsOnASingleLineOptions = {}; - LLVMStyle.AllowShortFunctionsOnASingleLineOptions.Other = true; + LLVMStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; LLVMStyle.AllowShortLoopsOnASingleLine = false; @@ -1824,9 +1813,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; GoogleStyle.AlignTrailingComments = {}; GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; - GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; - GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {}; - GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true; + GoogleStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false}); GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; @@ -1836,9 +1826,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { } else if (Language == FormatStyle::LK_JavaScript) { GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; - GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; - GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {}; - GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true; + GoogleStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false}); // TODO: still under discussion whether to switch to SLS_All. GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; @@ -1855,9 +1846,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; GoogleStyle.SpacesInContainerLiterals = false; } else if (Language == FormatStyle::LK_Proto) { - GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; - GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {}; - GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true; + GoogleStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false}); GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; // This affects protocol buffer options specifications and text protos. // Text protos are currently mostly formatted inside C++ raw string literals @@ -1876,9 +1868,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; } else if (Language == FormatStyle::LK_CSharp) { - GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; - GoogleStyle.AllowShortFunctionsOnASingleLineOptions = {}; - GoogleStyle.AllowShortFunctionsOnASingleLineOptions.Empty = true; + GoogleStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false}); GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; GoogleStyle.BreakStringLiterals = false; GoogleStyle.ColumnLimit = 100; @@ -1937,9 +1930,10 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { ChromiumStyle.AllowShortLoopsOnASingleLine = false; } else { ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; - ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; - ChromiumStyle.AllowShortFunctionsOnASingleLineOptions = {}; - ChromiumStyle.AllowShortFunctionsOnASingleLineOptions.Inline = true; + ChromiumStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; ChromiumStyle.AllowShortLoopsOnASingleLine = false; ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine; @@ -1953,9 +1947,10 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { FormatStyle getMozillaStyle() { FormatStyle MozillaStyle = getLLVMStyle(); MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; - MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; - MozillaStyle.AllowShortFunctionsOnASingleLineOptions = {}; - MozillaStyle.AllowShortFunctionsOnASingleLineOptions.Inline = true; + MozillaStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); MozillaStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_TopLevel; MozillaStyle.BinPackArguments = false; @@ -2037,8 +2032,7 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { Style.BraceWrapping.BeforeWhile = false; Style.PenaltyReturnTypeOnItsOwnLine = 1000; Style.AllowShortEnumsOnASingleLine = false; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; - Style.AllowShortFunctionsOnASingleLineOptions = {}; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); Style.AllowShortCaseLabelsOnASingleLine = false; Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; Style.AllowShortLoopsOnASingleLine = false; @@ -2210,7 +2204,6 @@ std::string configurationAsText(const FormatStyle &Style) { expandPresetsBraceWrapping(NonConstStyle); expandPresetsSpaceBeforeParens(NonConstStyle); expandPresetsSpacesInParens(NonConstStyle); - expandPresetsShortFunctionsOnSingleLine(NonConstStyle); Output << NonConstStyle; return Stream.str(); @@ -3773,7 +3766,6 @@ 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 cdf46f65e8b52..db2f8766f8d40 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5687,10 +5687,11 @@ 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.AllowShortFunctionsOnASingleLineOptions.Inline && - !Style.AllowShortFunctionsOnASingleLineOptions.Other) || + return (!Style.AllowShortFunctionsOnASingleLine.Inline && + !Style.AllowShortFunctionsOnASingleLine.Other) || (Left.NestingLevel == 0 && Line.Level == 0 && - Style.AllowShortFunctionsOnASingleLineOptions.Inline); + Style.AllowShortFunctionsOnASingleLine.Inline && + !Style.AllowShortFunctionsOnASingleLine.Other); } } 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 6f30bbc8a9e5f..fdec849cf363a 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -293,14 +293,14 @@ class LineJoiner { auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine, TheLine]() { - if (Style.AllowShortFunctionsOnASingleLineOptions.Other) + if (Style.AllowShortFunctionsOnASingleLine.Other) return true; - if (Style.AllowShortFunctionsOnASingleLineOptions.Empty && + if (Style.AllowShortFunctionsOnASingleLine.Empty && NextLine.First->is(tok::r_brace)) { return true; } - if (Style.AllowShortFunctionsOnASingleLineOptions.Inline) { + if (Style.AllowShortFunctionsOnASingleLine.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)) @@ -550,7 +550,7 @@ class LineJoiner { unsigned MergedLines = 0; if (MergeShortFunctions || - (Style.AllowShortFunctionsOnASingleLineOptions.Empty && + (Style.AllowShortFunctionsOnASingleLine.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 16ab406c9cade..c022db94cdb6a 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -256,9 +256,6 @@ 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, Other); } #undef CHECK_PARSE_BOOL @@ -614,23 +611,40 @@ TEST(ConfigParseTest, ParsesConfiguration) { CHECK_PARSE("AllowShortBlocksOnASingleLine: true", AllowShortBlocksOnASingleLine, FormatStyle::SBS_Always); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + // Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; CHECK_PARSE("AllowShortFunctionsOnASingleLine: None", - AllowShortFunctionsOnASingleLine, FormatStyle::SFS_None); + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle({})); CHECK_PARSE("AllowShortFunctionsOnASingleLine: Inline", - AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Inline); + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false})); CHECK_PARSE("AllowShortFunctionsOnASingleLine: Empty", - AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Empty); + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false})); CHECK_PARSE("AllowShortFunctionsOnASingleLine: All", - AllowShortFunctionsOnASingleLine, FormatStyle::SFS_All); - CHECK_PARSE("AllowShortFunctionsOnASingleLine: Custom", - AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Custom); + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true})); + CHECK_PARSE("AllowShortFunctionsOnASingleLine: InlineOnly", + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle({/*Empty=*/false, + /*Inline=*/true, + /*Other=*/false})); // For backward compatibility: CHECK_PARSE("AllowShortFunctionsOnASingleLine: false", - AllowShortFunctionsOnASingleLine, FormatStyle::SFS_None); + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle({})); CHECK_PARSE("AllowShortFunctionsOnASingleLine: true", - AllowShortFunctionsOnASingleLine, FormatStyle::SFS_All); + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true})); Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; CHECK_PARSE("AllowShortLambdasOnASingleLine: None", diff --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp index b26b9f4f4ff62..d3d0a0b56b5a0 100644 --- a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp +++ b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp @@ -540,7 +540,7 @@ TEST_F(DefinitionBlockSeparatorTest, Leave) { TEST_F(DefinitionBlockSeparatorTest, CSharp) { FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp); Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); Style.AllowShortEnumsOnASingleLine = false; verifyFormat("namespace {\r\n" "public class SomeTinyClass {\r\n" @@ -581,7 +581,7 @@ TEST_F(DefinitionBlockSeparatorTest, CSharp) { TEST_F(DefinitionBlockSeparatorTest, JavaScript) { FormatStyle Style = getLLVMStyle(FormatStyle::LK_JavaScript); Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); Style.AllowShortEnumsOnASingleLine = false; verifyFormat("export const enum Foo {\n" " A = 1,\n" diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 79ee1230eb6a7..382e9e855b622 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -388,7 +388,10 @@ TEST_F(FormatTest, RemovesEmptyLines) { "} // namespace"); FormatStyle Style = getLLVMStyle(); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); Style.MaxEmptyLinesToKeep = 2; Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterClass = true; @@ -3377,13 +3380,16 @@ TEST_F(FormatTest, MultiLineControlStatements) { Style.BraceWrapping.AfterFunction = true; Style.BraceWrapping.AfterStruct = false; Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_MultiLine; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); Style.ColumnLimit = 80; verifyFormat("void shortfunction() { bar(); }", Style); verifyFormat("struct T shortfunction() { return bar(); }", Style); verifyFormat("struct T {};", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); verifyFormat("void shortfunction()\n" "{\n" " bar();\n" @@ -3398,7 +3404,10 @@ TEST_F(FormatTest, MultiLineControlStatements) { Style.BraceWrapping.AfterFunction = false; Style.BraceWrapping.AfterStruct = true; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); verifyFormat("void shortfunction() { bar(); }", Style); verifyFormat("struct T shortfunction() { return bar(); }", Style); verifyFormat("struct T\n" @@ -3406,7 +3415,7 @@ TEST_F(FormatTest, MultiLineControlStatements) { "};", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); verifyFormat("void shortfunction() {\n" " bar();\n" "}", @@ -4201,7 +4210,9 @@ TEST_F(FormatTest, FormatsNamespaces) { FormatStyle ShortInlineFunctions = getLLVMStyle(); ShortInlineFunctions.NamespaceIndentation = FormatStyle::NI_All; ShortInlineFunctions.AllowShortFunctionsOnASingleLine = - FormatStyle::SFS_Inline; + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); verifyFormat("namespace {\n" " void f() {\n" " return;\n" @@ -8326,7 +8337,7 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) { "};", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); verifyNoChange("SomeClass::Constructor() :\n" " a(a), b(b), c(c) {\n" "}", @@ -8337,7 +8348,10 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) { Style); Style.ColumnLimit = 80; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); Style.ConstructorInitializerIndentWidth = 2; verifyFormat("SomeClass::Constructor() : a(a), b(b), c(c) {}", Style); verifyFormat("SomeClass::Constructor() :\n" @@ -12671,7 +12685,8 @@ TEST_F(FormatTest, UnderstandsAttributes) { verifyFormat("__attr1(nodebug) ::qualified_type f();", CustomAttrs); // Check that these are not parsed as function declarations: - CustomAttrs.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + CustomAttrs.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({}); CustomAttrs.BreakBeforeBraces = FormatStyle::BS_Allman; verifyFormat("SomeType s(InitValue);", CustomAttrs); verifyFormat("SomeType s{InitValue};", CustomAttrs); @@ -12772,7 +12787,8 @@ TEST_F(FormatTest, UnderstandsSquareAttributes) { // Make sure we do not parse attributes as lambda introducers. FormatStyle MultiLineFunctions = getLLVMStyle(); - MultiLineFunctions.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + MultiLineFunctions.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({}); verifyFormat("[[unused]] int b() {\n" " return 42;\n" "}", @@ -14870,7 +14886,8 @@ TEST_F(FormatTest, FormatsBracedListsInColumnLayout) { TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { FormatStyle DoNotMerge = getLLVMStyle(); - DoNotMerge.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + DoNotMerge.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({}); verifyFormat("void f() { return 42; }"); verifyFormat("void f() {\n" @@ -14941,7 +14958,7 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { FormatStyle DoNotMergeNoColumnLimit = NoColumnLimit; DoNotMergeNoColumnLimit.AllowShortFunctionsOnASingleLine = - FormatStyle::SFS_None; + FormatStyle::ShortFunctionStyle({}); verifyFormat("A() : b(0) {\n" "}", DoNotMergeNoColumnLimit); @@ -14989,7 +15006,10 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { TEST_F(FormatTest, PullEmptyFunctionDefinitionsIntoSingleLine) { FormatStyle MergeEmptyOnly = getLLVMStyle(); - MergeEmptyOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + MergeEmptyOnly.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false}); verifyFormat("class C {\n" " int f() {}\n" "};", @@ -15018,7 +15038,10 @@ TEST_F(FormatTest, PullEmptyFunctionDefinitionsIntoSingleLine) { TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) { FormatStyle MergeInlineOnly = getLLVMStyle(); - MergeInlineOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + MergeInlineOnly.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); verifyFormat("class C {\n" " int f() { return 42; }\n" "};", @@ -15122,10 +15145,10 @@ TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) { TEST_F(FormatTest, CustomShortFunctionOptions) { FormatStyle CustomEmpty = getLLVMStyle(); - CustomEmpty.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; - CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Empty = true; - CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Inline = false; - CustomEmpty.AllowShortFunctionsOnASingleLineOptions.Other = false; + CustomEmpty.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false}); // Empty functions should be on a single line verifyFormat("int f() {}", CustomEmpty); @@ -15161,10 +15184,10 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { // Test with Inline = true, All = false FormatStyle CustomInline = getLLVMStyle(); - CustomInline.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; - CustomInline.AllowShortFunctionsOnASingleLineOptions.Empty = false; - CustomInline.AllowShortFunctionsOnASingleLineOptions.Inline = true; - CustomInline.AllowShortFunctionsOnASingleLineOptions.Other = false; + CustomInline.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/false, + /*Inline=*/true, + /*Other=*/false}); verifyFormat("class C {\n" " int f() {}\n" @@ -15188,10 +15211,10 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { // Test with All = true FormatStyle CustomAll = getLLVMStyle(); - CustomAll.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; - CustomAll.AllowShortFunctionsOnASingleLineOptions.Empty = false; - CustomAll.AllowShortFunctionsOnASingleLineOptions.Inline = false; - CustomAll.AllowShortFunctionsOnASingleLineOptions.Other = true; + CustomAll.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); // All functions should be on a single line if they fit verifyFormat("int f() { return 42; }", CustomAll); @@ -15209,10 +15232,10 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { // Test various combinations FormatStyle CustomMixed = getLLVMStyle(); - CustomMixed.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Custom; - CustomMixed.AllowShortFunctionsOnASingleLineOptions.Empty = true; - CustomMixed.AllowShortFunctionsOnASingleLineOptions.Inline = true; - CustomMixed.AllowShortFunctionsOnASingleLineOptions.Other = false; + CustomMixed.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); // Empty functions should be on a single line verifyFormat("int f() {}", CustomMixed); @@ -15237,7 +15260,9 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) { FormatStyle MergeInlineOnly = getLLVMStyle(); MergeInlineOnly.AllowShortFunctionsOnASingleLine = - FormatStyle::SFS_InlineOnly; + FormatStyle::ShortFunctionStyle({/*Empty=*/false, + /*Inline=*/true, + /*Other=*/false}); verifyFormat("class C {\n" " int f() { return 42; }\n" "};", @@ -15282,7 +15307,7 @@ TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) { TEST_F(FormatTest, SplitEmptyFunction) { FormatStyle Style = getLLVMStyleWithColumns(40); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterFunction = true; Style.BraceWrapping.SplitEmptyFunction = false; @@ -15301,7 +15326,10 @@ TEST_F(FormatTest, SplitEmptyFunction) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false}); verifyFormat("int f() {}", Style); verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" "{}", @@ -15312,7 +15340,10 @@ TEST_F(FormatTest, SplitEmptyFunction) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); verifyFormat("class Foo {\n" " int f() {}\n" "};", @@ -15334,7 +15365,10 @@ TEST_F(FormatTest, SplitEmptyFunction) { "};", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); verifyFormat("int f() {}", Style); verifyFormat("int f() { return 0; }", Style); verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" @@ -15349,7 +15383,7 @@ TEST_F(FormatTest, SplitEmptyFunction) { TEST_F(FormatTest, SplitEmptyFunctionButNotRecord) { FormatStyle Style = getLLVMStyleWithColumns(40); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterFunction = true; Style.BraceWrapping.SplitEmptyFunction = true; @@ -15379,7 +15413,10 @@ TEST_F(FormatTest, SplitEmptyFunctionButNotRecord) { TEST_F(FormatTest, KeepShortFunctionAfterPPElse) { FormatStyle Style = getLLVMStyle(); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); verifyFormat("#ifdef A\n" "int f() {}\n" "#else\n" @@ -21492,7 +21529,9 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) { // Make a few changes to the style for testing purposes WhitesmithsBraceStyle.AllowShortFunctionsOnASingleLine = - FormatStyle::SFS_Empty; + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false}); WhitesmithsBraceStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None; // FIXME: this test case can't decide whether there should be a blank line @@ -23038,7 +23077,7 @@ TEST_F(FormatTest, BreakConstructorInitializersBeforeComma) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); verifyFormat("SomeClass::Constructor()\n" " : a(a)\n" " , b(b)\n" @@ -23049,7 +23088,10 @@ TEST_F(FormatTest, BreakConstructorInitializersBeforeComma) { Style); Style.ColumnLimit = 80; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); Style.ConstructorInitializerIndentWidth = 2; verifyFormat("SomeClass::Constructor()\n" " : a(a)\n" @@ -27198,7 +27240,7 @@ TEST_F(FormatTest, FormatDecayCopy) { TEST_F(FormatTest, Cpp20ModulesSupport) { FormatStyle Style = getLLVMStyle(); Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); verifyFormat("export import foo;", Style); verifyFormat("export import foo:bar;", Style); diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp index 151f7072e0c65..22c757509f5fb 100644 --- a/clang/unittests/Format/FormatTestCSharp.cpp +++ b/clang/unittests/Format/FormatTestCSharp.cpp @@ -1660,7 +1660,10 @@ TEST_F(FormatTestCSharp, EmptyShortBlock) { TEST_F(FormatTestCSharp, ShortFunctions) { FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp); Style.NamespaceIndentation = FormatStyle::NI_All; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); verifyFormat("interface Interface {\n" " void f() { return; }\n" "};", diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp index 78c9f887a159b..2108bb21f192e 100644 --- a/clang/unittests/Format/FormatTestJS.cpp +++ b/clang/unittests/Format/FormatTestJS.cpp @@ -1010,7 +1010,10 @@ TEST_F(FormatTestJS, TrailingCommaInsertion) { TEST_F(FormatTestJS, FunctionLiterals) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); verifyFormat("doFoo(function() {});"); verifyFormat("doFoo(function() { return 1; });", Style); verifyFormat("var func = function() {\n" @@ -1123,7 +1126,10 @@ TEST_F(FormatTestJS, DontWrapEmptyLiterals) { TEST_F(FormatTestJS, InliningFunctionLiterals) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); verifyFormat("var func = function() {\n" " return 1;\n" "};", @@ -1138,7 +1144,10 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); verifyFormat("var func = function() { return 1; };", Style); verifyFormat("var func = doSomething(function() { return 1; });", Style); verifyFormat( @@ -1149,7 +1158,7 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); verifyFormat("var func = function() {\n" " return 1;\n" "};", @@ -1171,7 +1180,10 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/false, + /*Other=*/false}); verifyFormat("var func = function() {\n" " return 1;\n" "};", @@ -1180,7 +1192,10 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) { TEST_F(FormatTestJS, MultipleFunctionLiterals) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/true}); verifyFormat("promise.then(\n" " function success() {\n" " doFoo();\n" diff --git a/clang/unittests/Format/FormatTestJava.cpp b/clang/unittests/Format/FormatTestJava.cpp index 33998bc7ff858..bba6541395171 100644 --- a/clang/unittests/Format/FormatTestJava.cpp +++ b/clang/unittests/Format/FormatTestJava.cpp @@ -594,7 +594,10 @@ TEST_F(FormatTestJava, RetainsLogicalShifts) { TEST_F(FormatTestJava, ShortFunctions) { FormatStyle Style = getLLVMStyle(FormatStyle::LK_Java); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/true, + /*Inline=*/true, + /*Other=*/false}); verifyFormat("enum Enum {\n" " E1,\n" " E2;\n" >From 7f80e4adcac43f3b2c393a499627a1ca4d0beaef Mon Sep 17 00:00:00 2001 From: Ivan Rymarchyk <> Date: Tue, 8 Apr 2025 21:13:35 -0700 Subject: [PATCH 4/8] fixed documentation error --- clang/docs/ClangFormatStyleOptions.rst | 1 + clang/include/clang/Format/Format.h | 1 + 2 files changed, 2 insertions(+) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 6f3b9f798093f..1c55b74395062 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1911,6 +1911,7 @@ the configuration (without a prefix: ``Auto``). statement. They can be read as a whole for compatibility. The choices are: + * ``None`` Never merge functions into a single line. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 2278bf3966296..e5c031c7b249f 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -829,6 +829,7 @@ struct FormatStyle { /// statement. /// /// They can be read as a whole for compatibility. The choices are: + /// /// * ``None`` /// Never merge functions into a single line. /// >From bbe22735987f4f24d278e73df74e59ad9b246d95 Mon Sep 17 00:00:00 2001 From: Ivan Rymarchyk <> Date: Wed, 9 Apr 2025 19:27:10 -0700 Subject: [PATCH 5/8] Fixed PR comments --- clang/docs/ClangFormatStyleOptions.rst | 2 +- clang/include/clang/Format/Format.h | 2 +- clang/lib/Format/TokenAnnotator.cpp | 8 +++----- clang/unittests/Format/ConfigParseTest.cpp | 1 - 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 1c55b74395062..d67c8891a4506 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1975,7 +1975,7 @@ the configuration (without a prefix: ``Auto``). AllowShortFunctionsOnASingleLine: Empty: false Inline: true - All: false + Other: false * ``bool Empty`` Merge top-level empty functions. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index e5c031c7b249f..7836fa91b20a8 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -887,7 +887,7 @@ struct FormatStyle { /// AllowShortFunctionsOnASingleLine: /// Empty: false /// Inline: true - /// All: false + /// Other: false /// \endcode struct ShortFunctionStyle { /// Merge top-level empty functions. diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index db2f8766f8d40..f85ddbe2f0523 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5687,11 +5687,9 @@ 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.Inline && - !Style.AllowShortFunctionsOnASingleLine.Other) || - (Left.NestingLevel == 0 && Line.Level == 0 && - Style.AllowShortFunctionsOnASingleLine.Inline && - !Style.AllowShortFunctionsOnASingleLine.Other); + return !(Left.NestingLevel == 0 && Line.Level == 0 + ? Style.AllowShortFunctionsOnASingleLine.Other + : Style.AllowShortFunctionsOnASingleLine.Inline); } } else if (Style.Language == FormatStyle::LK_Java) { if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight && diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index c022db94cdb6a..b48dd0a737eea 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -611,7 +611,6 @@ TEST(ConfigParseTest, ParsesConfiguration) { CHECK_PARSE("AllowShortBlocksOnASingleLine: true", AllowShortBlocksOnASingleLine, FormatStyle::SBS_Always); - // Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; CHECK_PARSE("AllowShortFunctionsOnASingleLine: None", AllowShortFunctionsOnASingleLine, FormatStyle::ShortFunctionStyle({})); >From 5ff5810b53308fb2df457b339743991b1fcc9695 Mon Sep 17 00:00:00 2001 From: Ivan Rymarchyk <> Date: Sun, 13 Apr 2025 15:14:16 -0700 Subject: [PATCH 6/8] marked options as deprecated --- clang/docs/ClangFormatStyleOptions.rst | 11 ++++++++--- clang/include/clang/Format/Format.h | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index d67c8891a4506..a01b9baf482e3 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1918,7 +1918,8 @@ the configuration (without a prefix: ``Auto``). * ``InlineOnly`` Only merge functions defined inside a class. Same as ``inline``, except it does not implies ``empty``: i.e. top level empty functions - are not merged either. + are not merged either. This option is **deprecated** and is retained + for backwards compatibility. See ``Inline`` of ``ShortFunctionStyle``. .. code-block:: c++ @@ -1932,7 +1933,9 @@ the configuration (without a prefix: ``Auto``). } * ``Empty`` - Only merge empty functions. + Only merge empty functions. This option is **deprecated** and is + retained for backwards compatibility. See ``Empty`` of + ``ShortFunctionStyle``. .. code-block:: c++ @@ -1942,7 +1945,9 @@ the configuration (without a prefix: ``Auto``). } * ``Inline`` - Only merge functions defined inside a class. Implies ``empty``. + Only merge functions defined inside a class. Implies ``empty``. This + option is **deprecated** and is retained for backwards compatibility. + See ``Inline`` and ``Empty`` of ``ShortFunctionStyle``. .. code-block:: c++ diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 7836fa91b20a8..448e8d0f2eb77 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -836,7 +836,8 @@ struct FormatStyle { /// * ``InlineOnly`` /// Only merge functions defined inside a class. Same as ``inline``, /// except it does not implies ``empty``: i.e. top level empty functions - /// are not merged either. + /// are not merged either. This option is **deprecated** and is retained + /// for backwards compatibility. See ``Inline`` of ``ShortFunctionStyle``. /// \code /// class Foo { /// void f() { foo(); } @@ -849,7 +850,9 @@ struct FormatStyle { /// \endcode /// /// * ``Empty`` - /// Only merge empty functions. + /// Only merge empty functions. This option is **deprecated** and is + /// retained for backwards compatibility. See ``Empty`` of + /// ``ShortFunctionStyle``. /// \code /// void f() {} /// void f2() { @@ -858,7 +861,9 @@ struct FormatStyle { /// \endcode /// /// * ``Inline`` - /// Only merge functions defined inside a class. Implies ``empty``. + /// Only merge functions defined inside a class. Implies ``empty``. This + /// option is **deprecated** and is retained for backwards compatibility. + /// See ``Inline`` and ``Empty`` of ``ShortFunctionStyle``. /// \code /// class Foo { /// void f() { foo(); } >From 70eafeabdff7f1f3e765f7dae29eec9c202170c8 Mon Sep 17 00:00:00 2001 From: Ivan Rymarchyk <> Date: Tue, 15 Apr 2025 20:38:36 -0700 Subject: [PATCH 7/8] fixed PR comments --- clang/include/clang/Format/Format.h | 3 +++ clang/lib/Format/TokenAnnotator.cpp | 2 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 5 +++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 448e8d0f2eb77..b56806ca2ccfa 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -934,6 +934,9 @@ struct FormatStyle { ShortFunctionStyle() : Empty(false), Inline(false), Other(false) {} ShortFunctionStyle(bool Empty, bool Inline, bool Other) : Empty(Empty), Inline(Inline), Other(Other) {} + bool isAll() const { + return Empty && Inline && Other; + } }; /// Dependent on the value, ``int f() { return 0; }`` can be put on a diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index f85ddbe2f0523..73ff1c537d1e8 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 !(Left.NestingLevel == 0 && Line.Level == 0 - ? Style.AllowShortFunctionsOnASingleLine.Other + ? Style.AllowShortFunctionsOnASingleLine.isAll() : Style.AllowShortFunctionsOnASingleLine.Inline); } } else if (Style.Language == FormatStyle::LK_Java) { diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index fdec849cf363a..c6b9ad02a22b5 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -293,14 +293,15 @@ class LineJoiner { auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine, TheLine]() { - if (Style.AllowShortFunctionsOnASingleLine.Other) + if (Style.AllowShortFunctionsOnASingleLine.isAll()) return true; if (Style.AllowShortFunctionsOnASingleLine.Empty && NextLine.First->is(tok::r_brace)) { return true; } - if (Style.AllowShortFunctionsOnASingleLine.Inline) { + if (Style.AllowShortFunctionsOnASingleLine.Inline && + !Style.AllowShortFunctionsOnASingleLine.isAll()) { // 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)) >From dd6493d703237cc0a1c9a8e61696482cd91edb92 Mon Sep 17 00:00:00 2001 From: Ivan Rymarchyk <> Date: Tue, 15 Apr 2025 21:42:01 -0700 Subject: [PATCH 8/8] added usage of 'other' --- clang/include/clang/Format/Format.h | 4 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 63 +++++++++++---------- clang/unittests/Format/FormatTest.cpp | 20 +++++++ 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index b56806ca2ccfa..38b68651e0322 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -934,9 +934,7 @@ struct FormatStyle { ShortFunctionStyle() : Empty(false), Inline(false), Other(false) {} ShortFunctionStyle(bool Empty, bool Inline, bool Other) : Empty(Empty), Inline(Inline), Other(Other) {} - bool isAll() const { - return Empty && Inline && Other; - } + bool isAll() const { return Empty && Inline && Other; } }; /// Dependent on the value, ``int f() { return 0; }`` can be put on a diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index c6b9ad02a22b5..71d53c1c60c58 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -295,47 +295,52 @@ class LineJoiner { TheLine]() { if (Style.AllowShortFunctionsOnASingleLine.isAll()) return true; - if (Style.AllowShortFunctionsOnASingleLine.Empty && - NextLine.First->is(tok::r_brace)) { + + // there might be a case where empty function is in class, so need to + // check inline later + bool empty_function = NextLine.First->is(tok::r_brace); + if (Style.AllowShortFunctionsOnASingleLine.Empty && empty_function) return true; - } - if (Style.AllowShortFunctionsOnASingleLine.Inline && - !Style.AllowShortFunctionsOnASingleLine.isAll()) { + if (TheLine->Level != 0) { + if (!Style.AllowShortFunctionsOnASingleLine.Inline) + return false; + // 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)) return true; - if (TheLine->Level != 0) { - if (!PreviousLine) - return false; - - // TODO: Use IndentTracker to avoid loop? - // Find the last line with lower level. - const AnnotatedLine *Line = nullptr; - for (auto J = I - 1; J >= AnnotatedLines.begin(); --J) { - assert(*J); - if (!(*J)->InPPDirective && !(*J)->isComment() && - (*J)->Level < TheLine->Level) { - Line = *J; - break; - } + if (!PreviousLine) + return false; + + // TODO: Use IndentTracker to avoid loop? + // Find the last line with lower level. + const AnnotatedLine *Line = nullptr; + for (auto J = I - 1; J >= AnnotatedLines.begin(); --J) { + assert(*J); + if (!(*J)->InPPDirective && !(*J)->isComment() && + (*J)->Level < TheLine->Level) { + Line = *J; + break; } + } - if (!Line) - return false; + if (!Line) + return false; - // Check if the found line starts a record. - const auto *LastNonComment = Line->getLastNonComment(); - // There must be another token (usually `{`), because we chose a - // non-PPDirective and non-comment line that has a smaller level. - assert(LastNonComment); - return isRecordLBrace(*LastNonComment); - } + // Check if the found line starts a record. + const auto *LastNonComment = Line->getLastNonComment(); + // There must be another token (usually `{`), because we chose a + // non-PPDirective and non-comment line that has a smaller level. + assert(LastNonComment); + return isRecordLBrace(*LastNonComment); } - return false; + if (empty_function && !Style.AllowShortFunctionsOnASingleLine.Empty) + return false; + + return Style.AllowShortFunctionsOnASingleLine.Other; }; bool MergeShortFunctions = ShouldMergeShortFunctions(); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 382e9e855b622..b780dee7660ae 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -15255,6 +15255,26 @@ TEST_F(FormatTest, CustomShortFunctionOptions) { " return 42;\n" "}", CustomMixed); + + FormatStyle OnlyOther = getLLVMStyle(); + OnlyOther.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle({/*Empty=*/false, + /*Inline=*/false, + /*Other=*/true}); + verifyFormat("void topLevelEmpty() {\n" + "}", + OnlyOther); + + verifyFormat("void topLevelNonEmpty() { return; }", OnlyOther); + + verifyFormat("class C {\n" + " int inlineEmpty() {\n" + " }\n" + " int inlineNonempty() {\n" + " return 42;\n" + " }\n" + "};", + OnlyOther); } TEST_F(FormatTest, PullInlineOnlyFunctionDefinitionsIntoSingleLine) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits