Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -205,6 +205,20 @@ /// \brief If \c true, short case labels will be contracted to a single line. bool AllowShortCaseLabelsOnASingleLine; + /// \brief Different styles for merging structures into a single line. + enum SingleLineStyle { + /// \brief Never merge into a single line. + SLS_None, + /// \brief Only merge nested structures. + SLS_Nested, + /// \brief Try to merge all. + SLS_All, + }; + + /// \brief Dependent on the value, dict literals will be contracted to + /// a single line. + SingleLineStyle AllowDictLiteralsOnASingleLine; + /// \brief Different styles for merging short functions containing at most one /// statement. enum ShortFunctionStyle { @@ -416,6 +430,7 @@ AlignTrailingComments == R.AlignTrailingComments && AllowAllParametersOfDeclarationOnNextLine == R.AllowAllParametersOfDeclarationOnNextLine && + AllowDictLiteralsOnASingleLine == R.AllowDictLiteralsOnASingleLine && AllowShortFunctionsOnASingleLine == R.AllowShortFunctionsOnASingleLine && AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine && Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -68,6 +68,16 @@ } }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FormatStyle::SingleLineStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::SLS_None); + IO.enumCase(Value, "false", FormatStyle::SLS_None); + IO.enumCase(Value, "All", FormatStyle::SLS_All); + IO.enumCase(Value, "true", FormatStyle::SLS_All); + IO.enumCase(Value, "Nested", FormatStyle::SLS_Nested); + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { IO.enumCase(Value, "None", FormatStyle::SFS_None); @@ -178,6 +188,8 @@ IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", Style.AllowAllParametersOfDeclarationOnNextLine); + IO.mapOptional("AllowDictLiteralsOnASingleLine", + Style.AllowDictLiteralsOnASingleLine); IO.mapOptional("AllowShortBlocksOnASingleLine", Style.AllowShortBlocksOnASingleLine); IO.mapOptional("AllowShortCaseLabelsOnASingleLine", @@ -332,6 +344,7 @@ LLVMStyle.AlignOperands = true; LLVMStyle.AlignTrailingComments = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; + LLVMStyle.AllowDictLiteralsOnASingleLine = FormatStyle::SLS_Nested; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortBlocksOnASingleLine = false; LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -1913,7 +1913,9 @@ Left.Previous->is(tok::char_constant)) return true; if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && - Left.NestingLevel == 0) + (Style.AllowDictLiteralsOnASingleLine == FormatStyle::SLS_None || + (Style.AllowDictLiteralsOnASingleLine == FormatStyle::SLS_Nested && + Left.NestingLevel == 0))) return true; } else if (Style.Language == FormatStyle::LK_Java) { if (Left.is(TT_LeadingJavaAnnotation) && Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -8818,6 +8818,19 @@ CHECK_PARSE("UseTab: false", UseTab, FormatStyle::UT_Never); CHECK_PARSE("UseTab: true", UseTab, FormatStyle::UT_Always); + Style.AllowDictLiteralsOnASingleLine = FormatStyle::SLS_Nested; + CHECK_PARSE("AllowDictLiteralsOnASingleLine: None", + AllowDictLiteralsOnASingleLine, FormatStyle::SLS_None); + CHECK_PARSE("AllowDictLiteralsOnASingleLine: Nested", + AllowDictLiteralsOnASingleLine, FormatStyle::SLS_Nested); + CHECK_PARSE("AllowDictLiteralsOnASingleLine: All", + AllowDictLiteralsOnASingleLine, FormatStyle::SLS_All); + // For backward compatibility: + CHECK_PARSE("AllowDictLiteralsOnASingleLine: false", + AllowDictLiteralsOnASingleLine, FormatStyle::SLS_None); + CHECK_PARSE("AllowDictLiteralsOnASingleLine: true", + AllowDictLiteralsOnASingleLine, FormatStyle::SLS_All); + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; CHECK_PARSE("AllowShortFunctionsOnASingleLine: None", AllowShortFunctionsOnASingleLine, FormatStyle::SFS_None); Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -43,6 +43,13 @@ return Style; } + static FormatStyle singleLineDictLiteralsStyle( + FormatStyle::SingleLineStyle SingleLineStyle) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); + Style.AllowDictLiteralsOnASingleLine = SingleLineStyle; + return Style; + } + static void verifyFormat( llvm::StringRef Code, const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) { @@ -98,6 +105,13 @@ " a: 1,\n" " b: 2\n" "};"); + verifyFormat("var {a, b} = {\n" + " a: 1,\n" + " b: 2\n" + "};", + singleLineDictLiteralsStyle(FormatStyle::SLS_None)); + verifyFormat("var {a, b} = {a: 1, b: 2};", + singleLineDictLiteralsStyle(FormatStyle::SLS_All)); } TEST_F(FormatTestJS, ContainerLiterals) { @@ -144,6 +158,14 @@ TEST_F(FormatTestJS, SpacesInContainerLiterals) { verifyFormat("var arr = [1, 2, 3];"); verifyFormat("f({a: 1, b: 2, c: 3});"); + verifyFormat("f({a: 1, b: 2, c: 3});", + singleLineDictLiteralsStyle(FormatStyle::SLS_All)); + verifyFormat("f({\n" + " a: 1,\n" + " b: 2,\n" + " c: 3\n" + "});", + singleLineDictLiteralsStyle(FormatStyle::SLS_None)); verifyFormat("var object_literal_with_long_name = {\n" " a: 'aaaaaaaaaaaaaaaaaa',\n"