13#include "llvm/Support/Debug.h"
16#define DEBUG_TYPE "format-formatter"
23bool startsExternCBlock(
const AnnotatedLine &
Line) {
26 return Line.startsWith(tok::kw_extern) &&
Next &&
Next->isStringLiteral() &&
27 NextNext && NextNext->is(tok::l_brace);
31 return Tok.isOneOf(TT_ClassLBrace, TT_EnumLBrace, TT_RecordLBrace,
32 TT_StructLBrace, TT_UnionLBrace);
44class LevelIndentTracker {
46 LevelIndentTracker(
const FormatStyle &Style,
47 const AdditionalKeywords &Keywords,
unsigned StartLevel,
49 : Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) {
50 for (
unsigned i = 0; i != StartLevel; ++i)
51 IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
55 unsigned getIndent()
const {
return Indent; }
59 void nextLine(
const AnnotatedLine &
Line) {
60 Offset = getIndentOffset(
Line);
63 if (
Line.Level >= IndentForLevel.size())
64 IndentForLevel.resize(
Line.Level + 1, -1);
65 if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave &&
67 Indent =
Line.InMacroBody
68 ? (
Line.Level -
Line.PPLevel) * Style.IndentWidth +
70 :
Line.First->OriginalColumn;
71 }
else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
72 (
Line.InPPDirective ||
73 (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
76 (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
77 Indent =
Line.InMacroBody
79 (
Line.Level -
Line.PPLevel) * Style.IndentWidth
81 Indent += AdditionalIndent;
86 if (!
Line.InPPDirective) {
87 assert(
Line.Level <= IndentForLevel.size());
88 IndentForLevel.resize(
Line.Level + 1);
90 Indent = getIndent(
Line.Level);
92 if (
static_cast<int>(Indent) + Offset >= 0)
94 if (
Line.IsContinuation)
95 Indent =
Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth;
103 void adjustToUnmodifiedLine(
const AnnotatedLine &
Line) {
104 if (
Line.InPPDirective ||
Line.IsContinuation)
106 assert(
Line.Level < IndentForLevel.size());
107 if (
Line.First->is(tok::comment) && IndentForLevel[
Line.Level] != -1)
109 unsigned LevelIndent =
Line.First->OriginalColumn;
110 if (
static_cast<int>(LevelIndent) - Offset >= 0)
111 LevelIndent -= Offset;
112 IndentForLevel[
Line.Level] = LevelIndent;
120 int getIndentOffset(
const AnnotatedLine &
Line) {
121 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
123 const auto &RootToken = *
Line.First;
125 RootToken.isAccessSpecifier(
false) ||
126 RootToken.isObjCAccessSpecifier() ||
127 (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
128 RootToken.Next && RootToken.Next->is(tok::colon))) {
132 return Style.IndentAccessModifiers ? -Style.IndentWidth
133 : Style.AccessModifierOffset;
143 unsigned getIndent(
unsigned Level)
const {
144 assert(Level < IndentForLevel.size());
145 if (IndentForLevel[Level] != -1)
146 return IndentForLevel[Level];
149 return getIndent(Level - 1) + Style.IndentWidth;
152 const FormatStyle &Style;
153 const AdditionalKeywords &Keywords;
154 const unsigned AdditionalIndent;
173getMatchingNamespaceToken(
const AnnotatedLine *
Line,
175 if (!
Line->startsWith(tok::r_brace))
177 size_t StartLineIndex =
Line->MatchingOpeningBlockLineIndex;
180 assert(StartLineIndex < AnnotatedLines.size());
181 return AnnotatedLines[StartLineIndex]->First->getNamespaceToken();
186 return NamespaceToken ? NamespaceToken->TokenText : StringRef();
190getMatchingNamespaceTokenText(
const AnnotatedLine *
Line,
193 getMatchingNamespaceToken(
Line, AnnotatedLines);
194 return NamespaceToken ? NamespaceToken->TokenText : StringRef();
199 LineJoiner(
const FormatStyle &Style,
const AdditionalKeywords &Keywords,
200 const SmallVectorImpl<AnnotatedLine *> &Lines)
201 : Style(Style), Keywords(Keywords), End(Lines.end()),
Next(Lines.begin()),
202 AnnotatedLines(Lines) {}
205 const AnnotatedLine *getNextMergedLine(
bool DryRun,
206 LevelIndentTracker &IndentTracker) {
209 const AnnotatedLine *Current = *
Next;
210 IndentTracker.nextLine(*Current);
211 unsigned MergedLines = tryFitMultipleLinesInOne(IndentTracker,
Next, End);
212 if (MergedLines > 0 && Style.ColumnLimit == 0) {
215 for (
unsigned i = 0; i < MergedLines; ++i)
216 if (
Next[i + 1]->
First->NewlinesBefore > 0)
220 for (
unsigned i = 0; i < MergedLines; ++i)
229 tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
236 const AnnotatedLine *TheLine = *I;
237 if (TheLine->Last->is(TT_LineComment))
239 const auto &NextLine = *I[1];
240 if (NextLine.Type ==
LT_Invalid || NextLine.First->MustBreakBefore)
242 if (TheLine->InPPDirective &&
243 (!NextLine.InPPDirective || NextLine.First->HasUnescapedNewline)) {
247 const auto Indent = IndentTracker.getIndent();
248 if (Style.ColumnLimit > 0 &&
Indent > Style.ColumnLimit)
255 Limit = TheLine->Last->TotalLength > Limit
257 : Limit - TheLine->Last->TotalLength;
259 if (TheLine->Last->is(TT_FunctionLBrace) &&
260 TheLine->First == TheLine->Last) {
261 const bool EmptyFunctionBody = NextLine.First->is(tok::r_brace);
262 if ((EmptyFunctionBody && !Style.BraceWrapping.SplitEmptyFunction) ||
263 (!EmptyFunctionBody &&
264 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always)) {
265 return tryMergeSimpleBlock(I, E, Limit);
269 const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] :
nullptr;
271 if (PreviousLine && TheLine->Last->is(tok::l_brace) &&
272 TheLine->First == TheLine->Last) {
273 bool EmptyBlock = NextLine.First->is(tok::r_brace);
276 if (
Tok &&
Tok->is(tok::comment))
277 Tok =
Tok->getNextNonComment();
279 if (
Tok &&
Tok->getNamespaceToken()) {
280 return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
281 ? tryMergeSimpleBlock(I, E, Limit)
285 if (
Tok &&
Tok->is(tok::kw_typedef))
286 Tok =
Tok->getNextNonComment();
287 if (
Tok &&
Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
288 tok::kw_extern, Keywords.kw_interface)) {
289 return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
290 ? tryMergeSimpleBlock(I, E, Limit)
294 if (
Tok &&
Tok->is(tok::kw_template) &&
295 Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) {
300 auto ShouldMergeShortFunctions = [
this, &I, &NextLine, PreviousLine,
302 if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All)
304 if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
305 NextLine.First->is(tok::r_brace)) {
309 if (Style.AllowShortFunctionsOnASingleLine &
310 FormatStyle::SFS_InlineOnly) {
313 if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
316 if (TheLine->Level != 0) {
322 const AnnotatedLine *
Line =
nullptr;
323 for (
auto J = I - 1; J >= AnnotatedLines.begin(); --J) {
325 if (((*J)->InPPDirective && !(*J)->InMacroBody) ||
326 (*J)->isComment() || (*J)->Level > TheLine->Level) {
329 if ((*J)->Level < TheLine->Level ||
330 (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
331 (*J)->First->is(tok::l_brace))) {
341 const auto *LastNonComment =
Line->getLastNonComment();
344 assert(LastNonComment);
345 return isRecordLBrace(*LastNonComment);
352 bool MergeShortFunctions = ShouldMergeShortFunctions();
354 const auto *FirstNonComment = TheLine->getFirstNonComment();
355 if (!FirstNonComment)
361 if (Style.AllowShortNamespacesOnASingleLine &&
362 TheLine->First->is(tok::kw_namespace)) {
363 const auto result = tryMergeNamespace(I, E, Limit);
368 if (Style.CompactNamespaces) {
369 if (
const auto *NSToken = TheLine->First->getNamespaceToken()) {
371 assert(TheLine->MatchingClosingBlockLineIndex > 0);
372 for (
auto ClosingLineIndex = TheLine->MatchingClosingBlockLineIndex - 1;
374 ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
375 I[J]->
Last->TotalLength < Limit;
376 ++J, --ClosingLineIndex) {
377 Limit -= I[J]->Last->TotalLength + 1;
381 auto *ClosingLine = AnnotatedLines.begin() + ClosingLineIndex + 1;
382 const int OutdentBy = I[J]->Level - TheLine->Level;
383 assert(OutdentBy >= 0);
384 for (
auto *CompactedLine = I + J; CompactedLine <= ClosingLine;
386 if (!(*CompactedLine)->InPPDirective) {
387 const int Level = (*CompactedLine)->Level;
388 (*CompactedLine)->Level = std::max(Level - OutdentBy, 0);
395 if (
auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) {
397 unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
398 for (; I + 1 + i != E &&
399 nsToken->TokenText ==
400 getMatchingNamespaceTokenText(I[i + 1], AnnotatedLines) &&
401 openingLine == I[i + 1]->MatchingOpeningBlockLineIndex;
402 i++, --openingLine) {
404 I[i + 1]->First->SpacesRequiredBefore =
405 I[i]->Last->isNot(tok::r_brace);
408 IndentTracker.nextLine(*I[i + 1]);
414 const auto *LastNonComment = TheLine->getLastNonComment();
415 assert(LastNonComment);
420 if (LastNonComment->is(TT_FunctionLBrace) &&
421 TheLine->First != LastNonComment) {
422 return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
426 if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
427 (FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
429 TheLine->startsWithExportBlock())) {
430 return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never
431 ? tryMergeSimpleBlock(I, E, Limit)
435 if (NextLine.First->is(TT_ControlStatementLBrace)) {
439 return Style.BraceWrapping.AfterControlStatement ==
440 FormatStyle::BWACS_Always
441 ? tryMergeSimpleBlock(I, E, Limit)
444 if (PreviousLine && TheLine->First->is(tok::l_brace)) {
445 switch (PreviousLine->First->Tok.getKind()) {
448 if (PreviousLine->First->Next &&
449 PreviousLine->First->Next->isOneOf(tok::objc_autoreleasepool,
450 tok::objc_synchronized)) {
456 case tok::kw_default:
467 if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord &&
468 TheLine->Last->is(tok::l_brace) && PreviousLine->Last) {
474 if (
Previous->is(tok::greater) && !PreviousLine->InPPDirective)
476 if (
Previous->is(tok::identifier)) {
479 if (PreviousPrevious &&
480 PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct)) {
488 if (TheLine->First->is(TT_SwitchExpressionLabel)) {
489 return Style.AllowShortCaseExpressionOnASingleLine
490 ? tryMergeShortCaseLabels(I, E, Limit)
494 if (TheLine->Last->is(tok::l_brace)) {
495 bool ShouldMerge =
false;
497 if (TheLine->Last->is(TT_EnumLBrace)) {
498 ShouldMerge = Style.AllowShortEnumsOnASingleLine;
499 }
else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
500 ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
501 }
else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) {
505 ShouldMerge = !Style.BraceWrapping.AfterClass ||
506 (NextLine.First->is(tok::r_brace) &&
507 !Style.BraceWrapping.SplitEmptyRecord);
508 }
else if (TheLine->InPPDirective ||
509 !TheLine->First->isOneOf(tok::kw_class, tok::kw_enum,
513 ShouldMerge = !Style.BraceWrapping.AfterFunction ||
514 (NextLine.First->is(tok::r_brace) &&
515 !Style.BraceWrapping.SplitEmptyFunction);
517 return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit) : 0;
521 if (NextLine.First->is(TT_FunctionLBrace) &&
522 Style.BraceWrapping.AfterFunction) {
523 if (NextLine.Last->is(TT_LineComment))
527 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
531 unsigned MergedLines = 0;
532 if (MergeShortFunctions ||
533 (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
534 NextLine.First == NextLine.Last && I + 2 != E &&
535 I[2]->First->is(tok::r_brace))) {
536 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
544 auto IsElseLine = [&TheLine]() ->
bool {
546 if (
First->is(tok::kw_else))
549 return First->is(tok::r_brace) &&
First->Next &&
550 First->Next->is(tok::kw_else);
552 if (TheLine->First->is(tok::kw_if) ||
553 (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine ==
554 FormatStyle::SIS_AllIfsAndElse))) {
555 return Style.AllowShortIfStatementsOnASingleLine
556 ? tryMergeSimpleControlStatement(I, E, Limit)
559 if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do,
561 return Style.AllowShortLoopsOnASingleLine
562 ? tryMergeSimpleControlStatement(I, E, Limit)
565 if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) {
566 return Style.AllowShortCaseLabelsOnASingleLine
567 ? tryMergeShortCaseLabels(I, E, Limit)
570 if (TheLine->InPPDirective &&
571 (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
572 return tryMergeSimplePPDirective(I, E, Limit);
583 if (I + 2 != E && I[2]->InPPDirective && !I[2]->
First->HasUnescapedNewline)
585 if (1 + I[1]->
Last->TotalLength > Limit)
598 const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace;
599 const auto *BraceOpenLine = I + OpenBraceWrapped;
601 assert(*BraceOpenLine);
602 if (BraceOpenLine[0]->
Last->isNot(TT_NamespaceLBrace))
605 if (std::distance(BraceOpenLine, E) <= 2)
608 if (BraceOpenLine[0]->
Last->is(tok::comment))
611 assert(BraceOpenLine[1]);
612 const auto &L1 = *BraceOpenLine[1];
613 if (L1.InPPDirective != (*I)->InPPDirective ||
614 (L1.InPPDirective && L1.First->HasUnescapedNewline)) {
618 assert(BraceOpenLine[2]);
619 const auto &L2 = *BraceOpenLine[2];
623 Limit = limitConsideringMacros(I + 1, E, Limit);
625 const auto LinesToBeMerged = OpenBraceWrapped + 2;
626 if (!nextNLinesFitInto(I, I + LinesToBeMerged, Limit))
631 if (L1.First->is(tok::kw_namespace)) {
632 if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)
635 assert(Limit >= L1.Last->TotalLength + 3);
636 const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
637 const auto MergedLines =
638 tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit);
639 if (MergedLines == 0)
641 const auto N = MergedLines + LinesToBeMerged;
643 if (std::distance(I, E) <= N)
647 if (I[N]->
First->is(TT_NamespaceRBrace) &&
648 !I[N]->First->MustBreakBefore &&
649 BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) &&
650 nextNLinesFitInto(I, I + N + 1, Limit)) {
660 if (L1.Last->isNot(tok::semi))
664 if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore)
668 return LinesToBeMerged;
677 if (Style.BraceWrapping.AfterControlStatement ==
678 FormatStyle::BWACS_Always &&
679 I[1]->First->is(tok::l_brace) &&
680 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
683 if (I[1]->InPPDirective != (*I)->InPPDirective ||
684 (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) {
687 Limit = limitConsideringMacros(I + 1, E, Limit);
688 AnnotatedLine &
Line = **I;
689 if (
Line.First->isNot(tok::kw_do) &&
Line.First->isNot(tok::kw_else) &&
690 Line.Last->isNot(tok::kw_else) &&
Line.Last->isNot(tok::r_paren)) {
694 if (
Line.First->is(tok::kw_do) &&
Line.Last->isNot(tok::kw_do))
696 if (1 + I[1]->
Last->TotalLength > Limit)
699 if (I[1]->
First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,
700 TT_ForEachMacro, TT_LineComment)) {
704 if (Style.AllowShortIfStatementsOnASingleLine ==
705 FormatStyle::SIS_WithoutElse) {
706 if (I + 2 != E &&
Line.startsWith(tok::kw_if) &&
707 I[2]->First->is(tok::kw_else)) {
717 if (Limit == 0 || I + 1 == E ||
718 I[1]->
First->isOneOf(tok::kw_case, tok::kw_default)) {
721 if (I[0]->
Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))
723 unsigned NumStmts = 0;
725 bool EndsWithComment =
false;
726 bool InPPDirective = I[0]->InPPDirective;
727 bool InMacroBody = I[0]->InMacroBody;
728 const unsigned Level = I[0]->Level;
729 for (; NumStmts < 3; ++NumStmts) {
730 if (I + 1 + NumStmts == E)
732 const AnnotatedLine *
Line = I[1 + NumStmts];
733 if (
Line->InPPDirective != InPPDirective)
735 if (
Line->InMacroBody != InMacroBody)
737 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
739 if (
Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
744 if (
Line->First->is(tok::comment)) {
745 if (Level !=
Line->Level)
747 const auto *J = I + 2 + NumStmts;
748 for (; J != E; ++J) {
750 if (
Line->InPPDirective != InPPDirective)
752 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
754 if (
Line->First->isNot(tok::comment) || Level !=
Line->Level)
759 if (
Line->Last->is(tok::comment))
760 EndsWithComment =
true;
761 Length += I[1 + NumStmts]->Last->TotalLength + 1;
763 if (NumStmts == 0 || NumStmts == 3 || Length > Limit)
775 AnnotatedLine &
Line = **I;
780 if (!Style.isJava() &&
Line.First->isOneOf(tok::at, tok::minus, tok::plus))
785 if (
Line.First->is(tok::kw_case) ||
786 (
Line.First->Next &&
Line.First->Next->is(tok::kw_else))) {
790 if (
Line.First->is(tok::kw_default)) {
792 if (
Tok &&
Tok->is(tok::colon))
796 auto IsCtrlStmt = [](
const auto &
Line) {
797 return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
798 tok::kw_do, tok::kw_for, TT_ForEachMacro);
801 const bool IsSplitBlock =
802 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never ||
803 (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty &&
804 I[1]->First->isNot(tok::r_brace));
806 if (IsCtrlStmt(
Line) ||
807 Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
808 tok::kw___finally, tok::r_brace,
809 Keywords.kw___except) ||
810 Line.startsWithExportBlock()) {
815 if (!Style.AllowShortIfStatementsOnASingleLine &&
816 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
817 !Style.BraceWrapping.AfterControlStatement &&
818 I[1]->First->isNot(tok::r_brace)) {
821 if (!Style.AllowShortIfStatementsOnASingleLine &&
822 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
823 Style.BraceWrapping.AfterControlStatement ==
824 FormatStyle::BWACS_Always &&
825 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
828 if (!Style.AllowShortLoopsOnASingleLine &&
829 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
831 !Style.BraceWrapping.AfterControlStatement &&
832 I[1]->First->isNot(tok::r_brace)) {
835 if (!Style.AllowShortLoopsOnASingleLine &&
836 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
838 Style.BraceWrapping.AfterControlStatement ==
839 FormatStyle::BWACS_Always &&
840 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
848 if (
Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
849 Keywords.kw___except, tok::kw___finally)) {
854 if (
Line.endsWith(tok::l_brace)) {
855 if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never &&
856 Line.First->is(TT_BlockLBrace)) {
860 if (IsSplitBlock &&
Line.First ==
Line.Last &&
861 I > AnnotatedLines.begin() &&
862 (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {
866 auto ShouldMerge = [
Tok]() {
867 if (
Tok->isNot(tok::r_brace) ||
Tok->MustBreakBefore)
870 return !
Next ||
Next->is(tok::semi);
875 Tok->SpacesRequiredBefore =
876 Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never ||
877 Line.Last->is(tok::comment);
878 Tok->CanBreakBefore =
true;
880 }
else if (Limit != 0 && !
Line.startsWithNamespace() &&
881 !startsExternCBlock(
Line)) {
883 if (isRecordLBrace(*
Line.Last))
889 Limit = limitConsideringMacros(I + 2, E, Limit);
891 if (!nextTwoLinesFitInto(I, Limit))
896 if (I[1]->
Last->is(TT_LineComment))
906 if (
Tok->isNot(tok::r_brace))
910 if (
Tok->Next &&
Tok->Next->is(tok::kw_else))
920 Line.First->is(TT_ControlStatementLBrace) &&
921 Style.BraceWrapping.AfterControlStatement ==
922 FormatStyle::BWACS_MultiLine) {
928 }
else if (I[1]->
First->is(tok::l_brace)) {
929 if (I[1]->
Last->is(TT_LineComment))
933 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))
936 unsigned MergedLines = 0;
937 if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never ||
938 (I[1]->First == I[1]->Last && I + 2 != E &&
939 I[2]->First->is(tok::r_brace))) {
940 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
956 if (I[0]->InPPDirective && I + 1 != E &&
957 !I[1]->
First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {
958 return Limit < 2 ? 0 : Limit - 2;
965 if (I[1]->
First->MustBreakBefore || I[2]->First->MustBreakBefore)
967 return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
973 unsigned JoinedLength = 0;
974 for (
const auto *J = I + 1; J != E; ++J) {
975 if ((*J)->First->MustBreakBefore)
978 JoinedLength += 1 + (*J)->Last->TotalLength;
979 if (JoinedLength > Limit)
985 bool containsMustBreak(
const AnnotatedLine *
Line) {
990 if (
Tok->MustBreakBefore)
995 void join(AnnotatedLine &A,
const AnnotatedLine &B) {
996 assert(!A.Last->Next);
997 assert(!B.First->Previous);
998 if (B.Affected || B.LeadingEmptyLinesAffected) {
999 assert(B.Affected || A.Last->Children.empty());
1002 A.Last->Next = B.First;
1003 B.First->Previous = A.Last;
1004 B.First->CanBreakBefore =
true;
1005 unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
1007 Tok->TotalLength += LengthA;
1012 const FormatStyle &Style;
1013 const AdditionalKeywords &Keywords;
1017 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
1021 if (
Tok->is(tok::hash) && !
Tok->Previous &&
Tok->Next &&
1022 Tok->Next->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef,
1023 tok::pp_elif, tok::pp_elifdef, tok::pp_elifndef,
1024 tok::pp_else, tok::pp_endif)) {
1040 Tok->SpacesRequiredBefore = 0;
1041 if (!
Tok->MustBreakBeforeFinalized)
1042 Tok->MustBreakBefore = 0;
1044 Tok->Finalized =
true;
1050static void printLineState(
const LineState &State) {
1051 llvm::dbgs() <<
"State: ";
1052 for (
const ParenState &P : State.Stack) {
1053 llvm::dbgs() << (P.Tok ? P.Tok->TokenText :
"F") <<
"|" << P.Indent <<
"|"
1054 << P.LastSpace <<
"|" << P.NestedBlockIndent <<
" ";
1056 llvm::dbgs() << State.NextToken->TokenText <<
"\n";
1061class LineFormatter {
1063 LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
1064 const FormatStyle &Style,
1065 UnwrappedLineFormatter *BlockFormatter)
1066 : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
1067 BlockFormatter(BlockFormatter) {}
1068 virtual ~LineFormatter() {}
1073 virtual unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1074 unsigned FirstStartColumn,
bool DryRun) = 0;
1097 bool formatChildren(LineState &State,
bool NewLine,
bool DryRun,
1098 unsigned &Penalty) {
1099 const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
1100 bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(
BK_Block);
1102 if (
Previous.Children.empty() || (!HasLBrace && !LBrace->MacroParent)) {
1108 if (NewLine ||
Previous.MacroParent) {
1109 const ParenState &P = State.Stack.back();
1111 int AdditionalIndent =
1112 P.Indent -
Previous.Children[0]->Level * Style.IndentWidth;
1114 BlockFormatter->format(
Previous.Children, DryRun, AdditionalIndent,
1119 if (
Previous.Children[0]->First->MustBreakBefore)
1130 const AnnotatedLine *Child =
Previous.Children[0];
1132 if (Child->Last->isTrailingComment())
1137 if (Style.ColumnLimit > 0 &&
1138 Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit) {
1143 Whitespaces->replaceWhitespace(
1144 *Child->First, 0, 1,
1145 State.Column,
false,
1146 State.Line->InPPDirective);
1149 formatLine(*Child, State.Column + 1, 0, DryRun);
1151 markFinalized(Child->First);
1153 State.Column += 1 + Child->Last->TotalLength;
1157 ContinuationIndenter *Indenter;
1160 WhitespaceManager *Whitespaces;
1161 const FormatStyle &Style;
1162 UnwrappedLineFormatter *BlockFormatter;
1166class NoColumnLimitLineFormatter :
public LineFormatter {
1168 NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
1169 WhitespaceManager *Whitespaces,
1170 const FormatStyle &Style,
1171 UnwrappedLineFormatter *BlockFormatter)
1172 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1176 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1177 unsigned FirstStartColumn,
bool DryRun)
override {
1179 LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
1181 while (State.NextToken) {
1183 Indenter->mustBreak(State) ||
1184 (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
1185 unsigned Penalty = 0;
1186 formatChildren(State, Newline,
false, Penalty);
1187 Indenter->addTokenToState(State, Newline,
false);
1194class NoLineBreakFormatter :
public LineFormatter {
1196 NoLineBreakFormatter(ContinuationIndenter *Indenter,
1197 WhitespaceManager *Whitespaces,
const FormatStyle &Style,
1198 UnwrappedLineFormatter *BlockFormatter)
1199 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1202 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1203 unsigned FirstStartColumn,
bool DryRun)
override {
1204 unsigned Penalty = 0;
1206 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1207 while (State.NextToken) {
1208 formatChildren(State,
false, DryRun, Penalty);
1209 Indenter->addTokenToState(
1210 State, State.NextToken->MustBreakBefore, DryRun);
1217class OptimizingLineFormatter :
public LineFormatter {
1219 OptimizingLineFormatter(ContinuationIndenter *Indenter,
1220 WhitespaceManager *Whitespaces,
1221 const FormatStyle &Style,
1222 UnwrappedLineFormatter *BlockFormatter)
1223 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1227 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1228 unsigned FirstStartColumn,
bool DryRun)
override {
1230 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1235 State.Stack.back().BreakBeforeParameter =
true;
1238 return analyzeSolutionSpace(State, DryRun);
1242 struct CompareLineStatePointers {
1243 bool operator()(LineState *obj1, LineState *obj2)
const {
1244 return *obj1 < *obj2;
1253 typedef std::pair<unsigned, unsigned> OrderedPenalty;
1258 StateNode(
const LineState &State,
bool NewLine, StateNode *
Previous)
1267 typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
1270 typedef std::priority_queue<QueueItem, SmallVector<QueueItem>,
1271 std::greater<QueueItem>>
1282 unsigned analyzeSolutionSpace(LineState &InitialState,
bool DryRun) {
1283 std::set<LineState *, CompareLineStatePointers> Seen;
1291 StateNode *RootNode =
1292 new (Allocator.Allocate()) StateNode(InitialState,
false,
nullptr);
1293 Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode));
1296 unsigned Penalty = 0;
1299 while (!Queue.empty()) {
1301 if (Count > 25'000'000)
1304 Penalty = Queue.top().first.first;
1305 StateNode *Node = Queue.top().second;
1306 if (!Node->State.NextToken) {
1307 LLVM_DEBUG(llvm::dbgs()
1308 <<
"\n---\nPenalty for line: " << Penalty <<
"\n");
1316 Node->State.IgnoreStackForComparison =
true;
1318 if (!Seen.insert(&Node->State).second) {
1323 FormatDecision LastFormat = Node->State.NextToken->getDecision();
1325 addNextStateToQueue(Penalty, Node,
false, &Count, &Queue);
1327 addNextStateToQueue(Penalty, Node,
true, &Count, &Queue);
1330 if (Queue.empty()) {
1333 LLVM_DEBUG(llvm::dbgs() <<
"Could not find a solution.\n");
1339 reconstructPath(InitialState, Queue.top().second);
1341 LLVM_DEBUG(llvm::dbgs()
1342 <<
"Total number of analyzed states: " << Count <<
"\n");
1343 LLVM_DEBUG(llvm::dbgs() <<
"---\n");
1352 void addNextStateToQueue(
unsigned Penalty, StateNode *PreviousNode,
1353 bool NewLine,
unsigned *Count, QueueType *Queue) {
1354 if (NewLine && !Indenter->canBreak(PreviousNode->State))
1356 if (!NewLine && Indenter->mustBreak(PreviousNode->State))
1359 StateNode *Node =
new (Allocator.Allocate())
1360 StateNode(PreviousNode->State, NewLine, PreviousNode);
1361 if (!formatChildren(Node->State, NewLine,
true, Penalty))
1364 Penalty += Indenter->addTokenToState(Node->State, NewLine,
true);
1366 Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
1372 void reconstructPath(LineState &State, StateNode *Best) {
1375 while (Best->Previous) {
1376 Path.push_back(Best);
1377 Best = Best->Previous;
1379 for (
const auto &Node : llvm::reverse(Path)) {
1380 unsigned Penalty = 0;
1381 formatChildren(State, Node->NewLine,
false, Penalty);
1382 Penalty += Indenter->addTokenToState(State, Node->NewLine,
false);
1385 printLineState(Node->Previous->State);
1386 if (Node->NewLine) {
1387 llvm::dbgs() <<
"Penalty for placing "
1388 << Node->Previous->State.NextToken->Tok.getName()
1389 <<
" on a new line: " << Penalty <<
"\n";
1395 llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
1402 int AdditionalIndent,
bool FixBadIndentation,
unsigned FirstStartColumn,
1403 unsigned NextStartColumn,
unsigned LastStartColumn) {
1404 LineJoiner Joiner(Style, Keywords, Lines);
1407 std::pair<const SmallVectorImpl<AnnotatedLine *> *,
unsigned> CacheKey(
1408 &Lines, AdditionalIndent);
1409 auto CacheIt = PenaltyCache.find(CacheKey);
1410 if (DryRun && CacheIt != PenaltyCache.end())
1411 return CacheIt->second;
1413 assert(!Lines.empty());
1414 unsigned Penalty = 0;
1415 LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
1424 bool FirstLine =
true;
1426 Joiner.getNextMergedLine(DryRun, IndentTracker);
1427 Line; PrevPrevLine = PreviousLine, PreviousLine =
Line,
Line = NextLine,
1428 FirstLine =
false) {
1429 assert(
Line->First);
1431 unsigned Indent = IndentTracker.getIndent();
1437 bool PreviousRBrace =
1438 PreviousLine && PreviousLine->
startsWith(tok::r_brace);
1439 bool ContinueFormatting =
1440 TheLine.
Level > RangeMinLevel ||
1441 (TheLine.
Level == RangeMinLevel && !PreviousRBrace &&
1444 bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
1446 bool ShouldFormat = TheLine.
Affected || FixIndentation;
1450 Status->FormatComplete =
false;
1457 bool LastLine = TheLine.
First->
is(tok::eof);
1458 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
Indent,
1459 LastLine ? LastStartColumn : NextStartColumn +
Indent);
1462 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1463 unsigned ColumnLimit = getColumnLimit(TheLine.
InPPDirective, NextLine);
1464 bool FitsIntoOneLine =
1468 (!Style.isJavaScript() || !Style.JavaScriptWrapImports)) ||
1469 (Style.isCSharp() &&
1471 if (Style.ColumnLimit == 0) {
1472 NoColumnLimitLineFormatter(Indenter, Whitespaces, Style,
this)
1473 .formatLine(TheLine, NextStartColumn +
Indent,
1474 FirstLine ? FirstStartColumn : 0, DryRun);
1475 }
else if (FitsIntoOneLine) {
1476 Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style,
this)
1477 .formatLine(TheLine, NextStartColumn +
Indent,
1478 FirstLine ? FirstStartColumn : 0, DryRun);
1480 Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style,
this)
1481 .formatLine(TheLine, NextStartColumn +
Indent,
1482 FirstLine ? FirstStartColumn : 0, DryRun);
1484 RangeMinLevel = std::min(RangeMinLevel, TheLine.
Level);
1490 if (!
Tok->Children.empty())
1496 bool StartsNewLine =
1499 IndentTracker.adjustToUnmodifiedLine(TheLine);
1501 bool ReformatLeadingWhitespace =
1502 StartsNewLine && ((PreviousLine && PreviousLine->
Affected) ||
1505 if (ReformatLeadingWhitespace) {
1506 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
1510 Whitespaces->addUntouchableToken(*TheLine.
First,
1518 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1522 markFinalized(TheLine.
First);
1524 PenaltyCache[CacheKey] = Penalty;
1532 const FormatStyle &Style) {
1533 const auto &RootToken = *
Line.First;
1535 std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
1537 if (RootToken.is(tok::r_brace) &&
1539 (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&
1545 if (!PreviousLine &&
Line.Level > 0)
1547 if (
Newlines == 0 && !RootToken.IsFirst)
1549 if (RootToken.IsFirst &&
1550 (!Style.KeepEmptyLines.AtStartOfFile || !RootToken.HasUnescapedNewline)) {
1555 if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine &&
1556 PreviousLine->
Last->
is(tok::l_brace) &&
1560 !startsExternCBlock(*PreviousLine)) {
1564 if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) {
1566 if (PreviousLine && PreviousLine->
endsWith(TT_NamespaceLBrace)) {
1567 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1569 else if (!
Line.startsWithNamespace())
1573 if (
Line.startsWith(TT_NamespaceRBrace)) {
1574 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1576 else if (!PreviousLine->
startsWith(TT_NamespaceRBrace))
1582 if (PreviousLine && RootToken.isAccessSpecifier()) {
1583 switch (Style.EmptyLineBeforeAccessModifier) {
1584 case FormatStyle::ELBAMS_Never:
1588 case FormatStyle::ELBAMS_Leave:
1589 Newlines = std::max(RootToken.NewlinesBefore, 1u);
1591 case FormatStyle::ELBAMS_LogicalBlock:
1594 if (PreviousLine->
First->isAccessSpecifier())
1597 case FormatStyle::ELBAMS_Always: {
1599 if (PreviousLine->
Last->
is(tok::comment))
1600 previousToken = PreviousLine->
Last->getPreviousNonComment();
1602 previousToken = PreviousLine->
Last;
1603 if ((!previousToken || previousToken->
isNot(tok::l_brace)) &&
1612 if (PreviousLine && PreviousLine->
First->isAccessSpecifier() &&
1613 (!PreviousLine->
InPPDirective || !RootToken.HasUnescapedNewline)) {
1616 if (!RootToken.isAccessSpecifier()) {
1617 switch (Style.EmptyLineAfterAccessModifier) {
1618 case FormatStyle::ELAAMS_Never:
1621 case FormatStyle::ELAAMS_Leave:
1624 case FormatStyle::ELAAMS_Always:
1625 if (RootToken.is(tok::r_brace))
1637void UnwrappedLineFormatter::formatFirstToken(
1638 const AnnotatedLine &
Line,
const AnnotatedLine *PreviousLine,
1639 const AnnotatedLine *PrevPrevLine,
1641 unsigned NewlineIndent) {
1643 if (RootToken.is(tok::eof)) {
1645 RootToken.NewlinesBefore,
1646 Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);
1647 unsigned TokenIndent =
Newlines ? NewlineIndent : 0;
1653 if (RootToken.Newlines < 0) {
1654 RootToken.Newlines =
1656 assert(RootToken.Newlines >= 0);
1659 if (RootToken.Newlines > 0)
1664 if (!Style.isJavaScript() &&
1665 Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash &&
1671 Whitespaces->replaceWhitespace(RootToken, RootToken.Newlines,
Indent,
Indent,
1673 Line.InPPDirective &&
1674 !RootToken.HasUnescapedNewline);
1678UnwrappedLineFormatter::getColumnLimit(
bool InPPDirective,
1682 bool ContinuesPPDirective =
1687 (NextLine->InPPDirective &&
1690 !NextLine->First->HasUnescapedNewline));
1691 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)