Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -1698,6 +1698,23 @@ @Mock DataLoad loader; +**BreakArrays** (``Boolean``) :versionbadge:`clang-format 16` + If ``true``, clang-format will always break after a Json array `[` + otherwise it will scan until the closing `]` to determine if it should add + newlines between elements (prettier compatible). + + NOTE: This is currently only for formatting JSON. + + .. code-block:: c++ + + true: false: + [ vs. [1, 2, 3, 4] + 1, + 2, + 3, + 4 + ] + **BreakBeforeBinaryOperators** (``BinaryOperatorStyle``) :versionbadge:`clang-format 3.6` The way to wrap binary operators. Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -872,6 +872,23 @@ /// \version 3.7 bool BinPackParameters; + /// If ``true``, clang-format will always break after a Json array `[` + /// otherwise it will scan until the closing `]` to determine if it should add + /// newlines between elements (prettier compatible). + /// + /// NOTE: This is currently only for formatting JSON. + /// \code + /// true: false: + /// [ vs. [1, 2, 3, 4] + /// 1, + /// 2, + /// 3, + /// 4 + /// ] + /// \endcode + /// \version 16 + bool BreakArrays; + /// The style of wrapping parameters on the same line (bin-packed) or /// on one line each. enum BinPackStyle : int8_t { @@ -3878,6 +3895,7 @@ AttributeMacros == R.AttributeMacros && BinPackArguments == R.BinPackArguments && BinPackParameters == R.BinPackParameters && + BreakArrays == R.BreakArrays && BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators && BreakBeforeBraces == R.BreakBeforeBraces && BreakBeforeConceptDeclarations == R.BreakBeforeConceptDeclarations && Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -728,6 +728,7 @@ IO.mapOptional("BreakAfterJavaFieldAnnotations", Style.BreakAfterJavaFieldAnnotations); + IO.mapOptional("BreakArrays", Style.BreakArrays); IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); IO.mapOptional("ColumnLimit", Style.ColumnLimit); IO.mapOptional("CommentPragmas", Style.CommentPragmas); @@ -1249,6 +1250,7 @@ LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; LLVMStyle.ExperimentalAutoDetectBinPacking = false; + LLVMStyle.BreakArrays = true; LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack; LLVMStyle.FixNamespaceComments = true; LLVMStyle.ForEachMacros.push_back("foreach"); Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -4399,18 +4399,22 @@ // } if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace)) return true; - // Always break after a JSON array opener. - // [ - // ] - if (Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) && - !Right.is(tok::r_square)) { - return true; + // Always break after a JSON array opener based on BreakArrays. + if ((Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) && + Right.isNot(tok::r_square)) || + Left.is(tok::comma)) { + if (Right.is(tok::l_brace)) + return true; + // scan to the right if an we see an object or an array inside + // then break. + for (const auto *Tok = &Right; Tok; Tok = Tok->Next) { + if (Tok->isOneOf(tok::l_brace, tok::l_square)) + return true; + if (Tok->isOneOf(tok::r_brace, tok::r_square)) + break; + } + return Style.BreakArrays; } - // Always break after successive entries. - // 1, - // 2 - if (Left.is(tok::comma)) - return true; } // If the last token before a '}', ']', or ')' is a comma or a trailing Index: clang/unittests/Format/FormatTestJson.cpp =================================================================== --- clang/unittests/Format/FormatTestJson.cpp +++ clang/unittests/Format/FormatTestJson.cpp @@ -159,6 +159,27 @@ "]"); } +TEST_F(FormatTestJson, JsonArrayOneLine) { + FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json); + Style.BreakArrays = false; + Style.SpacesInContainerLiterals = false; + verifyFormat("[]", Style); + verifyFormat("[1]", Style); + verifyFormat("[1, 2]", Style); + verifyFormat("[1, 2, 3]", Style); + verifyFormat("[1, 2, 3, 4]", Style); + verifyFormat("[1, 2, 3, 4, 5]", Style); + + verifyFormat("[\n" + " 1,\n" + " 2,\n" + " {\n" + " A: 1\n" + " }\n" + "]", + Style); +} + TEST_F(FormatTestJson, JsonNoStringSplit) { FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json); Style.IndentWidth = 4;