From 10234da71d6aab25c82b1913829fed6ae3b408cc Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 11 Aug 2019 17:48:36 +0000 Subject: [PATCH] [clang-format] Expand AllowShortBlocksOnASingleLine for WebKit See PR40840 Differential Revision: https://reviews.llvm.org/D66059 llvm-svn: 368539 --- clang/docs/ClangFormatStyleOptions.rst | 38 +++++++++++++++++++++++++--- clang/include/clang/Format/Format.h | 35 +++++++++++++++++++++++--- clang/lib/Format/Format.cpp | 14 +++++++++-- clang/lib/Format/TokenAnnotator.cpp | 3 ++- clang/lib/Format/UnwrappedLineFormatter.cpp | 11 ++++---- clang/unittests/Format/FormatTest.cpp | 39 ++++++++++++++++++++++------- 6 files changed, 116 insertions(+), 24 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 3ff61d2..50d8b365 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -344,10 +344,42 @@ the configuration (without a prefix: ``Auto``). int d, int e); -**AllowShortBlocksOnASingleLine** (``bool``) - Allows contracting simple braced statements to a single line. +**AllowShortBlocksOnASingleLine** (``ShortBlockStyle``) + Dependent on the value, ``while (true) { continue; }`` can be put on a + single line. + + Possible values: + + * ``SBS_Never`` (in configuration: ``Never``) + Never merge blocks into a single line. + + .. code-block:: c++ + + while (true) { + } + while (true) { + continue; + } + + * ``SBS_Empty`` (in configuration: ``Empty``) + Only merge empty blocks. + + .. code-block:: c++ + + while (true) {} + while (true) { + continue; + } + + * ``SBS_Always`` (in configuration: ``Always``) + Always merge short blocks into a single line. + + .. code-block:: c++ + + while (true) {} + while (true) { continue; } + - 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. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 657ec4e..7a6688b 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -216,10 +216,37 @@ struct FormatStyle { /// \endcode bool AllowAllParametersOfDeclarationOnNextLine; - /// Allows contracting simple braced statements to a single line. - /// - /// E.g., this allows ``if (a) { return; }`` to be put on a single line. - bool AllowShortBlocksOnASingleLine; + /// Different styles for merging short blocks containing at most one + /// statement. + enum ShortBlockStyle { + /// Never merge blocks into a single line. + /// \code + /// while (true) { + /// } + /// while (true) { + /// continue; + /// } + /// \endcode + SBS_Never, + /// Only merge empty blocks. + /// \code + /// while (true) {} + /// while (true) { + /// continue; + /// } + /// \endcode + SBS_Empty, + /// Always merge short blocks into a single line. + /// \code + /// while (true) {} + /// while (true) { continue; } + /// \endcode + SBS_Always, + }; + + /// Dependent on the value, ``while (true) { continue; }`` can be put on a + /// single line. + ShortBlockStyle AllowShortBlocksOnASingleLine; /// If ``true``, short case labels will be contracted to a single line. /// \code diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 6c4fedb..c15c00e 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -95,6 +95,16 @@ template <> struct ScalarEnumerationTraits { } }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::SBS_Never); + IO.enumCase(Value, "false", FormatStyle::SBS_Never); + IO.enumCase(Value, "Always", FormatStyle::SBS_Always); + IO.enumCase(Value, "true", FormatStyle::SBS_Always); + IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty); + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { IO.enumCase(Value, "None", FormatStyle::SFS_None); @@ -674,7 +684,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AllowAllConstructorInitializersOnNextLine = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; - LLVMStyle.AllowShortBlocksOnASingleLine = false; + LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; @@ -969,6 +979,7 @@ FormatStyle getWebKitStyle() { Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; Style.AlignOperands = false; Style.AlignTrailingComments = false; + Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; Style.BreakBeforeBraces = FormatStyle::BS_WebKit; Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; @@ -1019,7 +1030,6 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { Style.BraceWrapping.BeforeElse = true; Style.PenaltyReturnTypeOnItsOwnLine = 1000; Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; - Style.AllowShortBlocksOnASingleLine = false; 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 cc0a954..c0533bb 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3044,7 +3044,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, Style.BraceWrapping.AfterEnum) || (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) || (Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct); - if (Left.is(TT_ObjCBlockLBrace) && !Style.AllowShortBlocksOnASingleLine) + if (Left.is(TT_ObjCBlockLBrace) && + Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) return true; if (Left.is(TT_LambdaLBrace)) { diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index f41c77e..9878d45 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -300,7 +300,7 @@ private: // Try to merge a control statement block with left brace unwrapped if (TheLine->Last->is(tok::l_brace) && TheLine->First != TheLine->Last && TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) { - return Style.AllowShortBlocksOnASingleLine + return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never ? tryMergeSimpleBlock(I, E, Limit) : 0; } @@ -317,7 +317,7 @@ private: I != AnnotatedLines.begin() && I[-1]->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) { unsigned MergedLines = 0; - if (Style.AllowShortBlocksOnASingleLine) { + if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never) { MergedLines = tryMergeSimpleBlock(I - 1, E, Limit); // If we managed to merge the block, discard the first merged line // since we are merging starting from I. @@ -411,7 +411,8 @@ private: if (Limit == 0) return 0; if (Style.BraceWrapping.AfterControlStatement && - (I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine)) + I[1]->First->is(tok::l_brace) && + Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) return 0; if (I[1]->InPPDirective != (*I)->InPPDirective || (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) @@ -511,7 +512,7 @@ private: if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try, tok::kw___try, tok::kw_catch, tok::kw___finally, tok::kw_for, tok::r_brace, Keywords.kw___except)) { - if (!Style.AllowShortBlocksOnASingleLine) + if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) return 0; // Don't merge when we can't except the case when // the control statement block is empty @@ -607,7 +608,7 @@ private: return 0; Limit -= 2; unsigned MergedLines = 0; - if (Style.AllowShortBlocksOnASingleLine || + if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never || (I[1]->First == I[1]->Last && I + 2 != E && I[2]->First->is(tok::r_brace))) { MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 197c08b..3fe75ec 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -561,7 +561,8 @@ TEST_F(FormatTest, FormatLoopsWithoutCompoundStatement) { TEST_F(FormatTest, FormatShortBracedStatements) { FormatStyle AllowSimpleBracedStatements = getLLVMStyle(); AllowSimpleBracedStatements.ColumnLimit = 40; - AllowSimpleBracedStatements.AllowShortBlocksOnASingleLine = true; + AllowSimpleBracedStatements.AllowShortBlocksOnASingleLine = + FormatStyle::SBS_Always; AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_WithoutElse; @@ -714,7 +715,7 @@ TEST_F(FormatTest, FormatShortBracedStatements) { TEST_F(FormatTest, ShortBlocksInMacrosDontMergeWithCodeAfterMacro) { FormatStyle Style = getLLVMStyleWithColumns(60); - Style.AllowShortBlocksOnASingleLine = true; + Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always; Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_WithoutElse; Style.BreakBeforeBraces = FormatStyle::BS_Allman; EXPECT_EQ("#define A \\\n" @@ -1163,7 +1164,7 @@ TEST_F(FormatTest, FormatsSwitchStatement) { FormatStyle Style = getLLVMStyle(); Style.IndentCaseLabels = true; - Style.AllowShortBlocksOnASingleLine = false; + Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterCaseLabel = true; Style.BraceWrapping.AfterControlStatement = true; @@ -3692,10 +3693,10 @@ TEST_F(FormatTest, PutEmptyBlocksIntoOneLine) { EXPECT_EQ("{}", format("{}")); verifyFormat("enum E {};"); verifyFormat("enum E {}"); - EXPECT_EQ("void f() { }", format("void f() {}", getWebKitStyle())); FormatStyle Style = getLLVMStyle(); - Style.AllowShortBlocksOnASingleLine = true; Style.SpaceInEmptyBlock = true; + EXPECT_EQ("void f() { }", format("void f() {}", Style)); + Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; EXPECT_EQ("while (true) { }", format("while (true) {}", Style)); } @@ -11745,7 +11746,6 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(AllowAllArgumentsOnNextLine); CHECK_PARSE_BOOL(AllowAllConstructorInitializersOnNextLine); CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine); - CHECK_PARSE_BOOL(AllowShortBlocksOnASingleLine); CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine); CHECK_PARSE_BOOL(AllowShortLoopsOnASingleLine); CHECK_PARSE_BOOL(BinPackArguments); @@ -11920,6 +11920,19 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE("UseTab: false", UseTab, FormatStyle::UT_Never); CHECK_PARSE("UseTab: true", UseTab, FormatStyle::UT_Always); + Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; + CHECK_PARSE("AllowShortBlocksOnASingleLine: Never", + AllowShortBlocksOnASingleLine, FormatStyle::SBS_Never); + CHECK_PARSE("AllowShortBlocksOnASingleLine: Empty", + AllowShortBlocksOnASingleLine, FormatStyle::SBS_Empty); + CHECK_PARSE("AllowShortBlocksOnASingleLine: Always", + AllowShortBlocksOnASingleLine, FormatStyle::SBS_Always); + // For backward compatibility: + CHECK_PARSE("AllowShortBlocksOnASingleLine: false", + AllowShortBlocksOnASingleLine, FormatStyle::SBS_Never); + CHECK_PARSE("AllowShortBlocksOnASingleLine: true", + AllowShortBlocksOnASingleLine, FormatStyle::SBS_Always); + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; CHECK_PARSE("AllowShortFunctionsOnASingleLine: None", AllowShortFunctionsOnASingleLine, FormatStyle::SFS_None); @@ -12527,6 +12540,14 @@ TEST_F(FormatTest, FormatsWithWebKitStyle) { // Allow functions on a single line. verifyFormat("void f() { return; }", Style); + // Allow empty blocks on a single line and insert a space in empty blocks. + EXPECT_EQ("void f() { }", format("void f() {}", Style)); + EXPECT_EQ("while (true) { }", format("while (true) {}", Style)); + // However, don't merge non-empty short loops. + EXPECT_EQ("while (true) {\n" + " continue;\n" + "}", format("while (true) { continue; }", Style)); + // Constructor initializers are formatted one per line with the "," on the // new line. verifyFormat("Constructor()\n" @@ -13033,7 +13054,7 @@ TEST_F(FormatTest, EmptyLinesInLambdas) { TEST_F(FormatTest, FormatsBlocks) { FormatStyle ShortBlocks = getLLVMStyle(); - ShortBlocks.AllowShortBlocksOnASingleLine = true; + ShortBlocks.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always; verifyFormat("int (^Block)(int, int);", ShortBlocks); verifyFormat("int (^Block1)(int, int) = ^(int i, int j)", ShortBlocks); verifyFormat("void (^block)(int) = ^(id test) { int i; };", ShortBlocks); @@ -13191,10 +13212,10 @@ TEST_F(FormatTest, FormatsBlocksWithZeroColumnWidth) { "};", ZeroColumn); - ZeroColumn.AllowShortBlocksOnASingleLine = true; + ZeroColumn.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always; EXPECT_EQ("void (^largeBlock)(void) = ^{ int i; };", format("void (^largeBlock)(void) = ^{ int i; };", ZeroColumn)); - ZeroColumn.AllowShortBlocksOnASingleLine = false; + ZeroColumn.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; EXPECT_EQ("void (^largeBlock)(void) = ^{\n" " int i;\n" "};", -- 2.7.4