void UnwrappedLineFormatter::formatFirstToken(FormatToken &RootToken, const AnnotatedLine *PreviousLine, unsigned IndentLevel, unsigned Indent, bool InPPDirective) { unsigned Newlines = std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1); // Remove empty lines before "}" where applicable. if (RootToken.is(tok::r_brace) && (!RootToken.Next || (RootToken.Next->is(tok::semi) && !RootToken.Next->Next))) Newlines = std::min(Newlines, 1u); if (Newlines == 0 && !RootToken.IsFirst) Newlines = 1; if (RootToken.IsFirst && !RootToken.HasUnescapedNewline) Newlines = 0; // Remove empty lines after "{". if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine && PreviousLine->Last->is(tok::l_brace) && PreviousLine->First->isNot(tok::kw_namespace) && !startsExternCBlock(*PreviousLine)) Newlines = 1; // Insert extra new line before access specifiers. if (PreviousLine && PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) && RootToken.isAccessSpecifier() && RootToken.NewlinesBefore == 1) ++Newlines; // Remove empty lines after access specifiers. if (PreviousLine && PreviousLine->First->isAccessSpecifier() && (!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline)) Newlines = std::min(1u, Newlines); Whitespaces->replaceWhitespace(RootToken, Newlines, IndentLevel, Indent, Indent, InPPDirective && !RootToken.HasUnescapedNewline); }
void UnwrappedLineParser::calculateBraceTypes() { // We'll parse forward through the tokens until we hit // a closing brace or eof - note that getNextToken() will // parse macros, so this will magically work inside macro // definitions, too. unsigned StoredPosition = Tokens->getPosition(); unsigned Position = StoredPosition; FormatToken *Tok = FormatTok; // Keep a stack of positions of lbrace tokens. We will // update information about whether an lbrace starts a // braced init list or a different block during the loop. SmallVector<FormatToken *, 8> LBraceStack; assert(Tok->Tok.is(tok::l_brace)); do { // Get next none-comment token. FormatToken *NextTok; unsigned ReadTokens = 0; do { NextTok = Tokens->getNextToken(); ++ReadTokens; } while (NextTok->is(tok::comment)); switch (Tok->Tok.getKind()) { case tok::l_brace: LBraceStack.push_back(Tok); break; case tok::r_brace: if (!LBraceStack.empty()) { if (LBraceStack.back()->BlockKind == BK_Unknown) { bool ProbablyBracedList = false; if (Style.Language == FormatStyle::LK_Proto) { ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square); } else { // Using OriginalColumn to distinguish between ObjC methods and // binary operators is a bit hacky. bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) && NextTok->OriginalColumn == 0; // If there is a comma, semicolon or right paren after the closing // brace, we assume this is a braced initializer list. Note that // regardless how we mark inner braces here, we will overwrite the // BlockKind later if we parse a braced list (where all blocks // inside are by default braced lists), or when we explicitly detect // blocks (for example while parsing lambdas). // // We exclude + and - as they can be ObjC visibility modifiers. ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::semi, tok::period, tok::colon, tok::r_paren, tok::r_square, tok::l_brace, tok::l_paren) || (NextTok->isBinaryOperator() && !NextIsObjCMethod); } if (ProbablyBracedList) { Tok->BlockKind = BK_BracedInit; LBraceStack.back()->BlockKind = BK_BracedInit; } else { Tok->BlockKind = BK_Block; LBraceStack.back()->BlockKind = BK_Block; } } LBraceStack.pop_back(); } break; case tok::at: case tok::semi: case tok::kw_if: case tok::kw_while: case tok::kw_for: case tok::kw_switch: case tok::kw_try: if (!LBraceStack.empty()) LBraceStack.back()->BlockKind = BK_Block; break; default: break; } Tok = NextTok; Position += ReadTokens; } while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty()); // Assume other blocks for all unclosed opening braces. for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) { if (LBraceStack[i]->BlockKind == BK_Unknown) LBraceStack[i]->BlockKind = BK_Block; } FormatTok = Tokens->setPosition(StoredPosition); }
void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { // FIXME: At some point we might want to do this for other lists, too. if (!Token->MatchingParen || Token->isNot(tok::l_brace) || Token->NestingLevel != 0) return; FormatToken *ItemBegin = Token->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; bool HasNestedBracedList = false; for (unsigned i = 0, e = Commas.size() + 1; i != e; ++i) { // Skip comments on their own line. while (ItemBegin->HasUnescapedNewline && ItemBegin->isTrailingComment()) ItemBegin = ItemBegin->Next; MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore); if (ItemBegin->is(tok::l_brace)) HasNestedBracedList = true; const FormatToken *ItemEnd = NULL; if (i == Commas.size()) { ItemEnd = Token->MatchingParen; const FormatToken *NonCommentEnd = ItemEnd->getPreviousNonComment(); ItemLengths.push_back(CodePointsBetween(ItemBegin, NonCommentEnd)); if (Style.Cpp11BracedListStyle) { // In Cpp11 braced list style, the } and possibly other subsequent // tokens will need to stay on a line with the last element. while (ItemEnd->Next && !ItemEnd->Next->CanBreakBefore) ItemEnd = ItemEnd->Next; } else { // In other braced lists styles, the "}" can be wrapped to the new line. ItemEnd = Token->MatchingParen->Previous; } } else { ItemEnd = Commas[i]; // The comma is counted as part of the item when calculating the length. ItemLengths.push_back(CodePointsBetween(ItemBegin, ItemEnd)); // Consume trailing comments so the are included in EndOfLineItemLength. if (ItemEnd->Next && !ItemEnd->Next->HasUnescapedNewline && ItemEnd->Next->isTrailingComment()) ItemEnd = ItemEnd->Next; } EndOfLineItemLength.push_back(CodePointsBetween(ItemBegin, ItemEnd)); // If there is a trailing comma in the list, the next item will start at the // closing brace. Don't create an extra item for this. if (ItemEnd->getNextNonComment() == Token->MatchingParen) break; ItemBegin = ItemEnd->Next; } // We can never place more than ColumnLimit / 3 items in a row (because of the // spaces and the comma). for (unsigned Columns = 1; Columns <= Style.ColumnLimit / 3; ++Columns) { ColumnFormat Format; Format.Columns = Columns; Format.ColumnSizes.resize(Columns); Format.LineCount = 1; bool HasRowWithSufficientColumns = false; unsigned Column = 0; for (unsigned i = 0, e = ItemLengths.size(); i != e; ++i) { assert(i < MustBreakBeforeItem.size()); if (MustBreakBeforeItem[i] || Column == Columns) { ++Format.LineCount; Column = 0; } if (Column == Columns - 1) HasRowWithSufficientColumns = true; unsigned length = (Column == Columns - 1) ? EndOfLineItemLength[i] : ItemLengths[i]; Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], length); ++Column; } // If all rows are terminated early (e.g. by trailing comments), we don't // need to look further. if (!HasRowWithSufficientColumns) break; Format.TotalWidth = Columns - 1; // Width of the N-1 spaces. for (unsigned i = 0; i < Columns; ++i) { Format.TotalWidth += Format.ColumnSizes[i]; } // Ignore layouts that are bound to violate the column limit. if (Format.TotalWidth > Style.ColumnLimit) continue; // If this braced list has nested braced list, we format it either with one // element per line or with all elements on one line. if (HasNestedBracedList && Columns > 1 && Format.LineCount > 1) continue; Formats.push_back(Format); } }
void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { // FIXME: At some point we might want to do this for other lists, too. if (!Token->MatchingParen || Token->isNot(tok::l_brace)) 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 call // arguments. if (Style.Cpp11BracedListStyle && !Style.BinPackArguments && Commas.size() < 19) return; // Column format doesn't really make sense if we don't align after brackets. if (!Style.AlignAfterOpenBracket) 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; 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()) { ItemBegin = ItemBegin->Next; HasSeparatingComment = i > 0; } MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore); if (ItemBegin->is(tok::l_brace)) HasNestedBracedList = true; const FormatToken *ItemEnd = nullptr; if (i == Commas.size()) { ItemEnd = Token->MatchingParen; const FormatToken *NonCommentEnd = ItemEnd->getPreviousNonComment(); ItemLengths.push_back(CodePointsBetween(ItemBegin, NonCommentEnd)); if (Style.Cpp11BracedListStyle) { // In Cpp11 braced list style, the } and possibly other subsequent // tokens will need to stay on a line with the last element. while (ItemEnd->Next && !ItemEnd->Next->CanBreakBefore) ItemEnd = ItemEnd->Next; } else { // In other braced lists styles, the "}" can be wrapped to the new line. ItemEnd = Token->MatchingParen->Previous; } } else { ItemEnd = Commas[i]; // The comma is counted as part of the item when calculating the length. ItemLengths.push_back(CodePointsBetween(ItemBegin, ItemEnd)); // Consume trailing comments so the are included in EndOfLineItemLength. if (ItemEnd->Next && !ItemEnd->Next->HasUnescapedNewline && ItemEnd->Next->isTrailingComment()) ItemEnd = ItemEnd->Next; } EndOfLineItemLength.push_back(CodePointsBetween(ItemBegin, ItemEnd)); // If there is a trailing comma in the list, the next item will start at the // closing brace. Don't create an extra item for this. if (ItemEnd->getNextNonComment() == Token->MatchingParen) break; ItemBegin = ItemEnd->Next; } // 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 // spaces and the comma). unsigned MaxItems = Style.ColumnLimit / 3; std::vector<unsigned> MinSizeInColumn; MinSizeInColumn.reserve(MaxItems); for (unsigned Columns = 1; Columns <= MaxItems; ++Columns) { ColumnFormat Format; Format.Columns = Columns; Format.ColumnSizes.resize(Columns); MinSizeInColumn.assign(Columns, UINT_MAX); Format.LineCount = 1; bool HasRowWithSufficientColumns = false; unsigned Column = 0; for (unsigned i = 0, e = ItemLengths.size(); i != e; ++i) { assert(i < MustBreakBeforeItem.size()); if (MustBreakBeforeItem[i] || Column == Columns) { ++Format.LineCount; Column = 0; } if (Column == Columns - 1) HasRowWithSufficientColumns = true; unsigned Length = (Column == Columns - 1) ? EndOfLineItemLength[i] : ItemLengths[i]; 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 // need to look further. if (!HasRowWithSufficientColumns) break; Format.TotalWidth = Columns - 1; // Width of the N-1 spaces. 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) continue; Formats.push_back(Format); } }
void UnwrappedLineParser::calculateBraceTypes() { // We'll parse forward through the tokens until we hit // a closing brace or eof - note that getNextToken() will // parse macros, so this will magically work inside macro // definitions, too. unsigned StoredPosition = Tokens->getPosition(); unsigned Position = StoredPosition; FormatToken *Tok = FormatTok; // Keep a stack of positions of lbrace tokens. We will // update information about whether an lbrace starts a // braced init list or a different block during the loop. SmallVector<FormatToken *, 8> LBraceStack; assert(Tok->Tok.is(tok::l_brace)); do { // Get next none-comment token. FormatToken *NextTok; unsigned ReadTokens = 0; do { NextTok = Tokens->getNextToken(); ++ReadTokens; } while (NextTok->is(tok::comment)); switch (Tok->Tok.getKind()) { case tok::l_brace: LBraceStack.push_back(Tok); break; case tok::r_brace: if (!LBraceStack.empty()) { if (LBraceStack.back()->BlockKind == BK_Unknown) { // If there is a comma, semicolon or right paren after the closing // brace, we assume this is a braced initializer list. // FIXME: Note that this currently works only because we do not // use the brace information while inside a braced init list. // Thus, if the parent is a braced init list, we consider all // brace blocks inside it braced init list. That works good enough // for now, but we will need to fix it to correctly handle lambdas. if (NextTok->isOneOf(tok::comma, tok::semi, tok::r_paren, tok::l_brace, tok::colon)) { Tok->BlockKind = BK_BracedInit; LBraceStack.back()->BlockKind = BK_BracedInit; } else { Tok->BlockKind = BK_Block; LBraceStack.back()->BlockKind = BK_Block; } } LBraceStack.pop_back(); } break; case tok::semi: case tok::kw_if: case tok::kw_while: case tok::kw_for: case tok::kw_switch: case tok::kw_try: if (!LBraceStack.empty()) LBraceStack.back()->BlockKind = BK_Block; break; default: break; } Tok = NextTok; Position += ReadTokens; } while (Tok->Tok.isNot(tok::eof)); // Assume other blocks for all unclosed opening braces. for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) { if (LBraceStack[i]->BlockKind == BK_Unknown) LBraceStack[i]->BlockKind = BK_Block; } FormatTok = Tokens->setPosition(StoredPosition); }