13#include "llvm/Support/Debug.h"
16#define DEBUG_TYPE "format-formatter"
23bool startsExternCBlock(
const AnnotatedLine &
Line) {
26 return Line.startsWith(tok::kw_extern) &&
Next &&
Next->isStringLiteral() &&
27 NextNext && NextNext->is(tok::l_brace);
31 return Tok.isOneOf(TT_ClassLBrace, TT_EnumLBrace, TT_RecordLBrace,
32 TT_StructLBrace, TT_UnionLBrace);
44class LevelIndentTracker {
46 LevelIndentTracker(
const FormatStyle &Style,
47 const AdditionalKeywords &Keywords,
unsigned StartLevel,
49 : Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) {
50 for (
unsigned i = 0; i != StartLevel; ++i)
51 IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
55 unsigned getIndent()
const {
return Indent; }
59 void nextLine(
const AnnotatedLine &
Line) {
60 Offset = getIndentOffset(
Line);
63 if (
Line.Level >= IndentForLevel.size())
64 IndentForLevel.resize(
Line.Level + 1, -1);
65 if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave &&
67 Indent =
Line.InMacroBody
68 ? (
Line.Level -
Line.PPLevel) * Style.IndentWidth +
70 :
Line.First->OriginalColumn;
71 }
else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
72 (
Line.InPPDirective ||
73 (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
76 (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
77 Indent =
Line.InMacroBody
79 (
Line.Level -
Line.PPLevel) * Style.IndentWidth
81 Indent += AdditionalIndent;
86 if (!
Line.InPPDirective) {
87 assert(
Line.Level <= IndentForLevel.size());
88 IndentForLevel.resize(
Line.Level + 1);
90 Indent = getIndent(
Line.Level);
92 if (
static_cast<int>(Indent) + Offset >= 0)
94 if (
Line.IsContinuation)
95 Indent =
Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth;
103 void adjustToUnmodifiedLine(
const AnnotatedLine &
Line) {
104 if (
Line.InPPDirective ||
Line.IsContinuation)
106 assert(
Line.Level < IndentForLevel.size());
107 if (
Line.First->is(tok::comment) && IndentForLevel[
Line.Level] != -1)
109 unsigned LevelIndent =
Line.First->OriginalColumn;
110 if (
static_cast<int>(LevelIndent) - Offset >= 0)
111 LevelIndent -= Offset;
112 IndentForLevel[
Line.Level] = LevelIndent;
120 int getIndentOffset(
const AnnotatedLine &
Line) {
121 if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
123 const auto &RootToken = *
Line.First;
125 RootToken.isAccessSpecifier(
false) ||
126 RootToken.isObjCAccessSpecifier() ||
127 (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
128 RootToken.Next && RootToken.Next->is(tok::colon))) {
132 return Style.IndentAccessModifiers ? -Style.IndentWidth
133 : Style.AccessModifierOffset;
143 unsigned getIndent(
unsigned Level)
const {
144 assert(Level < IndentForLevel.size());
145 if (IndentForLevel[Level] != -1)
146 return IndentForLevel[Level];
149 return getIndent(Level - 1) + Style.IndentWidth;
152 const FormatStyle &Style;
153 const AdditionalKeywords &Keywords;
154 const unsigned AdditionalIndent;
173getMatchingNamespaceToken(
const AnnotatedLine *
Line,
175 if (!
Line->startsWith(tok::r_brace))
177 size_t StartLineIndex =
Line->MatchingOpeningBlockLineIndex;
180 assert(StartLineIndex < AnnotatedLines.size());
181 return AnnotatedLines[StartLineIndex]->First->getNamespaceToken();
186 return NamespaceToken ? NamespaceToken->TokenText : StringRef();
190getMatchingNamespaceTokenText(
const AnnotatedLine *
Line,
193 getMatchingNamespaceToken(
Line, AnnotatedLines);
194 return NamespaceToken ? NamespaceToken->TokenText : StringRef();
199 LineJoiner(
const FormatStyle &Style,
const AdditionalKeywords &Keywords,
200 const SmallVectorImpl<AnnotatedLine *> &Lines)
201 : Style(Style), Keywords(Keywords), End(Lines.end()),
Next(Lines.begin()),
202 AnnotatedLines(Lines) {}
205 const AnnotatedLine *getNextMergedLine(
bool DryRun,
206 LevelIndentTracker &IndentTracker) {
209 const AnnotatedLine *Current = *
Next;
210 IndentTracker.nextLine(*Current);
211 unsigned MergedLines = tryFitMultipleLinesInOne(IndentTracker,
Next, End);
212 if (MergedLines > 0 && Style.ColumnLimit == 0) {
215 for (
unsigned i = 0; i < MergedLines; ++i)
216 if (
Next[i + 1]->
First->NewlinesBefore > 0)
220 for (
unsigned i = 0; i < MergedLines; ++i)
229 tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
236 const AnnotatedLine *TheLine = *I;
237 if (TheLine->Last->is(TT_LineComment))
239 const auto &NextLine = *I[1];
240 if (NextLine.Type ==
LT_Invalid || NextLine.First->MustBreakBefore)
242 if (TheLine->InPPDirective &&
243 (!NextLine.InPPDirective || NextLine.First->HasUnescapedNewline)) {
247 const auto Indent = IndentTracker.getIndent();
248 if (Style.ColumnLimit > 0 &&
Indent > Style.ColumnLimit)
255 Limit = TheLine->Last->TotalLength > Limit
257 : Limit - TheLine->Last->TotalLength;
259 if (TheLine->Last->is(TT_FunctionLBrace) &&
260 TheLine->First == TheLine->Last) {
261 const bool EmptyFunctionBody = NextLine.First->is(tok::r_brace);
262 if ((EmptyFunctionBody && !Style.BraceWrapping.SplitEmptyFunction) ||
263 (!EmptyFunctionBody &&
264 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Always)) {
265 return tryMergeSimpleBlock(I, E, Limit);
269 const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] :
nullptr;
271 if (PreviousLine && TheLine->Last->is(tok::l_brace) &&
272 TheLine->First == TheLine->Last) {
273 bool EmptyBlock = NextLine.First->is(tok::r_brace);
276 if (
Tok &&
Tok->is(tok::comment))
277 Tok =
Tok->getNextNonComment();
279 if (
Tok &&
Tok->getNamespaceToken()) {
280 return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock
281 ? tryMergeSimpleBlock(I, E, Limit)
285 if (
Tok &&
Tok->is(tok::kw_typedef))
286 Tok =
Tok->getNextNonComment();
287 if (
Tok &&
Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
288 tok::kw_extern, Keywords.kw_interface,
289 Keywords.kw_record)) {
290 return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
291 ? tryMergeSimpleBlock(I, E, Limit)
295 if (
Tok &&
Tok->is(tok::kw_template) &&
296 Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) {
301 auto ShouldMergeShortFunctions = [
this, &I, &NextLine, PreviousLine,
303 if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All)
305 if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
306 NextLine.First->is(tok::r_brace)) {
310 if (Style.AllowShortFunctionsOnASingleLine &
311 FormatStyle::SFS_InlineOnly) {
314 if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))
317 if (TheLine->Level != 0) {
323 const AnnotatedLine *
Line =
nullptr;
324 for (
auto J = I - 1; J >= AnnotatedLines.begin(); --J) {
326 if (((*J)->InPPDirective && !(*J)->InMacroBody) ||
327 (*J)->isComment() || (*J)->Level > TheLine->Level) {
330 if ((*J)->Level < TheLine->Level ||
331 (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
332 (*J)->First->is(tok::l_brace))) {
342 const auto *LastNonComment =
Line->getLastNonComment();
345 assert(LastNonComment);
346 return isRecordLBrace(*LastNonComment);
353 bool MergeShortFunctions = ShouldMergeShortFunctions();
355 const auto *FirstNonComment = TheLine->getFirstNonComment();
356 if (!FirstNonComment)
362 if (Style.AllowShortNamespacesOnASingleLine &&
363 TheLine->First->is(tok::kw_namespace)) {
364 const auto result = tryMergeNamespace(I, E, Limit);
369 if (Style.CompactNamespaces) {
370 if (
const auto *NSToken = TheLine->First->getNamespaceToken()) {
372 assert(TheLine->MatchingClosingBlockLineIndex > 0);
373 for (
auto ClosingLineIndex = TheLine->MatchingClosingBlockLineIndex - 1;
375 ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
376 I[J]->
Last->TotalLength < Limit;
377 ++J, --ClosingLineIndex) {
378 Limit -= I[J]->Last->TotalLength + 1;
382 auto *ClosingLine = AnnotatedLines.begin() + ClosingLineIndex + 1;
383 const int OutdentBy = I[J]->Level - TheLine->Level;
384 assert(OutdentBy >= 0);
385 for (
auto *CompactedLine = I + J; CompactedLine <= ClosingLine;
387 if (!(*CompactedLine)->InPPDirective) {
388 const int Level = (*CompactedLine)->Level;
389 (*CompactedLine)->Level = std::max(Level - OutdentBy, 0);
396 if (
auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) {
398 unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1;
399 for (; I + 1 + i != E &&
400 nsToken->TokenText ==
401 getMatchingNamespaceTokenText(I[i + 1], AnnotatedLines) &&
402 openingLine == I[i + 1]->MatchingOpeningBlockLineIndex;
403 i++, --openingLine) {
405 I[i + 1]->First->SpacesRequiredBefore =
406 I[i]->Last->isNot(tok::r_brace);
409 IndentTracker.nextLine(*I[i + 1]);
415 const auto *LastNonComment = TheLine->getLastNonComment();
416 assert(LastNonComment);
421 if (LastNonComment->is(TT_FunctionLBrace) &&
422 TheLine->First != LastNonComment) {
423 return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
427 if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
428 (FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
430 TheLine->startsWithExportBlock())) {
431 return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never
432 ? tryMergeSimpleBlock(I, E, Limit)
436 if (NextLine.First->is(TT_ControlStatementLBrace)) {
440 return Style.BraceWrapping.AfterControlStatement ==
441 FormatStyle::BWACS_Always
442 ? tryMergeSimpleBlock(I, E, Limit)
445 if (PreviousLine && TheLine->First->is(tok::l_brace)) {
446 switch (PreviousLine->First->Tok.getKind()) {
449 if (PreviousLine->First->Next &&
450 PreviousLine->First->Next->isOneOf(tok::objc_autoreleasepool,
451 tok::objc_synchronized)) {
457 case tok::kw_default:
468 if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord &&
469 TheLine->Last->is(tok::l_brace) && PreviousLine->Last) {
475 if (
Previous->is(tok::greater) && !PreviousLine->InPPDirective)
477 if (
Previous->is(tok::identifier)) {
480 if (PreviousPrevious &&
481 PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct)) {
489 if (TheLine->First->is(TT_SwitchExpressionLabel)) {
490 return Style.AllowShortCaseExpressionOnASingleLine
491 ? tryMergeShortCaseLabels(I, E, Limit)
495 if (TheLine->Last->is(tok::l_brace)) {
496 bool ShouldMerge =
false;
498 if (TheLine->Last->is(TT_EnumLBrace)) {
499 ShouldMerge = Style.AllowShortEnumsOnASingleLine;
500 }
else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
501 ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
502 }
else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace,
507 ShouldMerge = !Style.BraceWrapping.AfterClass ||
508 (NextLine.First->is(tok::r_brace) &&
509 !Style.BraceWrapping.SplitEmptyRecord);
510 }
else if (TheLine->InPPDirective ||
511 TheLine->First->isNoneOf(tok::kw_class, tok::kw_enum,
512 tok::kw_struct, Keywords.kw_record)) {
515 ShouldMerge = !Style.BraceWrapping.AfterFunction ||
516 (NextLine.First->is(tok::r_brace) &&
517 !Style.BraceWrapping.SplitEmptyFunction);
519 return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit) : 0;
523 if (NextLine.First->is(TT_FunctionLBrace) &&
524 Style.BraceWrapping.AfterFunction) {
525 if (NextLine.Last->is(TT_LineComment))
529 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
533 unsigned MergedLines = 0;
534 if (MergeShortFunctions ||
535 (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
536 NextLine.First == NextLine.Last && I + 2 != E &&
537 I[2]->First->is(tok::r_brace))) {
538 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
546 auto IsElseLine = [&TheLine]() ->
bool {
548 if (
First->is(tok::kw_else))
551 return First->is(tok::r_brace) &&
First->Next &&
552 First->Next->is(tok::kw_else);
554 if (TheLine->First->is(tok::kw_if) ||
555 (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine ==
556 FormatStyle::SIS_AllIfsAndElse))) {
557 return Style.AllowShortIfStatementsOnASingleLine
558 ? tryMergeSimpleControlStatement(I, E, Limit)
561 if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do,
563 return Style.AllowShortLoopsOnASingleLine
564 ? tryMergeSimpleControlStatement(I, E, Limit)
567 if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) {
568 return Style.AllowShortCaseLabelsOnASingleLine
569 ? tryMergeShortCaseLabels(I, E, Limit)
572 if (TheLine->InPPDirective &&
573 (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
574 return tryMergeSimplePPDirective(I, E, Limit);
585 if (I + 2 != E && I[2]->InPPDirective && !I[2]->
First->HasUnescapedNewline)
587 if (1 + I[1]->
Last->TotalLength > Limit)
600 const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace;
601 const auto *BraceOpenLine = I + OpenBraceWrapped;
603 assert(*BraceOpenLine);
604 if (BraceOpenLine[0]->
Last->isNot(TT_NamespaceLBrace))
607 if (std::distance(BraceOpenLine, E) <= 2)
610 if (BraceOpenLine[0]->
Last->is(tok::comment))
613 assert(BraceOpenLine[1]);
614 const auto &L1 = *BraceOpenLine[1];
615 if (L1.InPPDirective != (*I)->InPPDirective ||
616 (L1.InPPDirective && L1.First->HasUnescapedNewline)) {
620 assert(BraceOpenLine[2]);
621 const auto &L2 = *BraceOpenLine[2];
625 Limit = limitConsideringMacros(I + 1, E, Limit);
627 const auto LinesToBeMerged = OpenBraceWrapped + 2;
628 if (!nextNLinesFitInto(I, I + LinesToBeMerged, Limit))
633 if (L1.First->is(tok::kw_namespace)) {
634 if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)
637 assert(Limit >= L1.Last->TotalLength + 3);
638 const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
639 const auto MergedLines =
640 tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit);
641 if (MergedLines == 0)
643 const auto N = MergedLines + LinesToBeMerged;
645 if (std::distance(I, E) <= N)
649 if (I[N]->
First->is(TT_NamespaceRBrace) &&
650 !I[N]->First->MustBreakBefore &&
651 BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) &&
652 nextNLinesFitInto(I, I + N + 1, Limit)) {
662 if (L1.Last->isNot(tok::semi))
666 if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore)
670 return LinesToBeMerged;
679 if (Style.BraceWrapping.AfterControlStatement ==
680 FormatStyle::BWACS_Always &&
681 I[1]->First->is(tok::l_brace) &&
682 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
685 if (I[1]->InPPDirective != (*I)->InPPDirective ||
686 (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) {
689 Limit = limitConsideringMacros(I + 1, E, Limit);
690 AnnotatedLine &
Line = **I;
691 if (
Line.First->isNoneOf(tok::kw_do, tok::kw_else) &&
692 Line.Last->isNoneOf(tok::kw_else, tok::r_paren)) {
696 if (
Line.First->is(tok::kw_do) &&
Line.Last->isNot(tok::kw_do))
698 if (1 + I[1]->
Last->TotalLength > Limit)
701 if (I[1]->
First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,
702 TT_ForEachMacro, TT_LineComment)) {
706 if (Style.AllowShortIfStatementsOnASingleLine ==
707 FormatStyle::SIS_WithoutElse) {
708 if (I + 2 != E &&
Line.startsWith(tok::kw_if) &&
709 I[2]->First->is(tok::kw_else)) {
719 if (Limit == 0 || I + 1 == E ||
720 I[1]->
First->isOneOf(tok::kw_case, tok::kw_default)) {
723 if (I[0]->
Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))
725 unsigned NumStmts = 0;
727 bool EndsWithComment =
false;
728 bool InPPDirective = I[0]->InPPDirective;
729 bool InMacroBody = I[0]->InMacroBody;
730 const unsigned Level = I[0]->Level;
731 for (; NumStmts < 3; ++NumStmts) {
732 if (I + 1 + NumStmts == E)
734 const AnnotatedLine *
Line = I[1 + NumStmts];
735 if (
Line->InPPDirective != InPPDirective)
737 if (
Line->InMacroBody != InMacroBody)
739 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
741 if (
Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
746 if (
Line->First->is(tok::comment)) {
747 if (Level !=
Line->Level)
749 const auto *J = I + 2 + NumStmts;
750 for (; J != E; ++J) {
752 if (
Line->InPPDirective != InPPDirective)
754 if (
Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
756 if (
Line->First->isNot(tok::comment) || Level !=
Line->Level)
761 if (
Line->Last->is(tok::comment))
762 EndsWithComment =
true;
763 Length += I[1 + NumStmts]->Last->TotalLength + 1;
765 if (NumStmts == 0 || NumStmts == 3 || Length > Limit)
777 AnnotatedLine &
Line = **I;
782 if (!Style.isJava() &&
Line.First->isOneOf(tok::at, tok::minus, tok::plus))
787 if (
Line.First->is(tok::kw_case) ||
788 (
Line.First->Next &&
Line.First->Next->is(tok::kw_else))) {
792 if (
Line.First->is(tok::kw_default)) {
794 if (
Tok &&
Tok->is(tok::colon))
798 auto IsCtrlStmt = [](
const auto &
Line) {
799 return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
800 tok::kw_do, tok::kw_for, TT_ForEachMacro);
803 const bool IsSplitBlock =
804 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never ||
805 (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty &&
806 I[1]->First->isNot(tok::r_brace));
808 if (IsCtrlStmt(
Line) ||
809 Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
810 tok::kw___finally, tok::r_brace,
811 Keywords.kw___except) ||
812 Line.startsWithExportBlock()) {
817 if (!Style.AllowShortIfStatementsOnASingleLine &&
818 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
819 !Style.BraceWrapping.AfterControlStatement &&
820 I[1]->First->isNot(tok::r_brace)) {
823 if (!Style.AllowShortIfStatementsOnASingleLine &&
824 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&
825 Style.BraceWrapping.AfterControlStatement ==
826 FormatStyle::BWACS_Always &&
827 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
830 if (!Style.AllowShortLoopsOnASingleLine &&
831 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
833 !Style.BraceWrapping.AfterControlStatement &&
834 I[1]->First->isNot(tok::r_brace)) {
837 if (!Style.AllowShortLoopsOnASingleLine &&
838 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,
840 Style.BraceWrapping.AfterControlStatement ==
841 FormatStyle::BWACS_Always &&
842 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {
850 if (
Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
851 Keywords.kw___except, tok::kw___finally)) {
856 if (
Line.endsWith(tok::l_brace)) {
857 if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never &&
858 Line.First->is(TT_BlockLBrace)) {
862 if (IsSplitBlock &&
Line.First ==
Line.Last &&
863 I > AnnotatedLines.begin() &&
864 (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {
868 auto ShouldMerge = [
Tok]() {
869 if (
Tok->isNot(tok::r_brace) ||
Tok->MustBreakBefore)
872 return !
Next ||
Next->is(tok::semi);
877 Tok->SpacesRequiredBefore =
878 Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never ||
879 Line.Last->is(tok::comment);
880 Tok->CanBreakBefore =
true;
882 }
else if (Limit != 0 && !
Line.startsWithNamespace() &&
883 !startsExternCBlock(
Line)) {
885 if (isRecordLBrace(*
Line.Last))
891 Limit = limitConsideringMacros(I + 2, E, Limit);
893 if (!nextTwoLinesFitInto(I, Limit))
898 if (I[1]->
Last->is(TT_LineComment))
908 if (
Tok->isNot(tok::r_brace))
912 if (
Tok->Next &&
Tok->Next->is(tok::kw_else))
922 Line.First->is(TT_ControlStatementLBrace) &&
923 Style.BraceWrapping.AfterControlStatement ==
924 FormatStyle::BWACS_MultiLine) {
930 }
else if (I[1]->
First->is(tok::l_brace)) {
931 if (I[1]->
Last->is(TT_LineComment))
935 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))
938 unsigned MergedLines = 0;
939 if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never ||
940 (I[1]->First == I[1]->Last && I + 2 != E &&
941 I[2]->First->is(tok::r_brace))) {
942 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
958 if (I[0]->InPPDirective && I + 1 != E &&
959 !I[1]->
First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {
960 return Limit < 2 ? 0 : Limit - 2;
967 if (I[1]->
First->MustBreakBefore || I[2]->First->MustBreakBefore)
969 return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
975 unsigned JoinedLength = 0;
976 for (
const auto *J = I + 1; J != E; ++J) {
977 if ((*J)->First->MustBreakBefore)
980 JoinedLength += 1 + (*J)->Last->TotalLength;
981 if (JoinedLength > Limit)
987 bool containsMustBreak(
const AnnotatedLine *
Line) {
992 if (
Tok->MustBreakBefore)
997 void join(AnnotatedLine &A,
const AnnotatedLine &B) {
998 assert(!A.Last->Next);
999 assert(!B.First->Previous);
1000 if (B.Affected || B.LeadingEmptyLinesAffected) {
1001 assert(B.Affected || A.Last->Children.empty());
1004 A.Last->Next = B.First;
1005 B.First->Previous = A.Last;
1006 B.First->CanBreakBefore =
true;
1007 unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
1009 Tok->TotalLength += LengthA;
1014 const FormatStyle &Style;
1015 const AdditionalKeywords &Keywords;
1019 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
1023 if (
Tok->is(tok::hash) && !
Tok->Previous &&
Tok->Next &&
1024 Tok->Next->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef,
1025 tok::pp_elif, tok::pp_elifdef, tok::pp_elifndef,
1026 tok::pp_else, tok::pp_endif)) {
1042 Tok->SpacesRequiredBefore = 0;
1043 if (!
Tok->MustBreakBeforeFinalized)
1044 Tok->MustBreakBefore = 0;
1046 Tok->Finalized =
true;
1052static void printLineState(
const LineState &State) {
1053 llvm::dbgs() <<
"State: ";
1054 for (
const ParenState &P : State.Stack) {
1055 llvm::dbgs() << (P.Tok ? P.Tok->TokenText :
"F") <<
"|" << P.Indent <<
"|"
1056 << P.LastSpace <<
"|" << P.NestedBlockIndent <<
" ";
1058 llvm::dbgs() << State.NextToken->TokenText <<
"\n";
1063class LineFormatter {
1065 LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,
1066 const FormatStyle &Style,
1067 UnwrappedLineFormatter *BlockFormatter)
1068 : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
1069 BlockFormatter(BlockFormatter) {}
1070 virtual ~LineFormatter() {}
1075 virtual unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1076 unsigned FirstStartColumn,
bool DryRun) = 0;
1099 bool formatChildren(LineState &State,
bool NewLine,
bool DryRun,
1100 unsigned &Penalty) {
1101 const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
1102 bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(
BK_Block);
1104 if (
Previous.Children.empty() || (!HasLBrace && !LBrace->MacroParent)) {
1110 if (NewLine ||
Previous.MacroParent) {
1111 const ParenState &P = State.Stack.back();
1113 int AdditionalIndent =
1114 P.Indent -
Previous.Children[0]->Level * Style.IndentWidth;
1116 BlockFormatter->format(
Previous.Children, DryRun, AdditionalIndent,
1121 if (
Previous.Children[0]->First->MustBreakBefore)
1132 const AnnotatedLine *Child =
Previous.Children[0];
1134 if (Child->Last->isTrailingComment())
1139 if (Style.ColumnLimit > 0 &&
1140 Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit) {
1145 Whitespaces->replaceWhitespace(
1146 *Child->First, 0, 1,
1147 State.Column,
false,
1148 State.Line->InPPDirective);
1151 formatLine(*Child, State.Column + 1, 0, DryRun);
1153 markFinalized(Child->First);
1155 State.Column += 1 + Child->Last->TotalLength;
1159 ContinuationIndenter *Indenter;
1162 WhitespaceManager *Whitespaces;
1163 const FormatStyle &Style;
1164 UnwrappedLineFormatter *BlockFormatter;
1168class NoColumnLimitLineFormatter :
public LineFormatter {
1170 NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,
1171 WhitespaceManager *Whitespaces,
1172 const FormatStyle &Style,
1173 UnwrappedLineFormatter *BlockFormatter)
1174 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1178 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1179 unsigned FirstStartColumn,
bool DryRun)
override {
1181 LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,
1183 while (State.NextToken) {
1185 Indenter->mustBreak(State) ||
1186 (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
1187 unsigned Penalty = 0;
1188 formatChildren(State, Newline,
false, Penalty);
1189 Indenter->addTokenToState(State, Newline,
false);
1196class NoLineBreakFormatter :
public LineFormatter {
1198 NoLineBreakFormatter(ContinuationIndenter *Indenter,
1199 WhitespaceManager *Whitespaces,
const FormatStyle &Style,
1200 UnwrappedLineFormatter *BlockFormatter)
1201 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1204 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1205 unsigned FirstStartColumn,
bool DryRun)
override {
1206 unsigned Penalty = 0;
1208 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1209 while (State.NextToken) {
1210 formatChildren(State,
false, DryRun, Penalty);
1211 Indenter->addTokenToState(
1212 State, State.NextToken->MustBreakBefore, DryRun);
1219class OptimizingLineFormatter :
public LineFormatter {
1221 OptimizingLineFormatter(ContinuationIndenter *Indenter,
1222 WhitespaceManager *Whitespaces,
1223 const FormatStyle &Style,
1224 UnwrappedLineFormatter *BlockFormatter)
1225 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}
1229 unsigned formatLine(
const AnnotatedLine &
Line,
unsigned FirstIndent,
1230 unsigned FirstStartColumn,
bool DryRun)
override {
1232 Indenter->getInitialState(FirstIndent, FirstStartColumn, &
Line, DryRun);
1237 State.Stack.back().BreakBeforeParameter =
true;
1240 return analyzeSolutionSpace(State, DryRun);
1244 struct CompareLineStatePointers {
1245 bool operator()(LineState *obj1, LineState *obj2)
const {
1246 return *obj1 < *obj2;
1255 typedef std::pair<unsigned, unsigned> OrderedPenalty;
1260 StateNode(
const LineState &State,
bool NewLine, StateNode *
Previous)
1269 typedef std::pair<OrderedPenalty, StateNode *> QueueItem;
1272 typedef std::priority_queue<QueueItem, SmallVector<QueueItem>,
1273 std::greater<QueueItem>>
1284 unsigned analyzeSolutionSpace(LineState &InitialState,
bool DryRun) {
1285 std::set<LineState *, CompareLineStatePointers> Seen;
1293 StateNode *RootNode =
1294 new (Allocator.Allocate()) StateNode(InitialState,
false,
nullptr);
1295 Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode));
1298 unsigned Penalty = 0;
1301 while (!Queue.empty()) {
1303 if (Count > 25'000'000)
1306 Penalty = Queue.top().first.first;
1307 StateNode *Node = Queue.top().second;
1308 if (!Node->State.NextToken) {
1309 LLVM_DEBUG(llvm::dbgs()
1310 <<
"\n---\nPenalty for line: " << Penalty <<
"\n");
1318 Node->State.IgnoreStackForComparison =
true;
1320 if (!Seen.insert(&Node->State).second) {
1325 FormatDecision LastFormat = Node->State.NextToken->getDecision();
1327 addNextStateToQueue(Penalty, Node,
false, &Count, &Queue);
1329 addNextStateToQueue(Penalty, Node,
true, &Count, &Queue);
1332 if (Queue.empty()) {
1335 LLVM_DEBUG(llvm::dbgs() <<
"Could not find a solution.\n");
1341 reconstructPath(InitialState, Queue.top().second);
1343 LLVM_DEBUG(llvm::dbgs()
1344 <<
"Total number of analyzed states: " << Count <<
"\n");
1345 LLVM_DEBUG(llvm::dbgs() <<
"---\n");
1354 void addNextStateToQueue(
unsigned Penalty, StateNode *PreviousNode,
1355 bool NewLine,
unsigned *Count, QueueType *Queue) {
1356 if (NewLine && !Indenter->canBreak(PreviousNode->State))
1358 if (!NewLine && Indenter->mustBreak(PreviousNode->State))
1361 StateNode *Node =
new (Allocator.Allocate())
1362 StateNode(PreviousNode->State, NewLine, PreviousNode);
1363 if (!formatChildren(Node->State, NewLine,
true, Penalty))
1366 Penalty += Indenter->addTokenToState(Node->State, NewLine,
true);
1368 Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
1374 void reconstructPath(LineState &State, StateNode *Best) {
1377 while (Best->Previous) {
1378 Path.push_back(Best);
1379 Best = Best->Previous;
1381 for (
const auto &Node : llvm::reverse(Path)) {
1382 unsigned Penalty = 0;
1383 formatChildren(State, Node->NewLine,
false, Penalty);
1384 Penalty += Indenter->addTokenToState(State, Node->NewLine,
false);
1387 printLineState(Node->Previous->State);
1388 if (Node->NewLine) {
1389 llvm::dbgs() <<
"Penalty for placing "
1390 << Node->Previous->State.NextToken->Tok.getName()
1391 <<
" on a new line: " << Penalty <<
"\n";
1397 llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
1404 int AdditionalIndent,
bool FixBadIndentation,
unsigned FirstStartColumn,
1405 unsigned NextStartColumn,
unsigned LastStartColumn) {
1406 LineJoiner Joiner(Style, Keywords, Lines);
1409 std::pair<const SmallVectorImpl<AnnotatedLine *> *,
unsigned> CacheKey(
1410 &Lines, AdditionalIndent);
1411 auto CacheIt = PenaltyCache.find(CacheKey);
1412 if (DryRun && CacheIt != PenaltyCache.end())
1413 return CacheIt->second;
1415 assert(!Lines.empty());
1416 unsigned Penalty = 0;
1417 LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
1426 bool FirstLine =
true;
1428 Joiner.getNextMergedLine(DryRun, IndentTracker);
1429 Line; PrevPrevLine = PreviousLine, PreviousLine =
Line,
Line = NextLine,
1430 FirstLine =
false) {
1431 assert(
Line->First);
1433 unsigned Indent = IndentTracker.getIndent();
1439 bool PreviousRBrace =
1440 PreviousLine && PreviousLine->
startsWith(tok::r_brace);
1441 bool ContinueFormatting =
1442 TheLine.
Level > RangeMinLevel ||
1443 (TheLine.
Level == RangeMinLevel && !PreviousRBrace &&
1446 bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
1448 bool ShouldFormat = TheLine.
Affected || FixIndentation;
1452 Status->FormatComplete =
false;
1459 bool LastLine = TheLine.
First->
is(tok::eof);
1460 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
Indent,
1461 LastLine ? LastStartColumn : NextStartColumn +
Indent);
1464 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1465 unsigned ColumnLimit = getColumnLimit(TheLine.
InPPDirective, NextLine);
1466 bool FitsIntoOneLine =
1470 (!Style.isJavaScript() || !Style.JavaScriptWrapImports)) ||
1471 (Style.isCSharp() &&
1473 if (Style.ColumnLimit == 0) {
1474 NoColumnLimitLineFormatter(Indenter, Whitespaces, Style,
this)
1475 .formatLine(TheLine, NextStartColumn +
Indent,
1476 FirstLine ? FirstStartColumn : 0, DryRun);
1477 }
else if (FitsIntoOneLine) {
1478 Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style,
this)
1479 .formatLine(TheLine, NextStartColumn +
Indent,
1480 FirstLine ? FirstStartColumn : 0, DryRun);
1482 Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style,
this)
1483 .formatLine(TheLine, NextStartColumn +
Indent,
1484 FirstLine ? FirstStartColumn : 0, DryRun);
1486 RangeMinLevel = std::min(RangeMinLevel, TheLine.
Level);
1492 if (!
Tok->Children.empty())
1498 bool StartsNewLine =
1501 IndentTracker.adjustToUnmodifiedLine(TheLine);
1503 bool ReformatLeadingWhitespace =
1504 StartsNewLine && ((PreviousLine && PreviousLine->
Affected) ||
1507 if (ReformatLeadingWhitespace) {
1508 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
1512 Whitespaces->addUntouchableToken(*TheLine.
First,
1520 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
1524 markFinalized(TheLine.
First);
1526 PenaltyCache[CacheKey] = Penalty;
1534 const FormatStyle &Style) {
1535 const auto &RootToken = *
Line.First;
1537 std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
1539 if (RootToken.is(tok::r_brace) &&
1541 (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&
1547 if (!PreviousLine &&
Line.Level > 0)
1549 if (
Newlines == 0 && !RootToken.IsFirst)
1551 if (RootToken.IsFirst &&
1552 (!Style.KeepEmptyLines.AtStartOfFile || !RootToken.HasUnescapedNewline)) {
1557 if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine &&
1558 PreviousLine->
Last->
is(tok::l_brace) &&
1562 !startsExternCBlock(*PreviousLine)) {
1566 if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) {
1568 if (PreviousLine && PreviousLine->
endsWith(TT_NamespaceLBrace)) {
1569 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1571 else if (!
Line.startsWithNamespace())
1575 if (
Line.startsWith(TT_NamespaceRBrace)) {
1576 if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
1578 else if (!PreviousLine->
startsWith(TT_NamespaceRBrace))
1584 if (PreviousLine && RootToken.isAccessSpecifier()) {
1585 switch (Style.EmptyLineBeforeAccessModifier) {
1586 case FormatStyle::ELBAMS_Never:
1590 case FormatStyle::ELBAMS_Leave:
1591 Newlines = std::max(RootToken.NewlinesBefore, 1u);
1593 case FormatStyle::ELBAMS_LogicalBlock:
1596 if (PreviousLine->
First->isAccessSpecifier())
1599 case FormatStyle::ELBAMS_Always: {
1601 if (PreviousLine->
Last->
is(tok::comment))
1602 previousToken = PreviousLine->
Last->getPreviousNonComment();
1604 previousToken = PreviousLine->
Last;
1605 if ((!previousToken || previousToken->
isNot(tok::l_brace)) &&
1614 if (PreviousLine && PreviousLine->
First->isAccessSpecifier() &&
1615 (!PreviousLine->
InPPDirective || !RootToken.HasUnescapedNewline)) {
1618 if (!RootToken.isAccessSpecifier()) {
1619 switch (Style.EmptyLineAfterAccessModifier) {
1620 case FormatStyle::ELAAMS_Never:
1623 case FormatStyle::ELAAMS_Leave:
1626 case FormatStyle::ELAAMS_Always:
1627 if (RootToken.is(tok::r_brace))
1639void UnwrappedLineFormatter::formatFirstToken(
1640 const AnnotatedLine &
Line,
const AnnotatedLine *PreviousLine,
1641 const AnnotatedLine *PrevPrevLine,
1643 unsigned NewlineIndent) {
1645 if (RootToken.is(tok::eof)) {
1647 RootToken.NewlinesBefore,
1648 Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);
1649 unsigned TokenIndent =
Newlines ? NewlineIndent : 0;
1655 if (RootToken.Newlines < 0) {
1656 RootToken.Newlines =
1658 assert(RootToken.Newlines >= 0);
1661 if (RootToken.Newlines > 0)
1666 if (!Style.isJavaScript() &&
1667 Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash &&
1673 Whitespaces->replaceWhitespace(RootToken, RootToken.Newlines,
Indent,
Indent,
1675 Line.InPPDirective &&
1676 !RootToken.HasUnescapedNewline);
1680UnwrappedLineFormatter::getColumnLimit(
bool InPPDirective,
1684 bool ContinuesPPDirective =
1689 (NextLine->InPPDirective &&
1692 !NextLine->First->HasUnescapedNewline));
1693 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)