diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index c61c808831704..2eb8ec6f4d702 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1905,15 +1905,21 @@ 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. + are not merged either. This option is **deprecated** and is retained + for backwards compatibility. See ``Inline`` of ``ShortFunctionStyle``. .. code-block:: c++ @@ -1926,8 +1932,10 @@ the configuration (without a prefix: ``Auto``). void f() { } - * ``SFS_Empty`` (in configuration: ``Empty``) - Only merge empty functions. + * ``Empty`` + Only merge empty functions. This option is **deprecated** and is + retained for backwards compatibility. See ``Empty`` of + ``ShortFunctionStyle``. .. code-block:: c++ @@ -1936,8 +1944,10 @@ the configuration (without a prefix: ``Auto``). bar2(); } - * ``SFS_Inline`` (in configuration: ``Inline``) - Only merge functions defined inside a class. Implies ``empty``. + * ``Inline`` + 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++ @@ -1949,7 +1959,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,6 +1969,52 @@ the configuration (without a prefix: ``Auto``). }; void f() { bar(); } + Also can be specified as a nested configuration flag: + + .. code-block:: c++ + + # Example of usage: + AllowShortFunctionsOnASingleLine: InlineOnly + + # or more granular control: + AllowShortFunctionsOnASingleLine: + Empty: false + Inline: true + Other: false + + * ``bool Empty`` Merge top-level empty functions. + + .. code-block:: c++ + + void f() {} + void f2() { + bar2(); + } + void f3() { /* comment */ } + + * ``bool Inline`` Merge functions defined inside a class. + + .. code-block:: c++ + + class Foo { + void f() { foo(); } + void g() {} + }; + void f() { + foo(); + } + void f() { + } + + * ``bool Other`` Merge all functions fitting on a single line. Please note that this + control does not include Empty + + .. 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 5d1fdb153b26e..c1440b6fd22d9 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -827,50 +827,126 @@ 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. + /// + /// 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. This option is **deprecated** and is retained + /// for backwards compatibility. See ``Inline`` of ``ShortFunctionStyle``. + /// \code + /// class Foo { + /// void f() { foo(); } + /// }; + /// void f() { + /// foo(); + /// } + /// void f() { + /// } + /// \endcode + /// + /// * ``Empty`` + /// Only merge empty functions. This option is **deprecated** and is + /// retained for backwards compatibility. See ``Empty`` of + /// ``ShortFunctionStyle``. + /// \code + /// void f() {} + /// void f2() { + /// bar2(); + /// } + /// \endcode + /// + /// * ``Inline`` + /// 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(); } + /// }; + /// 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 + /// # Example of usage: + /// AllowShortFunctionsOnASingleLine: InlineOnly + /// + /// # or more granular control: + /// AllowShortFunctionsOnASingleLine: + /// Empty: false + /// Inline: true + /// Other: false + /// \endcode + struct ShortFunctionStyle { + /// Merge top-level empty functions. /// \code /// void f() {} /// void f2() { /// bar2(); /// } + /// void f3() { /* comment */ } /// \endcode - SFS_Empty, - /// Only merge functions defined inside a class. Implies ``empty``. + bool Empty; + /// Merge functions defined inside a class. /// \code /// class Foo { /// void f() { foo(); } + /// void g() {} /// }; /// void f() { /// foo(); /// } - /// void f() {} + /// void f() { + /// } /// \endcode - SFS_Inline, - /// Merge all functions fitting on a single line. + bool Inline; + /// Merge all functions fitting on a single line. Please note that this + /// control does not include Empty /// \code /// class Foo { /// void f() { foo(); } /// }; /// void f() { bar(); } /// \endcode - SFS_All, + bool Other; + + bool operator==(const ShortFunctionStyle &R) const { + return Empty == R.Empty && Inline == R.Inline && Other == R.Other; + } + 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) {} + bool isAll() const { return Empty && Inline && Other; } + static ShortFunctionStyle setEmptyOnly() { + return ShortFunctionStyle(true, false, false); + } + static ShortFunctionStyle setEmptyAndInline() { + return ShortFunctionStyle(true, true, false); + } + static ShortFunctionStyle setInlineOnly() { + return ShortFunctionStyle(false, true, false); + } + static ShortFunctionStyle setAll() { + return ShortFunctionStyle(true, true, true); + } }; /// Dependent on the value, ``int f() { return 0; }`` can be put on a diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index bdaf264e9adce..d885e6d540bc4 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -622,15 +622,26 @@ template <> struct ScalarEnumerationTraits { } }; -template <> struct ScalarEnumerationTraits { - 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); +template <> struct MappingTraits { + static void enumInput(IO &IO, FormatStyle::ShortFunctionStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::ShortFunctionStyle({})); + IO.enumCase(Value, "Empty", + FormatStyle::ShortFunctionStyle::setEmptyOnly()); + IO.enumCase(Value, "Inline", + FormatStyle::ShortFunctionStyle::setEmptyAndInline()); + IO.enumCase(Value, "InlineOnly", + FormatStyle::ShortFunctionStyle::setInlineOnly()); + IO.enumCase(Value, "All", FormatStyle::ShortFunctionStyle::setAll()); + + // For backward compatibility. + IO.enumCase(Value, "true", FormatStyle::ShortFunctionStyle::setAll()); + IO.enumCase(Value, "false", FormatStyle::ShortFunctionStyle({})); + } + + static void mapping(IO &IO, FormatStyle::ShortFunctionStyle &Value) { + IO.mapOptional("Empty", Value.Empty); + IO.mapOptional("Inline", Value.Inline); + IO.mapOptional("Other", Value.Other); } }; @@ -1524,7 +1535,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true; LLVMStyle.AllowShortEnumsOnASingleLine = true; - LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + LLVMStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setAll(); LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; LLVMStyle.AllowShortLoopsOnASingleLine = false; @@ -1813,7 +1825,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; GoogleStyle.AlignTrailingComments = {}; GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; - GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + GoogleStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyOnly(); GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; @@ -1823,7 +1836,8 @@ 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.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyOnly(); // TODO: still under discussion whether to switch to SLS_All. GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; @@ -1840,7 +1854,8 @@ 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.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyOnly(); GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; // This affects protocol buffer options specifications and text protos. // Text protos are currently mostly formatted inside C++ raw string literals @@ -1859,7 +1874,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; } else if (Language == FormatStyle::LK_CSharp) { - GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + GoogleStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyOnly(); GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; GoogleStyle.BreakStringLiterals = false; GoogleStyle.ColumnLimit = 100; @@ -1917,7 +1933,8 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { ChromiumStyle.AllowShortLoopsOnASingleLine = false; } else { ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; - ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + ChromiumStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyAndInline(); ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; ChromiumStyle.AllowShortLoopsOnASingleLine = false; ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine; @@ -1931,7 +1948,8 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { FormatStyle getMozillaStyle() { FormatStyle MozillaStyle = getLLVMStyle(); MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; - MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + MozillaStyle.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyAndInline(); MozillaStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_TopLevel; MozillaStyle.BinPackArguments = false; @@ -2013,7 +2031,7 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { Style.BraceWrapping.BeforeWhile = false; Style.PenaltyReturnTypeOnItsOwnLine = 1000; Style.AllowShortEnumsOnASingleLine = false; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); Style.AllowShortCaseLabelsOnASingleLine = false; Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; Style.AllowShortLoopsOnASingleLine = false; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index aab8f054655fe..1e907a51ecf03 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5693,11 +5693,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 || - (Left.NestingLevel == 0 && Line.Level == 0 && - Style.AllowShortFunctionsOnASingleLine & - FormatStyle::SFS_InlineOnly); + if (Left.NestingLevel == 0 && Line.Level == 0) + return !Style.AllowShortFunctionsOnASingleLine.Other; + + return !Style.AllowShortFunctionsOnASingleLine.Inline; } } else if (Style.isJava()) { 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 f2ed027b2c047..26769e3c0d303 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -291,15 +291,16 @@ class LineJoiner { auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine, TheLine]() { - if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All) + if (Style.AllowShortFunctionsOnASingleLine.isAll()) return true; - if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && + + if (Style.AllowShortFunctionsOnASingleLine.Empty && NextLine.First->is(tok::r_brace)) { return true; } - if (Style.AllowShortFunctionsOnASingleLine & - FormatStyle::SFS_InlineOnly) { + if (Style.AllowShortFunctionsOnASingleLine.Inline && + !Style.AllowShortFunctionsOnASingleLine.Other) { // 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)) @@ -522,7 +523,7 @@ class LineJoiner { unsigned MergedLines = 0; if (MergeShortFunctions || - (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_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 aedfdd151d6d3..347a9c5287085 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -623,20 +623,29 @@ TEST(ConfigParseTest, ParsesConfiguration) { CHECK_PARSE("AllowShortBlocksOnASingleLine: true", AllowShortBlocksOnASingleLine, FormatStyle::SBS_Always); - 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::setEmptyAndInline()); CHECK_PARSE("AllowShortFunctionsOnASingleLine: Empty", - AllowShortFunctionsOnASingleLine, FormatStyle::SFS_Empty); + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle::setEmptyOnly()); CHECK_PARSE("AllowShortFunctionsOnASingleLine: All", - AllowShortFunctionsOnASingleLine, FormatStyle::SFS_All); + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle::setAll()); + CHECK_PARSE("AllowShortFunctionsOnASingleLine: InlineOnly", + AllowShortFunctionsOnASingleLine, + FormatStyle::ShortFunctionStyle::setInlineOnly()); + // 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::setAll()); Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; CHECK_PARSE("AllowShortLambdasOnASingleLine: None", diff --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp index 1f4245b703fb7..895ab0fe73cc9 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" @@ -586,7 +586,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 944e7c3fb152a..38a90fedccf46 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -388,7 +388,8 @@ TEST_F(FormatTest, RemovesEmptyLines) { "} // namespace"); FormatStyle Style = getLLVMStyle(); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setAll(); Style.MaxEmptyLinesToKeep = 2; Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterClass = true; @@ -3384,13 +3385,14 @@ 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::setAll(); 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" @@ -3405,7 +3407,8 @@ TEST_F(FormatTest, MultiLineControlStatements) { Style.BraceWrapping.AfterFunction = false; Style.BraceWrapping.AfterStruct = true; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setAll(); verifyFormat("void shortfunction() { bar(); }", Style); verifyFormat("struct T shortfunction() { return bar(); }", Style); verifyFormat("struct T\n" @@ -3413,7 +3416,7 @@ TEST_F(FormatTest, MultiLineControlStatements) { "};", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); verifyFormat("void shortfunction() {\n" " bar();\n" "}", @@ -4219,7 +4222,7 @@ TEST_F(FormatTest, FormatsNamespaces) { FormatStyle ShortInlineFunctions = getLLVMStyle(); ShortInlineFunctions.NamespaceIndentation = FormatStyle::NI_All; ShortInlineFunctions.AllowShortFunctionsOnASingleLine = - FormatStyle::SFS_Inline; + FormatStyle::ShortFunctionStyle::setEmptyAndInline(); verifyFormat("namespace {\n" " void f() {\n" " return;\n" @@ -8356,7 +8359,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" "}", @@ -8367,7 +8370,8 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) { Style); Style.ColumnLimit = 80; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setAll(); Style.ConstructorInitializerIndentWidth = 2; verifyFormat("SomeClass::Constructor() : a(a), b(b), c(c) {}", Style); verifyFormat("SomeClass::Constructor() :\n" @@ -12698,7 +12702,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); @@ -12806,7 +12811,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" "}", @@ -14906,7 +14912,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" @@ -14977,7 +14984,7 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { FormatStyle DoNotMergeNoColumnLimit = NoColumnLimit; DoNotMergeNoColumnLimit.AllowShortFunctionsOnASingleLine = - FormatStyle::SFS_None; + FormatStyle::ShortFunctionStyle({}); verifyFormat("A() : b(0) {\n" "}", DoNotMergeNoColumnLimit); @@ -15025,7 +15032,8 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { TEST_F(FormatTest, PullEmptyFunctionDefinitionsIntoSingleLine) { FormatStyle MergeEmptyOnly = getLLVMStyle(); - MergeEmptyOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + MergeEmptyOnly.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyOnly(); verifyFormat("class C {\n" " int f() {}\n" "};", @@ -15054,7 +15062,8 @@ TEST_F(FormatTest, PullEmptyFunctionDefinitionsIntoSingleLine) { TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) { FormatStyle MergeInlineOnly = getLLVMStyle(); - MergeInlineOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + MergeInlineOnly.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyAndInline(); verifyFormat("class C {\n" " int f() { return 42; }\n" "};", @@ -15163,10 +15172,116 @@ TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) { MergeInlineOnly); } +TEST_F(FormatTest, CustomShortFunctionOptions) { + FormatStyle CustomEmpty = getLLVMStyle(); + CustomEmpty.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyOnly(); + + // 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 comment + verifyFormat("void f3() { /* comment */ }", 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::ShortFunctionStyle::setInlineOnly(); + + 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::ShortFunctionStyle::setAll(); + + // 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::ShortFunctionStyle::setEmptyAndInline(); + + // 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 = - FormatStyle::SFS_InlineOnly; + FormatStyle::ShortFunctionStyle::setInlineOnly(); verifyFormat("class C {\n" " int f() { return 42; }\n" "};", @@ -15218,7 +15333,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; @@ -15237,7 +15352,8 @@ TEST_F(FormatTest, SplitEmptyFunction) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyOnly(); verifyFormat("int f() {}", Style); verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" "{}", @@ -15248,7 +15364,8 @@ TEST_F(FormatTest, SplitEmptyFunction) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyAndInline(); verifyFormat("class Foo {\n" " int f() {}\n" "};", @@ -15257,6 +15374,10 @@ TEST_F(FormatTest, SplitEmptyFunction) { " int f() { return 0; }\n" "};", Style); + verifyFormat("class Foo {\n" + " int f() { return 0; }\n" + "};", + Style); verifyFormat("class Foo {\n" " int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" " {}\n" @@ -15270,7 +15391,8 @@ TEST_F(FormatTest, SplitEmptyFunction) { "};", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setAll(); verifyFormat("int f() {}", Style); verifyFormat("int f() { return 0; }", Style); verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" @@ -15285,7 +15407,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; @@ -15315,7 +15437,8 @@ TEST_F(FormatTest, SplitEmptyFunctionButNotRecord) { TEST_F(FormatTest, KeepShortFunctionAfterPPElse) { FormatStyle Style = getLLVMStyle(); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setAll(); verifyFormat("#ifdef A\n" "int f() {}\n" "#else\n" @@ -21444,7 +21567,7 @@ TEST_F(FormatTest, WhitesmithsBraceBreaking) { // Make a few changes to the style for testing purposes WhitesmithsBraceStyle.AllowShortFunctionsOnASingleLine = - FormatStyle::SFS_Empty; + FormatStyle::ShortFunctionStyle::setEmptyOnly(); WhitesmithsBraceStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None; // FIXME: this test case can't decide whether there should be a blank line @@ -22989,7 +23112,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" @@ -23000,7 +23123,8 @@ TEST_F(FormatTest, BreakConstructorInitializersBeforeComma) { Style); Style.ColumnLimit = 80; - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setAll(); Style.ConstructorInitializerIndentWidth = 2; verifyFormat("SomeClass::Constructor()\n" " : a(a)\n" @@ -27296,7 +27420,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 ea85ed6140dd0..710e32a0a587f 100644 --- a/clang/unittests/Format/FormatTestCSharp.cpp +++ b/clang/unittests/Format/FormatTestCSharp.cpp @@ -1673,7 +1673,8 @@ 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::setEmptyAndInline(); verifyFormat("interface Interface {\n" " void f() { return; }\n" "};", diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp index 91577b9a49167..1733c27c7e7fc 100644 --- a/clang/unittests/Format/FormatTestJS.cpp +++ b/clang/unittests/Format/FormatTestJS.cpp @@ -1019,7 +1019,8 @@ TEST_F(FormatTestJS, TrailingCommaInsertion) { TEST_F(FormatTestJS, FunctionLiterals) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyAndInline(); verifyFormat("doFoo(function() {});"); verifyFormat("doFoo(function() { return 1; });", Style); verifyFormat("var func = function() {\n" @@ -1132,7 +1133,8 @@ TEST_F(FormatTestJS, DontWrapEmptyLiterals) { TEST_F(FormatTestJS, InliningFunctionLiterals) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyAndInline(); verifyFormat("var func = function() {\n" " return 1;\n" "};", @@ -1147,7 +1149,8 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setAll(); verifyFormat("var func = function() { return 1; };", Style); verifyFormat("var func = doSomething(function() { return 1; });", Style); verifyFormat( @@ -1158,7 +1161,7 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); verifyFormat("var func = function() {\n" " return 1;\n" "};", @@ -1180,16 +1183,47 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) { "}", Style); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyOnly(); verifyFormat("var func = function() {\n" " return 1;\n" "};", Style); } +TEST_F(FormatTestJS, InliningFunctionLiteralsNew) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); + Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle({}); + Style.AllowShortFunctionsOnASingleLine.Other = true; + verifyFormat("var func = function() { return 1; };", Style); + verifyFormat("var func = doSomething(function() {\n" + " return 1;\n" + "});", + Style); + verifyFormat("var outer = function() {\n" + " var inner = function() {\n" + " return 1;\n" + " }\n" + "};", + Style); + verifyFormat("function outer1(a, b) {\n" + " function inner1(a, b) {\n" + " return a;\n" + " }\n" + "}", + Style); + + verifyFormat("function outer1(a, b) {\n" + " function inner1_empty(a, b) {\n" + " }\n" + "}", + Style); +} + TEST_F(FormatTestJS, MultipleFunctionLiterals) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setAll(); verifyFormat("promise.then(\n" " function success() {\n" " doFoo();\n" diff --git a/clang/unittests/Format/FormatTestJava.cpp b/clang/unittests/Format/FormatTestJava.cpp index ca5aba043b932..13992d20589e0 100644 --- a/clang/unittests/Format/FormatTestJava.cpp +++ b/clang/unittests/Format/FormatTestJava.cpp @@ -596,7 +596,8 @@ TEST_F(FormatTestJava, RetainsLogicalShifts) { TEST_F(FormatTestJava, ShortFunctions) { FormatStyle Style = getLLVMStyle(FormatStyle::LK_Java); - Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + Style.AllowShortFunctionsOnASingleLine = + FormatStyle::ShortFunctionStyle::setEmptyAndInline(); verifyFormat("enum Enum {\n" " E1,\n" " E2;\n"