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);
276 const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] :
nullptr;
278 if (PreviousLine && TheLine->Last->is(tok::l_brace) &&
279 TheLine->First == TheLine->Last) {
280 bool EmptyBlock = NextLine.First->is(tok::r_brace);
283 if (
Tok &&
Tok->is(tok::comment))
284 Tok =
Tok->getNextNonComment();
286 if (
Tok &&
Tok->getNamespaceToken()) {
287 return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
288 ? tryMergeSimpleBlock(I, E, Limit)
292 if (
Tok &&
Tok->is(tok::kw_typedef))
293 Tok =
Tok->getNextNonComment();
294 if (
Tok &&
Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
295 tok::kw_extern, Keywords.kw_interface,
296 Keywords.kw_record)) {
297 return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
298 ? tryMergeSimpleBlock(I, E, Limit)
302 if (
Tok &&
Tok->is(tok::kw_template) &&
303 Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) {
308 auto ShouldMergeShortFunctions = [
this, &I, &NextLine, PreviousLine,
310 if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All)
312 if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
313 NextLine.First->is(tok::r_brace)) {
317 if (Style.AllowShortFunctionsOnASingleLine &
318 FormatStyle::SFS_InlineOnly) {
321 if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
324 if (TheLine->Level != 0) {
330 const AnnotatedLine *
Line =
nullptr;
331 for (
auto J = I - 1; J >= AnnotatedLines.begin(); --J) {
333 if (((*J)->InPPDirective && !(*J)->InMacroBody) ||
334 (*J)->isComment() || (*J)->Level > TheLine->Level) {
337 if ((*J)->Level < TheLine->Level ||
338 (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
339 (*J)->First->is(tok::l_brace))) {
349 const auto *LastNonComment =
Line->getLastNonComment();
352 assert(LastNonComment);
353 return isRecordLBrace(*LastNonComment);
360 bool MergeShortFunctions = ShouldMergeShortFunctions();
362 const auto *FirstNonComment = TheLine->getFirstNonComment();
363 if (!FirstNonComment)
369 if (Style.AllowShortNamespacesOnASingleLine &&
370 TheLine->First->is(tok::kw_namespace)) {
371 const auto result = tryMergeNamespace(I, E, Limit);
376 if (Style.CompactNamespaces) {
377 if (
const auto *NSToken = TheLine->First->getNamespaceToken()) {
379 assert(TheLine->MatchingClosingBlockLineIndex > 0);
380 for (
auto ClosingLineIndex = TheLine->MatchingClosingBlockLineIndex - 1;
382 ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
383 I[J]->
Last->TotalLength < Limit;
384 ++J, --ClosingLineIndex) {
385 Limit -= I[J]->Last->TotalLength + 1;
389 auto *ClosingLine = AnnotatedLines.begin() + ClosingLineIndex + 1;
390 const int OutdentBy = I[J]->Level - TheLine->Level;
391 assert(OutdentBy >= 0);
392 for (
auto *CompactedLine = I + J; CompactedLine <= ClosingLine;
394 if (!(*CompactedLine)->InPPDirective) {
395 const int Level = (*CompactedLine)->Level;
396 (*CompactedLine)->Level = std::max(Level - OutdentBy, 0);
403 if (
auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) {
405 unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
406 for (; I + 1 + i != E &&
407 nsToken->TokenText ==
408 getMatchingNamespaceTokenText(I[i + 1], AnnotatedLines) &&
409 openingLine == I[i + 1]->MatchingOpeningBlockLineIndex;
410 i++, --openingLine) {
412 I[i + 1]->First->SpacesRequiredBefore =
413 I[i]->Last->isNot(tok::r_brace);
416 IndentTracker.nextLine(*I[i + 1]);
422 const auto *LastNonComment = TheLine->getLastNonComment();
423 assert(LastNonComment);
428 if (LastNonComment->is(TT_FunctionLBrace) &&
429 TheLine->First != LastNonComment) {
430 return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
434 if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
435 (FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
437 TheLine->startsWithExportBlock())) {
438 return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never
439 ? tryMergeSimpleBlock(I, E, Limit)
443 if (NextLine.First->is(TT_ControlStatementLBrace)) {
447 return Style.BraceWrapping.AfterControlStatement ==
448 FormatStyle::BWACS_Always
449 ? tryMergeSimpleBlock(I, E, Limit)
452 if (PreviousLine && TheLine->First->is(tok::l_brace)) {
453 switch (PreviousLine->First->Tok.getKind()) {
456 if (PreviousLine->First->Next &&
457 PreviousLine->First->Next->isOneOf(tok::objc_autoreleasepool,
458 tok::objc_synchronized)) {
464 case tok::kw_default:
475 if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord &&
476 TheLine->Last->is(tok::l_brace) && PreviousLine->Last) {
482 if (
Previous->is(tok::greater) && !PreviousLine->InPPDirective)
484 if (
Previous->is(tok::identifier)) {
487 if (PreviousPrevious &&
488 PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct)) {
496 if (TheLine->First->is(TT_SwitchExpressionLabel)) {
497 return Style.AllowShortCaseExpressionOnASingleLine
498 ? tryMergeShortCaseLabels(I, E, Limit)
502 if (TheLine->Last->is(tok::l_brace)) {
503 bool ShouldMerge =
false;
505 if (TheLine->Last->is(TT_EnumLBrace)) {
506 ShouldMerge = Style.AllowShortEnumsOnASingleLine;
507 }
else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
508 ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
509 }
else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace,
514 ShouldMerge = !Style.BraceWrapping.AfterClass ||
515 (NextLine.First->is(tok::r_brace) &&
516 !Style.BraceWrapping.SplitEmptyRecord);
517 }
else if (TheLine->InPPDirective ||
518 TheLine->First->isNoneOf(tok::kw_class, tok::kw_enum,
519 tok::kw_struct, Keywords.kw_record)) {
522 ShouldMerge = !Style.BraceWrapping.AfterFunction ||
523 (NextLine.First->is(tok::r_brace) &&
524 !Style.BraceWrapping.SplitEmptyFunction);
526 return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit) : 0;
530 if (NextLine.First->is(TT_FunctionLBrace) &&
531 Style.BraceWrapping.AfterFunction) {
532 if (NextLine.Last->is(TT_LineComment))
536 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
540 unsigned MergedLines = 0;
541 if (MergeShortFunctions ||
542 (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
543 NextLine.First == NextLine.Last && I + 2 != E &&
544 I[2]->First->is(tok::r_brace))) {
545 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
553 auto IsElseLine = [&TheLine]() ->
bool {
555 if (
First->is(tok::kw_else))
558 return First->is(tok::r_brace) &&
First->Next &&
559 First->Next->is(tok::kw_else);
561 if (TheLine->First->is(tok::kw_if) ||
562 (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine ==
563 FormatStyle::SIS_AllIfsAndElse))) {
564 return Style.AllowShortIfStatementsOnASingleLine
565 ? tryMergeSimpleControlStatement(I, E, Limit)
568 if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do,
570 return Style.AllowShortLoopsOnASingleLine
571 ? tryMergeSimpleControlStatement(I, E, Limit)
574 if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) {
575 return Style.AllowShortCaseLabelsOnASingleLine
576 ? tryMergeShortCaseLabels(I, E, Limit)
579 if (TheLine->InPPDirective &&
580 (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
581 return tryMergeSimplePPDirective(I, E, Limit);
592 if (I + 2 != E && I[2]->InPPDirective && !I[2]->
First->HasUnescapedNewline)
594 if (1 + I[1]->
Last->TotalLength > Limit)
607 const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace;
608 const auto *BraceOpenLine = I + OpenBraceWrapped;
610 assert(*BraceOpenLine);
611 if (BraceOpenLine[0]->
Last->isNot(TT_NamespaceLBrace))
614 if (std::distance(BraceOpenLine, E) <= 2)
617 if (BraceOpenLine[0]->
Last->is(tok::comment))
620 assert(BraceOpenLine[1]);
621 const auto &L1 = *BraceOpenLine[1];
622 if (L1.InPPDirective != (*I)->InPPDirective ||
623 (L1.InPPDirective && L1.First->HasUnescapedNewline)) {
627 assert(BraceOpenLine[2]);
628 const auto &L2 = *BraceOpenLine[2];
632 Limit = limitConsideringMacros(I + 1, E, Limit);
634 const auto LinesToBeMerged = OpenBraceWrapped + 2;
635 if (!nextNLinesFitInto(I, I + LinesToBeMerged, Limit))
640 if (L1.First->is(tok::kw_namespace)) {
641 if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)
644 assert(Limit >= L1.Last->TotalLength + 3);
645 const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
646 const auto MergedLines =
647 tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit);
648 if (MergedLines == 0)
650 const auto N = MergedLines + LinesToBeMerged;
652 if (
auto Distance = std::distance(I, E);
653 static_cast<decltype(N)
>(Distance) <= N) {
658 if (I[N]->
First->is(TT_NamespaceRBrace) &&
659 !I[N]->First->MustBreakBefore &&
660 BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) &&
661 nextNLinesFitInto(I, I + N + 1, Limit)) {
671 if (L1.Last->isNot(tok::semi))
675 if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore)
679 return LinesToBeMerged;
688 if (Style.BraceWrapping.AfterControlStatement ==
689 FormatStyle::BWACS_Always &&
690 I[1]->First->is(tok::l_brace) &&
691 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
694 if (I[1]->InPPDirective != (*I)->InPPDirective ||
695 (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) {
698 Limit = limitConsideringMacros(I + 1, E, Limit);
699 AnnotatedLine &
Line = **I;
700 if (
Line.First->isNoneOf(tok::kw_do, tok::kw_else) &&
701 Line.Last->isNoneOf(tok::kw_else, tok::r_paren)) {
705 if (
Line.First->is(tok::kw_do) &&
Line.Last->isNot(tok::kw_do))
707 if (1 + I[1]->
Last->TotalLength > Limit)
710 if (I[1]->
First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,
711 TT_ForEachMacro, TT_LineComment)) {
715 if (Style.AllowShortIfStatementsOnASingleLine ==
716 FormatStyle::SIS_WithoutElse) {
717 if (I + 2 != E &&
Line.startsWith(tok::kw_if) &&
718 I[2]->First->is(tok::kw_else)) {
728 if (Limit == 0 || I + 1 == E ||
729 I[1]->
First->isOneOf(tok::kw_case, tok::kw_default)) {
732 if (I[0]->
Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))
734 unsigned NumStmts = 0;
736 bool EndsWithComment =
false;
737 bool InPPDirective = I[0]->InPPDirective;
738 bool InMacroBody = I[0]->InMacroBody;
739 const unsigned Level = I[0]->Level;
740 for (; NumStmts < 3; ++NumStmts) {
741 if (I + 1 + NumStmts == E)
743 const AnnotatedLine *
Line = I[1 + NumStmts];
744 if (
Line->InPPDirective != InPPDirective)
746 if (
Line->InMacroBody != InMacroBody)
748 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
750 if (
Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
755 if (
Line->First->is(tok::comment)) {
756 if (Level !=
Line->Level)
758 const auto *J = I + 2 + NumStmts;
759 for (; J != E; ++J) {
761 if (
Line->InPPDirective != InPPDirective)
763 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
765 if (
Line->First->isNot(tok::comment) || Level !=
Line->Level)
770 if (
Line->Last->is(tok::comment))
771 EndsWithComment =
true;
772 Length += I[1 + NumStmts]->Last->TotalLength + 1;
774 if (NumStmts == 0 || NumStmts == 3 || Length > Limit)
786 AnnotatedLine &
Line = **I;
791 if (!Style.isJava() &&
Line.First->isOneOf(tok::at, tok::minus, tok::plus))
796 if (
Line.First->is(tok::kw_case) ||
797 (
Line.First->Next &&
Line.First->Next->is(tok::kw_else))) {
801 if (
Line.First->is(tok::kw_default)) {
803 if (
Tok &&
Tok->is(tok::colon))
807 auto IsCtrlStmt = [](
const auto &
Line) {
808 return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
809 tok::kw_do, tok::kw_for, TT_ForEachMacro);
812 const bool IsSplitBlock =
813 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never ||
814 (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty &&
815 I[1]->First->isNot(tok::r_brace));
817 if (IsCtrlStmt(
Line) ||
818 Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
819 tok::kw___finally, tok::r_brace,
820 Keywords.kw___except) ||
821 Line.startsWithExportBlock()) {
826 if (!Style.AllowShortIfStatementsOnASingleLine &&
827 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
828 !Style.BraceWrapping.AfterControlStatement &&
829 I[1]->First->isNot(tok::r_brace)) {
832 if (!Style.AllowShortIfStatementsOnASingleLine &&
833 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
834 Style.BraceWrapping.AfterControlStatement ==
835 FormatStyle::BWACS_Always &&
836 I + 2 != E && I[2]->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 I[1]->First->isNot(tok::r_brace)) {
846 if (!Style.AllowShortLoopsOnASingleLine &&
847 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
849 Style.BraceWrapping.AfterControlStatement ==
850 FormatStyle::BWACS_Always &&
851 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
859 if (
Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
860 Keywords.kw___except, tok::kw___finally)) {
865 if (
Line.endsWith(tok::l_brace)) {
866 if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never &&
867 Line.First->is(TT_BlockLBrace)) {
871 if (IsSplitBlock &&
Line.First ==
Line.Last &&
872 I > AnnotatedLines.begin() &&
873 (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {
877 auto ShouldMerge = [
Tok]() {
878 if (
Tok->isNot(tok::r_brace) ||
Tok->MustBreakBefore)
881 return !
Next ||
Next->is(tok::semi);
886 Tok->SpacesRequiredBefore =
887 Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never ||
888 Line.Last->is(tok::comment);
889 Tok->CanBreakBefore =
true;
891 }
else if (Limit != 0 && !
Line.startsWithNamespace() &&
892 !startsExternCBlock(
Line)) {
894 if (isRecordLBrace(*
Line.Last))
900 Limit = limitConsideringMacros(I + 2, E, Limit);
902 if (!nextTwoLinesFitInto(I, Limit))
907 if (I[1]->
Last->is(TT_LineComment))
917 if (
Tok->isNot(tok::r_brace))
921 if (
Tok->Next &&
Tok->Next->is(tok::kw_else))
931 Line.First->is(TT_ControlStatementLBrace) &&
932 Style.BraceWrapping.AfterControlStatement ==
933 FormatStyle::BWACS_MultiLine) {
939 }
else if (I[1]->
First->is(tok::l_brace)) {
940 if (I[1]->
Last->is(TT_LineComment))
944 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))
947 unsigned MergedLines = 0;
948 if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never ||
949 (I[1]->First == I[1]->Last && I + 2 != E &&
950 I[2]->First->is(tok::r_brace))) {
951 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
967 if (I[0]->InPPDirective && I + 1 != E &&
968 !I[1]->
First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {
969 return Limit < 2 ? 0 : Limit - 2;
976 if (I[1]->
First->MustBreakBefore || I[2]->First->MustBreakBefore)
978 return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
984 unsigned JoinedLength = 0;
985 for (
const auto *J = I + 1; J != E; ++J) {
986 if ((*J)->First->MustBreakBefore)
989 JoinedLength += 1 + (*J)->Last->TotalLength;
990 if (JoinedLength > Limit)
996 bool containsMustBreak(
const AnnotatedLine *
Line) {
1001 if (
Tok->MustBreakBefore)
1006 void join(AnnotatedLine &A,
const AnnotatedLine &B) {
1007 assert(!A.Last->Next);
1008 assert(!B.First->Previous);
1009 if (B.Affected || B.LeadingEmptyLinesAffected) {
1010 assert(B.Affected || A.Last->Children.empty());
1013 A.Last->Next = B.First;
1014 B.First->Previous = A.Last;
1015 B.First->CanBreakBefore =
true;
1016 unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
1018 Tok->TotalLength += LengthA;
1023 const FormatStyle &Style;
1024 const AdditionalKeywords &Keywords;
1028 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
1032 if (
Tok->is(tok::hash) && !
Tok->Previous &&
Tok->Next &&
1033 Tok->Next->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef,
1034 tok::pp_elif, tok::pp_elifdef, tok::pp_elifndef,
1035 tok::pp_else, tok::pp_endif)) {
1051 Tok->SpacesRequiredBefore = 0;
1052 if (!
Tok->MustBreakBeforeFinalized)
1053 Tok->MustBreakBefore = 0;
1055 Tok->Finalized =
true;
1061static void printLineState(
const LineState &State) {
1062 llvm::dbgs() <<
"State: ";
1063 for (
const ParenState &P : State.Stack) {
1064 llvm::dbgs() << (P.Tok ? P.Tok->TokenText :
"F") <<
"|" << P.Indent.Total
1065 <<
"|" << P.LastSpace <<
"|" << P.NestedBlockIndent <<
" ";
1067 llvm::dbgs() << State.NextToken->TokenText <<
"\n";
1072class LineFormatter {
1074 LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
1075 const FormatStyle &Style,
1076 UnwrappedLineFormatter *BlockFormatter)
1077 : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
1078 BlockFormatter(BlockFormatter) {}
1079 virtual ~LineFormatter() {}
1084 virtual unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1085 unsigned FirstStartColumn,
bool DryRun) = 0;
1108 bool formatChildren(LineState &State,
bool NewLine,
bool DryRun,
1109 unsigned &Penalty) {
1110 const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
1111 bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(
BK_Block);
1113 if (
Previous.Children.empty() || (!HasLBrace && !LBrace->MacroParent)) {
1119 if (NewLine ||
Previous.MacroParent) {
1120 const ParenState &P = State.Stack.back();
1122 int AdditionalIndent =
1123 P.Indent.Total -
Previous.Children[0]->Level * Style.IndentWidth;
1125 BlockFormatter->format(
Previous.Children, DryRun, AdditionalIndent,
1130 if (
Previous.Children[0]->First->MustBreakBefore)
1141 const AnnotatedLine *Child =
Previous.Children[0];
1143 if (Child->Last->isTrailingComment())
1148 if (Style.ColumnLimit > 0 &&
1149 Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit) {
1154 Whitespaces->replaceWhitespace(
1155 *Child->First, 0, 1,
1156 State.Column,
false,
1157 State.Line->InPPDirective);
1160 formatLine(*Child, State.Column + 1, 0, DryRun);
1162 markFinalized(Child->First);
1164 State.Column += 1 + Child->Last->TotalLength;
1168 ContinuationIndenter *Indenter;
1171 WhitespaceManager *Whitespaces;
1172 const FormatStyle &Style;
1173 UnwrappedLineFormatter *BlockFormatter;
1177class NoColumnLimitLineFormatter :
public LineFormatter {
1179 NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
1180 WhitespaceManager *Whitespaces,
1181 const FormatStyle &Style,
1182 UnwrappedLineFormatter *BlockFormatter)
1183 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1187 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1188 unsigned FirstStartColumn,
bool DryRun)
override {
1190 LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
1192 while (State.NextToken) {
1194 Indenter->mustBreak(State) ||
1195 (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
1196 unsigned Penalty = 0;
1197 formatChildren(State, Newline,
false, Penalty);
1198 Indenter->addTokenToState(State, Newline,
false);
1205class NoLineBreakFormatter :
public LineFormatter {
1207 NoLineBreakFormatter(ContinuationIndenter *Indenter,
1208 WhitespaceManager *Whitespaces,
const FormatStyle &Style,
1209 UnwrappedLineFormatter *BlockFormatter)
1210 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1213 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1214 unsigned FirstStartColumn,
bool DryRun)
override {
1215 unsigned Penalty = 0;
1217 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1218 while (State.NextToken) {
1219 formatChildren(State,
false, DryRun, Penalty);
1220 Indenter->addTokenToState(
1221 State, State.NextToken->MustBreakBefore, DryRun);
1228class OptimizingLineFormatter :
public LineFormatter {
1230 OptimizingLineFormatter(ContinuationIndenter *Indenter,
1231 WhitespaceManager *Whitespaces,
1232 const FormatStyle &Style,
1233 UnwrappedLineFormatter *BlockFormatter)
1234 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1238 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1239 unsigned FirstStartColumn,
bool DryRun)
override {
1241 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1246 State.Stack.back().BreakBeforeParameter =
true;
1249 return analyzeSolutionSpace(State, DryRun);
1253 struct CompareLineStatePointers {
1254 bool operator()(LineState *obj1, LineState *obj2)
const {
1255 return *obj1 < *obj2;
1264 typedef std::pair<unsigned, unsigned> OrderedPenalty;
1269 StateNode(
const LineState &State,
bool NewLine, StateNode *
Previous)
1278 typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
1281 typedef std::priority_queue<QueueItem, SmallVector<QueueItem>,
1282 std::greater<QueueItem>>
1293 unsigned analyzeSolutionSpace(LineState &InitialState,
bool DryRun) {
1294 std::set<LineState *, CompareLineStatePointers> Seen;
1302 StateNode *RootNode =
1303 new (Allocator.Allocate()) StateNode(InitialState,
false,
nullptr);
1304 Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode));
1307 unsigned Penalty = 0;
1310 while (!Queue.empty()) {
1312 if (Count > 25'000'000)
1315 Penalty = Queue.top().first.first;
1316 StateNode *Node = Queue.top().second;
1317 if (!Node->State.NextToken) {
1318 LLVM_DEBUG(llvm::dbgs()
1319 <<
"\n---\nPenalty for line: " << Penalty <<
"\n");
1327 Node->State.IgnoreStackForComparison =
true;
1329 if (!Seen.insert(&Node->State).second) {
1334 FormatDecision LastFormat = Node->State.NextToken->getDecision();
1336 addNextStateToQueue(Penalty, Node,
false, &Count, &Queue);
1338 addNextStateToQueue(Penalty, Node,
true, &Count, &Queue);
1341 if (Queue.empty()) {
1344 LLVM_DEBUG(llvm::dbgs() <<
"Could not find a solution.\n");
1350 reconstructPath(InitialState, Queue.top().second);
1352 LLVM_DEBUG(llvm::dbgs()
1353 <<
"Total number of analyzed states: " << Count <<
"\n");
1354 LLVM_DEBUG(llvm::dbgs() <<
"---\n");
1363 void addNextStateToQueue(
unsigned Penalty, StateNode *PreviousNode,
1364 bool NewLine,
unsigned *Count, QueueType *Queue) {
1365 if (NewLine && !Indenter->canBreak(PreviousNode->State))
1367 if (!NewLine && Indenter->mustBreak(PreviousNode->State))
1370 StateNode *Node =
new (Allocator.Allocate())
1371 StateNode(PreviousNode->State, NewLine, PreviousNode);
1372 if (!formatChildren(Node->State, NewLine,
true, Penalty))
1375 Penalty += Indenter->addTokenToState(Node->State, NewLine,
true);
1377 Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
1383 void reconstructPath(LineState &State, StateNode *Best) {
1386 while (Best->Previous) {
1387 Path.push_back(Best);
1388 Best = Best->Previous;
1390 for (
const auto &Node : llvm::reverse(Path)) {
1391 unsigned Penalty = 0;
1392 formatChildren(State, Node->NewLine,
false, Penalty);
1393 Penalty += Indenter->addTokenToState(State, Node->NewLine,
false);
1396 printLineState(Node->Previous->State);
1397 if (Node->NewLine) {
1398 llvm::dbgs() <<
"Penalty for placing "
1399 << Node->Previous->State.NextToken->Tok.getName()
1400 <<
" on a new line: " << Penalty <<
"\n";
1406 llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
1413 int AdditionalIndent,
bool FixBadIndentation,
unsigned FirstStartColumn,
1414 unsigned NextStartColumn,
unsigned LastStartColumn) {
1415 LineJoiner Joiner(Style, Keywords, Lines);
1418 std::pair<const SmallVectorImpl<AnnotatedLine *> *,
unsigned> CacheKey(
1419 &Lines, AdditionalIndent);
1420 auto CacheIt = PenaltyCache.find(CacheKey);
1421 if (DryRun && CacheIt != PenaltyCache.end())
1422 return CacheIt->second;
1424 assert(!Lines.empty());
1425 unsigned Penalty = 0;
1426 LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
1435 bool FirstLine =
true;
1437 Joiner.getNextMergedLine(DryRun, IndentTracker);
1438 Line; PrevPrevLine = PreviousLine, PreviousLine =
Line,
Line = NextLine,
1439 FirstLine =
false) {
1440 assert(
Line->First);
1442 unsigned Indent = IndentTracker.getIndent();
1448 bool PreviousRBrace =
1449 PreviousLine && PreviousLine->
startsWith(tok::r_brace);
1450 bool ContinueFormatting =
1451 TheLine.
Level > RangeMinLevel ||
1452 (TheLine.
Level == RangeMinLevel && !PreviousRBrace &&
1455 bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
1457 bool ShouldFormat = TheLine.
Affected || FixIndentation;
1461 Status->FormatComplete =
false;
1468 bool LastLine = TheLine.
First->
is(tok::eof);
1469 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
Indent,
1470 LastLine ? LastStartColumn : NextStartColumn +
Indent);
1473 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1474 unsigned ColumnLimit = getColumnLimit(TheLine.
InPPDirective, NextLine);
1475 bool FitsIntoOneLine =
1479 (!Style.isJavaScript() || !Style.JavaScriptWrapImports)) ||
1480 (Style.isCSharp() &&
1482 if (Style.ColumnLimit == 0) {
1483 NoColumnLimitLineFormatter(Indenter, Whitespaces, Style,
this)
1484 .formatLine(TheLine, NextStartColumn +
Indent,
1485 FirstLine ? FirstStartColumn : 0, DryRun);
1486 }
else if (FitsIntoOneLine) {
1487 Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style,
this)
1488 .formatLine(TheLine, NextStartColumn +
Indent,
1489 FirstLine ? FirstStartColumn : 0, DryRun);
1491 Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style,
this)
1492 .formatLine(TheLine, NextStartColumn +
Indent,
1493 FirstLine ? FirstStartColumn : 0, DryRun);
1495 RangeMinLevel = std::min(RangeMinLevel, TheLine.
Level);
1501 if (!
Tok->Children.empty())
1507 bool StartsNewLine =
1510 IndentTracker.adjustToUnmodifiedLine(TheLine);
1512 bool ReformatLeadingWhitespace =
1513 StartsNewLine && ((PreviousLine && PreviousLine->
Affected) ||
1516 if (ReformatLeadingWhitespace) {
1517 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
1521 Whitespaces->addUntouchableToken(*TheLine.
First,
1529 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1533 markFinalized(TheLine.
First);
1535 PenaltyCache[CacheKey] = Penalty;
1543 const FormatStyle &Style) {
1544 const auto &RootToken = *
Line.First;
1546 std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
1548 if (RootToken.is(tok::r_brace) &&
1550 (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&
1556 if (!PreviousLine &&
Line.Level > 0)
1558 if (
Newlines == 0 && !RootToken.IsFirst)
1560 if (RootToken.IsFirst &&
1561 (!Style.KeepEmptyLines.AtStartOfFile || !RootToken.HasUnescapedNewline)) {
1566 if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine &&
1567 PreviousLine->
Last->
is(tok::l_brace) &&
1571 !startsExternCBlock(*PreviousLine)) {
1575 if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) {
1577 if (PreviousLine && PreviousLine->
endsWith(TT_NamespaceLBrace)) {
1578 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1580 else if (!
Line.startsWithNamespace())
1584 if (
Line.startsWith(TT_NamespaceRBrace)) {
1585 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1587 else if (!PreviousLine->
startsWith(TT_NamespaceRBrace))
1593 if (PreviousLine && RootToken.isAccessSpecifier()) {
1594 switch (Style.EmptyLineBeforeAccessModifier) {
1595 case FormatStyle::ELBAMS_Never:
1599 case FormatStyle::ELBAMS_Leave:
1600 Newlines = std::max(RootToken.NewlinesBefore, 1u);
1602 case FormatStyle::ELBAMS_LogicalBlock:
1605 if (PreviousLine->
First->isAccessSpecifier())
1608 case FormatStyle::ELBAMS_Always: {
1610 if (PreviousLine->
Last->
is(tok::comment))
1611 previousToken = PreviousLine->
Last->getPreviousNonComment();
1613 previousToken = PreviousLine->
Last;
1614 if ((!previousToken || previousToken->
isNot(tok::l_brace)) &&
1623 if (PreviousLine && PreviousLine->
First->isAccessSpecifier() &&
1624 (!PreviousLine->
InPPDirective || !RootToken.HasUnescapedNewline)) {
1627 if (!RootToken.isAccessSpecifier()) {
1628 switch (Style.EmptyLineAfterAccessModifier) {
1629 case FormatStyle::ELAAMS_Never:
1632 case FormatStyle::ELAAMS_Leave:
1635 case FormatStyle::ELAAMS_Always:
1636 if (RootToken.is(tok::r_brace))
1648void UnwrappedLineFormatter::formatFirstToken(
1649 const AnnotatedLine &
Line,
const AnnotatedLine *PreviousLine,
1650 const AnnotatedLine *PrevPrevLine,
1652 unsigned NewlineIndent) {
1654 if (RootToken.is(tok::eof)) {
1656 RootToken.NewlinesBefore,
1657 Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);
1658 unsigned TokenIndent =
Newlines ? NewlineIndent : 0;
1664 if (RootToken.Newlines < 0) {
1665 RootToken.Newlines =
1667 assert(RootToken.Newlines >= 0);
1670 if (RootToken.Newlines > 0)
1675 if (!Style.isJavaScript() &&
1676 Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash &&
1682 Whitespaces->replaceWhitespace(RootToken, RootToken.Newlines,
Indent,
Indent,
1684 Line.InPPDirective &&
1685 !RootToken.HasUnescapedNewline);
1689UnwrappedLineFormatter::getColumnLimit(
bool InPPDirective,
1693 bool ContinuesPPDirective =
1698 (NextLine->InPPDirective &&
1701 !NextLine->First->HasUnescapedNewline));
1702 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)