From: Daniel Jasper Date: Mon, 11 May 2015 13:35:40 +0000 (+0000) Subject: clang-format: Improve column layout. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=75557a85f8e6d7d795405cf1a4b20a528e78a75e;p=clang clang-format: Improve column layout. Specifically, calculate the deviation between the shortest and longest element (which is used to prevent excessive whitespace) per column, not overall. This automatically handles the corner cases of a single column and a single row so that the actualy implementation becomes simpler. Before: vector x = {1, aaaaaaaaaaaaaaaaaaaaaa, 2, bbbbbbbbbbbbbbbbbbbbbb, 3, cccccccccccccccccccccc}; After: vector x = {1, aaaaaaaaaaaaaaaaaaaaaa, 2, bbbbbbbbbbbbbbbbbbbbbb, 3, cccccccccccccccccccccc}; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@236992 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/FormatToken.cpp b/lib/Format/FormatToken.cpp index cc1ef55fa4..b565ee1f20 100644 --- a/lib/Format/FormatToken.cpp +++ b/lib/Format/FormatToken.cpp @@ -150,9 +150,6 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { // trailing comments which are otherwise ignored for column alignment. SmallVector EndOfLineItemLength; - unsigned MinItemLength = Style.ColumnLimit; - unsigned MaxItemLength = 0; - for (unsigned i = 0, e = Commas.size() + 1; i != e; ++i) { // Skip comments on their own line. while (ItemBegin->HasUnescapedNewline && ItemBegin->isTrailingComment()) @@ -179,8 +176,6 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { ItemEnd = Commas[i]; // The comma is counted as part of the item when calculating the length. ItemLengths.push_back(CodePointsBetween(ItemBegin, ItemEnd)); - MinItemLength = std::min(MinItemLength, ItemLengths.back()); - MaxItemLength = std::max(MaxItemLength, ItemLengths.back()); // Consume trailing comments so the are included in EndOfLineItemLength. if (ItemEnd->Next && !ItemEnd->Next->HasUnescapedNewline && @@ -197,19 +192,17 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { // If this doesn't have a nested list, we require at least 6 elements in order // create a column layout. If it has a nested list, column layout ensures one - // list element per line. If the difference between the shortest and longest - // element is too large, column layout would create too much whitespace. + // list element per line. if (Commas.size() < 5 || Token->NestingLevel != 0) return; // We can never place more than ColumnLimit / 3 items in a row (because of the // spaces and the comma). - unsigned MaxColumns = - MaxItemLength - MinItemLength > 10 ? 1 : Style.ColumnLimit / 3; - for (unsigned Columns = 1; Columns <= MaxColumns; ++Columns) { + for (unsigned Columns = 1; Columns <= Style.ColumnLimit / 3; ++Columns) { ColumnFormat Format; Format.Columns = Columns; Format.ColumnSizes.resize(Columns); + std::vector MinSizeInColumn(Columns, UINT_MAX); Format.LineCount = 1; bool HasRowWithSufficientColumns = false; unsigned Column = 0; @@ -221,9 +214,10 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { } if (Column == Columns - 1) HasRowWithSufficientColumns = true; - unsigned length = + unsigned Length = (Column == Columns - 1) ? EndOfLineItemLength[i] : ItemLengths[i]; - Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], length); + Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], Length); + MinSizeInColumn[Column] = std::min(MinSizeInColumn[Column], Length); ++Column; } // If all rows are terminated early (e.g. by trailing comments), we don't @@ -231,9 +225,19 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { if (!HasRowWithSufficientColumns) break; Format.TotalWidth = Columns - 1; // Width of the N-1 spaces. - for (unsigned i = 0; i < Columns; ++i) { + + for (unsigned i = 0; i < Columns; ++i) Format.TotalWidth += Format.ColumnSizes[i]; - } + + // Don't use this Format, if the difference between the longest and shortest + // element in a column exceeds a threshold to avoid excessive spaces. + if ([&] { + for (unsigned i = 0; i < Columns - 1; ++i) + if (Format.ColumnSizes[i] - MinSizeInColumn[i] > 10) + return true; + return false; + }()) + continue; // Ignore layouts that are bound to violate the column limit. if (Format.TotalWidth > Style.ColumnLimit) diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 43f94f0ce6..9098d2b9bf 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -6305,6 +6305,11 @@ TEST_F(FormatTest, FormatsBracedListsInColumnLayout) { " \"aaaaaaaaaaaa\",\n" " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n" "};"); + verifyFormat("vector x = {1, 2, 3, 4, aaaaaaaaaaaaaaaaa, 6};"); + verifyFormat("vector x = {1, aaaaaaaaaaaaaaaaaaaaaa,\n" + " 2, bbbbbbbbbbbbbbbbbbbbbb,\n" + " 3, cccccccccccccccccccccc};", + getLLVMStyleWithColumns(60)); // Trailing commas. verifyFormat("vector x = {\n"