diff options
Diffstat (limited to 'lib/Format/FormatToken.cpp')
-rw-r--r-- | lib/Format/FormatToken.cpp | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/lib/Format/FormatToken.cpp b/lib/Format/FormatToken.cpp index badb3a3..88678ca 100644 --- a/lib/Format/FormatToken.cpp +++ b/lib/Format/FormatToken.cpp @@ -18,6 +18,7 @@ #include "clang/Format/Format.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" +#include <climits> namespace clang { namespace format { @@ -59,12 +60,13 @@ void TokenRole::precomputeFormattingInfos(const FormatToken *Token) {} unsigned CommaSeparatedList::formatAfterToken(LineState &State, ContinuationIndenter *Indenter, bool DryRun) { - if (!State.NextToken->Previous || !State.NextToken->Previous->Previous) + if (State.NextToken == nullptr || !State.NextToken->Previous) return 0; // Ensure that we start on the opening brace. - const FormatToken *LBrace = State.NextToken->Previous->Previous; - if (LBrace->isNot(tok::l_brace) || LBrace->BlockKind == BK_Block || + const FormatToken *LBrace = + State.NextToken->Previous->getPreviousNonComment(); + if (!LBrace || LBrace->isNot(tok::l_brace) || LBrace->BlockKind == BK_Block || LBrace->Type == TT_DictLiteral || LBrace->Next->Type == TT_DesignatedInitializerPeriod) return 0; @@ -132,9 +134,9 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { return; // In C++11 braced list style, we should not format in columns unless they - // have many items (20 or more) or we allow bin-packing of function - // parameters. - if (Style.Cpp11BracedListStyle && !Style.BinPackParameters && + // have many items (20 or more) or we allow bin-packing of function call + // arguments. + if (Style.Cpp11BracedListStyle && !Style.BinPackArguments && Commas.size() < 19) return; @@ -143,19 +145,21 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { return; FormatToken *ItemBegin = Token->Next; + while (ItemBegin->isTrailingComment()) + ItemBegin = ItemBegin->Next; SmallVector<bool, 8> MustBreakBeforeItem; // The lengths of an item if it is put at the end of the line. This includes // trailing comments which are otherwise ignored for column alignment. SmallVector<unsigned, 8> EndOfLineItemLength; - unsigned MinItemLength = Style.ColumnLimit; - unsigned MaxItemLength = 0; - + bool HasSeparatingComment = false; for (unsigned i = 0, e = Commas.size() + 1; i != e; ++i) { // Skip comments on their own line. - while (ItemBegin->HasUnescapedNewline && ItemBegin->isTrailingComment()) + while (ItemBegin->HasUnescapedNewline && ItemBegin->isTrailingComment()) { ItemBegin = ItemBegin->Next; + HasSeparatingComment = i > 0; + } MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore); if (ItemBegin->is(tok::l_brace)) @@ -178,8 +182,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 && @@ -194,12 +196,9 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { ItemBegin = ItemEnd->Next; } - // 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. - if (HasNestedBracedList || Commas.size() < 5 || Token->NestingLevel != 0 || - MaxItemLength - MinItemLength > 10) + // Don't use column layout for nested lists, lists with few elements and in + // presence of separating comments. + if (Token->NestingLevel != 0 || Commas.size() < 5 || HasSeparatingComment) return; // We can never place more than ColumnLimit / 3 items in a row (because of the @@ -208,6 +207,7 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { ColumnFormat Format; Format.Columns = Columns; Format.ColumnSizes.resize(Columns); + std::vector<unsigned> MinSizeInColumn(Columns, UINT_MAX); Format.LineCount = 1; bool HasRowWithSufficientColumns = false; unsigned Column = 0; @@ -219,9 +219,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 @@ -229,9 +230,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) |