MyDeveloperDay created this revision. MyDeveloperDay added reviewers: HazardyKnusperkeks, curdeius, owenpan. MyDeveloperDay added a project: clang-format. Herald added a project: All. MyDeveloperDay requested review of this revision. Herald added a project: clang.
Working in a mixed environment of both vscode/vim with a team configured prettier configuration, this can leave clang-format and prettier fighting each other over the formatting of arrays, both simple arrays of elements. This review aims to add some "control knobs" to the Json formatting in clang-format to help align the two tools so they can be used interchangeably. This will allow simply arrays `[1, 2, 3]` to remain on a single line but will break those arrays based on context within that array. Happy to change the name of the option (this is the third name I tried) Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D133589 Files: clang/docs/ClangFormatStyleOptions.rst clang/include/clang/Format/Format.h clang/lib/Format/Format.cpp clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/FormatTestJson.cpp
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.JsonMultilineArrays = 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; Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -4399,18 +4399,48 @@ // } if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace)) return true; - // Always break after a JSON array opener. + // Always break after a JSON array opener based on JsonMultilineArrays // [ // ] if (Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) && !Right.is(tok::r_square)) { - return true; + if (Right.is(tok::l_brace)) + return true; + // scan to the right if an we see an object or an array inside + // then break + const auto *Tok = &Right; + while (Tok) { + if (Tok->isOneOf(tok::l_brace, tok::l_square)) { + return true; + } + if (Tok->isOneOf(tok::r_brace, tok::r_square)) { + break; + } + Tok = Tok->Next; + } + return Style.JsonMultilineArrays; } // Always break after successive entries. // 1, // 2 - if (Left.is(tok::comma)) - return true; + if (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 + const auto *Tok = &Right; + while (Tok) { + if (Tok->isOneOf(tok::l_brace, tok::l_square)) { + return true; + } + if (Tok->isOneOf(tok::r_brace, tok::r_square)) { + break; + } + Tok = Tok->Next; + } + return Style.JsonMultilineArrays; + } } // If the last token before a '}', ']', or ')' is a comma or a trailing Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -756,6 +756,8 @@ IO.mapOptional("ExperimentalAutoDetectBinPacking", Style.ExperimentalAutoDetectBinPacking); + IO.mapOptional("JsonMultilineArrays", Style.JsonMultilineArrays); + IO.mapOptional("PackConstructorInitializers", Style.PackConstructorInitializers); // For backward compatibility: @@ -1249,6 +1251,7 @@ LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; LLVMStyle.ExperimentalAutoDetectBinPacking = false; + LLVMStyle.JsonMultilineArrays = true; LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack; LLVMStyle.FixNamespaceComments = true; LLVMStyle.ForEachMacros.push_back("foreach"); Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -2058,6 +2058,21 @@ /// \version 12 EmptyLineBeforeAccessModifierStyle EmptyLineBeforeAccessModifier; + /// 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) + /// \code + /// true: false: + /// [ vs. [1, 2, 3, 4] + /// 1, + /// 2, + /// 3, + /// 4 + /// ] + /// \endcode + /// \version 16 + bool JsonMultilineArrays; + /// If ``true``, clang-format detects whether function calls and /// definitions are formatted with one parameter per line. /// @@ -3897,6 +3912,7 @@ DisableFormat == R.DisableFormat && EmptyLineAfterAccessModifier == R.EmptyLineAfterAccessModifier && EmptyLineBeforeAccessModifier == R.EmptyLineBeforeAccessModifier && + JsonMultilineArrays == R.JsonMultilineArrays && ExperimentalAutoDetectBinPacking == R.ExperimentalAutoDetectBinPacking && PackConstructorInitializers == R.PackConstructorInitializers && Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -3112,6 +3112,21 @@ false: import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,} from "some/module.js" +**JsonMultilineArrays** (``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) + + .. code-block:: c++ + + true: false: + [ vs. [1, 2, 3, 4] + 1, + 2, + 3, + 4 + ] + **KeepEmptyLinesAtTheStartOfBlocks** (``Boolean``) :versionbadge:`clang-format 3.7` If true, the empty line at the start of blocks is kept.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits