|  | //===--- UnwrappedLineFormatter.cpp - Format C++ code ---------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "UnwrappedLineFormatter.h" | 
|  | #include "FormatToken.h" | 
|  | #include "NamespaceEndCommentsFixer.h" | 
|  | #include "WhitespaceManager.h" | 
|  | #include "llvm/Support/Debug.h" | 
|  | #include <queue> | 
|  |  | 
|  | #define DEBUG_TYPE "format-formatter" | 
|  |  | 
|  | namespace clang { | 
|  | namespace format { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | bool startsExternCBlock(const AnnotatedLine &Line) { | 
|  | const FormatToken *Next = Line.First->getNextNonComment(); | 
|  | const FormatToken *NextNext = Next ? Next->getNextNonComment() : nullptr; | 
|  | return Line.startsWith(tok::kw_extern) && Next && Next->isStringLiteral() && | 
|  | NextNext && NextNext->is(tok::l_brace); | 
|  | } | 
|  |  | 
|  | bool isRecordLBrace(const FormatToken &Tok) { | 
|  | return Tok.isOneOf(TT_ClassLBrace, TT_EnumLBrace, TT_RecordLBrace, | 
|  | TT_StructLBrace, TT_UnionLBrace); | 
|  | } | 
|  |  | 
|  | /// Tracks the indent level of \c AnnotatedLines across levels. | 
|  | /// | 
|  | /// \c nextLine must be called for each \c AnnotatedLine, after which \c | 
|  | /// getIndent() will return the indent for the last line \c nextLine was called | 
|  | /// with. | 
|  | /// If the line is not formatted (and thus the indent does not change), calling | 
|  | /// \c adjustToUnmodifiedLine after the call to \c nextLine will cause | 
|  | /// subsequent lines on the same level to be indented at the same level as the | 
|  | /// given line. | 
|  | class LevelIndentTracker { | 
|  | public: | 
|  | LevelIndentTracker(const FormatStyle &Style, | 
|  | const AdditionalKeywords &Keywords, unsigned StartLevel, | 
|  | int AdditionalIndent) | 
|  | : Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) { | 
|  | for (unsigned i = 0; i != StartLevel; ++i) | 
|  | IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent); | 
|  | } | 
|  |  | 
|  | /// Returns the indent for the current line. | 
|  | unsigned getIndent() const { return Indent; } | 
|  |  | 
|  | /// Update the indent state given that \p Line is going to be formatted | 
|  | /// next. | 
|  | void nextLine(const AnnotatedLine &Line) { | 
|  | Offset = getIndentOffset(Line); | 
|  | // Update the indent level cache size so that we can rely on it | 
|  | // having the right size in adjustToUnmodifiedline. | 
|  | if (Line.Level >= IndentForLevel.size()) | 
|  | IndentForLevel.resize(Line.Level + 1, -1); | 
|  | if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave && | 
|  | (Line.InPPDirective || Line.Type == LT_CommentAbovePPDirective)) { | 
|  | Indent = Line.InMacroBody | 
|  | ? (Line.Level - Line.PPLevel) * Style.IndentWidth + | 
|  | AdditionalIndent | 
|  | : Line.First->OriginalColumn; | 
|  | } else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None && | 
|  | (Line.InPPDirective || | 
|  | (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash && | 
|  | Line.Type == LT_CommentAbovePPDirective))) { | 
|  | unsigned PPIndentWidth = | 
|  | (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth; | 
|  | Indent = Line.InMacroBody | 
|  | ? Line.PPLevel * PPIndentWidth + | 
|  | (Line.Level - Line.PPLevel) * Style.IndentWidth | 
|  | : Line.Level * PPIndentWidth; | 
|  | Indent += AdditionalIndent; | 
|  | } else { | 
|  | // When going to lower levels, forget previous higher levels so that we | 
|  | // recompute future higher levels. But don't forget them if we enter a PP | 
|  | // directive, since these do not terminate a C++ code block. | 
|  | if (!Line.InPPDirective) { | 
|  | assert(Line.Level <= IndentForLevel.size()); | 
|  | IndentForLevel.resize(Line.Level + 1); | 
|  | } | 
|  | Indent = getIndent(Line.Level); | 
|  | } | 
|  | if (static_cast<int>(Indent) + Offset >= 0) | 
|  | Indent += Offset; | 
|  | if (Line.IsContinuation) | 
|  | Indent = Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth; | 
|  | } | 
|  |  | 
|  | /// Update the level indent to adapt to the given \p Line. | 
|  | /// | 
|  | /// When a line is not formatted, we move the subsequent lines on the same | 
|  | /// level to the same indent. | 
|  | /// Note that \c nextLine must have been called before this method. | 
|  | void adjustToUnmodifiedLine(const AnnotatedLine &Line) { | 
|  | if (Line.InPPDirective || Line.IsContinuation) | 
|  | return; | 
|  | assert(Line.Level < IndentForLevel.size()); | 
|  | if (Line.First->is(tok::comment) && IndentForLevel[Line.Level] != -1) | 
|  | return; | 
|  | unsigned LevelIndent = Line.First->OriginalColumn; | 
|  | if (static_cast<int>(LevelIndent) - Offset >= 0) | 
|  | LevelIndent -= Offset; | 
|  | IndentForLevel[Line.Level] = LevelIndent; | 
|  | } | 
|  |  | 
|  | private: | 
|  | /// Get the offset of the line relatively to the level. | 
|  | /// | 
|  | /// For example, 'public:' labels in classes are offset by 1 or 2 | 
|  | /// characters to the left from their level. | 
|  | int getIndentOffset(const AnnotatedLine &Line) { | 
|  | if (Style.isJava() || Style.isJavaScript() || Style.isCSharp()) | 
|  | return 0; | 
|  | const auto &RootToken = *Line.First; | 
|  | if (Line.Type == LT_AccessModifier || | 
|  | RootToken.isAccessSpecifier(/*ColonRequired=*/false) || | 
|  | RootToken.isObjCAccessSpecifier() || | 
|  | (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && | 
|  | RootToken.Next && RootToken.Next->is(tok::colon))) { | 
|  | // The AccessModifierOffset may be overridden by IndentAccessModifiers, | 
|  | // in which case we take a negative value of the IndentWidth to simulate | 
|  | // the upper indent level. | 
|  | return Style.IndentAccessModifiers ? -Style.IndentWidth | 
|  | : Style.AccessModifierOffset; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /// Get the indent of \p Level from \p IndentForLevel. | 
|  | /// | 
|  | /// \p IndentForLevel must contain the indent for the level \c l | 
|  | /// at \p IndentForLevel[l], or a value < 0 if the indent for | 
|  | /// that level is unknown. | 
|  | unsigned getIndent(unsigned Level) const { | 
|  | assert(Level < IndentForLevel.size()); | 
|  | if (IndentForLevel[Level] != -1) | 
|  | return IndentForLevel[Level]; | 
|  | if (Level == 0) | 
|  | return 0; | 
|  | return getIndent(Level - 1) + Style.IndentWidth; | 
|  | } | 
|  |  | 
|  | const FormatStyle &Style; | 
|  | const AdditionalKeywords &Keywords; | 
|  | const unsigned AdditionalIndent; | 
|  |  | 
|  | /// The indent in characters for each level. It remembers the indent of | 
|  | /// previous lines (that are not PP directives) of equal or lower levels. This | 
|  | /// is used to align formatted lines to the indent of previous non-formatted | 
|  | /// lines. Think about the --lines parameter of clang-format. | 
|  | SmallVector<int> IndentForLevel; | 
|  |  | 
|  | /// Offset of the current line relative to the indent level. | 
|  | /// | 
|  | /// For example, the 'public' keywords is often indented with a negative | 
|  | /// offset. | 
|  | int Offset = 0; | 
|  |  | 
|  | /// The current line's indent. | 
|  | unsigned Indent = 0; | 
|  | }; | 
|  |  | 
|  | const FormatToken * | 
|  | getMatchingNamespaceToken(const AnnotatedLine *Line, | 
|  | const ArrayRef<AnnotatedLine *> &AnnotatedLines) { | 
|  | if (!Line->startsWith(tok::r_brace)) | 
|  | return nullptr; | 
|  | size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex; | 
|  | if (StartLineIndex == UnwrappedLine::kInvalidIndex) | 
|  | return nullptr; | 
|  | assert(StartLineIndex < AnnotatedLines.size()); | 
|  | return AnnotatedLines[StartLineIndex]->First->getNamespaceToken(); | 
|  | } | 
|  |  | 
|  | StringRef getNamespaceTokenText(const AnnotatedLine *Line) { | 
|  | const FormatToken *NamespaceToken = Line->First->getNamespaceToken(); | 
|  | return NamespaceToken ? NamespaceToken->TokenText : StringRef(); | 
|  | } | 
|  |  | 
|  | StringRef | 
|  | getMatchingNamespaceTokenText(const AnnotatedLine *Line, | 
|  | const ArrayRef<AnnotatedLine *> &AnnotatedLines) { | 
|  | const FormatToken *NamespaceToken = | 
|  | getMatchingNamespaceToken(Line, AnnotatedLines); | 
|  | return NamespaceToken ? NamespaceToken->TokenText : StringRef(); | 
|  | } | 
|  |  | 
|  | class LineJoiner { | 
|  | public: | 
|  | LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords, | 
|  | const SmallVectorImpl<AnnotatedLine *> &Lines) | 
|  | : Style(Style), Keywords(Keywords), End(Lines.end()), Next(Lines.begin()), | 
|  | AnnotatedLines(Lines) {} | 
|  |  | 
|  | /// Returns the next line, merging multiple lines into one if possible. | 
|  | const AnnotatedLine *getNextMergedLine(bool DryRun, | 
|  | LevelIndentTracker &IndentTracker) { | 
|  | if (Next == End) | 
|  | return nullptr; | 
|  | const AnnotatedLine *Current = *Next; | 
|  | IndentTracker.nextLine(*Current); | 
|  | unsigned MergedLines = tryFitMultipleLinesInOne(IndentTracker, Next, End); | 
|  | if (MergedLines > 0 && Style.ColumnLimit == 0) { | 
|  | // Disallow line merging if there is a break at the start of one of the | 
|  | // input lines. | 
|  | for (unsigned i = 0; i < MergedLines; ++i) | 
|  | if (Next[i + 1]->First->NewlinesBefore > 0) | 
|  | MergedLines = 0; | 
|  | } | 
|  | if (!DryRun) | 
|  | for (unsigned i = 0; i < MergedLines; ++i) | 
|  | join(*Next[0], *Next[i + 1]); | 
|  | Next = Next + MergedLines + 1; | 
|  | return Current; | 
|  | } | 
|  |  | 
|  | private: | 
|  | /// Calculates how many lines can be merged into 1 starting at \p I. | 
|  | unsigned | 
|  | tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker, | 
|  | ArrayRef<AnnotatedLine *>::const_iterator I, | 
|  | ArrayRef<AnnotatedLine *>::const_iterator E) { | 
|  | // Can't join the last line with anything. | 
|  | if (I + 1 == E) | 
|  | return 0; | 
|  | // We can never merge stuff if there are trailing line comments. | 
|  | const AnnotatedLine *TheLine = *I; | 
|  | if (TheLine->Last->is(TT_LineComment)) | 
|  | return 0; | 
|  | const auto &NextLine = *I[1]; | 
|  | if (NextLine.Type == LT_Invalid || NextLine.First->MustBreakBefore) | 
|  | return 0; | 
|  | if (TheLine->InPPDirective && | 
|  | (!NextLine.InPPDirective || NextLine.First->HasUnescapedNewline)) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | const auto Indent = IndentTracker.getIndent(); | 
|  | if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit) | 
|  | return 0; | 
|  |  | 
|  | unsigned Limit = | 
|  | Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent; | 
|  | // If we already exceed the column limit, we set 'Limit' to 0. The different | 
|  | // tryMerge..() functions can then decide whether to still do merging. | 
|  | Limit = TheLine->Last->TotalLength > Limit | 
|  | ? 0 | 
|  | : Limit - TheLine->Last->TotalLength; | 
|  |  | 
|  | if (TheLine->Last->is(TT_FunctionLBrace) && | 
|  | TheLine->First == TheLine->Last) { | 
|  | const bool EmptyFunctionBody = NextLine.First->is(tok::r_brace); | 
|  | if ((EmptyFunctionBody && !Style.BraceWrapping.SplitEmptyFunction) || | 
|  | (!EmptyFunctionBody && | 
|  | Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always)) { | 
|  | return tryMergeSimpleBlock(I, E, Limit); | 
|  | } | 
|  | } | 
|  |  | 
|  | const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] : nullptr; | 
|  | // Handle empty record blocks where the brace has already been wrapped. | 
|  | if (PreviousLine && TheLine->Last->is(tok::l_brace) && | 
|  | TheLine->First == TheLine->Last) { | 
|  | bool EmptyBlock = NextLine.First->is(tok::r_brace); | 
|  |  | 
|  | const FormatToken *Tok = PreviousLine->First; | 
|  | if (Tok && Tok->is(tok::comment)) | 
|  | Tok = Tok->getNextNonComment(); | 
|  |  | 
|  | if (Tok && Tok->getNamespaceToken()) { | 
|  | return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock | 
|  | ? tryMergeSimpleBlock(I, E, Limit) | 
|  | : 0; | 
|  | } | 
|  |  | 
|  | if (Tok && Tok->is(tok::kw_typedef)) | 
|  | Tok = Tok->getNextNonComment(); | 
|  | if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union, | 
|  | tok::kw_extern, Keywords.kw_interface)) { | 
|  | return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock | 
|  | ? tryMergeSimpleBlock(I, E, Limit) | 
|  | : 0; | 
|  | } | 
|  |  | 
|  | if (Tok && Tok->is(tok::kw_template) && | 
|  | Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine, | 
|  | TheLine]() { | 
|  | if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All) | 
|  | return true; | 
|  | if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && | 
|  | NextLine.First->is(tok::r_brace)) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | if (Style.AllowShortFunctionsOnASingleLine & | 
|  | FormatStyle::SFS_InlineOnly) { | 
|  | // Just checking TheLine->Level != 0 is not enough, because it | 
|  | // provokes treating functions inside indented namespaces as short. | 
|  | if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace)) | 
|  | return true; | 
|  |  | 
|  | if (TheLine->Level != 0) { | 
|  | if (!PreviousLine) | 
|  | return false; | 
|  |  | 
|  | // TODO: Use IndentTracker to avoid loop? | 
|  | // Find the last line with lower level. | 
|  | const AnnotatedLine *Line = nullptr; | 
|  | for (auto J = I - 1; J >= AnnotatedLines.begin(); --J) { | 
|  | assert(*J); | 
|  | if (((*J)->InPPDirective && !(*J)->InMacroBody) || | 
|  | (*J)->isComment() || (*J)->Level > TheLine->Level) { | 
|  | continue; | 
|  | } | 
|  | if ((*J)->Level < TheLine->Level || | 
|  | (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths && | 
|  | (*J)->First->is(tok::l_brace))) { | 
|  | Line = *J; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (!Line) | 
|  | return false; | 
|  |  | 
|  | // Check if the found line starts a record. | 
|  | const auto *LastNonComment = Line->getLastNonComment(); | 
|  | // There must be another token (usually `{`), because we chose a | 
|  | // non-PPDirective and non-comment line that has a smaller level. | 
|  | assert(LastNonComment); | 
|  | return isRecordLBrace(*LastNonComment); | 
|  | } | 
|  | } | 
|  |  | 
|  | return false; | 
|  | }; | 
|  |  | 
|  | bool MergeShortFunctions = ShouldMergeShortFunctions(); | 
|  |  | 
|  | const auto *FirstNonComment = TheLine->getFirstNonComment(); | 
|  | if (!FirstNonComment) | 
|  | return 0; | 
|  |  | 
|  | // FIXME: There are probably cases where we should use FirstNonComment | 
|  | // instead of TheLine->First. | 
|  |  | 
|  | if (Style.AllowShortNamespacesOnASingleLine && | 
|  | TheLine->First->is(tok::kw_namespace)) { | 
|  | const auto result = tryMergeNamespace(I, E, Limit); | 
|  | if (result > 0) | 
|  | return result; | 
|  | } | 
|  |  | 
|  | if (Style.CompactNamespaces) { | 
|  | if (const auto *NSToken = TheLine->First->getNamespaceToken()) { | 
|  | int J = 1; | 
|  | assert(TheLine->MatchingClosingBlockLineIndex > 0); | 
|  | for (auto ClosingLineIndex = TheLine->MatchingClosingBlockLineIndex - 1; | 
|  | I + J != E && NSToken->TokenText == getNamespaceTokenText(I[J]) && | 
|  | ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex && | 
|  | I[J]->Last->TotalLength < Limit; | 
|  | ++J, --ClosingLineIndex) { | 
|  | Limit -= I[J]->Last->TotalLength + 1; | 
|  |  | 
|  | // Reduce indent level for bodies of namespaces which were compacted, | 
|  | // but only if their content was indented in the first place. | 
|  | auto *ClosingLine = AnnotatedLines.begin() + ClosingLineIndex + 1; | 
|  | const int OutdentBy = I[J]->Level - TheLine->Level; | 
|  | assert(OutdentBy >= 0); | 
|  | for (auto *CompactedLine = I + J; CompactedLine <= ClosingLine; | 
|  | ++CompactedLine) { | 
|  | if (!(*CompactedLine)->InPPDirective) { | 
|  | const int Level = (*CompactedLine)->Level; | 
|  | (*CompactedLine)->Level = std::max(Level - OutdentBy, 0); | 
|  | } | 
|  | } | 
|  | } | 
|  | return J - 1; | 
|  | } | 
|  |  | 
|  | if (auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) { | 
|  | int i = 0; | 
|  | unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1; | 
|  | for (; I + 1 + i != E && | 
|  | nsToken->TokenText == | 
|  | getMatchingNamespaceTokenText(I[i + 1], AnnotatedLines) && | 
|  | openingLine == I[i + 1]->MatchingOpeningBlockLineIndex; | 
|  | i++, --openingLine) { | 
|  | // No space between consecutive braces. | 
|  | I[i + 1]->First->SpacesRequiredBefore = | 
|  | I[i]->Last->isNot(tok::r_brace); | 
|  |  | 
|  | // Indent like the outer-most namespace. | 
|  | IndentTracker.nextLine(*I[i + 1]); | 
|  | } | 
|  | return i; | 
|  | } | 
|  | } | 
|  |  | 
|  | const auto *LastNonComment = TheLine->getLastNonComment(); | 
|  | assert(LastNonComment); | 
|  | // FIXME: There are probably cases where we should use LastNonComment | 
|  | // instead of TheLine->Last. | 
|  |  | 
|  | // Try to merge a function block with left brace unwrapped. | 
|  | if (LastNonComment->is(TT_FunctionLBrace) && | 
|  | TheLine->First != LastNonComment) { | 
|  | return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0; | 
|  | } | 
|  |  | 
|  | // Try to merge a control statement block with left brace unwrapped. | 
|  | if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last && | 
|  | (FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for, | 
|  | TT_ForEachMacro) || | 
|  | TheLine->startsWithExportBlock())) { | 
|  | return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never | 
|  | ? tryMergeSimpleBlock(I, E, Limit) | 
|  | : 0; | 
|  | } | 
|  | // Try to merge a control statement block with left brace wrapped. | 
|  | if (NextLine.First->is(TT_ControlStatementLBrace)) { | 
|  | // If possible, merge the next line's wrapped left brace with the | 
|  | // current line. Otherwise, leave it on the next line, as this is a | 
|  | // multi-line control statement. | 
|  | return Style.BraceWrapping.AfterControlStatement == | 
|  | FormatStyle::BWACS_Always | 
|  | ? tryMergeSimpleBlock(I, E, Limit) | 
|  | : 0; | 
|  | } | 
|  | if (PreviousLine && TheLine->First->is(tok::l_brace)) { | 
|  | switch (PreviousLine->First->Tok.getKind()) { | 
|  | case tok::at: | 
|  | // Don't merge block with left brace wrapped after ObjC special blocks. | 
|  | if (PreviousLine->First->Next && | 
|  | PreviousLine->First->Next->isOneOf(tok::objc_autoreleasepool, | 
|  | tok::objc_synchronized)) { | 
|  | return 0; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case tok::kw_case: | 
|  | case tok::kw_default: | 
|  | // Don't merge block with left brace wrapped after case labels. | 
|  | return 0; | 
|  |  | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Don't merge an empty template class or struct if SplitEmptyRecords | 
|  | // is defined. | 
|  | if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord && | 
|  | TheLine->Last->is(tok::l_brace) && PreviousLine->Last) { | 
|  | const FormatToken *Previous = PreviousLine->Last; | 
|  | if (Previous) { | 
|  | if (Previous->is(tok::comment)) | 
|  | Previous = Previous->getPreviousNonComment(); | 
|  | if (Previous) { | 
|  | if (Previous->is(tok::greater) && !PreviousLine->InPPDirective) | 
|  | return 0; | 
|  | if (Previous->is(tok::identifier)) { | 
|  | const FormatToken *PreviousPrevious = | 
|  | Previous->getPreviousNonComment(); | 
|  | if (PreviousPrevious && | 
|  | PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct)) { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if (TheLine->First->is(TT_SwitchExpressionLabel)) { | 
|  | return Style.AllowShortCaseExpressionOnASingleLine | 
|  | ? tryMergeShortCaseLabels(I, E, Limit) | 
|  | : 0; | 
|  | } | 
|  |  | 
|  | if (TheLine->Last->is(tok::l_brace)) { | 
|  | bool ShouldMerge = false; | 
|  | // Try to merge records. | 
|  | if (TheLine->Last->is(TT_EnumLBrace)) { | 
|  | ShouldMerge = Style.AllowShortEnumsOnASingleLine; | 
|  | } else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) { | 
|  | ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine; | 
|  | } else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) { | 
|  | // NOTE: We use AfterClass (whereas AfterStruct exists) for both classes | 
|  | // and structs, but it seems that wrapping is still handled correctly | 
|  | // elsewhere. | 
|  | ShouldMerge = !Style.BraceWrapping.AfterClass || | 
|  | (NextLine.First->is(tok::r_brace) && | 
|  | !Style.BraceWrapping.SplitEmptyRecord); | 
|  | } else if (TheLine->InPPDirective || | 
|  | !TheLine->First->isOneOf(tok::kw_class, tok::kw_enum, | 
|  | tok::kw_struct)) { | 
|  | // Try to merge a block with left brace unwrapped that wasn't yet | 
|  | // covered. | 
|  | ShouldMerge = !Style.BraceWrapping.AfterFunction || | 
|  | (NextLine.First->is(tok::r_brace) && | 
|  | !Style.BraceWrapping.SplitEmptyFunction); | 
|  | } | 
|  | return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit) : 0; | 
|  | } | 
|  |  | 
|  | // Try to merge a function block with left brace wrapped. | 
|  | if (NextLine.First->is(TT_FunctionLBrace) && | 
|  | Style.BraceWrapping.AfterFunction) { | 
|  | if (NextLine.Last->is(TT_LineComment)) | 
|  | return 0; | 
|  |  | 
|  | // Check for Limit <= 2 to account for the " {". | 
|  | if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine))) | 
|  | return 0; | 
|  | Limit -= 2; | 
|  |  | 
|  | unsigned MergedLines = 0; | 
|  | if (MergeShortFunctions || | 
|  | (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && | 
|  | NextLine.First == NextLine.Last && I + 2 != E && | 
|  | I[2]->First->is(tok::r_brace))) { | 
|  | MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); | 
|  | // If we managed to merge the block, count the function header, which is | 
|  | // on a separate line. | 
|  | if (MergedLines > 0) | 
|  | ++MergedLines; | 
|  | } | 
|  | return MergedLines; | 
|  | } | 
|  | auto IsElseLine = [&TheLine]() -> bool { | 
|  | const FormatToken *First = TheLine->First; | 
|  | if (First->is(tok::kw_else)) | 
|  | return true; | 
|  |  | 
|  | return First->is(tok::r_brace) && First->Next && | 
|  | First->Next->is(tok::kw_else); | 
|  | }; | 
|  | if (TheLine->First->is(tok::kw_if) || | 
|  | (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine == | 
|  | FormatStyle::SIS_AllIfsAndElse))) { | 
|  | return Style.AllowShortIfStatementsOnASingleLine | 
|  | ? tryMergeSimpleControlStatement(I, E, Limit) | 
|  | : 0; | 
|  | } | 
|  | if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do, | 
|  | TT_ForEachMacro)) { | 
|  | return Style.AllowShortLoopsOnASingleLine | 
|  | ? tryMergeSimpleControlStatement(I, E, Limit) | 
|  | : 0; | 
|  | } | 
|  | if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) { | 
|  | return Style.AllowShortCaseLabelsOnASingleLine | 
|  | ? tryMergeShortCaseLabels(I, E, Limit) | 
|  | : 0; | 
|  | } | 
|  | if (TheLine->InPPDirective && | 
|  | (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) { | 
|  | return tryMergeSimplePPDirective(I, E, Limit); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | unsigned | 
|  | tryMergeSimplePPDirective(ArrayRef<AnnotatedLine *>::const_iterator I, | 
|  | ArrayRef<AnnotatedLine *>::const_iterator E, | 
|  | unsigned Limit) { | 
|  | if (Limit == 0) | 
|  | return 0; | 
|  | if (I + 2 != E && I[2]->InPPDirective && !I[2]->First->HasUnescapedNewline) | 
|  | return 0; | 
|  | if (1 + I[1]->Last->TotalLength > Limit) | 
|  | return 0; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | unsigned tryMergeNamespace(ArrayRef<AnnotatedLine *>::const_iterator I, | 
|  | ArrayRef<AnnotatedLine *>::const_iterator E, | 
|  | unsigned Limit) { | 
|  | if (Limit == 0) | 
|  | return 0; | 
|  |  | 
|  | // The merging code is relative to the opening namespace brace, which could | 
|  | // be either on the first or second line due to the brace wrapping rules. | 
|  | const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace; | 
|  | const auto *BraceOpenLine = I + OpenBraceWrapped; | 
|  |  | 
|  | assert(*BraceOpenLine); | 
|  | if (BraceOpenLine[0]->Last->isNot(TT_NamespaceLBrace)) | 
|  | return 0; | 
|  |  | 
|  | if (std::distance(BraceOpenLine, E) <= 2) | 
|  | return 0; | 
|  |  | 
|  | if (BraceOpenLine[0]->Last->is(tok::comment)) | 
|  | return 0; | 
|  |  | 
|  | assert(BraceOpenLine[1]); | 
|  | const auto &L1 = *BraceOpenLine[1]; | 
|  | if (L1.InPPDirective != (*I)->InPPDirective || | 
|  | (L1.InPPDirective && L1.First->HasUnescapedNewline)) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | assert(BraceOpenLine[2]); | 
|  | const auto &L2 = *BraceOpenLine[2]; | 
|  | if (L2.Type == LT_Invalid) | 
|  | return 0; | 
|  |  | 
|  | Limit = limitConsideringMacros(I + 1, E, Limit); | 
|  |  | 
|  | const auto LinesToBeMerged = OpenBraceWrapped + 2; | 
|  | if (!nextNLinesFitInto(I, I + LinesToBeMerged, Limit)) | 
|  | return 0; | 
|  |  | 
|  | // Check if it's a namespace inside a namespace, and call recursively if so. | 
|  | // '3' is the sizes of the whitespace and closing brace for " _inner_ }". | 
|  | if (L1.First->is(tok::kw_namespace)) { | 
|  | if (L1.Last->is(tok::comment) || !Style.CompactNamespaces) | 
|  | return 0; | 
|  |  | 
|  | assert(Limit >= L1.Last->TotalLength + 3); | 
|  | const auto InnerLimit = Limit - L1.Last->TotalLength - 3; | 
|  | const auto MergedLines = | 
|  | tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit); | 
|  | if (MergedLines == 0) | 
|  | return 0; | 
|  | const auto N = MergedLines + LinesToBeMerged; | 
|  | // Check if there is even a line after the inner result. | 
|  | if (std::distance(I, E) <= N) | 
|  | return 0; | 
|  | // Check that the line after the inner result starts with a closing brace | 
|  | // which we are permitted to merge into one line. | 
|  | if (I[N]->First->is(TT_NamespaceRBrace) && | 
|  | !I[N]->First->MustBreakBefore && | 
|  | BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) && | 
|  | nextNLinesFitInto(I, I + N + 1, Limit)) { | 
|  | return N; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // There's no inner namespace, so we are considering to merge at most one | 
|  | // line. | 
|  |  | 
|  | // The line which is in the namespace should end with semicolon. | 
|  | if (L1.Last->isNot(tok::semi)) | 
|  | return 0; | 
|  |  | 
|  | // Last, check that the third line starts with a closing brace. | 
|  | if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore) | 
|  | return 0; | 
|  |  | 
|  | // If so, merge all lines. | 
|  | return LinesToBeMerged; | 
|  | } | 
|  |  | 
|  | unsigned | 
|  | tryMergeSimpleControlStatement(ArrayRef<AnnotatedLine *>::const_iterator I, | 
|  | ArrayRef<AnnotatedLine *>::const_iterator E, | 
|  | unsigned Limit) { | 
|  | if (Limit == 0) | 
|  | return 0; | 
|  | if (Style.BraceWrapping.AfterControlStatement == | 
|  | FormatStyle::BWACS_Always && | 
|  | I[1]->First->is(tok::l_brace) && | 
|  | Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) { | 
|  | return 0; | 
|  | } | 
|  | if (I[1]->InPPDirective != (*I)->InPPDirective || | 
|  | (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) { | 
|  | return 0; | 
|  | } | 
|  | Limit = limitConsideringMacros(I + 1, E, Limit); | 
|  | AnnotatedLine &Line = **I; | 
|  | if (Line.First->isNot(tok::kw_do) && Line.First->isNot(tok::kw_else) && | 
|  | Line.Last->isNot(tok::kw_else) && Line.Last->isNot(tok::r_paren)) { | 
|  | return 0; | 
|  | } | 
|  | // Only merge `do while` if `do` is the only statement on the line. | 
|  | if (Line.First->is(tok::kw_do) && Line.Last->isNot(tok::kw_do)) | 
|  | return 0; | 
|  | if (1 + I[1]->Last->TotalLength > Limit) | 
|  | return 0; | 
|  | // Don't merge with loops, ifs, a single semicolon or a line comment. | 
|  | if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while, | 
|  | TT_ForEachMacro, TT_LineComment)) { | 
|  | return 0; | 
|  | } | 
|  | // Only inline simple if's (no nested if or else), unless specified | 
|  | if (Style.AllowShortIfStatementsOnASingleLine == | 
|  | FormatStyle::SIS_WithoutElse) { | 
|  | if (I + 2 != E && Line.startsWith(tok::kw_if) && | 
|  | I[2]->First->is(tok::kw_else)) { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | unsigned tryMergeShortCaseLabels(ArrayRef<AnnotatedLine *>::const_iterator I, | 
|  | ArrayRef<AnnotatedLine *>::const_iterator E, | 
|  | unsigned Limit) { | 
|  | if (Limit == 0 || I + 1 == E || | 
|  | I[1]->First->isOneOf(tok::kw_case, tok::kw_default)) { | 
|  | return 0; | 
|  | } | 
|  | if (I[0]->Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace)) | 
|  | return 0; | 
|  | unsigned NumStmts = 0; | 
|  | unsigned Length = 0; | 
|  | bool EndsWithComment = false; | 
|  | bool InPPDirective = I[0]->InPPDirective; | 
|  | bool InMacroBody = I[0]->InMacroBody; | 
|  | const unsigned Level = I[0]->Level; | 
|  | for (; NumStmts < 3; ++NumStmts) { | 
|  | if (I + 1 + NumStmts == E) | 
|  | break; | 
|  | const AnnotatedLine *Line = I[1 + NumStmts]; | 
|  | if (Line->InPPDirective != InPPDirective) | 
|  | break; | 
|  | if (Line->InMacroBody != InMacroBody) | 
|  | break; | 
|  | if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace)) | 
|  | break; | 
|  | if (Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch, | 
|  | tok::kw_while) || | 
|  | EndsWithComment) { | 
|  | return 0; | 
|  | } | 
|  | if (Line->First->is(tok::comment)) { | 
|  | if (Level != Line->Level) | 
|  | return 0; | 
|  | const auto *J = I + 2 + NumStmts; | 
|  | for (; J != E; ++J) { | 
|  | Line = *J; | 
|  | if (Line->InPPDirective != InPPDirective) | 
|  | break; | 
|  | if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace)) | 
|  | break; | 
|  | if (Line->First->isNot(tok::comment) || Level != Line->Level) | 
|  | return 0; | 
|  | } | 
|  | break; | 
|  | } | 
|  | if (Line->Last->is(tok::comment)) | 
|  | EndsWithComment = true; | 
|  | Length += I[1 + NumStmts]->Last->TotalLength + 1; // 1 for the space. | 
|  | } | 
|  | if (NumStmts == 0 || NumStmts == 3 || Length > Limit) | 
|  | return 0; | 
|  | return NumStmts; | 
|  | } | 
|  |  | 
|  | unsigned tryMergeSimpleBlock(ArrayRef<AnnotatedLine *>::const_iterator I, | 
|  | ArrayRef<AnnotatedLine *>::const_iterator E, | 
|  | unsigned Limit) { | 
|  | // Don't merge with a preprocessor directive. | 
|  | if (I[1]->Type == LT_PreprocessorDirective) | 
|  | return 0; | 
|  |  | 
|  | AnnotatedLine &Line = **I; | 
|  |  | 
|  | // Don't merge ObjC @ keywords and methods. | 
|  | // FIXME: If an option to allow short exception handling clauses on a single | 
|  | // line is added, change this to not return for @try and friends. | 
|  | if (!Style.isJava() && Line.First->isOneOf(tok::at, tok::minus, tok::plus)) | 
|  | return 0; | 
|  |  | 
|  | // Check that the current line allows merging. This depends on whether we | 
|  | // are in a control flow statements as well as several style flags. | 
|  | if (Line.First->is(tok::kw_case) || | 
|  | (Line.First->Next && Line.First->Next->is(tok::kw_else))) { | 
|  | return 0; | 
|  | } | 
|  | // default: in switch statement | 
|  | if (Line.First->is(tok::kw_default)) { | 
|  | const FormatToken *Tok = Line.First->getNextNonComment(); | 
|  | if (Tok && Tok->is(tok::colon)) | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | auto IsCtrlStmt = [](const auto &Line) { | 
|  | return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while, | 
|  | tok::kw_do, tok::kw_for, TT_ForEachMacro); | 
|  | }; | 
|  |  | 
|  | const bool IsSplitBlock = | 
|  | Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never || | 
|  | (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty && | 
|  | I[1]->First->isNot(tok::r_brace)); | 
|  |  | 
|  | if (IsCtrlStmt(Line) || | 
|  | Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch, | 
|  | tok::kw___finally, tok::r_brace, | 
|  | Keywords.kw___except) || | 
|  | Line.startsWithExportBlock()) { | 
|  | if (IsSplitBlock) | 
|  | return 0; | 
|  | // Don't merge when we can't except the case when | 
|  | // the control statement block is empty | 
|  | if (!Style.AllowShortIfStatementsOnASingleLine && | 
|  | Line.First->isOneOf(tok::kw_if, tok::kw_else) && | 
|  | !Style.BraceWrapping.AfterControlStatement && | 
|  | I[1]->First->isNot(tok::r_brace)) { | 
|  | return 0; | 
|  | } | 
|  | if (!Style.AllowShortIfStatementsOnASingleLine && | 
|  | Line.First->isOneOf(tok::kw_if, tok::kw_else) && | 
|  | Style.BraceWrapping.AfterControlStatement == | 
|  | FormatStyle::BWACS_Always && | 
|  | I + 2 != E && I[2]->First->isNot(tok::r_brace)) { | 
|  | return 0; | 
|  | } | 
|  | if (!Style.AllowShortLoopsOnASingleLine && | 
|  | Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for, | 
|  | TT_ForEachMacro) && | 
|  | !Style.BraceWrapping.AfterControlStatement && | 
|  | I[1]->First->isNot(tok::r_brace)) { | 
|  | return 0; | 
|  | } | 
|  | if (!Style.AllowShortLoopsOnASingleLine && | 
|  | Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for, | 
|  | TT_ForEachMacro) && | 
|  | Style.BraceWrapping.AfterControlStatement == | 
|  | FormatStyle::BWACS_Always && | 
|  | I + 2 != E && I[2]->First->isNot(tok::r_brace)) { | 
|  | return 0; | 
|  | } | 
|  | // FIXME: Consider an option to allow short exception handling clauses on | 
|  | // a single line. | 
|  | // FIXME: This isn't covered by tests. | 
|  | // FIXME: For catch, __except, __finally the first token on the line | 
|  | // is '}', so this isn't correct here. | 
|  | if (Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch, | 
|  | Keywords.kw___except, tok::kw___finally)) { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (Line.endsWith(tok::l_brace)) { | 
|  | if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never && | 
|  | Line.First->is(TT_BlockLBrace)) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (IsSplitBlock && Line.First == Line.Last && | 
|  | I > AnnotatedLines.begin() && | 
|  | (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) { | 
|  | return 0; | 
|  | } | 
|  | FormatToken *Tok = I[1]->First; | 
|  | auto ShouldMerge = [Tok]() { | 
|  | if (Tok->isNot(tok::r_brace) || Tok->MustBreakBefore) | 
|  | return false; | 
|  | const FormatToken *Next = Tok->getNextNonComment(); | 
|  | return !Next || Next->is(tok::semi); | 
|  | }; | 
|  |  | 
|  | if (ShouldMerge()) { | 
|  | // We merge empty blocks even if the line exceeds the column limit. | 
|  | Tok->SpacesRequiredBefore = | 
|  | Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never || | 
|  | Line.Last->is(tok::comment); | 
|  | Tok->CanBreakBefore = true; | 
|  | return 1; | 
|  | } else if (Limit != 0 && !Line.startsWithNamespace() && | 
|  | !startsExternCBlock(Line)) { | 
|  | // We don't merge short records. | 
|  | if (isRecordLBrace(*Line.Last)) | 
|  | return 0; | 
|  |  | 
|  | // Check that we still have three lines and they fit into the limit. | 
|  | if (I + 2 == E || I[2]->Type == LT_Invalid) | 
|  | return 0; | 
|  | Limit = limitConsideringMacros(I + 2, E, Limit); | 
|  |  | 
|  | if (!nextTwoLinesFitInto(I, Limit)) | 
|  | return 0; | 
|  |  | 
|  | // Second, check that the next line does not contain any braces - if it | 
|  | // does, readability declines when putting it into a single line. | 
|  | if (I[1]->Last->is(TT_LineComment)) | 
|  | return 0; | 
|  | do { | 
|  | if (Tok->is(tok::l_brace) && Tok->isNot(BK_BracedInit)) | 
|  | return 0; | 
|  | Tok = Tok->Next; | 
|  | } while (Tok); | 
|  |  | 
|  | // Last, check that the third line starts with a closing brace. | 
|  | Tok = I[2]->First; | 
|  | if (Tok->isNot(tok::r_brace)) | 
|  | return 0; | 
|  |  | 
|  | // Don't merge "if (a) { .. } else {". | 
|  | if (Tok->Next && Tok->Next->is(tok::kw_else)) | 
|  | return 0; | 
|  |  | 
|  | // Don't merge a trailing multi-line control statement block like: | 
|  | // } else if (foo && | 
|  | //            bar) | 
|  | // { <-- current Line | 
|  | //   baz(); | 
|  | // } | 
|  | if (Line.First == Line.Last && | 
|  | Line.First->is(TT_ControlStatementLBrace) && | 
|  | Style.BraceWrapping.AfterControlStatement == | 
|  | FormatStyle::BWACS_MultiLine) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | return 2; | 
|  | } | 
|  | } else if (I[1]->First->is(tok::l_brace)) { | 
|  | if (I[1]->Last->is(TT_LineComment)) | 
|  | return 0; | 
|  |  | 
|  | // Check for Limit <= 2 to account for the " {". | 
|  | if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I))) | 
|  | return 0; | 
|  | Limit -= 2; | 
|  | unsigned MergedLines = 0; | 
|  | if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never || | 
|  | (I[1]->First == I[1]->Last && I + 2 != E && | 
|  | I[2]->First->is(tok::r_brace))) { | 
|  | MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); | 
|  | // If we managed to merge the block, count the statement header, which | 
|  | // is on a separate line. | 
|  | if (MergedLines > 0) | 
|  | ++MergedLines; | 
|  | } | 
|  | return MergedLines; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /// Returns the modified column limit for \p I if it is inside a macro and | 
|  | /// needs a trailing '\'. | 
|  | unsigned limitConsideringMacros(ArrayRef<AnnotatedLine *>::const_iterator I, | 
|  | ArrayRef<AnnotatedLine *>::const_iterator E, | 
|  | unsigned Limit) { | 
|  | if (I[0]->InPPDirective && I + 1 != E && | 
|  | !I[1]->First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) { | 
|  | return Limit < 2 ? 0 : Limit - 2; | 
|  | } | 
|  | return Limit; | 
|  | } | 
|  |  | 
|  | bool nextTwoLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I, | 
|  | unsigned Limit) { | 
|  | if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore) | 
|  | return false; | 
|  | return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit; | 
|  | } | 
|  |  | 
|  | bool nextNLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I, | 
|  | ArrayRef<AnnotatedLine *>::const_iterator E, | 
|  | unsigned Limit) { | 
|  | unsigned JoinedLength = 0; | 
|  | for (const auto *J = I + 1; J != E; ++J) { | 
|  | if ((*J)->First->MustBreakBefore) | 
|  | return false; | 
|  |  | 
|  | JoinedLength += 1 + (*J)->Last->TotalLength; | 
|  | if (JoinedLength > Limit) | 
|  | return false; | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool containsMustBreak(const AnnotatedLine *Line) { | 
|  | assert(Line->First); | 
|  | // Ignore the first token, because in this situation, it applies more to the | 
|  | // last token of the previous line. | 
|  | for (const FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) | 
|  | if (Tok->MustBreakBefore) | 
|  | return true; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void join(AnnotatedLine &A, const AnnotatedLine &B) { | 
|  | assert(!A.Last->Next); | 
|  | assert(!B.First->Previous); | 
|  | if (B.Affected || B.LeadingEmptyLinesAffected) { | 
|  | assert(B.Affected || A.Last->Children.empty()); | 
|  | A.Affected = true; | 
|  | } | 
|  | A.Last->Next = B.First; | 
|  | B.First->Previous = A.Last; | 
|  | B.First->CanBreakBefore = true; | 
|  | unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore; | 
|  | for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) { | 
|  | Tok->TotalLength += LengthA; | 
|  | A.Last = Tok; | 
|  | } | 
|  | } | 
|  |  | 
|  | const FormatStyle &Style; | 
|  | const AdditionalKeywords &Keywords; | 
|  | const ArrayRef<AnnotatedLine *>::const_iterator End; | 
|  |  | 
|  | ArrayRef<AnnotatedLine *>::const_iterator Next; | 
|  | const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines; | 
|  | }; | 
|  |  | 
|  | static void markFinalized(FormatToken *Tok) { | 
|  | if (Tok->is(tok::hash) && !Tok->Previous && Tok->Next && | 
|  | Tok->Next->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef, | 
|  | tok::pp_elif, tok::pp_elifdef, tok::pp_elifndef, | 
|  | tok::pp_else, tok::pp_endif)) { | 
|  | Tok = Tok->Next; | 
|  | } | 
|  | for (; Tok; Tok = Tok->Next) { | 
|  | if (Tok->MacroCtx && Tok->MacroCtx->Role == MR_ExpandedArg) { | 
|  | // In the first pass we format all macro arguments in the expanded token | 
|  | // stream. Instead of finalizing the macro arguments, we mark that they | 
|  | // will be modified as unexpanded arguments (as part of the macro call | 
|  | // formatting) in the next pass. | 
|  | Tok->MacroCtx->Role = MR_UnexpandedArg; | 
|  | // Reset whether spaces or a line break are required before this token, as | 
|  | // that is context dependent, and that context may change when formatting | 
|  | // the macro call.  For example, given M(x) -> 2 * x, and the macro call | 
|  | // M(var), the token 'var' will have SpacesRequiredBefore = 1 after being | 
|  | // formatted as part of the expanded macro, but SpacesRequiredBefore = 0 | 
|  | // for its position within the macro call. | 
|  | Tok->SpacesRequiredBefore = 0; | 
|  | if (!Tok->MustBreakBeforeFinalized) | 
|  | Tok->MustBreakBefore = 0; | 
|  | } else { | 
|  | Tok->Finalized = true; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #ifndef NDEBUG | 
|  | static void printLineState(const LineState &State) { | 
|  | llvm::dbgs() << "State: "; | 
|  | for (const ParenState &P : State.Stack) { | 
|  | llvm::dbgs() << (P.Tok ? P.Tok->TokenText : "F") << "|" << P.Indent << "|" | 
|  | << P.LastSpace << "|" << P.NestedBlockIndent << " "; | 
|  | } | 
|  | llvm::dbgs() << State.NextToken->TokenText << "\n"; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /// Base class for classes that format one \c AnnotatedLine. | 
|  | class LineFormatter { | 
|  | public: | 
|  | LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces, | 
|  | const FormatStyle &Style, | 
|  | UnwrappedLineFormatter *BlockFormatter) | 
|  | : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style), | 
|  | BlockFormatter(BlockFormatter) {} | 
|  | virtual ~LineFormatter() {} | 
|  |  | 
|  | /// Formats an \c AnnotatedLine and returns the penalty. | 
|  | /// | 
|  | /// If \p DryRun is \c false, directly applies the changes. | 
|  | virtual unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent, | 
|  | unsigned FirstStartColumn, bool DryRun) = 0; | 
|  |  | 
|  | protected: | 
|  | /// If the \p State's next token is an r_brace closing a nested block, | 
|  | /// format the nested block before it. | 
|  | /// | 
|  | /// Returns \c true if all children could be placed successfully and adapts | 
|  | /// \p Penalty as well as \p State. If \p DryRun is false, also directly | 
|  | /// creates changes using \c Whitespaces. | 
|  | /// | 
|  | /// The crucial idea here is that children always get formatted upon | 
|  | /// encountering the closing brace right after the nested block. Now, if we | 
|  | /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is | 
|  | /// \c false), the entire block has to be kept on the same line (which is only | 
|  | /// possible if it fits on the line, only contains a single statement, etc. | 
|  | /// | 
|  | /// If \p NewLine is true, we format the nested block on separate lines, i.e. | 
|  | /// break after the "{", format all lines with correct indentation and the put | 
|  | /// the closing "}" on yet another new line. | 
|  | /// | 
|  | /// This enables us to keep the simple structure of the | 
|  | /// \c UnwrappedLineFormatter, where we only have two options for each token: | 
|  | /// break or don't break. | 
|  | bool formatChildren(LineState &State, bool NewLine, bool DryRun, | 
|  | unsigned &Penalty) { | 
|  | const FormatToken *LBrace = State.NextToken->getPreviousNonComment(); | 
|  | bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(BK_Block); | 
|  | FormatToken &Previous = *State.NextToken->Previous; | 
|  | if (Previous.Children.empty() || (!HasLBrace && !LBrace->MacroParent)) { | 
|  | // The previous token does not open a block. Nothing to do. We don't | 
|  | // assert so that we can simply call this function for all tokens. | 
|  | return true; | 
|  | } | 
|  |  | 
|  | if (NewLine || Previous.MacroParent) { | 
|  | const ParenState &P = State.Stack.back(); | 
|  |  | 
|  | int AdditionalIndent = | 
|  | P.Indent - Previous.Children[0]->Level * Style.IndentWidth; | 
|  | Penalty += | 
|  | BlockFormatter->format(Previous.Children, DryRun, AdditionalIndent, | 
|  | /*FixBadIndentation=*/true); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | if (Previous.Children[0]->First->MustBreakBefore) | 
|  | return false; | 
|  |  | 
|  | // Cannot merge into one line if this line ends on a comment. | 
|  | if (Previous.is(tok::comment)) | 
|  | return false; | 
|  |  | 
|  | // Cannot merge multiple statements into a single line. | 
|  | if (Previous.Children.size() > 1) | 
|  | return false; | 
|  |  | 
|  | const AnnotatedLine *Child = Previous.Children[0]; | 
|  | // We can't put the closing "}" on a line with a trailing comment. | 
|  | if (Child->Last->isTrailingComment()) | 
|  | return false; | 
|  |  | 
|  | // If the child line exceeds the column limit, we wouldn't want to merge it. | 
|  | // We add +2 for the trailing " }". | 
|  | if (Style.ColumnLimit > 0 && | 
|  | Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (!DryRun) { | 
|  | Whitespaces->replaceWhitespace( | 
|  | *Child->First, /*Newlines=*/0, /*Spaces=*/1, | 
|  | /*StartOfTokenColumn=*/State.Column, /*IsAligned=*/false, | 
|  | State.Line->InPPDirective); | 
|  | } | 
|  | Penalty += | 
|  | formatLine(*Child, State.Column + 1, /*FirstStartColumn=*/0, DryRun); | 
|  | if (!DryRun) | 
|  | markFinalized(Child->First); | 
|  |  | 
|  | State.Column += 1 + Child->Last->TotalLength; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | ContinuationIndenter *Indenter; | 
|  |  | 
|  | private: | 
|  | WhitespaceManager *Whitespaces; | 
|  | const FormatStyle &Style; | 
|  | UnwrappedLineFormatter *BlockFormatter; | 
|  | }; | 
|  |  | 
|  | /// Formatter that keeps the existing line breaks. | 
|  | class NoColumnLimitLineFormatter : public LineFormatter { | 
|  | public: | 
|  | NoColumnLimitLineFormatter(ContinuationIndenter *Indenter, | 
|  | WhitespaceManager *Whitespaces, | 
|  | const FormatStyle &Style, | 
|  | UnwrappedLineFormatter *BlockFormatter) | 
|  | : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {} | 
|  |  | 
|  | /// Formats the line, simply keeping all of the input's line breaking | 
|  | /// decisions. | 
|  | unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent, | 
|  | unsigned FirstStartColumn, bool DryRun) override { | 
|  | assert(!DryRun); | 
|  | LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn, | 
|  | &Line, /*DryRun=*/false); | 
|  | while (State.NextToken) { | 
|  | bool Newline = | 
|  | Indenter->mustBreak(State) || | 
|  | (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0); | 
|  | unsigned Penalty = 0; | 
|  | formatChildren(State, Newline, /*DryRun=*/false, Penalty); | 
|  | Indenter->addTokenToState(State, Newline, /*DryRun=*/false); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /// Formatter that puts all tokens into a single line without breaks. | 
|  | class NoLineBreakFormatter : public LineFormatter { | 
|  | public: | 
|  | NoLineBreakFormatter(ContinuationIndenter *Indenter, | 
|  | WhitespaceManager *Whitespaces, const FormatStyle &Style, | 
|  | UnwrappedLineFormatter *BlockFormatter) | 
|  | : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {} | 
|  |  | 
|  | /// Puts all tokens into a single line. | 
|  | unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent, | 
|  | unsigned FirstStartColumn, bool DryRun) override { | 
|  | unsigned Penalty = 0; | 
|  | LineState State = | 
|  | Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun); | 
|  | while (State.NextToken) { | 
|  | formatChildren(State, /*NewLine=*/false, DryRun, Penalty); | 
|  | Indenter->addTokenToState( | 
|  | State, /*Newline=*/State.NextToken->MustBreakBefore, DryRun); | 
|  | } | 
|  | return Penalty; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /// Finds the best way to break lines. | 
|  | class OptimizingLineFormatter : public LineFormatter { | 
|  | public: | 
|  | OptimizingLineFormatter(ContinuationIndenter *Indenter, | 
|  | WhitespaceManager *Whitespaces, | 
|  | const FormatStyle &Style, | 
|  | UnwrappedLineFormatter *BlockFormatter) | 
|  | : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {} | 
|  |  | 
|  | /// Formats the line by finding the best line breaks with line lengths | 
|  | /// below the column limit. | 
|  | unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent, | 
|  | unsigned FirstStartColumn, bool DryRun) override { | 
|  | LineState State = | 
|  | Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun); | 
|  |  | 
|  | // If the ObjC method declaration does not fit on a line, we should format | 
|  | // it with one arg per line. | 
|  | if (State.Line->Type == LT_ObjCMethodDecl) | 
|  | State.Stack.back().BreakBeforeParameter = true; | 
|  |  | 
|  | // Find best solution in solution space. | 
|  | return analyzeSolutionSpace(State, DryRun); | 
|  | } | 
|  |  | 
|  | private: | 
|  | struct CompareLineStatePointers { | 
|  | bool operator()(LineState *obj1, LineState *obj2) const { | 
|  | return *obj1 < *obj2; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /// A pair of <penalty, count> that is used to prioritize the BFS on. | 
|  | /// | 
|  | /// In case of equal penalties, we want to prefer states that were inserted | 
|  | /// first. During state generation we make sure that we insert states first | 
|  | /// that break the line as late as possible. | 
|  | typedef std::pair<unsigned, unsigned> OrderedPenalty; | 
|  |  | 
|  | /// An edge in the solution space from \c Previous->State to \c State, | 
|  | /// inserting a newline dependent on the \c NewLine. | 
|  | struct StateNode { | 
|  | StateNode(const LineState &State, bool NewLine, StateNode *Previous) | 
|  | : State(State), NewLine(NewLine), Previous(Previous) {} | 
|  | LineState State; | 
|  | bool NewLine; | 
|  | StateNode *Previous; | 
|  | }; | 
|  |  | 
|  | /// An item in the prioritized BFS search queue. The \c StateNode's | 
|  | /// \c State has the given \c OrderedPenalty. | 
|  | typedef std::pair<OrderedPenalty, StateNode *> QueueItem; | 
|  |  | 
|  | /// The BFS queue type. | 
|  | typedef std::priority_queue<QueueItem, SmallVector<QueueItem>, | 
|  | std::greater<QueueItem>> | 
|  | QueueType; | 
|  |  | 
|  | /// Analyze the entire solution space starting from \p InitialState. | 
|  | /// | 
|  | /// This implements a variant of Dijkstra's algorithm on the graph that spans | 
|  | /// the solution space (\c LineStates are the nodes). The algorithm tries to | 
|  | /// find the shortest path (the one with lowest penalty) from \p InitialState | 
|  | /// to a state where all tokens are placed. Returns the penalty. | 
|  | /// | 
|  | /// If \p DryRun is \c false, directly applies the changes. | 
|  | unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun) { | 
|  | std::set<LineState *, CompareLineStatePointers> Seen; | 
|  |  | 
|  | // Increasing count of \c StateNode items we have created. This is used to | 
|  | // create a deterministic order independent of the container. | 
|  | unsigned Count = 0; | 
|  | QueueType Queue; | 
|  |  | 
|  | // Insert start element into queue. | 
|  | StateNode *RootNode = | 
|  | new (Allocator.Allocate()) StateNode(InitialState, false, nullptr); | 
|  | Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode)); | 
|  | ++Count; | 
|  |  | 
|  | unsigned Penalty = 0; | 
|  |  | 
|  | // While not empty, take first element and follow edges. | 
|  | while (!Queue.empty()) { | 
|  | // Quit if we still haven't found a solution by now. | 
|  | if (Count > 25'000'000) | 
|  | return 0; | 
|  |  | 
|  | Penalty = Queue.top().first.first; | 
|  | StateNode *Node = Queue.top().second; | 
|  | if (!Node->State.NextToken) { | 
|  | LLVM_DEBUG(llvm::dbgs() | 
|  | << "\n---\nPenalty for line: " << Penalty << "\n"); | 
|  | break; | 
|  | } | 
|  | Queue.pop(); | 
|  |  | 
|  | // Cut off the analysis of certain solutions if the analysis gets too | 
|  | // complex. See description of IgnoreStackForComparison. | 
|  | if (Count > 50'000) | 
|  | Node->State.IgnoreStackForComparison = true; | 
|  |  | 
|  | if (!Seen.insert(&Node->State).second) { | 
|  | // State already examined with lower penalty. | 
|  | continue; | 
|  | } | 
|  |  | 
|  | FormatDecision LastFormat = Node->State.NextToken->getDecision(); | 
|  | if (LastFormat == FD_Unformatted || LastFormat == FD_Continue) | 
|  | addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue); | 
|  | if (LastFormat == FD_Unformatted || LastFormat == FD_Break) | 
|  | addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue); | 
|  | } | 
|  |  | 
|  | if (Queue.empty()) { | 
|  | // We were unable to find a solution, do nothing. | 
|  | // FIXME: Add diagnostic? | 
|  | LLVM_DEBUG(llvm::dbgs() << "Could not find a solution.\n"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // Reconstruct the solution. | 
|  | if (!DryRun) | 
|  | reconstructPath(InitialState, Queue.top().second); | 
|  |  | 
|  | LLVM_DEBUG(llvm::dbgs() | 
|  | << "Total number of analyzed states: " << Count << "\n"); | 
|  | LLVM_DEBUG(llvm::dbgs() << "---\n"); | 
|  |  | 
|  | return Penalty; | 
|  | } | 
|  |  | 
|  | /// Add the following state to the analysis queue \c Queue. | 
|  | /// | 
|  | /// Assume the current state is \p PreviousNode and has been reached with a | 
|  | /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true. | 
|  | void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode, | 
|  | bool NewLine, unsigned *Count, QueueType *Queue) { | 
|  | if (NewLine && !Indenter->canBreak(PreviousNode->State)) | 
|  | return; | 
|  | if (!NewLine && Indenter->mustBreak(PreviousNode->State)) | 
|  | return; | 
|  |  | 
|  | StateNode *Node = new (Allocator.Allocate()) | 
|  | StateNode(PreviousNode->State, NewLine, PreviousNode); | 
|  | if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty)) | 
|  | return; | 
|  |  | 
|  | Penalty += Indenter->addTokenToState(Node->State, NewLine, true); | 
|  |  | 
|  | Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node)); | 
|  | ++(*Count); | 
|  | } | 
|  |  | 
|  | /// Applies the best formatting by reconstructing the path in the | 
|  | /// solution space that leads to \c Best. | 
|  | void reconstructPath(LineState &State, StateNode *Best) { | 
|  | llvm::SmallVector<StateNode *> Path; | 
|  | // We do not need a break before the initial token. | 
|  | while (Best->Previous) { | 
|  | Path.push_back(Best); | 
|  | Best = Best->Previous; | 
|  | } | 
|  | for (const auto &Node : llvm::reverse(Path)) { | 
|  | unsigned Penalty = 0; | 
|  | formatChildren(State, Node->NewLine, /*DryRun=*/false, Penalty); | 
|  | Penalty += Indenter->addTokenToState(State, Node->NewLine, false); | 
|  |  | 
|  | LLVM_DEBUG({ | 
|  | printLineState(Node->Previous->State); | 
|  | if (Node->NewLine) { | 
|  | llvm::dbgs() << "Penalty for placing " | 
|  | << Node->Previous->State.NextToken->Tok.getName() | 
|  | << " on a new line: " << Penalty << "\n"; | 
|  | } | 
|  | }); | 
|  | } | 
|  | } | 
|  |  | 
|  | llvm::SpecificBumpPtrAllocator<StateNode> Allocator; | 
|  | }; | 
|  |  | 
|  | } // anonymous namespace | 
|  |  | 
|  | unsigned UnwrappedLineFormatter::format( | 
|  | const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun, | 
|  | int AdditionalIndent, bool FixBadIndentation, unsigned FirstStartColumn, | 
|  | unsigned NextStartColumn, unsigned LastStartColumn) { | 
|  | LineJoiner Joiner(Style, Keywords, Lines); | 
|  |  | 
|  | // Try to look up already computed penalty in DryRun-mode. | 
|  | std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey( | 
|  | &Lines, AdditionalIndent); | 
|  | auto CacheIt = PenaltyCache.find(CacheKey); | 
|  | if (DryRun && CacheIt != PenaltyCache.end()) | 
|  | return CacheIt->second; | 
|  |  | 
|  | assert(!Lines.empty()); | 
|  | unsigned Penalty = 0; | 
|  | LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level, | 
|  | AdditionalIndent); | 
|  | const AnnotatedLine *PrevPrevLine = nullptr; | 
|  | const AnnotatedLine *PreviousLine = nullptr; | 
|  | const AnnotatedLine *NextLine = nullptr; | 
|  |  | 
|  | // The minimum level of consecutive lines that have been formatted. | 
|  | unsigned RangeMinLevel = UINT_MAX; | 
|  |  | 
|  | bool FirstLine = true; | 
|  | for (const AnnotatedLine *Line = | 
|  | Joiner.getNextMergedLine(DryRun, IndentTracker); | 
|  | Line; PrevPrevLine = PreviousLine, PreviousLine = Line, Line = NextLine, | 
|  | FirstLine = false) { | 
|  | assert(Line->First); | 
|  | const AnnotatedLine &TheLine = *Line; | 
|  | unsigned Indent = IndentTracker.getIndent(); | 
|  |  | 
|  | // We continue formatting unchanged lines to adjust their indent, e.g. if a | 
|  | // scope was added. However, we need to carefully stop doing this when we | 
|  | // exit the scope of affected lines to prevent indenting the entire | 
|  | // remaining file if it currently missing a closing brace. | 
|  | bool PreviousRBrace = | 
|  | PreviousLine && PreviousLine->startsWith(tok::r_brace); | 
|  | bool ContinueFormatting = | 
|  | TheLine.Level > RangeMinLevel || | 
|  | (TheLine.Level == RangeMinLevel && !PreviousRBrace && | 
|  | !TheLine.startsWith(TT_NamespaceRBrace)); | 
|  |  | 
|  | bool FixIndentation = (FixBadIndentation || ContinueFormatting) && | 
|  | Indent != TheLine.First->OriginalColumn; | 
|  | bool ShouldFormat = TheLine.Affected || FixIndentation; | 
|  | // We cannot format this line; if the reason is that the line had a | 
|  | // parsing error, remember that. | 
|  | if (ShouldFormat && TheLine.Type == LT_Invalid && Status) { | 
|  | Status->FormatComplete = false; | 
|  | Status->Line = | 
|  | SourceMgr.getSpellingLineNumber(TheLine.First->Tok.getLocation()); | 
|  | } | 
|  |  | 
|  | if (ShouldFormat && TheLine.Type != LT_Invalid) { | 
|  | if (!DryRun) { | 
|  | bool LastLine = TheLine.First->is(tok::eof); | 
|  | formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines, Indent, | 
|  | LastLine ? LastStartColumn : NextStartColumn + Indent); | 
|  | } | 
|  |  | 
|  | NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker); | 
|  | unsigned ColumnLimit = getColumnLimit(TheLine.InPPDirective, NextLine); | 
|  | bool FitsIntoOneLine = | 
|  | !TheLine.ContainsMacroCall && | 
|  | (TheLine.Last->TotalLength + Indent <= ColumnLimit || | 
|  | (TheLine.Type == LT_ImportStatement && | 
|  | (!Style.isJavaScript() || !Style.JavaScriptWrapImports)) || | 
|  | (Style.isCSharp() && | 
|  | TheLine.InPPDirective)); // don't split #regions in C# | 
|  | if (Style.ColumnLimit == 0) { | 
|  | NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this) | 
|  | .formatLine(TheLine, NextStartColumn + Indent, | 
|  | FirstLine ? FirstStartColumn : 0, DryRun); | 
|  | } else if (FitsIntoOneLine) { | 
|  | Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style, this) | 
|  | .formatLine(TheLine, NextStartColumn + Indent, | 
|  | FirstLine ? FirstStartColumn : 0, DryRun); | 
|  | } else { | 
|  | Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this) | 
|  | .formatLine(TheLine, NextStartColumn + Indent, | 
|  | FirstLine ? FirstStartColumn : 0, DryRun); | 
|  | } | 
|  | RangeMinLevel = std::min(RangeMinLevel, TheLine.Level); | 
|  | } else { | 
|  | // If no token in the current line is affected, we still need to format | 
|  | // affected children. | 
|  | if (TheLine.ChildrenAffected) { | 
|  | for (const FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) | 
|  | if (!Tok->Children.empty()) | 
|  | format(Tok->Children, DryRun); | 
|  | } | 
|  |  | 
|  | // Adapt following lines on the current indent level to the same level | 
|  | // unless the current \c AnnotatedLine is not at the beginning of a line. | 
|  | bool StartsNewLine = | 
|  | TheLine.First->NewlinesBefore > 0 || TheLine.First->IsFirst; | 
|  | if (StartsNewLine) | 
|  | IndentTracker.adjustToUnmodifiedLine(TheLine); | 
|  | if (!DryRun) { | 
|  | bool ReformatLeadingWhitespace = | 
|  | StartsNewLine && ((PreviousLine && PreviousLine->Affected) || | 
|  | TheLine.LeadingEmptyLinesAffected); | 
|  | // Format the first token. | 
|  | if (ReformatLeadingWhitespace) { | 
|  | formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines, | 
|  | TheLine.First->OriginalColumn, | 
|  | TheLine.First->OriginalColumn); | 
|  | } else { | 
|  | Whitespaces->addUntouchableToken(*TheLine.First, | 
|  | TheLine.InPPDirective); | 
|  | } | 
|  |  | 
|  | // Notify the WhitespaceManager about the unchanged whitespace. | 
|  | for (FormatToken *Tok = TheLine.First->Next; Tok; Tok = Tok->Next) | 
|  | Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective); | 
|  | } | 
|  | NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker); | 
|  | RangeMinLevel = UINT_MAX; | 
|  | } | 
|  | if (!DryRun) | 
|  | markFinalized(TheLine.First); | 
|  | } | 
|  | PenaltyCache[CacheKey] = Penalty; | 
|  | return Penalty; | 
|  | } | 
|  |  | 
|  | static auto computeNewlines(const AnnotatedLine &Line, | 
|  | const AnnotatedLine *PreviousLine, | 
|  | const AnnotatedLine *PrevPrevLine, | 
|  | const SmallVectorImpl<AnnotatedLine *> &Lines, | 
|  | const FormatStyle &Style) { | 
|  | const auto &RootToken = *Line.First; | 
|  | auto 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)) && | 
|  | // Do not remove empty lines before namespace closing "}". | 
|  | !getNamespaceToken(&Line, Lines)) { | 
|  | Newlines = std::min(Newlines, 1u); | 
|  | } | 
|  | // Remove empty lines at the start of nested blocks (lambdas/arrow functions) | 
|  | if (!PreviousLine && Line.Level > 0) | 
|  | Newlines = std::min(Newlines, 1u); | 
|  | if (Newlines == 0 && !RootToken.IsFirst) | 
|  | Newlines = 1; | 
|  | if (RootToken.IsFirst && | 
|  | (!Style.KeepEmptyLines.AtStartOfFile || !RootToken.HasUnescapedNewline)) { | 
|  | Newlines = 0; | 
|  | } | 
|  |  | 
|  | // Remove empty lines after "{". | 
|  | if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine && | 
|  | PreviousLine->Last->is(tok::l_brace) && | 
|  | !PreviousLine->startsWithNamespace() && | 
|  | !(PrevPrevLine && PrevPrevLine->startsWithNamespace() && | 
|  | PreviousLine->startsWith(tok::l_brace)) && | 
|  | !startsExternCBlock(*PreviousLine)) { | 
|  | Newlines = 1; | 
|  | } | 
|  |  | 
|  | if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) { | 
|  | // Modify empty lines after TT_NamespaceLBrace. | 
|  | if (PreviousLine && PreviousLine->endsWith(TT_NamespaceLBrace)) { | 
|  | if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never) | 
|  | Newlines = 1; | 
|  | else if (!Line.startsWithNamespace()) | 
|  | Newlines = std::max(Newlines, 2u); | 
|  | } | 
|  | // Modify empty lines before TT_NamespaceRBrace. | 
|  | if (Line.startsWith(TT_NamespaceRBrace)) { | 
|  | if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never) | 
|  | Newlines = 1; | 
|  | else if (!PreviousLine->startsWith(TT_NamespaceRBrace)) | 
|  | Newlines = std::max(Newlines, 2u); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Insert or remove empty line before access specifiers. | 
|  | if (PreviousLine && RootToken.isAccessSpecifier()) { | 
|  | switch (Style.EmptyLineBeforeAccessModifier) { | 
|  | case FormatStyle::ELBAMS_Never: | 
|  | if (Newlines > 1) | 
|  | Newlines = 1; | 
|  | break; | 
|  | case FormatStyle::ELBAMS_Leave: | 
|  | Newlines = std::max(RootToken.NewlinesBefore, 1u); | 
|  | break; | 
|  | case FormatStyle::ELBAMS_LogicalBlock: | 
|  | if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) && Newlines <= 1) | 
|  | Newlines = 2; | 
|  | if (PreviousLine->First->isAccessSpecifier()) | 
|  | Newlines = 1; // Previous is an access modifier remove all new lines. | 
|  | break; | 
|  | case FormatStyle::ELBAMS_Always: { | 
|  | const FormatToken *previousToken; | 
|  | if (PreviousLine->Last->is(tok::comment)) | 
|  | previousToken = PreviousLine->Last->getPreviousNonComment(); | 
|  | else | 
|  | previousToken = PreviousLine->Last; | 
|  | if ((!previousToken || previousToken->isNot(tok::l_brace)) && | 
|  | Newlines <= 1) { | 
|  | Newlines = 2; | 
|  | } | 
|  | } break; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Insert or remove empty line after access specifiers. | 
|  | if (PreviousLine && PreviousLine->First->isAccessSpecifier() && | 
|  | (!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline)) { | 
|  | // EmptyLineBeforeAccessModifier is handling the case when two access | 
|  | // modifiers follow each other. | 
|  | if (!RootToken.isAccessSpecifier()) { | 
|  | switch (Style.EmptyLineAfterAccessModifier) { | 
|  | case FormatStyle::ELAAMS_Never: | 
|  | Newlines = 1; | 
|  | break; | 
|  | case FormatStyle::ELAAMS_Leave: | 
|  | Newlines = std::max(Newlines, 1u); | 
|  | break; | 
|  | case FormatStyle::ELAAMS_Always: | 
|  | if (RootToken.is(tok::r_brace)) // Do not add at end of class. | 
|  | Newlines = 1u; | 
|  | else | 
|  | Newlines = std::max(Newlines, 2u); | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return Newlines; | 
|  | } | 
|  |  | 
|  | void UnwrappedLineFormatter::formatFirstToken( | 
|  | const AnnotatedLine &Line, const AnnotatedLine *PreviousLine, | 
|  | const AnnotatedLine *PrevPrevLine, | 
|  | const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent, | 
|  | unsigned NewlineIndent) { | 
|  | FormatToken &RootToken = *Line.First; | 
|  | if (RootToken.is(tok::eof)) { | 
|  | unsigned Newlines = std::min( | 
|  | RootToken.NewlinesBefore, | 
|  | Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1); | 
|  | unsigned TokenIndent = Newlines ? NewlineIndent : 0; | 
|  | Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent, | 
|  | TokenIndent); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (RootToken.Newlines < 0) { | 
|  | RootToken.Newlines = | 
|  | computeNewlines(Line, PreviousLine, PrevPrevLine, Lines, Style); | 
|  | assert(RootToken.Newlines >= 0); | 
|  | } | 
|  |  | 
|  | if (RootToken.Newlines > 0) | 
|  | Indent = NewlineIndent; | 
|  |  | 
|  | // Preprocessor directives get indented before the hash only if specified. In | 
|  | // Javascript import statements are indented like normal statements. | 
|  | if (!Style.isJavaScript() && | 
|  | Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash && | 
|  | (Line.Type == LT_PreprocessorDirective || | 
|  | Line.Type == LT_ImportStatement)) { | 
|  | Indent = 0; | 
|  | } | 
|  |  | 
|  | Whitespaces->replaceWhitespace(RootToken, RootToken.Newlines, Indent, Indent, | 
|  | /*IsAligned=*/false, | 
|  | Line.InPPDirective && | 
|  | !RootToken.HasUnescapedNewline); | 
|  | } | 
|  |  | 
|  | unsigned | 
|  | UnwrappedLineFormatter::getColumnLimit(bool InPPDirective, | 
|  | const AnnotatedLine *NextLine) const { | 
|  | // In preprocessor directives reserve two chars for trailing " \" if the | 
|  | // next line continues the preprocessor directive. | 
|  | bool ContinuesPPDirective = | 
|  | InPPDirective && | 
|  | // If there is no next line, this is likely a child line and the parent | 
|  | // continues the preprocessor directive. | 
|  | (!NextLine || | 
|  | (NextLine->InPPDirective && | 
|  | // If there is an unescaped newline between this line and the next, the | 
|  | // next line starts a new preprocessor directive. | 
|  | !NextLine->First->HasUnescapedNewline)); | 
|  | return Style.ColumnLimit - (ContinuesPPDirective ? 2 : 0); | 
|  | } | 
|  |  | 
|  | } // namespace format | 
|  | } // namespace clang |