From: Daniel Jasper Date: Wed, 10 Sep 2014 13:11:45 +0000 (+0000) Subject: clang-format: Add option to allow short case labels on a single line. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c661f601f8e9d834cc3a90aff5cfe1190956fd4e;p=clang clang-format: Add option to allow short case labels on a single line. On a single line: switch (a) { case 1: x = 1; return; case 2: x = 2; return; default: break; } Not on a single line: switch (a) { case 1: x = 1; return; case 2: x = 2; return; default: break; } This partly addresses llvm.org/PR16535. In the long run, we probably want to lay these out in columns. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@217501 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index 332fe3becd..c7981cfcdf 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -148,6 +148,9 @@ the configuration (without a prefix: ``Auto``). E.g., this allows ``if (a) { return; }`` to be put on a single line. +**AllowShortCaseLabelsOnASingleLine** (``bool``) + If ``true``, short case labels will be contracted to a single line. + **AllowShortFunctionsOnASingleLine** (``ShortFunctionStyle``) Dependent on the value, ``int f() { return 0; }`` can be put on a single line. @@ -257,7 +260,7 @@ the configuration (without a prefix: ``Auto``). **DerivePointerAlignment** (``bool``) If ``true``, analyze the formatted file for the most common - alignment of ``&`` and ``*``. ``PointerAlignment`` is then used only as fallback. + alignment of & and *. ``PointerAlignment`` is then used only as fallback. **DisableFormat** (``bool``) Disables formatting at all. @@ -374,6 +377,9 @@ the configuration (without a prefix: ``Auto``). Align pointer in the middle. +**SpaceAfterCStyleCast** (``bool``) + If ``true``, a space may be inserted after C style casts. + **SpaceBeforeAssignmentOperators** (``bool``) If ``false``, spaces will be removed before assignment operators. @@ -411,9 +417,6 @@ the configuration (without a prefix: ``Auto``). **SpacesInCStyleCastParentheses** (``bool``) If ``true``, spaces may be inserted into C style casts. -**SpaceAfterCStyleCast** (``bool``) - If ``true``, a space may be inserted after C style casts. - **SpacesInContainerLiterals** (``bool``) If ``true``, spaces are inserted inside container literals (e.g. ObjC and Javascript array and dict literals). @@ -422,8 +425,7 @@ the configuration (without a prefix: ``Auto``). If ``true``, spaces will be inserted after '(' and before ')'. **SpacesInSquareBrackets** (``bool``) - If ``true``, spaces will be inserted after '[' and before ']' in array - declarations and element access expressions, but not in lambdas. + If ``true``, spaces will be inserted after '[' and before ']'. **Standard** (``LanguageStandard``) Format compatible with this standard, e.g. use diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index a6d17542e4..abf505922e 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -195,6 +195,9 @@ struct FormatStyle { /// single line. bool AllowShortLoopsOnASingleLine; + /// \brief If \c true, short case labels will be contracted to a single line. + bool AllowShortCaseLabelsOnASingleLine; + /// \brief Different styles for merging short functions containing at most one /// statement. enum ShortFunctionStyle { diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 7e243b6e0e..5b2f222bfc 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -167,6 +167,8 @@ template <> struct MappingTraits { Style.AllowAllParametersOfDeclarationOnNextLine); IO.mapOptional("AllowShortBlocksOnASingleLine", Style.AllowShortBlocksOnASingleLine); + IO.mapOptional("AllowShortCaseLabelsOnASingleLine", + Style.AllowShortCaseLabelsOnASingleLine); IO.mapOptional("AllowShortIfStatementsOnASingleLine", Style.AllowShortIfStatementsOnASingleLine); IO.mapOptional("AllowShortLoopsOnASingleLine", @@ -313,6 +315,7 @@ FormatStyle getLLVMStyle() { LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortBlocksOnASingleLine = false; + LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; LLVMStyle.AllowShortIfStatementsOnASingleLine = false; LLVMStyle.AllowShortLoopsOnASingleLine = false; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = false; @@ -642,6 +645,11 @@ public: ? tryMergeSimpleControlStatement(I, E, Limit) : 0; } + if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) { + return Style.AllowShortCaseLabelsOnASingleLine + ? tryMergeShortCaseLabels(I, E, Limit) + : 0; + } if (TheLine->InPPDirective && (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) { return tryMergeSimplePPDirective(I, E, Limit); @@ -694,6 +702,30 @@ private: return 1; } + unsigned tryMergeShortCaseLabels( + SmallVectorImpl::const_iterator I, + SmallVectorImpl::const_iterator E, unsigned Limit) { + if (Limit == 0 || I + 1 == E || + I[1]->First->isOneOf(tok::kw_case, tok::kw_default)) + return 0; + unsigned NumStmts = 0; + unsigned Length = 0; + for (; NumStmts < 3; ++NumStmts) { + if (I + 1 + NumStmts == E) + break; + const AnnotatedLine *Line = I[1 + NumStmts]; + if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace)) + break; + if (Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch, + tok::kw_while)) + return 0; + Length += I[1 + NumStmts]->Last->TotalLength + 1; // 1 for the space. + } + if (NumStmts == 0 || NumStmts == 3 || Length > Limit) + return 0; + return NumStmts; + } + unsigned tryMergeSimpleBlock(SmallVectorImpl::const_iterator I, SmallVectorImpl::const_iterator E, diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 6f00acf38f..8b8aaf1b4a 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -700,6 +700,47 @@ TEST_F(FormatTest, CaseRanges) { "}"); } +TEST_F(FormatTest, ShortCaseLabels) { + FormatStyle Style = getLLVMStyle(); + Style.AllowShortCaseLabelsOnASingleLine = true; + verifyFormat("switch (a) {\n" + "case 1: x = 1; break;\n" + "case 2: return;\n" + "case 3:\n" + "case 4:\n" + "case 5: return;\n" + "default: y = 1; break;\n" + "}", + Style); + verifyFormat("switch (a) {\n" + "case 1: {\n" + "}\n" + "case 2: {\n" + " return;\n" + "}\n" + "case 3: {\n" + " x = 1;\n" + " return;\n" + "}\n" + "case 4:\n" + " if (x)\n" + " return;\n" + "}", + Style); + Style.ColumnLimit = 21; + verifyFormat("switch (a) {\n" + "case 1: x = 1; break;\n" + "case 2: return;\n" + "case 3:\n" + "case 4:\n" + "case 5: return;\n" + "default:\n" + " y = 1;\n" + " break;\n" + "}", + Style); +} + TEST_F(FormatTest, FormatsLabels) { verifyFormat("void f() {\n" " some_code();\n" @@ -8316,6 +8357,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(AlignTrailingComments); CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine); CHECK_PARSE_BOOL(AllowShortBlocksOnASingleLine); + CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine); CHECK_PARSE_BOOL(AllowShortIfStatementsOnASingleLine); CHECK_PARSE_BOOL(AllowShortLoopsOnASingleLine); CHECK_PARSE_BOOL(AlwaysBreakAfterDefinitionReturnType);