clang API Documentation

FormatToken.cpp
Go to the documentation of this file.
00001 //===--- FormatToken.cpp - Format C++ code --------------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 ///
00010 /// \file
00011 /// \brief This file implements specific functions of \c FormatTokens and their
00012 /// roles.
00013 ///
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "FormatToken.h"
00017 #include "ContinuationIndenter.h"
00018 #include "clang/Format/Format.h"
00019 #include "llvm/ADT/SmallVector.h"
00020 #include "llvm/Support/Debug.h"
00021 
00022 namespace clang {
00023 namespace format {
00024 
00025 // FIXME: This is copy&pasted from Sema. Put it in a common place and remove
00026 // duplication.
00027 bool FormatToken::isSimpleTypeSpecifier() const {
00028   switch (Tok.getKind()) {
00029   case tok::kw_short:
00030   case tok::kw_long:
00031   case tok::kw___int64:
00032   case tok::kw___int128:
00033   case tok::kw_signed:
00034   case tok::kw_unsigned:
00035   case tok::kw_void:
00036   case tok::kw_char:
00037   case tok::kw_int:
00038   case tok::kw_half:
00039   case tok::kw_float:
00040   case tok::kw_double:
00041   case tok::kw_wchar_t:
00042   case tok::kw_bool:
00043   case tok::kw___underlying_type:
00044   case tok::annot_typename:
00045   case tok::kw_char16_t:
00046   case tok::kw_char32_t:
00047   case tok::kw_typeof:
00048   case tok::kw_decltype:
00049     return true;
00050   default:
00051     return false;
00052   }
00053 }
00054 
00055 TokenRole::~TokenRole() {}
00056 
00057 void TokenRole::precomputeFormattingInfos(const FormatToken *Token) {}
00058 
00059 unsigned CommaSeparatedList::formatAfterToken(LineState &State,
00060                                               ContinuationIndenter *Indenter,
00061                                               bool DryRun) {
00062   if (!State.NextToken->Previous || !State.NextToken->Previous->Previous)
00063     return 0;
00064 
00065   // Ensure that we start on the opening brace.
00066   const FormatToken *LBrace = State.NextToken->Previous->Previous;
00067   if (LBrace->isNot(tok::l_brace) || LBrace->BlockKind == BK_Block ||
00068       LBrace->Type == TT_DictLiteral ||
00069       LBrace->Next->Type == TT_DesignatedInitializerPeriod)
00070     return 0;
00071 
00072   // Calculate the number of code points we have to format this list. As the
00073   // first token is already placed, we have to subtract it.
00074   unsigned RemainingCodePoints =
00075       Style.ColumnLimit - State.Column + State.NextToken->Previous->ColumnWidth;
00076 
00077   // Find the best ColumnFormat, i.e. the best number of columns to use.
00078   const ColumnFormat *Format = getColumnFormat(RemainingCodePoints);
00079   // If no ColumnFormat can be used, the braced list would generally be
00080   // bin-packed. Add a severe penalty to this so that column layouts are
00081   // preferred if possible.
00082   if (!Format)
00083     return 10000;
00084 
00085   // Format the entire list.
00086   unsigned Penalty = 0;
00087   unsigned Column = 0;
00088   unsigned Item = 0;
00089   while (State.NextToken != LBrace->MatchingParen) {
00090     bool NewLine = false;
00091     unsigned ExtraSpaces = 0;
00092 
00093     // If the previous token was one of our commas, we are now on the next item.
00094     if (Item < Commas.size() && State.NextToken->Previous == Commas[Item]) {
00095       if (!State.NextToken->isTrailingComment()) {
00096         ExtraSpaces += Format->ColumnSizes[Column] - ItemLengths[Item];
00097         ++Column;
00098       }
00099       ++Item;
00100     }
00101 
00102     if (Column == Format->Columns || State.NextToken->MustBreakBefore) {
00103       Column = 0;
00104       NewLine = true;
00105     }
00106 
00107     // Place token using the continuation indenter and store the penalty.
00108     Penalty += Indenter->addTokenToState(State, NewLine, DryRun, ExtraSpaces);
00109   }
00110   return Penalty;
00111 }
00112 
00113 unsigned CommaSeparatedList::formatFromToken(LineState &State,
00114                                              ContinuationIndenter *Indenter,
00115                                              bool DryRun) {
00116   if (HasNestedBracedList)
00117     State.Stack.back().AvoidBinPacking = true;
00118   return 0;
00119 }
00120 
00121 // Returns the lengths in code points between Begin and End (both included),
00122 // assuming that the entire sequence is put on a single line.
00123 static unsigned CodePointsBetween(const FormatToken *Begin,
00124                                   const FormatToken *End) {
00125   assert(End->TotalLength >= Begin->TotalLength);
00126   return End->TotalLength - Begin->TotalLength + Begin->ColumnWidth;
00127 }
00128 
00129 void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
00130   // FIXME: At some point we might want to do this for other lists, too.
00131   if (!Token->MatchingParen || Token->isNot(tok::l_brace))
00132     return;
00133 
00134   // In C++11 braced list style, we should not format in columns unless they
00135   // have many items (20 or more) or we allow bin-packing of function
00136   // parameters.
00137   if (Style.Cpp11BracedListStyle && !Style.BinPackParameters &&
00138       Commas.size() < 19)
00139     return;
00140 
00141   FormatToken *ItemBegin = Token->Next;
00142   SmallVector<bool, 8> MustBreakBeforeItem;
00143 
00144   // The lengths of an item if it is put at the end of the line. This includes
00145   // trailing comments which are otherwise ignored for column alignment.
00146   SmallVector<unsigned, 8> EndOfLineItemLength;
00147 
00148   unsigned MinItemLength = Style.ColumnLimit;
00149   unsigned MaxItemLength = 0;
00150 
00151   for (unsigned i = 0, e = Commas.size() + 1; i != e; ++i) {
00152     // Skip comments on their own line.
00153     while (ItemBegin->HasUnescapedNewline && ItemBegin->isTrailingComment())
00154       ItemBegin = ItemBegin->Next;
00155 
00156     MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore);
00157     if (ItemBegin->is(tok::l_brace))
00158       HasNestedBracedList = true;
00159     const FormatToken *ItemEnd = nullptr;
00160     if (i == Commas.size()) {
00161       ItemEnd = Token->MatchingParen;
00162       const FormatToken *NonCommentEnd = ItemEnd->getPreviousNonComment();
00163       ItemLengths.push_back(CodePointsBetween(ItemBegin, NonCommentEnd));
00164       if (Style.Cpp11BracedListStyle) {
00165         // In Cpp11 braced list style, the } and possibly other subsequent
00166         // tokens will need to stay on a line with the last element.
00167         while (ItemEnd->Next && !ItemEnd->Next->CanBreakBefore)
00168           ItemEnd = ItemEnd->Next;
00169       } else {
00170         // In other braced lists styles, the "}" can be wrapped to the new line.
00171         ItemEnd = Token->MatchingParen->Previous;
00172       }
00173     } else {
00174       ItemEnd = Commas[i];
00175       // The comma is counted as part of the item when calculating the length.
00176       ItemLengths.push_back(CodePointsBetween(ItemBegin, ItemEnd));
00177       MinItemLength = std::min(MinItemLength, ItemLengths.back());
00178       MaxItemLength = std::max(MaxItemLength, ItemLengths.back());
00179 
00180       // Consume trailing comments so the are included in EndOfLineItemLength.
00181       if (ItemEnd->Next && !ItemEnd->Next->HasUnescapedNewline &&
00182           ItemEnd->Next->isTrailingComment())
00183         ItemEnd = ItemEnd->Next;
00184     }
00185     EndOfLineItemLength.push_back(CodePointsBetween(ItemBegin, ItemEnd));
00186     // If there is a trailing comma in the list, the next item will start at the
00187     // closing brace. Don't create an extra item for this.
00188     if (ItemEnd->getNextNonComment() == Token->MatchingParen)
00189       break;
00190     ItemBegin = ItemEnd->Next;
00191   }
00192 
00193   // If this doesn't have a nested list, we require at least 6 elements in order
00194   // create a column layout. If it has a nested list, column layout ensures one
00195   // list element per line. If the difference between the shortest and longest
00196   // element is too large, column layout would create too much whitespace.
00197   if (HasNestedBracedList || Commas.size() < 5 || Token->NestingLevel != 0 ||
00198       MaxItemLength - MinItemLength > 10)
00199     return;
00200 
00201   // We can never place more than ColumnLimit / 3 items in a row (because of the
00202   // spaces and the comma).
00203   for (unsigned Columns = 1; Columns <= Style.ColumnLimit / 3; ++Columns) {
00204     ColumnFormat Format;
00205     Format.Columns = Columns;
00206     Format.ColumnSizes.resize(Columns);
00207     Format.LineCount = 1;
00208     bool HasRowWithSufficientColumns = false;
00209     unsigned Column = 0;
00210     for (unsigned i = 0, e = ItemLengths.size(); i != e; ++i) {
00211       assert(i < MustBreakBeforeItem.size());
00212       if (MustBreakBeforeItem[i] || Column == Columns) {
00213         ++Format.LineCount;
00214         Column = 0;
00215       }
00216       if (Column == Columns - 1)
00217         HasRowWithSufficientColumns = true;
00218       unsigned length =
00219           (Column == Columns - 1) ? EndOfLineItemLength[i] : ItemLengths[i];
00220       Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], length);
00221       ++Column;
00222     }
00223     // If all rows are terminated early (e.g. by trailing comments), we don't
00224     // need to look further.
00225     if (!HasRowWithSufficientColumns)
00226       break;
00227     Format.TotalWidth = Columns - 1; // Width of the N-1 spaces.
00228     for (unsigned i = 0; i < Columns; ++i) {
00229       Format.TotalWidth += Format.ColumnSizes[i];
00230     }
00231 
00232     // Ignore layouts that are bound to violate the column limit.
00233     if (Format.TotalWidth > Style.ColumnLimit)
00234       continue;
00235 
00236     Formats.push_back(Format);
00237   }
00238 }
00239 
00240 const CommaSeparatedList::ColumnFormat *
00241 CommaSeparatedList::getColumnFormat(unsigned RemainingCharacters) const {
00242   const ColumnFormat *BestFormat = nullptr;
00243   for (SmallVector<ColumnFormat, 4>::const_reverse_iterator
00244            I = Formats.rbegin(),
00245            E = Formats.rend();
00246        I != E; ++I) {
00247     if (I->TotalWidth <= RemainingCharacters) {
00248       if (BestFormat && I->LineCount > BestFormat->LineCount)
00249         break;
00250       BestFormat = &*I;
00251     }
00252   }
00253   return BestFormat;
00254 }
00255 
00256 } // namespace format
00257 } // namespace clang