diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -395,6 +395,21 @@ return; } +**AllowShortEnumsOnASingleLine** (``bool``) + Allow short enums on a single line. + + .. code-block:: c++ + + true: + enum { A, B } myEnum; + + false: + enum + { + A, + B + } myEnum; + **AllowShortFunctionsOnASingleLine** (``ShortFunctionStyle``) Dependent on the value, ``int f() { return 0; }`` can be put on a single line. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -221,6 +221,20 @@ /// \endcode bool AllowAllParametersOfDeclarationOnNextLine; + /// Allow short enums on a single line. + /// \code + /// true: + /// enum { A, B } myEnum; + /// + /// false: + /// enum + /// { + /// A, + /// B + /// } myEnum; + /// \endcode + bool AllowShortEnumsOnASingleLine; + /// Different styles for merging short blocks containing at most one /// statement. enum ShortBlockStyle { @@ -2175,6 +2189,7 @@ R.AllowAllConstructorInitializersOnNextLine && AllowAllParametersOfDeclarationOnNextLine == R.AllowAllParametersOfDeclarationOnNextLine && + AllowShortEnumsOnASingleLine == R.AllowShortEnumsOnASingleLine && AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine && AllowShortCaseLabelsOnASingleLine == R.AllowShortCaseLabelsOnASingleLine && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -399,6 +399,8 @@ Style.AllowAllConstructorInitializersOnNextLine); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", Style.AllowAllParametersOfDeclarationOnNextLine); + IO.mapOptional("AllowShortEnumsOnASingleLine", + Style.AllowShortEnumsOnASingleLine); IO.mapOptional("AllowShortBlocksOnASingleLine", Style.AllowShortBlocksOnASingleLine); IO.mapOptional("AllowShortCaseLabelsOnASingleLine", @@ -754,6 +756,7 @@ LLVMStyle.AllowAllArgumentsOnNextLine = true; LLVMStyle.AllowAllConstructorInitializersOnNextLine = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; + LLVMStyle.AllowShortEnumsOnASingleLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; @@ -1139,6 +1142,7 @@ Style.BraceWrapping.BeforeCatch = true; Style.BraceWrapping.BeforeElse = true; Style.PenaltyReturnTypeOnItsOwnLine = 1000; + Style.AllowShortEnumsOnASingleLine = false; Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; Style.AllowShortCaseLabelsOnASingleLine = false; Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -98,7 +98,7 @@ void readTokenWithJavaScriptASI(); void parseStructuralElement(); bool tryToParseBracedList(); - bool parseBracedList(bool ContinueOnSemicolons = false, + bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false, tok::TokenKind ClosingBraceKind = tok::r_brace); void parseParens(); void parseSquare(bool LambdaIntroducer = false); diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1745,6 +1745,7 @@ } bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons, + bool IsEnum, tok::TokenKind ClosingBraceKind) { bool HasError = false; @@ -1785,6 +1786,8 @@ } } if (FormatTok->Tok.getKind() == ClosingBraceKind) { + if (IsEnum && !Style.AllowShortEnumsOnASingleLine) + addUnwrappedLine(); nextToken(); return !HasError; } @@ -1843,6 +1846,8 @@ break; case tok::comma: nextToken(); + if (IsEnum && !Style.AllowShortEnumsOnASingleLine) + addUnwrappedLine(); break; default: nextToken(); @@ -2301,9 +2306,18 @@ return true; } + if (!Style.AllowShortEnumsOnASingleLine) + addUnwrappedLine(); // Parse enum body. nextToken(); - bool HasError = !parseBracedList(/*ContinueOnSemicolons=*/true); + if (!Style.AllowShortEnumsOnASingleLine) { + addUnwrappedLine(); + Line->Level += 1; + } + bool HasError = !parseBracedList(/*ContinueOnSemicolons=*/true, + /*IsEnum=*/true); + if (!Style.AllowShortEnumsOnASingleLine) + Line->Level -= 1; if (HasError) { if (FormatTok->is(tok::semi)) nextToken(); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -1298,6 +1298,20 @@ "}"); } +TEST_F(FormatTest, ShortEnums) { + FormatStyle Style = getLLVMStyle(); + Style.AllowShortEnumsOnASingleLine = true; + verifyFormat("enum { A, B, C } ShortEnum1, ShortEnum2;", Style); + Style.AllowShortEnumsOnASingleLine = false; + verifyFormat("enum\n" + "{\n" + " A,\n" + " B,\n" + " C\n" + "} ShortEnum1, ShortEnum2;", + Style); +} + TEST_F(FormatTest, ShortCaseLabels) { FormatStyle Style = getLLVMStyle(); Style.AllowShortCaseLabelsOnASingleLine = true; @@ -12959,6 +12973,7 @@ CHECK_PARSE_BOOL(AllowAllConstructorInitializersOnNextLine); CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine); CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine); + CHECK_PARSE_BOOL(AllowShortEnumsOnASingleLine); CHECK_PARSE_BOOL(AllowShortLoopsOnASingleLine); CHECK_PARSE_BOOL(BinPackArguments); CHECK_PARSE_BOOL(BinPackParameters); diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp --- a/clang/unittests/Format/FormatTestCSharp.cpp +++ b/clang/unittests/Format/FormatTestCSharp.cpp @@ -343,7 +343,13 @@ } TEST_F(FormatTestCSharp, CSharpKeyWordEscaping) { - verifyFormat("public enum var { none, @string, bool, @enum }"); + verifyFormat("public enum var\n" + "{\n" + " none,\n" + " @string,\n" + " bool,\n" + " @enum\n" + "}"); } TEST_F(FormatTestCSharp, CSharpNullCoalescing) {