12#include "llvm/Support/Debug.h"
15#define DEBUG_TYPE "format-formatter"
22bool startsExternCBlock(
const AnnotatedLine &
Line) {
25 return Line.startsWith(tok::kw_extern) &&
Next &&
Next->isStringLiteral() &&
26 NextNext && NextNext->is(tok::l_brace);
30 return Tok.isOneOf(TT_ClassLBrace, TT_EnumLBrace, TT_RecordLBrace,
31 TT_StructLBrace, TT_UnionLBrace);
43class LevelIndentTracker {
46 const AdditionalKeywords &Keywords,
unsigned StartLevel,
48 : Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) {
49 for (
unsigned i = 0; i != StartLevel; ++i)
50 IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
54 unsigned getIndent()
const {
return Indent; }
58 void nextLine(
const AnnotatedLine &
Line) {
59 Offset = getIndentOffset(
Line);
62 if (
Line.Level >= IndentForLevel.size())
63 IndentForLevel.resize(
Line.Level + 1, -1);
66 Indent =
Line.InMacroBody
67 ? (
Line.Level -
Line.PPLevel) * Style.IndentWidth +
69 :
Line.First->OriginalColumn;
71 (
Line.InPPDirective ||
74 unsigned PPIndentWidth =
75 (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
76 Indent =
Line.InMacroBody
77 ?
Line.PPLevel * PPIndentWidth +
78 (
Line.Level -
Line.PPLevel) * Style.IndentWidth
79 :
Line.Level * PPIndentWidth;
80 Indent += AdditionalIndent;
85 if (!
Line.InPPDirective) {
86 assert(
Line.Level <= IndentForLevel.size());
87 IndentForLevel.resize(
Line.Level + 1);
89 Indent = getIndent(
Line.Level);
91 if (
static_cast<int>(Indent) + Offset >= 0)
93 if (
Line.IsContinuation)
94 Indent =
Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth;
102 void adjustToUnmodifiedLine(
const AnnotatedLine &
Line) {
103 if (
Line.InPPDirective ||
Line.IsContinuation)
105 assert(
Line.Level < IndentForLevel.size());
106 if (
Line.First->is(tok::comment) && IndentForLevel[
Line.Level] != -1)
108 unsigned LevelIndent =
Line.First->OriginalColumn;
109 if (
static_cast<int>(LevelIndent) - Offset >= 0)
110 LevelIndent -= Offset;
111 IndentForLevel[
Line.Level] = LevelIndent;
119 int getIndentOffset(
const AnnotatedLine &
Line) {
120 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
123 const auto &RootToken = *
Line.First;
126 RootToken.Next && RootToken.Next->is(TT_GotoLabelColon)) {
127 return -
static_cast<int>(Style.IndentWidth / 2);
131 RootToken.isAccessSpecifier(
false) ||
132 RootToken.isObjCAccessSpecifier() ||
133 (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
134 RootToken.Next && RootToken.Next->is(tok::colon))) {
140 : Style.AccessModifierOffset;
150 unsigned getIndent(
unsigned Level)
const {
151 assert(Level < IndentForLevel.size());
152 if (IndentForLevel[Level] != -1)
153 return IndentForLevel[Level];
156 return getIndent(Level - 1) + Style.IndentWidth;
160 const AdditionalKeywords &Keywords;
161 const unsigned AdditionalIndent;
180getMatchingNamespaceToken(
const AnnotatedLine *
Line,
182 if (!
Line->startsWith(tok::r_brace))
184 size_t StartLineIndex =
Line->MatchingOpeningBlockLineIndex;
187 assert(StartLineIndex < AnnotatedLines.size());
188 return AnnotatedLines[StartLineIndex]->First->getNamespaceToken();
193 return NamespaceToken ? NamespaceToken->TokenText : StringRef();
197getMatchingNamespaceTokenText(
const AnnotatedLine *
Line,
200 getMatchingNamespaceToken(
Line, AnnotatedLines);
201 return NamespaceToken ? NamespaceToken->TokenText : StringRef();
206 LineJoiner(
const FormatStyle &Style,
const AdditionalKeywords &Keywords,
207 const SmallVectorImpl<AnnotatedLine *> &Lines)
208 : Style(Style), Keywords(Keywords), End(Lines.end()),
Next(Lines.begin()),
209 AnnotatedLines(Lines) {}
212 const AnnotatedLine *getNextMergedLine(
bool DryRun,
213 LevelIndentTracker &IndentTracker) {
216 const AnnotatedLine *Current = *
Next;
217 IndentTracker.nextLine(*Current);
218 unsigned MergedLines =
219 Current->InMacroExpansion
221 : tryFitMultipleLinesInOne(IndentTracker,
Next, End);
222 if (MergedLines > 0 && Style.ColumnLimit == 0) {
225 for (
unsigned i = 0; i < MergedLines; ++i)
226 if (
Next[i + 1]->
First->NewlinesBefore > 0)
229 if (MergedLines > 0) {
230 bool MergingEmptyBlock = MergedLines == 1 &&
231 Next[0]->endsWith(tok::l_brace) &&
232 Next[1]->startsWith(tok::r_brace);
233 for (
unsigned i = 0; i <= MergedLines; ++i) {
234 if (cannotMergeMacroLine(
Next[i],
236 MergingEmptyBlock)) {
243 for (
unsigned i = 0; i < MergedLines; ++i)
252 tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
259 const AnnotatedLine *TheLine = *I;
260 if (TheLine->Last->is(TT_LineComment))
262 const auto &NextLine = *I[1];
263 if (NextLine.Type ==
LT_Invalid || NextLine.First->MustBreakBefore)
265 if (TheLine->InPPDirective &&
266 (!NextLine.InPPDirective || NextLine.First->HasUnescapedNewline)) {
270 const auto Indent = IndentTracker.getIndent();
271 if (Style.ColumnLimit > 0 &&
Indent > Style.ColumnLimit)
278 Limit = TheLine->Last->TotalLength > Limit
280 : Limit - TheLine->Last->TotalLength;
282 if (TheLine->Last->is(TT_FunctionLBrace) &&
283 TheLine->First == TheLine->Last) {
284 const bool EmptyFunctionBody = NextLine.First->is(tok::r_brace);
285 if ((EmptyFunctionBody && !Style.BraceWrapping.SplitEmptyFunction) ||
286 (!EmptyFunctionBody &&
288 return tryMergeSimpleBlock(I, E, Limit);
294 if (NextLine.First->isOneOf(TT_ClassLBrace, TT_StructLBrace,
296 if (
unsigned MergedLines = tryMergeRecord(I, E, Limit))
302 if (Style.CompactCaseLabels &&
303 NextLine.First->isOneOf(tok::kw_case, tok::kw_default) &&
304 TheLine->Level <= NextLine.Level + 1 &&
305 canJoinWithCaseLabel(TheLine, *NextLine.First)) {
306 IndentTracker.nextLine(NextLine);
307 unsigned MergedLinesInCaseBody =
308 Style.AllowShortCaseLabelsOnASingleLine
309 ? tryMergeShortCaseLabels(I + 1, E, Limit)
311 return 1 + MergedLinesInCaseBody;
314 const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] :
nullptr;
317 if (PreviousLine && TheLine->Last->is(tok::l_brace) &&
318 TheLine->First == TheLine->Last) {
319 const bool EmptyBlock = NextLine.First->is(tok::r_brace);
323 if (
Tok &&
Tok->getNamespaceToken()) {
324 return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
325 ? tryMergeSimpleBlock(I, E, Limit)
329 if (
Tok &&
Tok->is(tok::kw_typedef))
330 Tok =
Tok->getNextNonComment();
332 if (
Tok &&
Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union))
333 return tryMergeRecord(I, E, Limit);
335 if (
Tok &&
Tok->isOneOf(tok::kw_extern, Keywords.kw_interface)) {
336 return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
337 ? tryMergeSimpleBlock(I, E, Limit)
341 if (
Tok &&
Tok->is(tok::kw_template) &&
342 Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) {
347 auto ShouldMergeShortFunctions = [&] {
348 if (Style.AllowShortFunctionsOnASingleLine.isAll())
351 if (Style.AllowShortFunctionsOnASingleLine.Empty &&
352 NextLine.First->is(tok::r_brace)) {
356 if (Style.AllowShortFunctionsOnASingleLine.Inline &&
357 !Style.AllowShortFunctionsOnASingleLine.Other) {
358 if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
363 if (
const auto Level = TheLine->Level; Level > 0) {
369 const AnnotatedLine *
Line =
nullptr;
370 for (
auto J = I - 1; J >= AnnotatedLines.begin(); --J) {
373 if (TheLine->InMacroBody && !L->InMacroBody)
375 if (L->isComment() || (!TheLine->InPPDirective && L->InPPDirective))
377 if (L->Level < Level ||
378 (L->Level == Level && L->First->is(tok::l_brace) &&
389 const auto *LastNonComment =
Line->getLastNonComment();
392 assert(LastNonComment);
393 return isRecordLBrace(*LastNonComment);
400 bool MergeShortFunctions = ShouldMergeShortFunctions();
402 const auto *FirstNonComment = TheLine->getFirstNonComment();
403 if (!FirstNonComment)
409 if (Style.AllowShortNamespacesOnASingleLine &&
410 TheLine->First->is(tok::kw_namespace)) {
411 const auto result = tryMergeNamespace(I, E, Limit);
416 if (Style.CompactNamespaces) {
417 if (
const auto *NSToken = TheLine->First->getNamespaceToken()) {
419 assert(TheLine->MatchingClosingBlockLineIndex > 0);
420 for (
auto ClosingLineIndex = TheLine->MatchingClosingBlockLineIndex - 1;
422 ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
423 I[J]->
Last->TotalLength < Limit;
424 ++J, --ClosingLineIndex) {
425 Limit -= I[J]->Last->TotalLength + 1;
429 auto *ClosingLine = AnnotatedLines.begin() + ClosingLineIndex + 1;
430 const int OutdentBy = I[J]->Level - TheLine->Level;
431 assert(OutdentBy >= 0);
432 for (
auto *CompactedLine = I + J; CompactedLine <= ClosingLine;
434 if (!(*CompactedLine)->InPPDirective) {
435 const int Level = (*CompactedLine)->Level;
436 (*CompactedLine)->Level = std::max(Level - OutdentBy, 0);
443 if (
auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) {
445 unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
446 for (; I + 1 + i != E &&
447 nsToken->TokenText ==
448 getMatchingNamespaceTokenText(I[i + 1], AnnotatedLines) &&
449 openingLine == I[i + 1]->MatchingOpeningBlockLineIndex;
450 i++, --openingLine) {
452 I[i + 1]->First->SpacesRequiredBefore =
453 I[i]->Last->isNot(tok::r_brace);
456 IndentTracker.nextLine(*I[i + 1]);
462 const auto *LastNonComment = TheLine->getLastNonComment();
463 assert(LastNonComment);
468 if (LastNonComment->is(TT_FunctionLBrace) &&
469 TheLine->First != LastNonComment) {
470 return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
474 if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
475 (FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
477 (TheLine->Last->is(TT_ExportLBrace) &&
478 !Style.BraceWrapping.AfterExportBlock))) {
480 ? tryMergeSimpleBlock(I, E, Limit)
484 if (NextLine.First->is(TT_ControlStatementLBrace)) {
488 return Style.BraceWrapping.AfterControlStatement ==
490 ? tryMergeSimpleBlock(I, E, Limit)
493 if (PreviousLine && TheLine->First->is(tok::l_brace)) {
494 switch (PreviousLine->First->Tok.getKind()) {
497 if (PreviousLine->First->Next &&
498 PreviousLine->First->Next->isOneOf(tok::objc_autoreleasepool,
499 tok::objc_synchronized)) {
505 case tok::kw_default:
516 if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord &&
517 TheLine->Last->is(tok::l_brace) && PreviousLine->Last) {
523 if (
Previous->is(tok::greater) && !PreviousLine->InPPDirective)
525 if (
Previous->is(tok::identifier)) {
528 if (PreviousPrevious &&
529 PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct,
538 if (TheLine->First->is(TT_SwitchExpressionLabel)) {
539 return Style.AllowShortCaseExpressionOnASingleLine
540 ? tryMergeShortCaseLabels(I, E, Limit)
544 if (TheLine->Last->is(tok::l_brace)) {
545 bool ShouldMerge =
false;
547 if (TheLine->Last->is(TT_EnumLBrace)) {
548 ShouldMerge = Style.AllowShortEnumsOnASingleLine;
549 }
else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
550 ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
551 }
else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace,
553 return tryMergeRecord(I, E, Limit);
554 }
else if (TheLine->Last->is(TT_RecordLBrace) && Style.isJava()) {
557 ShouldMerge = !Style.BraceWrapping.AfterClass ||
558 (NextLine.First->is(tok::r_brace) &&
559 !Style.BraceWrapping.SplitEmptyRecord);
560 }
else if (TheLine->InPPDirective ||
561 TheLine->First->isNoneOf(tok::kw_class, tok::kw_enum,
562 tok::kw_struct, tok::kw_union)) {
565 ShouldMerge = !Style.BraceWrapping.AfterFunction ||
566 (NextLine.First->is(tok::r_brace) &&
567 !Style.BraceWrapping.SplitEmptyFunction);
569 return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit) : 0;
573 if (NextLine.First->is(TT_FunctionLBrace) &&
574 Style.BraceWrapping.AfterFunction) {
575 if (NextLine.Last->is(TT_LineComment))
579 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
583 unsigned MergedLines = 0;
584 if (MergeShortFunctions ||
585 (Style.AllowShortFunctionsOnASingleLine.Empty &&
586 NextLine.First == NextLine.Last && I + 2 != E &&
587 I[2]->First->is(tok::r_brace))) {
588 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
596 auto IsElseLine = [&TheLine]() ->
bool {
598 if (
First->is(tok::kw_else))
601 return First->is(tok::r_brace) &&
First->Next &&
602 First->Next->is(tok::kw_else);
604 if (TheLine->First->is(tok::kw_if) ||
605 (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine ==
607 return Style.AllowShortIfStatementsOnASingleLine
608 ? tryMergeSimpleControlStatement(I, E, Limit)
611 if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do,
613 return Style.AllowShortLoopsOnASingleLine
614 ? tryMergeSimpleControlStatement(I, E, Limit)
617 if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) {
618 return Style.AllowShortCaseLabelsOnASingleLine
619 ? tryMergeShortCaseLabels(I, E, Limit)
622 if (TheLine->InPPDirective &&
623 (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
624 return tryMergeSimplePPDirective(I, E, Limit);
632 const auto *
Line = I[0];
633 const auto *NextLine = I[1];
636 if (
Line->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace, TT_UnionLBrace)) {
637 auto ShouldWrapLBrace = [&](TokenType LBraceType) {
638 switch (LBraceType) {
640 return Style.BraceWrapping.AfterClass;
641 case TT_StructLBrace:
642 return Style.BraceWrapping.AfterStruct;
644 return Style.BraceWrapping.AfterUnion;
650 auto TryMergeShortRecord = [&] {
651 switch (Style.AllowShortRecordOnASingleLine) {
657 return NextLine->First->is(tok::r_brace);
662 (!ShouldWrapLBrace(
Line->Last->getType()) ||
663 (!Style.BraceWrapping.SplitEmptyRecord && TryMergeShortRecord()))) {
664 return tryMergeSimpleBlock(I, E, Limit);
670 if (NextLine->First->isOneOf(TT_ClassLBrace, TT_StructLBrace,
672 if (I + 2 == E || I[2]->
First->is(tok::r_brace) ||
677 return tryMergeSimpleBlock(I, E, Limit);
681 if (I != AnnotatedLines.begin() &&
682 I[-1]->First->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union)) {
683 const bool IsEmptyBlock =
684 Line->Last->is(tok::l_brace) && NextLine->First->is(tok::r_brace);
686 if ((IsEmptyBlock && !Style.BraceWrapping.SplitEmptyRecord) ||
689 return tryMergeSimpleBlock(I, E, Limit);
696 bool canJoinWithCaseLabel(
const AnnotatedLine *
Line,
698 if (
Line->endsWith(tok::semi, tok::kw_break))
701 if (
Line->startsWith(TT_AttributeLSquare) &&
702 Line->endsWith(tok::semi, TT_AttributeRSquare)) {
703 return !LabelTok.mustBreakAfterAttributes(Style);
715 if (I + 2 != E && I[2]->InPPDirective && !I[2]->
First->HasUnescapedNewline)
717 if (1 + I[1]->
Last->TotalLength > Limit)
730 const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace;
731 const auto *BraceOpenLine = I + OpenBraceWrapped;
733 assert(*BraceOpenLine);
734 if (BraceOpenLine[0]->
Last->isNot(TT_NamespaceLBrace))
737 if (std::distance(BraceOpenLine, E) <= 2)
740 if (BraceOpenLine[0]->
Last->is(tok::comment))
743 assert(BraceOpenLine[1]);
744 const auto &L1 = *BraceOpenLine[1];
745 if (L1.InPPDirective != (*I)->InPPDirective ||
746 (L1.InPPDirective && L1.First->HasUnescapedNewline)) {
750 assert(BraceOpenLine[2]);
751 const auto &L2 = *BraceOpenLine[2];
755 Limit = limitConsideringMacros(I + 1, E, Limit);
757 const auto LinesToBeMerged = OpenBraceWrapped + 2;
761 if (L1.First->is(tok::kw_namespace)) {
762 if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)
766 const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
767 const auto MergedLines =
768 tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit);
769 if (MergedLines == 0)
771 const auto N = MergedLines + LinesToBeMerged;
773 if (
auto Distance = std::distance(I, E);
774 static_cast<std::remove_const_t<decltype(N)
>>(Distance) <= N) {
779 if (I[N]->
First->is(TT_NamespaceRBrace) &&
780 !I[N]->First->MustBreakBefore &&
781 BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) &&
782 nextNLinesFitInto(I, I + N + 1, Limit)) {
792 if (L1.Last->isNot(tok::semi))
796 if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore)
799 if (!nextTwoLinesFitInto(I, Limit))
802 return LinesToBeMerged;
811 if (Style.BraceWrapping.AfterControlStatement ==
813 I[1]->First->is(tok::l_brace) &&
817 if (I[1]->InPPDirective != (*I)->InPPDirective ||
818 (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) {
821 Limit = limitConsideringMacros(I + 1, E, Limit);
822 AnnotatedLine &
Line = **I;
823 if (
Line.First->isNoneOf(tok::kw_do, tok::kw_else) &&
824 Line.Last->isNoneOf(tok::kw_else, tok::r_paren)) {
828 if (
Line.First->is(tok::kw_do) &&
Line.Last->isNot(tok::kw_do))
830 if (1 + I[1]->
Last->TotalLength > Limit)
833 if (I[1]->
First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,
834 TT_ForEachMacro, TT_LineComment)) {
838 if (Style.AllowShortIfStatementsOnASingleLine ==
840 if (I + 2 != E &&
Line.startsWith(tok::kw_if) &&
841 I[2]->First->is(tok::kw_else)) {
851 if (Limit == 0 || I + 1 == E ||
852 I[1]->
First->isOneOf(tok::kw_case, tok::kw_default)) {
855 if (I[0]->
Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))
857 unsigned NumStmts = 0;
859 bool EndsWithComment =
false;
860 bool InPPDirective = I[0]->InPPDirective;
861 bool InMacroBody = I[0]->InMacroBody;
862 const unsigned Level = I[0]->Level;
863 for (; NumStmts < 3; ++NumStmts) {
864 if (I + 1 + NumStmts == E)
866 const AnnotatedLine *
Line = I[1 + NumStmts];
867 if (
Line->InPPDirective != InPPDirective)
869 if (
Line->InMacroBody != InMacroBody)
871 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
873 if (
Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
878 const auto *J = I + 2 + NumStmts;
879 if (Style.CompactCaseLabels && J != E &&
880 (*J)->First->isOneOf(tok::kw_case, tok::kw_default) &&
881 canJoinWithCaseLabel(
Line, *(*J)->First)) {
885 if (
Line->First->is(tok::comment)) {
886 if (Level !=
Line->Level)
888 for (; J != E; ++J) {
890 if (
Line->InPPDirective != InPPDirective)
892 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
894 if (
Line->First->isNot(tok::comment) || Level !=
Line->Level)
899 if (
Line->Last->is(tok::comment))
900 EndsWithComment =
true;
901 Length += I[1 + NumStmts]->Last->TotalLength + 1;
903 if (NumStmts == 0 || NumStmts == 3 || Length > Limit)
915 AnnotatedLine &
Line = **I;
920 if (!Style.isJava() &&
Line.First->isOneOf(tok::at, tok::minus, tok::plus))
925 if (
Line.First->is(tok::kw_case) ||
926 (
Line.First->Next &&
Line.First->Next->is(tok::kw_else))) {
930 if (
Line.First->is(tok::kw_default)) {
932 if (
Tok &&
Tok->is(tok::colon))
936 auto IsCtrlStmt = [](
const auto &
Line) {
937 return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
938 tok::kw_do, tok::kw_for, TT_ForEachMacro);
941 const bool IsSplitBlock =
944 I[1]->First->isNot(tok::r_brace));
946 if (IsCtrlStmt(
Line) ||
947 Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
948 tok::kw___finally, tok::r_brace,
949 Keywords.kw___except) ||
950 Line.Last->is(TT_ExportLBrace)) {
955 if (!Style.AllowShortIfStatementsOnASingleLine &&
956 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
957 !Style.BraceWrapping.AfterControlStatement &&
958 I[1]->First->isNot(tok::r_brace)) {
961 if (!Style.AllowShortIfStatementsOnASingleLine &&
962 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
963 Style.BraceWrapping.AfterControlStatement ==
965 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
968 if (!Style.AllowShortLoopsOnASingleLine &&
969 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
971 !Style.BraceWrapping.AfterControlStatement &&
972 I[1]->First->isNot(tok::r_brace)) {
975 if (!Style.AllowShortLoopsOnASingleLine &&
976 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
978 Style.BraceWrapping.AfterControlStatement ==
980 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
988 if (
Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
989 Keywords.kw___except, tok::kw___finally)) {
994 if (
Line.endsWith(tok::l_brace)) {
995 if (Style.BraceWrapping.AfterExportBlock &&
996 Line.First->is(TT_ExportLBrace)) {
1001 Line.First->is(TT_BlockLBrace)) {
1005 if (IsSplitBlock &&
Line.First ==
Line.Last &&
1006 I > AnnotatedLines.begin() &&
1007 (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {
1011 auto ShouldMerge = [
Tok]() {
1012 if (
Tok->isNot(tok::r_brace) ||
Tok->MustBreakBefore)
1015 return !
Next ||
Next->is(tok::semi);
1018 if (ShouldMerge()) {
1020 Tok->SpacesRequiredBefore =
1022 Line.Last->is(tok::comment);
1023 Tok->CanBreakBefore =
true;
1025 }
else if (Limit != 0 && !
Line.startsWithNamespace() &&
1026 !startsExternCBlock(
Line)) {
1028 if (
Line.Last->isOneOf(TT_EnumLBrace, TT_RecordLBrace))
1031 if (
Line.Last->isOneOf(TT_ClassLBrace, TT_StructLBrace,
1041 Limit = limitConsideringMacros(I + 2, E, Limit);
1043 if (!nextTwoLinesFitInto(I, Limit))
1049 if (I[1]->
Last->is(TT_LineComment))
1054 if (
Tok->is(tok::r_brace) &&
1055 (!
Tok->MatchingParen ||
1065 if (
Tok->isNot(tok::r_brace) || I[2]->Level !=
Line.Level)
1069 if (
Tok->Next &&
Tok->Next->is(tok::kw_else))
1079 Line.First->is(TT_ControlStatementLBrace) &&
1080 Style.BraceWrapping.AfterControlStatement ==
1087 }
else if (I[1]->
First->is(tok::l_brace)) {
1088 if (I[1]->
Last->is(TT_LineComment))
1092 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))
1095 unsigned MergedLines = 0;
1097 auto TryMergeBlock = [&] {
1102 return I[1]->First == I[1]->Last && I + 2 != E &&
1103 I[2]->First->is(tok::r_brace);
1106 if (TryMergeBlock()) {
1107 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
1110 if (MergedLines > 0)
1123 if (I[0]->InPPDirective && I + 1 != E &&
1124 !I[1]->
First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {
1125 return Limit < 2 ? 0 : Limit - 2;
1132 if (I[1]->
First->MustBreakBefore || I[2]->First->MustBreakBefore)
1134 return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
1140 unsigned JoinedLength = 0;
1141 for (
const auto *J = I + 1; J != E; ++J) {
1142 if ((*J)->First->MustBreakBefore)
1145 JoinedLength += 1 + (*J)->Last->TotalLength;
1146 if (JoinedLength > Limit)
1152 bool containsMustBreak(
const AnnotatedLine *
Line) {
1153 assert(
Line->First);
1157 if (
Tok->MustBreakBefore)
1162 bool cannotMergeMacroLine(
const AnnotatedLine *
Line,
bool AllowMultiLine) {
1163 assert(
Line->First);
1164 if (
Line->Last->MacroParent)
1169 if (
Tok->MacroParent && !
Tok->Children.empty())
1177 void join(AnnotatedLine &A,
const AnnotatedLine &B) {
1178 assert(!A.Last->Next);
1179 assert(!B.First->Previous);
1180 if (B.Affected || B.LeadingEmptyLinesAffected) {
1181 assert(B.Affected || A.Last->Children.empty());
1184 A.Last->Next = B.First;
1185 B.First->Previous = A.Last;
1186 B.First->CanBreakBefore =
true;
1187 unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
1189 Tok->TotalLength += LengthA;
1195 const AdditionalKeywords &Keywords;
1199 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
1202static void markFinalized(
FormatToken *
Tok,
bool SkipFirst =
false) {
1203 if (
Tok->is(tok::hash) && !
Tok->Previous &&
Tok->Next &&
1204 Tok->Next->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef,
1205 tok::pp_elif, tok::pp_elifdef, tok::pp_elifndef,
1206 tok::pp_else, tok::pp_endif)) {
1223 Tok->SpacesRequiredBefore = 0;
1224 if (!
Tok->MustBreakBeforeFinalized)
1225 Tok->MustBreakBefore = 0;
1226 }
else if (!
First || !SkipFirst) {
1227 Tok->Finalized =
true;
1233static void printLineState(
const LineState &State) {
1234 llvm::dbgs() <<
"State: ";
1235 for (
const ParenState &P : State.Stack) {
1236 llvm::dbgs() << (P.Tok ? P.Tok->TokenText :
"F") <<
"|" << P.Indent.Total
1237 <<
"|" << P.LastSpace <<
"|" << P.NestedBlockIndent <<
" ";
1239 llvm::dbgs() << State.NextToken->TokenText <<
"\n";
1244class LineFormatter {
1246 LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
1248 UnwrappedLineFormatter *BlockFormatter)
1249 : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
1250 BlockFormatter(BlockFormatter) {}
1251 virtual ~LineFormatter() {}
1256 virtual uint64_t formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1257 unsigned FirstStartColumn,
bool DryRun) = 0;
1280 bool formatChildren(LineState &State,
bool NewLine,
bool DryRun,
1281 uint64_t &Penalty) {
1282 const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
1283 bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(
BK_Block);
1285 if (
Previous.Children.empty() || (!HasLBrace && !LBrace->MacroParent)) {
1291 if (NewLine ||
Previous.MacroParent) {
1292 ParenState &P = State.Stack.back();
1294 int AdditionalIndent =
1295 P.Indent.Total -
Previous.Children[0]->Level * Style.IndentWidth;
1297 BlockFormatter->format(
Previous.Children, DryRun, AdditionalIndent,
1300 P.NestedBlockIndent = P.Indent.Total;
1304 if (
Previous.Children[0]->First->MustBreakBefore)
1315 const AnnotatedLine *Child =
Previous.Children[0];
1317 if (Child->Last->isTrailingComment())
1322 if (Style.ColumnLimit > 0 &&
1323 Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit) {
1328 Whitespaces->replaceWhitespace(
1329 *Child->First, 0, 1,
1330 State.Column,
nullptr,
1331 State.Line->InPPDirective);
1334 formatLine(*Child, State.Column + 1, 0, DryRun);
1336 markFinalized(Child->First);
1338 State.Column += 1 + Child->Last->TotalLength;
1342 ContinuationIndenter *Indenter;
1345 WhitespaceManager *Whitespaces;
1347 UnwrappedLineFormatter *BlockFormatter;
1351class NoColumnLimitLineFormatter :
public LineFormatter {
1353 NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
1354 WhitespaceManager *Whitespaces,
1356 UnwrappedLineFormatter *BlockFormatter)
1357 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1361 uint64_t formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1362 unsigned FirstStartColumn,
bool DryRun)
override {
1364 LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
1366 while (State.NextToken) {
1368 Indenter->mustBreak(State) ||
1369 (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
1370 uint64_t Penalty = 0;
1371 formatChildren(State, Newline,
false, Penalty);
1372 Indenter->addTokenToState(State, Newline,
false);
1379class NoLineBreakFormatter :
public LineFormatter {
1381 NoLineBreakFormatter(ContinuationIndenter *Indenter,
1382 WhitespaceManager *Whitespaces,
const FormatStyle &Style,
1383 UnwrappedLineFormatter *BlockFormatter)
1384 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1387 uint64_t formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1388 unsigned FirstStartColumn,
bool DryRun)
override {
1389 uint64_t Penalty = 0;
1391 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1392 while (State.NextToken) {
1393 formatChildren(State,
false, DryRun, Penalty);
1394 Indenter->addTokenToState(
1395 State, State.NextToken->MustBreakBefore, DryRun);
1402class OptimizingLineFormatter :
public LineFormatter {
1404 OptimizingLineFormatter(ContinuationIndenter *Indenter,
1405 WhitespaceManager *Whitespaces,
1407 UnwrappedLineFormatter *BlockFormatter)
1408 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1412 uint64_t formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1413 unsigned FirstStartColumn,
bool DryRun)
override {
1415 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1420 State.Stack.back().BreakBeforeParameter =
true;
1423 return analyzeSolutionSpace(State, DryRun);
1427 struct CompareLineStatePointers {
1428 bool operator()(LineState *obj1, LineState *obj2)
const {
1429 return *obj1 < *obj2;
1438 typedef std::pair<uint64_t, unsigned> OrderedPenalty;
1443 StateNode(
const LineState &State,
bool NewLine, StateNode *
Previous)
1452 typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
1455 typedef std::priority_queue<QueueItem, SmallVector<QueueItem>,
1456 std::greater<QueueItem>>
1467 uint64_t analyzeSolutionSpace(LineState &InitialState,
bool DryRun) {
1468 std::set<LineState *, CompareLineStatePointers> Seen;
1476 StateNode *RootNode =
1477 new (Allocator.Allocate()) StateNode(InitialState,
false,
nullptr);
1478 Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode));
1481 uint64_t Penalty = 0;
1484 while (!Queue.empty()) {
1486 if (Count > 25'000'000)
1489 Penalty = Queue.top().first.first;
1490 StateNode *Node = Queue.top().second;
1491 if (!Node->State.NextToken) {
1492 LLVM_DEBUG(llvm::dbgs()
1493 <<
"\n---\nPenalty for line: " << Penalty <<
"\n");
1501 Node->State.IgnoreStackForComparison =
true;
1503 if (!Seen.insert(&Node->State).second) {
1508 FormatDecision LastFormat = Node->State.NextToken->getDecision();
1510 addNextStateToQueue(Penalty, Node,
false, &Count, &Queue);
1512 addNextStateToQueue(Penalty, Node,
true, &Count, &Queue);
1515 if (Queue.empty()) {
1518 LLVM_DEBUG(llvm::dbgs() <<
"Could not find a solution.\n");
1524 reconstructPath(InitialState, Queue.top().second);
1526 LLVM_DEBUG(llvm::dbgs()
1527 <<
"Total number of analyzed states: " << Count <<
"\n");
1528 LLVM_DEBUG(llvm::dbgs() <<
"---\n");
1537 void addNextStateToQueue(uint64_t Penalty, StateNode *PreviousNode,
1538 bool NewLine,
unsigned *Count, QueueType *Queue) {
1539 if (NewLine && !Indenter->canBreak(PreviousNode->State))
1541 if (!NewLine && Indenter->mustBreak(PreviousNode->State))
1544 StateNode *Node =
new (Allocator.Allocate())
1545 StateNode(PreviousNode->State, NewLine, PreviousNode);
1546 if (!formatChildren(Node->State, NewLine,
true, Penalty))
1549 Penalty += Indenter->addTokenToState(Node->State, NewLine,
true);
1551 Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
1557 void reconstructPath(LineState &State, StateNode *Best) {
1560 while (Best->Previous) {
1561 Path.push_back(Best);
1562 Best = Best->Previous;
1564 for (
const auto &Node : llvm::reverse(Path)) {
1565 uint64_t Penalty = 0;
1566 formatChildren(State, Node->NewLine,
false, Penalty);
1567 Penalty += Indenter->addTokenToState(State, Node->NewLine,
false);
1570 printLineState(Node->Previous->State);
1571 if (Node->NewLine) {
1572 llvm::dbgs() <<
"Penalty for placing "
1573 << Node->Previous->State.NextToken->Tok.getName()
1574 <<
" on a new line: " << Penalty <<
"\n";
1580 llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
1587 int AdditionalIndent,
bool FixBadIndentation,
unsigned FirstStartColumn,
1588 unsigned NextStartColumn,
unsigned LastStartColumn) {
1589 LineJoiner Joiner(Style, Keywords, Lines);
1592 std::pair<const SmallVectorImpl<AnnotatedLine *> *,
unsigned> CacheKey(
1593 &Lines, AdditionalIndent);
1594 auto CacheIt = PenaltyCache.find(CacheKey);
1595 if (DryRun && CacheIt != PenaltyCache.end())
1596 return CacheIt->second;
1598 assert(!Lines.empty());
1599 uint64_t Penalty = 0;
1600 LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
1609 bool FirstLine =
true;
1611 Joiner.getNextMergedLine(DryRun, IndentTracker);
1612 Line; PrevPrevLine = PreviousLine, PreviousLine =
Line,
Line = NextLine,
1613 FirstLine =
false) {
1614 assert(
Line->First);
1616 unsigned Indent = IndentTracker.getIndent();
1622 bool PreviousRBrace =
1623 PreviousLine && PreviousLine->
startsWith(tok::r_brace);
1624 bool ContinueFormatting =
1625 TheLine.
Level > RangeMinLevel ||
1626 (TheLine.
Level == RangeMinLevel && !PreviousRBrace &&
1629 bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
1631 bool ShouldFormat = TheLine.
Affected || FixIndentation;
1635 Status->FormatComplete =
false;
1642 bool LastLine = TheLine.
First->
is(tok::eof);
1643 formatFirstToken(TheLine, PreviousLine, PrevPrevLine,
Indent,
1644 LastLine ? LastStartColumn : NextStartColumn +
Indent);
1647 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1648 unsigned ColumnLimit = getColumnLimit(TheLine.
InPPDirective, NextLine);
1649 bool FitsIntoOneLine =
1653 (!Style.isJavaScript() || !Style.JavaScriptWrapImports)) ||
1654 (Style.isCSharp() &&
1656 if (Style.ColumnLimit == 0) {
1657 NoColumnLimitLineFormatter(Indenter, Whitespaces, Style,
this)
1658 .formatLine(TheLine, NextStartColumn +
Indent,
1659 FirstLine ? FirstStartColumn : 0, DryRun);
1660 }
else if (FitsIntoOneLine) {
1661 Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style,
this)
1662 .formatLine(TheLine, NextStartColumn +
Indent,
1663 FirstLine ? FirstStartColumn : 0, DryRun);
1665 Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style,
this)
1666 .formatLine(TheLine, NextStartColumn +
Indent,
1667 FirstLine ? FirstStartColumn : 0, DryRun);
1669 RangeMinLevel = std::min(RangeMinLevel, TheLine.
Level);
1675 if (!
Tok->Children.empty())
1681 bool StartsNewLine =
1684 IndentTracker.adjustToUnmodifiedLine(TheLine);
1686 bool ReformatLeadingWhitespace =
1687 StartsNewLine && ((PreviousLine && PreviousLine->
Affected) ||
1690 if (ReformatLeadingWhitespace) {
1691 formatFirstToken(TheLine, PreviousLine, PrevPrevLine,
1695 Whitespaces->addUntouchableToken(*TheLine.
First,
1703 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1709 PenaltyCache[CacheKey] = Penalty;
1717 const auto &RootToken = *
Line.First;
1719 return RootToken.NewlinesBefore;
1721 std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
1723 if (RootToken.is(tok::r_brace) &&
1725 (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&
1727 (
Line.InPPDirective || !
Line.startsWith(TT_NamespaceRBrace)) &&
1728 !Style.KeepEmptyLines.AtEndOfBlock) {
1732 if (!PreviousLine &&
Line.Level > 0)
1734 if (
Newlines == 0 && !RootToken.IsFirst)
1736 if (RootToken.IsFirst &&
1737 (!Style.KeepEmptyLines.AtStartOfFile || !RootToken.HasUnescapedNewline)) {
1742 if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine &&
1743 PreviousLine->
Last->
is(tok::l_brace) &&
1747 !startsExternCBlock(*PreviousLine)) {
1753 if (PreviousLine && PreviousLine->
endsWith(TT_NamespaceLBrace)) {
1756 else if (!
Line.startsWithNamespace())
1760 if (
Line.startsWith(TT_NamespaceRBrace)) {
1763 else if (!PreviousLine->
startsWith(TT_NamespaceRBrace))
1769 if (PreviousLine && RootToken.isAccessSpecifier()) {
1770 switch (Style.EmptyLineBeforeAccessModifier) {
1776 Newlines = std::max(RootToken.NewlinesBefore, 1u);
1781 if (PreviousLine->
First->isAccessSpecifier())
1786 if (PreviousLine->
Last->
is(tok::comment))
1787 previousToken = PreviousLine->
Last->getPreviousNonComment();
1789 previousToken = PreviousLine->
Last;
1790 if ((!previousToken || previousToken->
isNot(tok::l_brace)) &&
1799 if (PreviousLine && PreviousLine->
First->isAccessSpecifier() &&
1800 (!PreviousLine->
InPPDirective || !RootToken.HasUnescapedNewline)) {
1803 if (!RootToken.isAccessSpecifier()) {
1804 switch (Style.EmptyLineAfterAccessModifier) {
1812 if (RootToken.is(tok::r_brace))
1824void UnwrappedLineFormatter::formatFirstToken(
const AnnotatedLine &
Line,
1825 const AnnotatedLine *PreviousLine,
1826 const AnnotatedLine *PrevPrevLine,
1828 unsigned NewlineIndent) {
1830 if (RootToken.is(tok::eof)) {
1832 RootToken.NewlinesBefore,
1833 Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);
1834 unsigned TokenIndent =
Newlines ? NewlineIndent : 0;
1836 RootToken,
Newlines, TokenIndent, TokenIndent,
nullptr,
1839 !
Line.InMacroExpansion);
1843 if (RootToken.Newlines < 0) {
1844 RootToken.Newlines =
1846 assert(RootToken.Newlines >= 0);
1849 if (RootToken.Newlines > 0)
1854 if (!Style.isJavaScript() &&
1861 Whitespaces->replaceWhitespace(
1862 RootToken, RootToken.Newlines,
Indent,
Indent,
nullptr,
1863 Line.InPPDirective && !RootToken.HasUnescapedNewline,
1864 0, !
Line.InMacroExpansion);
1868UnwrappedLineFormatter::getColumnLimit(
bool InPPDirective,
1872 bool ContinuesPPDirective =
1877 (NextLine->InPPDirective &&
1880 !NextLine->First->HasUnescapedNewline));
1881 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.
Top level wrappers for InstallAPI frontend operations.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)