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())
124 const auto &RootToken = *
Line.First;
126 if (Style.IndentGotoLabels == FormatStyle::IGLS_HalfIndent &&
127 RootToken.Next && RootToken.Next->is(TT_GotoLabelColon)) {
128 return -
static_cast<int>(Style.IndentWidth / 2);
132 RootToken.isAccessSpecifier(
false) ||
133 RootToken.isObjCAccessSpecifier() ||
134 (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
135 RootToken.Next && RootToken.Next->is(tok::colon))) {
139 return Style.IndentAccessModifiers ? -Style.IndentWidth
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;
159 const FormatStyle &Style;
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 = tryFitMultipleLinesInOne(IndentTracker,
Next, End);
219 if (MergedLines > 0 && Style.ColumnLimit == 0) {
222 for (
unsigned i = 0; i < MergedLines; ++i)
223 if (
Next[i + 1]->
First->NewlinesBefore > 0)
227 for (
unsigned i = 0; i < MergedLines; ++i)
236 tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
243 const AnnotatedLine *TheLine = *I;
244 if (TheLine->Last->is(TT_LineComment))
246 const auto &NextLine = *I[1];
247 if (NextLine.Type ==
LT_Invalid || NextLine.First->MustBreakBefore)
249 if (TheLine->InPPDirective &&
250 (!NextLine.InPPDirective || NextLine.First->HasUnescapedNewline)) {
254 const auto Indent = IndentTracker.getIndent();
255 if (Style.ColumnLimit > 0 &&
Indent > Style.ColumnLimit)
262 Limit = TheLine->Last->TotalLength > Limit
264 : Limit - TheLine->Last->TotalLength;
266 if (TheLine->Last->is(TT_FunctionLBrace) &&
267 TheLine->First == TheLine->Last) {
268 const bool EmptyFunctionBody = NextLine.First->is(tok::r_brace);
269 if ((EmptyFunctionBody && !Style.BraceWrapping.SplitEmptyFunction) ||
270 (!EmptyFunctionBody &&
271 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always)) {
272 return tryMergeSimpleBlock(I, E, Limit);
278 if (NextLine.First->isOneOf(TT_ClassLBrace, TT_StructLBrace,
280 if (
unsigned MergedLines = tryMergeRecord(I, E, Limit))
284 const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] :
nullptr;
287 if (PreviousLine && TheLine->Last->is(tok::l_brace) &&
288 TheLine->First == TheLine->Last) {
289 const bool EmptyBlock = NextLine.First->is(tok::r_brace);
293 if (
Tok &&
Tok->getNamespaceToken()) {
294 return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
295 ? tryMergeSimpleBlock(I, E, Limit)
299 if (
Tok &&
Tok->is(tok::kw_typedef))
300 Tok =
Tok->getNextNonComment();
302 if (
Tok &&
Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union))
303 return tryMergeRecord(I, E, Limit);
305 if (
Tok &&
Tok->isOneOf(tok::kw_extern, Keywords.kw_interface)) {
306 return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
307 ? tryMergeSimpleBlock(I, E, Limit)
311 if (
Tok &&
Tok->is(tok::kw_template) &&
312 Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) {
317 auto ShouldMergeShortFunctions = [
this, &I, &NextLine, PreviousLine,
319 if (Style.AllowShortFunctionsOnASingleLine.isAll())
322 if (Style.AllowShortFunctionsOnASingleLine.Empty &&
323 NextLine.First->is(tok::r_brace)) {
327 if (Style.AllowShortFunctionsOnASingleLine.Inline &&
328 !Style.AllowShortFunctionsOnASingleLine.Other) {
331 if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
334 if (TheLine->Level != 0) {
340 const AnnotatedLine *
Line =
nullptr;
341 for (
auto J = I - 1; J >= AnnotatedLines.begin(); --J) {
343 if (((*J)->InPPDirective && !(*J)->InMacroBody) ||
344 (*J)->isComment() || (*J)->Level > TheLine->Level) {
347 if ((*J)->Level < TheLine->Level ||
348 (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
349 (*J)->First->is(tok::l_brace))) {
359 const auto *LastNonComment =
Line->getLastNonComment();
362 assert(LastNonComment);
363 return isRecordLBrace(*LastNonComment);
370 bool MergeShortFunctions = ShouldMergeShortFunctions();
372 const auto *FirstNonComment = TheLine->getFirstNonComment();
373 if (!FirstNonComment)
379 if (Style.AllowShortNamespacesOnASingleLine &&
380 TheLine->First->is(tok::kw_namespace)) {
381 const auto result = tryMergeNamespace(I, E, Limit);
386 if (Style.CompactNamespaces) {
387 if (
const auto *NSToken = TheLine->First->getNamespaceToken()) {
389 assert(TheLine->MatchingClosingBlockLineIndex > 0);
390 for (
auto ClosingLineIndex = TheLine->MatchingClosingBlockLineIndex - 1;
392 ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
393 I[J]->
Last->TotalLength < Limit;
394 ++J, --ClosingLineIndex) {
395 Limit -= I[J]->Last->TotalLength + 1;
399 auto *ClosingLine = AnnotatedLines.begin() + ClosingLineIndex + 1;
400 const int OutdentBy = I[J]->Level - TheLine->Level;
401 assert(OutdentBy >= 0);
402 for (
auto *CompactedLine = I + J; CompactedLine <= ClosingLine;
404 if (!(*CompactedLine)->InPPDirective) {
405 const int Level = (*CompactedLine)->Level;
406 (*CompactedLine)->Level = std::max(Level - OutdentBy, 0);
413 if (
auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) {
415 unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
416 for (; I + 1 + i != E &&
417 nsToken->TokenText ==
418 getMatchingNamespaceTokenText(I[i + 1], AnnotatedLines) &&
419 openingLine == I[i + 1]->MatchingOpeningBlockLineIndex;
420 i++, --openingLine) {
422 I[i + 1]->First->SpacesRequiredBefore =
423 I[i]->Last->isNot(tok::r_brace);
426 IndentTracker.nextLine(*I[i + 1]);
432 const auto *LastNonComment = TheLine->getLastNonComment();
433 assert(LastNonComment);
438 if (LastNonComment->is(TT_FunctionLBrace) &&
439 TheLine->First != LastNonComment) {
440 return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
444 if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
445 (FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
447 TheLine->startsWithExportBlock())) {
448 return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never
449 ? tryMergeSimpleBlock(I, E, Limit)
453 if (NextLine.First->is(TT_ControlStatementLBrace)) {
457 return Style.BraceWrapping.AfterControlStatement ==
458 FormatStyle::BWACS_Always
459 ? tryMergeSimpleBlock(I, E, Limit)
462 if (PreviousLine && TheLine->First->is(tok::l_brace)) {
463 switch (PreviousLine->First->Tok.getKind()) {
466 if (PreviousLine->First->Next &&
467 PreviousLine->First->Next->isOneOf(tok::objc_autoreleasepool,
468 tok::objc_synchronized)) {
474 case tok::kw_default:
485 if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord &&
486 TheLine->Last->is(tok::l_brace) && PreviousLine->Last) {
492 if (
Previous->is(tok::greater) && !PreviousLine->InPPDirective)
494 if (
Previous->is(tok::identifier)) {
497 if (PreviousPrevious &&
498 PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct,
507 if (TheLine->First->is(TT_SwitchExpressionLabel)) {
508 return Style.AllowShortCaseExpressionOnASingleLine
509 ? tryMergeShortCaseLabels(I, E, Limit)
513 if (TheLine->Last->is(tok::l_brace)) {
514 bool ShouldMerge =
false;
516 if (TheLine->Last->is(TT_EnumLBrace)) {
517 ShouldMerge = Style.AllowShortEnumsOnASingleLine;
518 }
else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
519 ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
520 }
else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace,
522 (TheLine->Last->is(TT_RecordLBrace) && Style.isJava())) {
523 return tryMergeRecord(I, E, Limit);
524 }
else if (TheLine->InPPDirective ||
525 TheLine->First->isNoneOf(tok::kw_class, tok::kw_enum,
526 tok::kw_struct, tok::kw_union)) {
529 ShouldMerge = !Style.BraceWrapping.AfterFunction ||
530 (NextLine.First->is(tok::r_brace) &&
531 !Style.BraceWrapping.SplitEmptyFunction);
533 return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit) : 0;
537 if (NextLine.First->is(TT_FunctionLBrace) &&
538 Style.BraceWrapping.AfterFunction) {
539 if (NextLine.Last->is(TT_LineComment))
543 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
547 unsigned MergedLines = 0;
548 if (MergeShortFunctions ||
549 (Style.AllowShortFunctionsOnASingleLine.Empty &&
550 NextLine.First == NextLine.Last && I + 2 != E &&
551 I[2]->First->is(tok::r_brace))) {
552 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
560 auto IsElseLine = [&TheLine]() ->
bool {
562 if (
First->is(tok::kw_else))
565 return First->is(tok::r_brace) &&
First->Next &&
566 First->Next->is(tok::kw_else);
568 if (TheLine->First->is(tok::kw_if) ||
569 (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine ==
570 FormatStyle::SIS_AllIfsAndElse))) {
571 return Style.AllowShortIfStatementsOnASingleLine
572 ? tryMergeSimpleControlStatement(I, E, Limit)
575 if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do,
577 return Style.AllowShortLoopsOnASingleLine
578 ? tryMergeSimpleControlStatement(I, E, Limit)
581 if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) {
582 return Style.AllowShortCaseLabelsOnASingleLine
583 ? tryMergeShortCaseLabels(I, E, Limit)
586 if (TheLine->InPPDirective &&
587 (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
588 return tryMergeSimplePPDirective(I, E, Limit);
596 const auto *
Line = I[0];
597 const auto *NextLine = I[1];
600 if (
Line->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace, TT_UnionLBrace)) {
601 auto ShouldWrapLBrace = [&](TokenType LBraceType) {
602 switch (LBraceType) {
604 return Style.BraceWrapping.AfterClass;
605 case TT_StructLBrace:
606 return Style.BraceWrapping.AfterStruct;
608 return Style.BraceWrapping.AfterUnion;
614 auto TryMergeShortRecord = [&] {
615 switch (Style.AllowShortRecordOnASingleLine) {
616 case FormatStyle::SRS_Never:
618 case FormatStyle::SRS_Always:
621 return NextLine->First->is(tok::r_brace);
625 if (Style.AllowShortRecordOnASingleLine != FormatStyle::SRS_Never &&
626 (!ShouldWrapLBrace(
Line->Last->getType()) ||
627 (!Style.BraceWrapping.SplitEmptyRecord && TryMergeShortRecord()))) {
628 return tryMergeSimpleBlock(I, E, Limit);
634 if (NextLine->First->isOneOf(TT_ClassLBrace, TT_StructLBrace,
636 if (I + 2 == E || I[2]->
First->is(tok::r_brace) ||
637 Style.AllowShortRecordOnASingleLine != FormatStyle::SRS_Always) {
641 return tryMergeSimpleBlock(I, E, Limit);
645 if (I != AnnotatedLines.begin() &&
646 I[-1]->First->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union)) {
647 const bool IsEmptyBlock =
648 Line->Last->is(tok::l_brace) && NextLine->First->is(tok::r_brace);
650 if ((IsEmptyBlock && !Style.BraceWrapping.SplitEmptyRecord) ||
652 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always)) {
653 return tryMergeSimpleBlock(I, E, Limit);
666 if (I + 2 != E && I[2]->InPPDirective && !I[2]->
First->HasUnescapedNewline)
668 if (1 + I[1]->
Last->TotalLength > Limit)
681 const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace;
682 const auto *BraceOpenLine = I + OpenBraceWrapped;
684 assert(*BraceOpenLine);
685 if (BraceOpenLine[0]->
Last->isNot(TT_NamespaceLBrace))
688 if (std::distance(BraceOpenLine, E) <= 2)
691 if (BraceOpenLine[0]->
Last->is(tok::comment))
694 assert(BraceOpenLine[1]);
695 const auto &L1 = *BraceOpenLine[1];
696 if (L1.InPPDirective != (*I)->InPPDirective ||
697 (L1.InPPDirective && L1.First->HasUnescapedNewline)) {
701 assert(BraceOpenLine[2]);
702 const auto &L2 = *BraceOpenLine[2];
706 Limit = limitConsideringMacros(I + 1, E, Limit);
708 const auto LinesToBeMerged = OpenBraceWrapped + 2;
712 if (L1.First->is(tok::kw_namespace)) {
713 if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)
717 const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
718 const auto MergedLines =
719 tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit);
720 if (MergedLines == 0)
722 const auto N = MergedLines + LinesToBeMerged;
724 if (
auto Distance = std::distance(I, E);
725 static_cast<std::remove_const_t<decltype(N)
>>(Distance) <= N) {
730 if (I[N]->
First->is(TT_NamespaceRBrace) &&
731 !I[N]->First->MustBreakBefore &&
732 BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) &&
733 nextNLinesFitInto(I, I + N + 1, Limit)) {
743 if (L1.Last->isNot(tok::semi))
747 if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore)
750 if (!nextTwoLinesFitInto(I, Limit))
753 return LinesToBeMerged;
762 if (Style.BraceWrapping.AfterControlStatement ==
763 FormatStyle::BWACS_Always &&
764 I[1]->First->is(tok::l_brace) &&
765 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
768 if (I[1]->InPPDirective != (*I)->InPPDirective ||
769 (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) {
772 Limit = limitConsideringMacros(I + 1, E, Limit);
773 AnnotatedLine &
Line = **I;
774 if (
Line.First->isNoneOf(tok::kw_do, tok::kw_else) &&
775 Line.Last->isNoneOf(tok::kw_else, tok::r_paren)) {
779 if (
Line.First->is(tok::kw_do) &&
Line.Last->isNot(tok::kw_do))
781 if (1 + I[1]->
Last->TotalLength > Limit)
784 if (I[1]->
First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,
785 TT_ForEachMacro, TT_LineComment)) {
789 if (Style.AllowShortIfStatementsOnASingleLine ==
790 FormatStyle::SIS_WithoutElse) {
791 if (I + 2 != E &&
Line.startsWith(tok::kw_if) &&
792 I[2]->First->is(tok::kw_else)) {
802 if (Limit == 0 || I + 1 == E ||
803 I[1]->
First->isOneOf(tok::kw_case, tok::kw_default)) {
806 if (I[0]->
Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))
808 unsigned NumStmts = 0;
810 bool EndsWithComment =
false;
811 bool InPPDirective = I[0]->InPPDirective;
812 bool InMacroBody = I[0]->InMacroBody;
813 const unsigned Level = I[0]->Level;
814 for (; NumStmts < 3; ++NumStmts) {
815 if (I + 1 + NumStmts == E)
817 const AnnotatedLine *
Line = I[1 + NumStmts];
818 if (
Line->InPPDirective != InPPDirective)
820 if (
Line->InMacroBody != InMacroBody)
822 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
824 if (
Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
829 if (
Line->First->is(tok::comment)) {
830 if (Level !=
Line->Level)
832 const auto *J = I + 2 + NumStmts;
833 for (; J != E; ++J) {
835 if (
Line->InPPDirective != InPPDirective)
837 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
839 if (
Line->First->isNot(tok::comment) || Level !=
Line->Level)
844 if (
Line->Last->is(tok::comment))
845 EndsWithComment =
true;
846 Length += I[1 + NumStmts]->Last->TotalLength + 1;
848 if (NumStmts == 0 || NumStmts == 3 || Length > Limit)
860 AnnotatedLine &
Line = **I;
865 if (!Style.isJava() &&
Line.First->isOneOf(tok::at, tok::minus, tok::plus))
870 if (
Line.First->is(tok::kw_case) ||
871 (
Line.First->Next &&
Line.First->Next->is(tok::kw_else))) {
875 if (
Line.First->is(tok::kw_default)) {
877 if (
Tok &&
Tok->is(tok::colon))
881 auto IsCtrlStmt = [](
const auto &
Line) {
882 return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
883 tok::kw_do, tok::kw_for, TT_ForEachMacro);
886 const bool IsSplitBlock =
887 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never ||
888 (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty &&
889 I[1]->First->isNot(tok::r_brace));
891 if (IsCtrlStmt(
Line) ||
892 Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
893 tok::kw___finally, tok::r_brace,
894 Keywords.kw___except) ||
895 Line.startsWithExportBlock()) {
900 if (!Style.AllowShortIfStatementsOnASingleLine &&
901 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
902 !Style.BraceWrapping.AfterControlStatement &&
903 I[1]->First->isNot(tok::r_brace)) {
906 if (!Style.AllowShortIfStatementsOnASingleLine &&
907 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
908 Style.BraceWrapping.AfterControlStatement ==
909 FormatStyle::BWACS_Always &&
910 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
913 if (!Style.AllowShortLoopsOnASingleLine &&
914 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
916 !Style.BraceWrapping.AfterControlStatement &&
917 I[1]->First->isNot(tok::r_brace)) {
920 if (!Style.AllowShortLoopsOnASingleLine &&
921 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
923 Style.BraceWrapping.AfterControlStatement ==
924 FormatStyle::BWACS_Always &&
925 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
933 if (
Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
934 Keywords.kw___except, tok::kw___finally)) {
939 if (
Line.endsWith(tok::l_brace)) {
940 if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never &&
941 Line.First->is(TT_BlockLBrace)) {
945 if (IsSplitBlock &&
Line.First ==
Line.Last &&
946 I > AnnotatedLines.begin() &&
947 (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {
951 auto ShouldMerge = [
Tok]() {
952 if (
Tok->isNot(tok::r_brace) ||
Tok->MustBreakBefore)
955 return !
Next ||
Next->is(tok::semi);
960 Tok->SpacesRequiredBefore =
961 Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never ||
962 Line.Last->is(tok::comment);
963 Tok->CanBreakBefore =
true;
965 }
else if (Limit != 0 && !
Line.startsWithNamespace() &&
966 !startsExternCBlock(
Line)) {
968 if (
Line.Last->isOneOf(TT_EnumLBrace, TT_RecordLBrace))
971 if (
Line.Last->isOneOf(TT_ClassLBrace, TT_StructLBrace,
974 Style.AllowShortRecordOnASingleLine != FormatStyle::SRS_Always) {
981 Limit = limitConsideringMacros(I + 2, E, Limit);
983 if (!nextTwoLinesFitInto(I, Limit))
988 if (I[1]->
Last->is(TT_LineComment))
991 if (
Tok->isOneOf(tok::l_brace, tok::r_brace) &&
1000 if (
Tok->isNot(tok::r_brace))
1004 if (
Tok->Next &&
Tok->Next->is(tok::kw_else))
1014 Line.First->is(TT_ControlStatementLBrace) &&
1015 Style.BraceWrapping.AfterControlStatement ==
1016 FormatStyle::BWACS_MultiLine) {
1022 }
else if (I[1]->
First->is(tok::l_brace)) {
1023 if (I[1]->
Last->is(TT_LineComment))
1027 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))
1030 unsigned MergedLines = 0;
1032 auto TryMergeBlock = [&] {
1033 if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never ||
1034 Style.AllowShortRecordOnASingleLine == FormatStyle::SRS_Always) {
1037 return I[1]->First == I[1]->Last && I + 2 != E &&
1038 I[2]->First->is(tok::r_brace);
1041 if (TryMergeBlock()) {
1042 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
1045 if (MergedLines > 0)
1058 if (I[0]->InPPDirective && I + 1 != E &&
1059 !I[1]->
First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {
1060 return Limit < 2 ? 0 : Limit - 2;
1067 if (I[1]->
First->MustBreakBefore || I[2]->First->MustBreakBefore)
1069 return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
1075 unsigned JoinedLength = 0;
1076 for (
const auto *J = I + 1; J != E; ++J) {
1077 if ((*J)->First->MustBreakBefore)
1080 JoinedLength += 1 + (*J)->Last->TotalLength;
1081 if (JoinedLength > Limit)
1087 bool containsMustBreak(
const AnnotatedLine *
Line) {
1088 assert(
Line->First);
1092 if (
Tok->MustBreakBefore)
1097 void join(AnnotatedLine &A,
const AnnotatedLine &B) {
1098 assert(!A.Last->Next);
1099 assert(!B.First->Previous);
1100 if (B.Affected || B.LeadingEmptyLinesAffected) {
1101 assert(B.Affected || A.Last->Children.empty());
1104 A.Last->Next = B.First;
1105 B.First->Previous = A.Last;
1106 B.First->CanBreakBefore =
true;
1107 unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
1109 Tok->TotalLength += LengthA;
1114 const FormatStyle &Style;
1115 const AdditionalKeywords &Keywords;
1119 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
1123 if (
Tok->is(tok::hash) && !
Tok->Previous &&
Tok->Next &&
1124 Tok->Next->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef,
1125 tok::pp_elif, tok::pp_elifdef, tok::pp_elifndef,
1126 tok::pp_else, tok::pp_endif)) {
1142 Tok->SpacesRequiredBefore = 0;
1143 if (!
Tok->MustBreakBeforeFinalized)
1144 Tok->MustBreakBefore = 0;
1146 Tok->Finalized =
true;
1152static void printLineState(
const LineState &State) {
1153 llvm::dbgs() <<
"State: ";
1154 for (
const ParenState &P : State.Stack) {
1155 llvm::dbgs() << (P.Tok ? P.Tok->TokenText :
"F") <<
"|" << P.Indent.Total
1156 <<
"|" << P.LastSpace <<
"|" << P.NestedBlockIndent <<
" ";
1158 llvm::dbgs() << State.NextToken->TokenText <<
"\n";
1163class LineFormatter {
1165 LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
1166 const FormatStyle &Style,
1167 UnwrappedLineFormatter *BlockFormatter)
1168 : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
1169 BlockFormatter(BlockFormatter) {}
1170 virtual ~LineFormatter() {}
1175 virtual unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1176 unsigned FirstStartColumn,
bool DryRun) = 0;
1199 bool formatChildren(LineState &State,
bool NewLine,
bool DryRun,
1200 unsigned &Penalty) {
1201 const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
1202 bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(
BK_Block);
1204 if (
Previous.Children.empty() || (!HasLBrace && !LBrace->MacroParent)) {
1210 if (NewLine ||
Previous.MacroParent) {
1211 const ParenState &P = State.Stack.back();
1213 int AdditionalIndent =
1214 P.Indent.Total -
Previous.Children[0]->Level * Style.IndentWidth;
1216 BlockFormatter->format(
Previous.Children, DryRun, AdditionalIndent,
1221 if (
Previous.Children[0]->First->MustBreakBefore)
1232 const AnnotatedLine *Child =
Previous.Children[0];
1234 if (Child->Last->isTrailingComment())
1239 if (Style.ColumnLimit > 0 &&
1240 Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit) {
1245 Whitespaces->replaceWhitespace(
1246 *Child->First, 0, 1,
1247 State.Column,
false,
1248 State.Line->InPPDirective);
1251 formatLine(*Child, State.Column + 1, 0, DryRun);
1253 markFinalized(Child->First);
1255 State.Column += 1 + Child->Last->TotalLength;
1259 ContinuationIndenter *Indenter;
1262 WhitespaceManager *Whitespaces;
1263 const FormatStyle &Style;
1264 UnwrappedLineFormatter *BlockFormatter;
1268class NoColumnLimitLineFormatter :
public LineFormatter {
1270 NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
1271 WhitespaceManager *Whitespaces,
1272 const FormatStyle &Style,
1273 UnwrappedLineFormatter *BlockFormatter)
1274 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1278 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1279 unsigned FirstStartColumn,
bool DryRun)
override {
1281 LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
1283 while (State.NextToken) {
1285 Indenter->mustBreak(State) ||
1286 (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
1287 unsigned Penalty = 0;
1288 formatChildren(State, Newline,
false, Penalty);
1289 Indenter->addTokenToState(State, Newline,
false);
1296class NoLineBreakFormatter :
public LineFormatter {
1298 NoLineBreakFormatter(ContinuationIndenter *Indenter,
1299 WhitespaceManager *Whitespaces,
const FormatStyle &Style,
1300 UnwrappedLineFormatter *BlockFormatter)
1301 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1304 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1305 unsigned FirstStartColumn,
bool DryRun)
override {
1306 unsigned Penalty = 0;
1308 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1309 while (State.NextToken) {
1310 formatChildren(State,
false, DryRun, Penalty);
1311 Indenter->addTokenToState(
1312 State, State.NextToken->MustBreakBefore, DryRun);
1319class OptimizingLineFormatter :
public LineFormatter {
1321 OptimizingLineFormatter(ContinuationIndenter *Indenter,
1322 WhitespaceManager *Whitespaces,
1323 const FormatStyle &Style,
1324 UnwrappedLineFormatter *BlockFormatter)
1325 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1329 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1330 unsigned FirstStartColumn,
bool DryRun)
override {
1332 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1337 State.Stack.back().BreakBeforeParameter =
true;
1340 return analyzeSolutionSpace(State, DryRun);
1344 struct CompareLineStatePointers {
1345 bool operator()(LineState *obj1, LineState *obj2)
const {
1346 return *obj1 < *obj2;
1355 typedef std::pair<unsigned, unsigned> OrderedPenalty;
1360 StateNode(
const LineState &State,
bool NewLine, StateNode *
Previous)
1369 typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
1372 typedef std::priority_queue<QueueItem, SmallVector<QueueItem>,
1373 std::greater<QueueItem>>
1384 unsigned analyzeSolutionSpace(LineState &InitialState,
bool DryRun) {
1385 std::set<LineState *, CompareLineStatePointers> Seen;
1393 StateNode *RootNode =
1394 new (Allocator.Allocate()) StateNode(InitialState,
false,
nullptr);
1395 Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode));
1398 unsigned Penalty = 0;
1401 while (!Queue.empty()) {
1403 if (Count > 25'000'000)
1406 Penalty = Queue.top().first.first;
1407 StateNode *Node = Queue.top().second;
1408 if (!Node->State.NextToken) {
1409 LLVM_DEBUG(llvm::dbgs()
1410 <<
"\n---\nPenalty for line: " << Penalty <<
"\n");
1418 Node->State.IgnoreStackForComparison =
true;
1420 if (!Seen.insert(&Node->State).second) {
1425 FormatDecision LastFormat = Node->State.NextToken->getDecision();
1427 addNextStateToQueue(Penalty, Node,
false, &Count, &Queue);
1429 addNextStateToQueue(Penalty, Node,
true, &Count, &Queue);
1432 if (Queue.empty()) {
1435 LLVM_DEBUG(llvm::dbgs() <<
"Could not find a solution.\n");
1441 reconstructPath(InitialState, Queue.top().second);
1443 LLVM_DEBUG(llvm::dbgs()
1444 <<
"Total number of analyzed states: " << Count <<
"\n");
1445 LLVM_DEBUG(llvm::dbgs() <<
"---\n");
1454 void addNextStateToQueue(
unsigned Penalty, StateNode *PreviousNode,
1455 bool NewLine,
unsigned *Count, QueueType *Queue) {
1456 if (NewLine && !Indenter->canBreak(PreviousNode->State))
1458 if (!NewLine && Indenter->mustBreak(PreviousNode->State))
1461 StateNode *Node =
new (Allocator.Allocate())
1462 StateNode(PreviousNode->State, NewLine, PreviousNode);
1463 if (!formatChildren(Node->State, NewLine,
true, Penalty))
1466 Penalty += Indenter->addTokenToState(Node->State, NewLine,
true);
1468 Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
1474 void reconstructPath(LineState &State, StateNode *Best) {
1477 while (Best->Previous) {
1478 Path.push_back(Best);
1479 Best = Best->Previous;
1481 for (
const auto &Node : llvm::reverse(Path)) {
1482 unsigned Penalty = 0;
1483 formatChildren(State, Node->NewLine,
false, Penalty);
1484 Penalty += Indenter->addTokenToState(State, Node->NewLine,
false);
1487 printLineState(Node->Previous->State);
1488 if (Node->NewLine) {
1489 llvm::dbgs() <<
"Penalty for placing "
1490 << Node->Previous->State.NextToken->Tok.getName()
1491 <<
" on a new line: " << Penalty <<
"\n";
1497 llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
1504 int AdditionalIndent,
bool FixBadIndentation,
unsigned FirstStartColumn,
1505 unsigned NextStartColumn,
unsigned LastStartColumn) {
1506 LineJoiner Joiner(Style, Keywords, Lines);
1509 std::pair<const SmallVectorImpl<AnnotatedLine *> *,
unsigned> CacheKey(
1510 &Lines, AdditionalIndent);
1511 auto CacheIt = PenaltyCache.find(CacheKey);
1512 if (DryRun && CacheIt != PenaltyCache.end())
1513 return CacheIt->second;
1515 assert(!Lines.empty());
1516 unsigned Penalty = 0;
1517 LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
1526 bool FirstLine =
true;
1528 Joiner.getNextMergedLine(DryRun, IndentTracker);
1529 Line; PrevPrevLine = PreviousLine, PreviousLine =
Line,
Line = NextLine,
1530 FirstLine =
false) {
1531 assert(
Line->First);
1533 unsigned Indent = IndentTracker.getIndent();
1539 bool PreviousRBrace =
1540 PreviousLine && PreviousLine->
startsWith(tok::r_brace);
1541 bool ContinueFormatting =
1542 TheLine.
Level > RangeMinLevel ||
1543 (TheLine.
Level == RangeMinLevel && !PreviousRBrace &&
1546 bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
1548 bool ShouldFormat = TheLine.
Affected || FixIndentation;
1552 Status->FormatComplete =
false;
1559 bool LastLine = TheLine.
First->
is(tok::eof);
1560 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
Indent,
1561 LastLine ? LastStartColumn : NextStartColumn +
Indent);
1564 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1565 unsigned ColumnLimit = getColumnLimit(TheLine.
InPPDirective, NextLine);
1566 bool FitsIntoOneLine =
1570 (!Style.isJavaScript() || !Style.JavaScriptWrapImports)) ||
1571 (Style.isCSharp() &&
1573 if (Style.ColumnLimit == 0) {
1574 NoColumnLimitLineFormatter(Indenter, Whitespaces, Style,
this)
1575 .formatLine(TheLine, NextStartColumn +
Indent,
1576 FirstLine ? FirstStartColumn : 0, DryRun);
1577 }
else if (FitsIntoOneLine) {
1578 Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style,
this)
1579 .formatLine(TheLine, NextStartColumn +
Indent,
1580 FirstLine ? FirstStartColumn : 0, DryRun);
1582 Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style,
this)
1583 .formatLine(TheLine, NextStartColumn +
Indent,
1584 FirstLine ? FirstStartColumn : 0, DryRun);
1586 RangeMinLevel = std::min(RangeMinLevel, TheLine.
Level);
1592 if (!
Tok->Children.empty())
1598 bool StartsNewLine =
1601 IndentTracker.adjustToUnmodifiedLine(TheLine);
1603 bool ReformatLeadingWhitespace =
1604 StartsNewLine && ((PreviousLine && PreviousLine->
Affected) ||
1607 if (ReformatLeadingWhitespace) {
1608 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
1612 Whitespaces->addUntouchableToken(*TheLine.
First,
1620 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1624 markFinalized(TheLine.
First);
1626 PenaltyCache[CacheKey] = Penalty;
1634 const FormatStyle &Style) {
1635 const auto &RootToken = *
Line.First;
1637 std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
1639 if (RootToken.is(tok::r_brace) &&
1641 (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&
1647 if (!PreviousLine &&
Line.Level > 0)
1649 if (
Newlines == 0 && !RootToken.IsFirst)
1651 if (RootToken.IsFirst &&
1652 (!Style.KeepEmptyLines.AtStartOfFile || !RootToken.HasUnescapedNewline)) {
1657 if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine &&
1658 PreviousLine->
Last->
is(tok::l_brace) &&
1662 !startsExternCBlock(*PreviousLine)) {
1666 if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) {
1668 if (PreviousLine && PreviousLine->
endsWith(TT_NamespaceLBrace)) {
1669 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1671 else if (!
Line.startsWithNamespace())
1675 if (
Line.startsWith(TT_NamespaceRBrace)) {
1676 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1678 else if (!PreviousLine->
startsWith(TT_NamespaceRBrace))
1684 if (PreviousLine && RootToken.isAccessSpecifier()) {
1685 switch (Style.EmptyLineBeforeAccessModifier) {
1686 case FormatStyle::ELBAMS_Never:
1690 case FormatStyle::ELBAMS_Leave:
1691 Newlines = std::max(RootToken.NewlinesBefore, 1u);
1693 case FormatStyle::ELBAMS_LogicalBlock:
1696 if (PreviousLine->
First->isAccessSpecifier())
1699 case FormatStyle::ELBAMS_Always: {
1701 if (PreviousLine->
Last->
is(tok::comment))
1702 previousToken = PreviousLine->
Last->getPreviousNonComment();
1704 previousToken = PreviousLine->
Last;
1705 if ((!previousToken || previousToken->
isNot(tok::l_brace)) &&
1714 if (PreviousLine && PreviousLine->
First->isAccessSpecifier() &&
1715 (!PreviousLine->
InPPDirective || !RootToken.HasUnescapedNewline)) {
1718 if (!RootToken.isAccessSpecifier()) {
1719 switch (Style.EmptyLineAfterAccessModifier) {
1720 case FormatStyle::ELAAMS_Never:
1723 case FormatStyle::ELAAMS_Leave:
1726 case FormatStyle::ELAAMS_Always:
1727 if (RootToken.is(tok::r_brace))
1739void UnwrappedLineFormatter::formatFirstToken(
1740 const AnnotatedLine &
Line,
const AnnotatedLine *PreviousLine,
1741 const AnnotatedLine *PrevPrevLine,
1743 unsigned NewlineIndent) {
1745 if (RootToken.is(tok::eof)) {
1747 RootToken.NewlinesBefore,
1748 Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);
1749 unsigned TokenIndent =
Newlines ? NewlineIndent : 0;
1755 if (RootToken.Newlines < 0) {
1756 RootToken.Newlines =
1758 assert(RootToken.Newlines >= 0);
1761 if (RootToken.Newlines > 0)
1766 if (!Style.isJavaScript() &&
1767 Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash &&
1773 Whitespaces->replaceWhitespace(RootToken, RootToken.Newlines,
Indent,
Indent,
1775 Line.InPPDirective &&
1776 !RootToken.HasUnescapedNewline);
1780UnwrappedLineFormatter::getColumnLimit(
bool InPPDirective,
1784 bool ContinuesPPDirective =
1789 (NextLine->InPPDirective &&
1792 !NextLine->First->HasUnescapedNewline));
1793 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)