13#include "llvm/Support/Debug.h"
16#define DEBUG_TYPE "format-formatter"
23bool startsExternCBlock(
const AnnotatedLine &
Line) {
26 return Line.startsWith(tok::kw_extern) &&
Next &&
Next->isStringLiteral() &&
27 NextNext && NextNext->is(tok::l_brace);
31 return Tok.isOneOf(TT_ClassLBrace, TT_EnumLBrace, TT_RecordLBrace,
32 TT_StructLBrace, TT_UnionLBrace);
44class LevelIndentTracker {
46 LevelIndentTracker(
const FormatStyle &Style,
47 const AdditionalKeywords &Keywords,
unsigned StartLevel,
49 : Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) {
50 for (
unsigned i = 0; i != StartLevel; ++i)
51 IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
55 unsigned getIndent()
const {
return Indent; }
59 void nextLine(
const AnnotatedLine &
Line) {
60 Offset = getIndentOffset(
Line);
63 if (
Line.Level >= IndentForLevel.size())
64 IndentForLevel.resize(
Line.Level + 1, -1);
65 if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave &&
67 Indent =
Line.InMacroBody
68 ? (
Line.Level -
Line.PPLevel) * Style.IndentWidth +
70 :
Line.First->OriginalColumn;
71 }
else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
72 (
Line.InPPDirective ||
73 (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
76 (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
77 Indent =
Line.InMacroBody
79 (
Line.Level -
Line.PPLevel) * Style.IndentWidth
81 Indent += AdditionalIndent;
86 if (!
Line.InPPDirective) {
87 assert(
Line.Level <= IndentForLevel.size());
88 IndentForLevel.resize(
Line.Level + 1);
90 Indent = getIndent(
Line.Level);
92 if (
static_cast<int>(Indent) + Offset >= 0)
94 if (
Line.IsContinuation)
95 Indent =
Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth;
103 void adjustToUnmodifiedLine(
const AnnotatedLine &
Line) {
104 if (
Line.InPPDirective ||
Line.IsContinuation)
106 assert(
Line.Level < IndentForLevel.size());
107 if (
Line.First->is(tok::comment) && IndentForLevel[
Line.Level] != -1)
109 unsigned LevelIndent =
Line.First->OriginalColumn;
110 if (
static_cast<int>(LevelIndent) - Offset >= 0)
111 LevelIndent -= Offset;
112 IndentForLevel[
Line.Level] = LevelIndent;
120 int getIndentOffset(
const AnnotatedLine &
Line) {
121 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
123 const auto &RootToken = *
Line.First;
125 RootToken.isAccessSpecifier(
false) ||
126 RootToken.isObjCAccessSpecifier() ||
127 (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
128 RootToken.Next && RootToken.Next->is(tok::colon))) {
132 return Style.IndentAccessModifiers ? -Style.IndentWidth
133 : Style.AccessModifierOffset;
143 unsigned getIndent(
unsigned Level)
const {
144 assert(Level < IndentForLevel.size());
145 if (IndentForLevel[Level] != -1)
146 return IndentForLevel[Level];
149 return getIndent(Level - 1) + Style.IndentWidth;
152 const FormatStyle &Style;
153 const AdditionalKeywords &Keywords;
154 const unsigned AdditionalIndent;
173getMatchingNamespaceToken(
const AnnotatedLine *
Line,
175 if (!
Line->startsWith(tok::r_brace))
177 size_t StartLineIndex =
Line->MatchingOpeningBlockLineIndex;
180 assert(StartLineIndex < AnnotatedLines.size());
181 return AnnotatedLines[StartLineIndex]->First->getNamespaceToken();
186 return NamespaceToken ? NamespaceToken->TokenText : StringRef();
190getMatchingNamespaceTokenText(
const AnnotatedLine *
Line,
193 getMatchingNamespaceToken(
Line, AnnotatedLines);
194 return NamespaceToken ? NamespaceToken->TokenText : StringRef();
199 LineJoiner(
const FormatStyle &Style,
const AdditionalKeywords &Keywords,
200 const SmallVectorImpl<AnnotatedLine *> &Lines)
201 : Style(Style), Keywords(Keywords), End(Lines.end()),
Next(Lines.begin()),
202 AnnotatedLines(Lines) {}
205 const AnnotatedLine *getNextMergedLine(
bool DryRun,
206 LevelIndentTracker &IndentTracker) {
209 const AnnotatedLine *Current = *
Next;
210 IndentTracker.nextLine(*Current);
211 unsigned MergedLines = tryFitMultipleLinesInOne(IndentTracker,
Next, End);
212 if (MergedLines > 0 && Style.ColumnLimit == 0) {
215 for (
unsigned i = 0; i < MergedLines; ++i)
216 if (
Next[i + 1]->
First->NewlinesBefore > 0)
220 for (
unsigned i = 0; i < MergedLines; ++i)
229 tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
236 const AnnotatedLine *TheLine = *I;
237 if (TheLine->Last->is(TT_LineComment))
239 const auto &NextLine = *I[1];
240 if (NextLine.Type ==
LT_Invalid || NextLine.First->MustBreakBefore)
242 if (TheLine->InPPDirective &&
243 (!NextLine.InPPDirective || NextLine.First->HasUnescapedNewline)) {
247 const auto Indent = IndentTracker.getIndent();
248 if (Style.ColumnLimit > 0 &&
Indent > Style.ColumnLimit)
255 Limit = TheLine->Last->TotalLength > Limit
257 : Limit - TheLine->Last->TotalLength;
259 if (TheLine->Last->is(TT_FunctionLBrace) &&
260 TheLine->First == TheLine->Last) {
261 const bool EmptyFunctionBody = NextLine.First->is(tok::r_brace);
262 if ((EmptyFunctionBody && !Style.BraceWrapping.SplitEmptyFunction) ||
263 (!EmptyFunctionBody &&
264 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always)) {
265 return tryMergeSimpleBlock(I, E, Limit);
269 const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] :
nullptr;
271 if (PreviousLine && TheLine->Last->is(tok::l_brace) &&
272 TheLine->First == TheLine->Last) {
273 bool EmptyBlock = NextLine.First->is(tok::r_brace);
276 if (
Tok &&
Tok->is(tok::comment))
277 Tok =
Tok->getNextNonComment();
279 if (
Tok &&
Tok->getNamespaceToken()) {
280 return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
281 ? tryMergeSimpleBlock(I, E, Limit)
285 if (
Tok &&
Tok->is(tok::kw_typedef))
286 Tok =
Tok->getNextNonComment();
287 if (
Tok &&
Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
288 tok::kw_extern, Keywords.kw_interface,
289 Keywords.kw_record)) {
290 return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
291 ? tryMergeSimpleBlock(I, E, Limit)
295 if (
Tok &&
Tok->is(tok::kw_template) &&
296 Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) {
301 auto ShouldMergeShortFunctions = [
this, &I, &NextLine, PreviousLine,
303 if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All)
305 if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
306 NextLine.First->is(tok::r_brace)) {
310 if (Style.AllowShortFunctionsOnASingleLine &
311 FormatStyle::SFS_InlineOnly) {
314 if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
317 if (TheLine->Level != 0) {
323 const AnnotatedLine *
Line =
nullptr;
324 for (
auto J = I - 1; J >= AnnotatedLines.begin(); --J) {
326 if (((*J)->InPPDirective && !(*J)->InMacroBody) ||
327 (*J)->isComment() || (*J)->Level > TheLine->Level) {
330 if ((*J)->Level < TheLine->Level ||
331 (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
332 (*J)->First->is(tok::l_brace))) {
342 const auto *LastNonComment =
Line->getLastNonComment();
345 assert(LastNonComment);
346 return isRecordLBrace(*LastNonComment);
353 bool MergeShortFunctions = ShouldMergeShortFunctions();
355 const auto *FirstNonComment = TheLine->getFirstNonComment();
356 if (!FirstNonComment)
362 if (Style.AllowShortNamespacesOnASingleLine &&
363 TheLine->First->is(tok::kw_namespace)) {
364 const auto result = tryMergeNamespace(I, E, Limit);
369 if (Style.CompactNamespaces) {
370 if (
const auto *NSToken = TheLine->First->getNamespaceToken()) {
372 assert(TheLine->MatchingClosingBlockLineIndex > 0);
373 for (
auto ClosingLineIndex = TheLine->MatchingClosingBlockLineIndex - 1;
375 ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
376 I[J]->
Last->TotalLength < Limit;
377 ++J, --ClosingLineIndex) {
378 Limit -= I[J]->Last->TotalLength + 1;
382 auto *ClosingLine = AnnotatedLines.begin() + ClosingLineIndex + 1;
383 const int OutdentBy = I[J]->Level - TheLine->Level;
384 assert(OutdentBy >= 0);
385 for (
auto *CompactedLine = I + J; CompactedLine <= ClosingLine;
387 if (!(*CompactedLine)->InPPDirective) {
388 const int Level = (*CompactedLine)->Level;
389 (*CompactedLine)->Level = std::max(Level - OutdentBy, 0);
396 if (
auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) {
398 unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
399 for (; I + 1 + i != E &&
400 nsToken->TokenText ==
401 getMatchingNamespaceTokenText(I[i + 1], AnnotatedLines) &&
402 openingLine == I[i + 1]->MatchingOpeningBlockLineIndex;
403 i++, --openingLine) {
405 I[i + 1]->First->SpacesRequiredBefore =
406 I[i]->Last->isNot(tok::r_brace);
409 IndentTracker.nextLine(*I[i + 1]);
415 const auto *LastNonComment = TheLine->getLastNonComment();
416 assert(LastNonComment);
421 if (LastNonComment->is(TT_FunctionLBrace) &&
422 TheLine->First != LastNonComment) {
423 return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
427 if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
428 (FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
430 TheLine->startsWithExportBlock())) {
431 return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never
432 ? tryMergeSimpleBlock(I, E, Limit)
436 if (NextLine.First->is(TT_ControlStatementLBrace)) {
440 return Style.BraceWrapping.AfterControlStatement ==
441 FormatStyle::BWACS_Always
442 ? tryMergeSimpleBlock(I, E, Limit)
445 if (PreviousLine && TheLine->First->is(tok::l_brace)) {
446 switch (PreviousLine->First->Tok.getKind()) {
449 if (PreviousLine->First->Next &&
450 PreviousLine->First->Next->isOneOf(tok::objc_autoreleasepool,
451 tok::objc_synchronized)) {
457 case tok::kw_default:
468 if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord &&
469 TheLine->Last->is(tok::l_brace) && PreviousLine->Last) {
475 if (
Previous->is(tok::greater) && !PreviousLine->InPPDirective)
477 if (
Previous->is(tok::identifier)) {
480 if (PreviousPrevious &&
481 PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct)) {
489 if (TheLine->First->is(TT_SwitchExpressionLabel)) {
490 return Style.AllowShortCaseExpressionOnASingleLine
491 ? tryMergeShortCaseLabels(I, E, Limit)
495 if (TheLine->Last->is(tok::l_brace)) {
496 bool ShouldMerge =
false;
498 if (TheLine->Last->is(TT_EnumLBrace)) {
499 ShouldMerge = Style.AllowShortEnumsOnASingleLine;
500 }
else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
501 ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
502 }
else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace,
507 ShouldMerge = !Style.BraceWrapping.AfterClass ||
508 (NextLine.First->is(tok::r_brace) &&
509 !Style.BraceWrapping.SplitEmptyRecord);
510 }
else if (TheLine->InPPDirective ||
511 TheLine->First->isNoneOf(tok::kw_class, tok::kw_enum,
512 tok::kw_struct, Keywords.kw_record)) {
515 ShouldMerge = !Style.BraceWrapping.AfterFunction ||
516 (NextLine.First->is(tok::r_brace) &&
517 !Style.BraceWrapping.SplitEmptyFunction);
519 return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit) : 0;
523 if (NextLine.First->is(TT_FunctionLBrace) &&
524 Style.BraceWrapping.AfterFunction) {
525 if (NextLine.Last->is(TT_LineComment))
529 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
533 unsigned MergedLines = 0;
534 if (MergeShortFunctions ||
535 (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
536 NextLine.First == NextLine.Last && I + 2 != E &&
537 I[2]->First->is(tok::r_brace))) {
538 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
546 auto IsElseLine = [&TheLine]() ->
bool {
548 if (
First->is(tok::kw_else))
551 return First->is(tok::r_brace) &&
First->Next &&
552 First->Next->is(tok::kw_else);
554 if (TheLine->First->is(tok::kw_if) ||
555 (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine ==
556 FormatStyle::SIS_AllIfsAndElse))) {
557 return Style.AllowShortIfStatementsOnASingleLine
558 ? tryMergeSimpleControlStatement(I, E, Limit)
561 if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do,
563 return Style.AllowShortLoopsOnASingleLine
564 ? tryMergeSimpleControlStatement(I, E, Limit)
567 if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) {
568 return Style.AllowShortCaseLabelsOnASingleLine
569 ? tryMergeShortCaseLabels(I, E, Limit)
572 if (TheLine->InPPDirective &&
573 (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
574 return tryMergeSimplePPDirective(I, E, Limit);
585 if (I + 2 != E && I[2]->InPPDirective && !I[2]->
First->HasUnescapedNewline)
587 if (1 + I[1]->
Last->TotalLength > Limit)
600 const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace;
601 const auto *BraceOpenLine = I + OpenBraceWrapped;
603 assert(*BraceOpenLine);
604 if (BraceOpenLine[0]->
Last->isNot(TT_NamespaceLBrace))
607 if (std::distance(BraceOpenLine, E) <= 2)
610 if (BraceOpenLine[0]->
Last->is(tok::comment))
613 assert(BraceOpenLine[1]);
614 const auto &L1 = *BraceOpenLine[1];
615 if (L1.InPPDirective != (*I)->InPPDirective ||
616 (L1.InPPDirective && L1.First->HasUnescapedNewline)) {
620 assert(BraceOpenLine[2]);
621 const auto &L2 = *BraceOpenLine[2];
625 Limit = limitConsideringMacros(I + 1, E, Limit);
627 const auto LinesToBeMerged = OpenBraceWrapped + 2;
628 if (!nextNLinesFitInto(I, I + LinesToBeMerged, Limit))
633 if (L1.First->is(tok::kw_namespace)) {
634 if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)
637 assert(Limit >= L1.Last->TotalLength + 3);
638 const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
639 const auto MergedLines =
640 tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit);
641 if (MergedLines == 0)
643 const auto N = MergedLines + LinesToBeMerged;
645 if (
auto Distance = std::distance(I, E);
646 static_cast<decltype(N)
>(Distance) <= N) {
651 if (I[N]->
First->is(TT_NamespaceRBrace) &&
652 !I[N]->First->MustBreakBefore &&
653 BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) &&
654 nextNLinesFitInto(I, I + N + 1, Limit)) {
664 if (L1.Last->isNot(tok::semi))
668 if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore)
672 return LinesToBeMerged;
681 if (Style.BraceWrapping.AfterControlStatement ==
682 FormatStyle::BWACS_Always &&
683 I[1]->First->is(tok::l_brace) &&
684 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
687 if (I[1]->InPPDirective != (*I)->InPPDirective ||
688 (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) {
691 Limit = limitConsideringMacros(I + 1, E, Limit);
692 AnnotatedLine &
Line = **I;
693 if (
Line.First->isNoneOf(tok::kw_do, tok::kw_else) &&
694 Line.Last->isNoneOf(tok::kw_else, tok::r_paren)) {
698 if (
Line.First->is(tok::kw_do) &&
Line.Last->isNot(tok::kw_do))
700 if (1 + I[1]->
Last->TotalLength > Limit)
703 if (I[1]->
First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,
704 TT_ForEachMacro, TT_LineComment)) {
708 if (Style.AllowShortIfStatementsOnASingleLine ==
709 FormatStyle::SIS_WithoutElse) {
710 if (I + 2 != E &&
Line.startsWith(tok::kw_if) &&
711 I[2]->First->is(tok::kw_else)) {
721 if (Limit == 0 || I + 1 == E ||
722 I[1]->
First->isOneOf(tok::kw_case, tok::kw_default)) {
725 if (I[0]->
Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))
727 unsigned NumStmts = 0;
729 bool EndsWithComment =
false;
730 bool InPPDirective = I[0]->InPPDirective;
731 bool InMacroBody = I[0]->InMacroBody;
732 const unsigned Level = I[0]->Level;
733 for (; NumStmts < 3; ++NumStmts) {
734 if (I + 1 + NumStmts == E)
736 const AnnotatedLine *
Line = I[1 + NumStmts];
737 if (
Line->InPPDirective != InPPDirective)
739 if (
Line->InMacroBody != InMacroBody)
741 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
743 if (
Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
748 if (
Line->First->is(tok::comment)) {
749 if (Level !=
Line->Level)
751 const auto *J = I + 2 + NumStmts;
752 for (; J != E; ++J) {
754 if (
Line->InPPDirective != InPPDirective)
756 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
758 if (
Line->First->isNot(tok::comment) || Level !=
Line->Level)
763 if (
Line->Last->is(tok::comment))
764 EndsWithComment =
true;
765 Length += I[1 + NumStmts]->Last->TotalLength + 1;
767 if (NumStmts == 0 || NumStmts == 3 || Length > Limit)
779 AnnotatedLine &
Line = **I;
784 if (!Style.isJava() &&
Line.First->isOneOf(tok::at, tok::minus, tok::plus))
789 if (
Line.First->is(tok::kw_case) ||
790 (
Line.First->Next &&
Line.First->Next->is(tok::kw_else))) {
794 if (
Line.First->is(tok::kw_default)) {
796 if (
Tok &&
Tok->is(tok::colon))
800 auto IsCtrlStmt = [](
const auto &
Line) {
801 return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
802 tok::kw_do, tok::kw_for, TT_ForEachMacro);
805 const bool IsSplitBlock =
806 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never ||
807 (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty &&
808 I[1]->First->isNot(tok::r_brace));
810 if (IsCtrlStmt(
Line) ||
811 Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
812 tok::kw___finally, tok::r_brace,
813 Keywords.kw___except) ||
814 Line.startsWithExportBlock()) {
819 if (!Style.AllowShortIfStatementsOnASingleLine &&
820 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
821 !Style.BraceWrapping.AfterControlStatement &&
822 I[1]->First->isNot(tok::r_brace)) {
825 if (!Style.AllowShortIfStatementsOnASingleLine &&
826 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
827 Style.BraceWrapping.AfterControlStatement ==
828 FormatStyle::BWACS_Always &&
829 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
832 if (!Style.AllowShortLoopsOnASingleLine &&
833 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
835 !Style.BraceWrapping.AfterControlStatement &&
836 I[1]->First->isNot(tok::r_brace)) {
839 if (!Style.AllowShortLoopsOnASingleLine &&
840 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
842 Style.BraceWrapping.AfterControlStatement ==
843 FormatStyle::BWACS_Always &&
844 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
852 if (
Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
853 Keywords.kw___except, tok::kw___finally)) {
858 if (
Line.endsWith(tok::l_brace)) {
859 if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never &&
860 Line.First->is(TT_BlockLBrace)) {
864 if (IsSplitBlock &&
Line.First ==
Line.Last &&
865 I > AnnotatedLines.begin() &&
866 (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {
870 auto ShouldMerge = [
Tok]() {
871 if (
Tok->isNot(tok::r_brace) ||
Tok->MustBreakBefore)
874 return !
Next ||
Next->is(tok::semi);
879 Tok->SpacesRequiredBefore =
880 Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never ||
881 Line.Last->is(tok::comment);
882 Tok->CanBreakBefore =
true;
884 }
else if (Limit != 0 && !
Line.startsWithNamespace() &&
885 !startsExternCBlock(
Line)) {
887 if (isRecordLBrace(*
Line.Last))
893 Limit = limitConsideringMacros(I + 2, E, Limit);
895 if (!nextTwoLinesFitInto(I, Limit))
900 if (I[1]->
Last->is(TT_LineComment))
910 if (
Tok->isNot(tok::r_brace))
914 if (
Tok->Next &&
Tok->Next->is(tok::kw_else))
924 Line.First->is(TT_ControlStatementLBrace) &&
925 Style.BraceWrapping.AfterControlStatement ==
926 FormatStyle::BWACS_MultiLine) {
932 }
else if (I[1]->
First->is(tok::l_brace)) {
933 if (I[1]->
Last->is(TT_LineComment))
937 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))
940 unsigned MergedLines = 0;
941 if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never ||
942 (I[1]->First == I[1]->Last && I + 2 != E &&
943 I[2]->First->is(tok::r_brace))) {
944 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
960 if (I[0]->InPPDirective && I + 1 != E &&
961 !I[1]->
First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {
962 return Limit < 2 ? 0 : Limit - 2;
969 if (I[1]->
First->MustBreakBefore || I[2]->First->MustBreakBefore)
971 return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
977 unsigned JoinedLength = 0;
978 for (
const auto *J = I + 1; J != E; ++J) {
979 if ((*J)->First->MustBreakBefore)
982 JoinedLength += 1 + (*J)->Last->TotalLength;
983 if (JoinedLength > Limit)
989 bool containsMustBreak(
const AnnotatedLine *
Line) {
994 if (
Tok->MustBreakBefore)
999 void join(AnnotatedLine &A,
const AnnotatedLine &B) {
1000 assert(!A.Last->Next);
1001 assert(!B.First->Previous);
1002 if (B.Affected || B.LeadingEmptyLinesAffected) {
1003 assert(B.Affected || A.Last->Children.empty());
1006 A.Last->Next = B.First;
1007 B.First->Previous = A.Last;
1008 B.First->CanBreakBefore =
true;
1009 unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
1011 Tok->TotalLength += LengthA;
1016 const FormatStyle &Style;
1017 const AdditionalKeywords &Keywords;
1021 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
1025 if (
Tok->is(tok::hash) && !
Tok->Previous &&
Tok->Next &&
1026 Tok->Next->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef,
1027 tok::pp_elif, tok::pp_elifdef, tok::pp_elifndef,
1028 tok::pp_else, tok::pp_endif)) {
1044 Tok->SpacesRequiredBefore = 0;
1045 if (!
Tok->MustBreakBeforeFinalized)
1046 Tok->MustBreakBefore = 0;
1048 Tok->Finalized =
true;
1054static void printLineState(
const LineState &State) {
1055 llvm::dbgs() <<
"State: ";
1056 for (
const ParenState &P : State.Stack) {
1057 llvm::dbgs() << (P.Tok ? P.Tok->TokenText :
"F") <<
"|" << P.Indent.Total
1058 <<
"|" << P.LastSpace <<
"|" << P.NestedBlockIndent <<
" ";
1060 llvm::dbgs() << State.NextToken->TokenText <<
"\n";
1065class LineFormatter {
1067 LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
1068 const FormatStyle &Style,
1069 UnwrappedLineFormatter *BlockFormatter)
1070 : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
1071 BlockFormatter(BlockFormatter) {}
1072 virtual ~LineFormatter() {}
1077 virtual unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1078 unsigned FirstStartColumn,
bool DryRun) = 0;
1101 bool formatChildren(LineState &State,
bool NewLine,
bool DryRun,
1102 unsigned &Penalty) {
1103 const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
1104 bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(
BK_Block);
1106 if (
Previous.Children.empty() || (!HasLBrace && !LBrace->MacroParent)) {
1112 if (NewLine ||
Previous.MacroParent) {
1113 const ParenState &P = State.Stack.back();
1115 int AdditionalIndent =
1116 P.Indent.Total -
Previous.Children[0]->Level * Style.IndentWidth;
1118 BlockFormatter->format(
Previous.Children, DryRun, AdditionalIndent,
1123 if (
Previous.Children[0]->First->MustBreakBefore)
1134 const AnnotatedLine *Child =
Previous.Children[0];
1136 if (Child->Last->isTrailingComment())
1141 if (Style.ColumnLimit > 0 &&
1142 Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit) {
1147 Whitespaces->replaceWhitespace(
1148 *Child->First, 0, 1,
1149 State.Column,
false,
1150 State.Line->InPPDirective);
1153 formatLine(*Child, State.Column + 1, 0, DryRun);
1155 markFinalized(Child->First);
1157 State.Column += 1 + Child->Last->TotalLength;
1161 ContinuationIndenter *Indenter;
1164 WhitespaceManager *Whitespaces;
1165 const FormatStyle &Style;
1166 UnwrappedLineFormatter *BlockFormatter;
1170class NoColumnLimitLineFormatter :
public LineFormatter {
1172 NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
1173 WhitespaceManager *Whitespaces,
1174 const FormatStyle &Style,
1175 UnwrappedLineFormatter *BlockFormatter)
1176 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1180 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1181 unsigned FirstStartColumn,
bool DryRun)
override {
1183 LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
1185 while (State.NextToken) {
1187 Indenter->mustBreak(State) ||
1188 (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
1189 unsigned Penalty = 0;
1190 formatChildren(State, Newline,
false, Penalty);
1191 Indenter->addTokenToState(State, Newline,
false);
1198class NoLineBreakFormatter :
public LineFormatter {
1200 NoLineBreakFormatter(ContinuationIndenter *Indenter,
1201 WhitespaceManager *Whitespaces,
const FormatStyle &Style,
1202 UnwrappedLineFormatter *BlockFormatter)
1203 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1206 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1207 unsigned FirstStartColumn,
bool DryRun)
override {
1208 unsigned Penalty = 0;
1210 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1211 while (State.NextToken) {
1212 formatChildren(State,
false, DryRun, Penalty);
1213 Indenter->addTokenToState(
1214 State, State.NextToken->MustBreakBefore, DryRun);
1221class OptimizingLineFormatter :
public LineFormatter {
1223 OptimizingLineFormatter(ContinuationIndenter *Indenter,
1224 WhitespaceManager *Whitespaces,
1225 const FormatStyle &Style,
1226 UnwrappedLineFormatter *BlockFormatter)
1227 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1231 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1232 unsigned FirstStartColumn,
bool DryRun)
override {
1234 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1239 State.Stack.back().BreakBeforeParameter =
true;
1242 return analyzeSolutionSpace(State, DryRun);
1246 struct CompareLineStatePointers {
1247 bool operator()(LineState *obj1, LineState *obj2)
const {
1248 return *obj1 < *obj2;
1257 typedef std::pair<unsigned, unsigned> OrderedPenalty;
1262 StateNode(
const LineState &State,
bool NewLine, StateNode *
Previous)
1271 typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
1274 typedef std::priority_queue<QueueItem, SmallVector<QueueItem>,
1275 std::greater<QueueItem>>
1286 unsigned analyzeSolutionSpace(LineState &InitialState,
bool DryRun) {
1287 std::set<LineState *, CompareLineStatePointers> Seen;
1295 StateNode *RootNode =
1296 new (Allocator.Allocate()) StateNode(InitialState,
false,
nullptr);
1297 Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode));
1300 unsigned Penalty = 0;
1303 while (!Queue.empty()) {
1305 if (Count > 25'000'000)
1308 Penalty = Queue.top().first.first;
1309 StateNode *Node = Queue.top().second;
1310 if (!Node->State.NextToken) {
1311 LLVM_DEBUG(llvm::dbgs()
1312 <<
"\n---\nPenalty for line: " << Penalty <<
"\n");
1320 Node->State.IgnoreStackForComparison =
true;
1322 if (!Seen.insert(&Node->State).second) {
1327 FormatDecision LastFormat = Node->State.NextToken->getDecision();
1329 addNextStateToQueue(Penalty, Node,
false, &Count, &Queue);
1331 addNextStateToQueue(Penalty, Node,
true, &Count, &Queue);
1334 if (Queue.empty()) {
1337 LLVM_DEBUG(llvm::dbgs() <<
"Could not find a solution.\n");
1343 reconstructPath(InitialState, Queue.top().second);
1345 LLVM_DEBUG(llvm::dbgs()
1346 <<
"Total number of analyzed states: " << Count <<
"\n");
1347 LLVM_DEBUG(llvm::dbgs() <<
"---\n");
1356 void addNextStateToQueue(
unsigned Penalty, StateNode *PreviousNode,
1357 bool NewLine,
unsigned *Count, QueueType *Queue) {
1358 if (NewLine && !Indenter->canBreak(PreviousNode->State))
1360 if (!NewLine && Indenter->mustBreak(PreviousNode->State))
1363 StateNode *Node =
new (Allocator.Allocate())
1364 StateNode(PreviousNode->State, NewLine, PreviousNode);
1365 if (!formatChildren(Node->State, NewLine,
true, Penalty))
1368 Penalty += Indenter->addTokenToState(Node->State, NewLine,
true);
1370 Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
1376 void reconstructPath(LineState &State, StateNode *Best) {
1379 while (Best->Previous) {
1380 Path.push_back(Best);
1381 Best = Best->Previous;
1383 for (
const auto &Node : llvm::reverse(Path)) {
1384 unsigned Penalty = 0;
1385 formatChildren(State, Node->NewLine,
false, Penalty);
1386 Penalty += Indenter->addTokenToState(State, Node->NewLine,
false);
1389 printLineState(Node->Previous->State);
1390 if (Node->NewLine) {
1391 llvm::dbgs() <<
"Penalty for placing "
1392 << Node->Previous->State.NextToken->Tok.getName()
1393 <<
" on a new line: " << Penalty <<
"\n";
1399 llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
1406 int AdditionalIndent,
bool FixBadIndentation,
unsigned FirstStartColumn,
1407 unsigned NextStartColumn,
unsigned LastStartColumn) {
1408 LineJoiner Joiner(Style, Keywords, Lines);
1411 std::pair<const SmallVectorImpl<AnnotatedLine *> *,
unsigned> CacheKey(
1412 &Lines, AdditionalIndent);
1413 auto CacheIt = PenaltyCache.find(CacheKey);
1414 if (DryRun && CacheIt != PenaltyCache.end())
1415 return CacheIt->second;
1417 assert(!Lines.empty());
1418 unsigned Penalty = 0;
1419 LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
1428 bool FirstLine =
true;
1430 Joiner.getNextMergedLine(DryRun, IndentTracker);
1431 Line; PrevPrevLine = PreviousLine, PreviousLine =
Line,
Line = NextLine,
1432 FirstLine =
false) {
1433 assert(
Line->First);
1435 unsigned Indent = IndentTracker.getIndent();
1441 bool PreviousRBrace =
1442 PreviousLine && PreviousLine->
startsWith(tok::r_brace);
1443 bool ContinueFormatting =
1444 TheLine.
Level > RangeMinLevel ||
1445 (TheLine.
Level == RangeMinLevel && !PreviousRBrace &&
1448 bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
1450 bool ShouldFormat = TheLine.
Affected || FixIndentation;
1454 Status->FormatComplete =
false;
1461 bool LastLine = TheLine.
First->
is(tok::eof);
1462 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
Indent,
1463 LastLine ? LastStartColumn : NextStartColumn +
Indent);
1466 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1467 unsigned ColumnLimit = getColumnLimit(TheLine.
InPPDirective, NextLine);
1468 bool FitsIntoOneLine =
1472 (!Style.isJavaScript() || !Style.JavaScriptWrapImports)) ||
1473 (Style.isCSharp() &&
1475 if (Style.ColumnLimit == 0) {
1476 NoColumnLimitLineFormatter(Indenter, Whitespaces, Style,
this)
1477 .formatLine(TheLine, NextStartColumn +
Indent,
1478 FirstLine ? FirstStartColumn : 0, DryRun);
1479 }
else if (FitsIntoOneLine) {
1480 Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style,
this)
1481 .formatLine(TheLine, NextStartColumn +
Indent,
1482 FirstLine ? FirstStartColumn : 0, DryRun);
1484 Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style,
this)
1485 .formatLine(TheLine, NextStartColumn +
Indent,
1486 FirstLine ? FirstStartColumn : 0, DryRun);
1488 RangeMinLevel = std::min(RangeMinLevel, TheLine.
Level);
1494 if (!
Tok->Children.empty())
1500 bool StartsNewLine =
1503 IndentTracker.adjustToUnmodifiedLine(TheLine);
1505 bool ReformatLeadingWhitespace =
1506 StartsNewLine && ((PreviousLine && PreviousLine->
Affected) ||
1509 if (ReformatLeadingWhitespace) {
1510 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
1514 Whitespaces->addUntouchableToken(*TheLine.
First,
1522 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1526 markFinalized(TheLine.
First);
1528 PenaltyCache[CacheKey] = Penalty;
1536 const FormatStyle &Style) {
1537 const auto &RootToken = *
Line.First;
1539 std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
1541 if (RootToken.is(tok::r_brace) &&
1543 (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&
1549 if (!PreviousLine &&
Line.Level > 0)
1551 if (
Newlines == 0 && !RootToken.IsFirst)
1553 if (RootToken.IsFirst &&
1554 (!Style.KeepEmptyLines.AtStartOfFile || !RootToken.HasUnescapedNewline)) {
1559 if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine &&
1560 PreviousLine->
Last->
is(tok::l_brace) &&
1564 !startsExternCBlock(*PreviousLine)) {
1568 if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) {
1570 if (PreviousLine && PreviousLine->
endsWith(TT_NamespaceLBrace)) {
1571 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1573 else if (!
Line.startsWithNamespace())
1577 if (
Line.startsWith(TT_NamespaceRBrace)) {
1578 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1580 else if (!PreviousLine->
startsWith(TT_NamespaceRBrace))
1586 if (PreviousLine && RootToken.isAccessSpecifier()) {
1587 switch (Style.EmptyLineBeforeAccessModifier) {
1588 case FormatStyle::ELBAMS_Never:
1592 case FormatStyle::ELBAMS_Leave:
1593 Newlines = std::max(RootToken.NewlinesBefore, 1u);
1595 case FormatStyle::ELBAMS_LogicalBlock:
1598 if (PreviousLine->
First->isAccessSpecifier())
1601 case FormatStyle::ELBAMS_Always: {
1603 if (PreviousLine->
Last->
is(tok::comment))
1604 previousToken = PreviousLine->
Last->getPreviousNonComment();
1606 previousToken = PreviousLine->
Last;
1607 if ((!previousToken || previousToken->
isNot(tok::l_brace)) &&
1616 if (PreviousLine && PreviousLine->
First->isAccessSpecifier() &&
1617 (!PreviousLine->
InPPDirective || !RootToken.HasUnescapedNewline)) {
1620 if (!RootToken.isAccessSpecifier()) {
1621 switch (Style.EmptyLineAfterAccessModifier) {
1622 case FormatStyle::ELAAMS_Never:
1625 case FormatStyle::ELAAMS_Leave:
1628 case FormatStyle::ELAAMS_Always:
1629 if (RootToken.is(tok::r_brace))
1641void UnwrappedLineFormatter::formatFirstToken(
1642 const AnnotatedLine &
Line,
const AnnotatedLine *PreviousLine,
1643 const AnnotatedLine *PrevPrevLine,
1645 unsigned NewlineIndent) {
1647 if (RootToken.is(tok::eof)) {
1649 RootToken.NewlinesBefore,
1650 Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);
1651 unsigned TokenIndent =
Newlines ? NewlineIndent : 0;
1657 if (RootToken.Newlines < 0) {
1658 RootToken.Newlines =
1660 assert(RootToken.Newlines >= 0);
1663 if (RootToken.Newlines > 0)
1668 if (!Style.isJavaScript() &&
1669 Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash &&
1675 Whitespaces->replaceWhitespace(RootToken, RootToken.Newlines,
Indent,
Indent,
1677 Line.InPPDirective &&
1678 !RootToken.HasUnescapedNewline);
1682UnwrappedLineFormatter::getColumnLimit(
bool InPPDirective,
1686 bool ContinuesPPDirective =
1691 (NextLine->InPPDirective &&
1694 !NextLine->First->HasUnescapedNewline));
1695 return Style.ColumnLimit - (ContinuesPPDirective ? 2 : 0);
WhitespaceManager class manages whitespace around tokens and their replacements.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
The JSON file list parser is used to communicate input to InstallAPI.
int PPIndentWidth
The number of columns to use for indentation of preprocessor statements. When set to -1 (default) Ind...
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)