clang: lib/Format/UnwrappedLineFormatter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

13#include "llvm/Support/Debug.h"

14#include

15

16#define DEBUG_TYPE "format-formatter"

17

19namespace format {

20

21namespace {

22

23bool startsExternCBlock(const AnnotatedLine &Line) {

24 const FormatToken *Next = Line.First->getNextNonComment();

25 const FormatToken *NextNext = Next ? Next->getNextNonComment() : nullptr;

26 return Line.startsWith(tok::kw_extern) && Next && Next->isStringLiteral() &&

27 NextNext && NextNext->is(tok::l_brace);

28}

29

30bool isRecordLBrace(const FormatToken &Tok) {

31 return Tok.isOneOf(TT_ClassLBrace, TT_EnumLBrace, TT_RecordLBrace,

32 TT_StructLBrace, TT_UnionLBrace);

33}

34

35

36

37

38

39

40

41

42

43

44class LevelIndentTracker {

45public:

46 LevelIndentTracker(const FormatStyle &Style,

47 const AdditionalKeywords &Keywords, unsigned StartLevel,

48 int AdditionalIndent)

49 : Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) {

50 for (unsigned i = 0; i != StartLevel; ++i)

51 IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);

52 }

53

54

55 unsigned getIndent() const { return Indent; }

56

57

58

59 void nextLine(const AnnotatedLine &Line) {

60 Offset = getIndentOffset(Line);

61

62

63 if (Line.Level >= IndentForLevel.size())

64 IndentForLevel.resize(Line.Level + 1, -1);

66 (Line.InPPDirective ||

69 unsigned PPIndentWidth =

70 (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;

71 Indent = Line.InMacroBody

72 ? Line.PPLevel * PPIndentWidth +

73 (Line.Level - Line.PPLevel) * Style.IndentWidth

74 : Line.Level * PPIndentWidth;

75 Indent += AdditionalIndent;

76 } else {

77

78

79

80 if (Line.InPPDirective) {

81 assert(Line.Level <= IndentForLevel.size());

82 IndentForLevel.resize(Line.Level + 1);

83 }

84 Indent = getIndent(Line.Level);

85 }

86 if (static_cast<int>(Indent) + Offset >= 0)

87 Indent += Offset;

88 if (Line.IsContinuation)

89 Indent = Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth;

90 }

91

92

93

94

95

96

97 void adjustToUnmodifiedLine(const AnnotatedLine &Line) {

98 if (Line.InPPDirective || Line.IsContinuation)

99 return;

100 assert(Line.Level < IndentForLevel.size());

101 if (Line.First->is(tok::comment) && IndentForLevel[Line.Level] != -1)

102 return;

103 unsigned LevelIndent = Line.First->OriginalColumn;

104 if (static_cast<int>(LevelIndent) - Offset >= 0)

105 LevelIndent -= Offset;

106 IndentForLevel[Line.Level] = LevelIndent;

107 }

108

109private:

110

111

112

113

114 int getIndentOffset(const AnnotatedLine &Line) {

116 Style.isCSharp()) {

117 return 0;

118 }

119

120 auto IsAccessModifier = [&](const FormatToken &RootToken) {

122 return true;

123

124 const auto *Next = RootToken.Next;

125

126

127 if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&

128 Next && Next->is(tok::colon)) {

129 return true;

130 }

131

132 if (Next && Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots) &&

133 Next->Next && Next->Next->is(tok::colon)) {

134 return true;

135 }

136

137

138 return !Next && RootToken.isAccessSpecifier(false);

139 };

140

141 if (IsAccessModifier(*Line.First)) {

142

143

144

145 return Style.IndentAccessModifiers ? -Style.IndentWidth

146 : Style.AccessModifierOffset;

147 }

148

149 return 0;

150 }

151

152

153

154

155

156

157 unsigned getIndent(unsigned Level) const {

158 assert(Level < IndentForLevel.size());

159 if (IndentForLevel[Level] != -1)

160 return IndentForLevel[Level];

161 if (Level == 0)

162 return 0;

163 return getIndent(Level - 1) + Style.IndentWidth;

164 }

165

166 const FormatStyle &Style;

167 const AdditionalKeywords &Keywords;

168 const unsigned AdditionalIndent;

169

170

171

172

173

174 SmallVector IndentForLevel;

175

176

177

178

179

180 int Offset = 0;

181

182

183 unsigned Indent = 0;

184};

185

186const FormatToken *

187getMatchingNamespaceToken(const AnnotatedLine *Line,

188 const ArrayRef<AnnotatedLine *> &AnnotatedLines) {

189 if (Line->startsWith(tok::r_brace))

190 return nullptr;

191 size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex;

193 return nullptr;

194 assert(StartLineIndex < AnnotatedLines.size());

195 return AnnotatedLines[StartLineIndex]->First->getNamespaceToken();

196}

197

199 const FormatToken *NamespaceToken = Line->First->getNamespaceToken();

200 return NamespaceToken ? NamespaceToken->TokenText : StringRef();

201}

202

203StringRef

204getMatchingNamespaceTokenText(const AnnotatedLine *Line,

205 const ArrayRef<AnnotatedLine *> &AnnotatedLines) {

206 const FormatToken *NamespaceToken =

207 getMatchingNamespaceToken(Line, AnnotatedLines);

208 return NamespaceToken ? NamespaceToken->TokenText : StringRef();

209}

210

211class LineJoiner {

212public:

213 LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords,

214 const SmallVectorImpl<AnnotatedLine *> &Lines)

215 : Style(Style), Keywords(Keywords), End(Lines.end()), Next(Lines.begin()),

216 AnnotatedLines(Lines) {}

217

218

219 const AnnotatedLine *getNextMergedLine(bool DryRun,

220 LevelIndentTracker &IndentTracker) {

221 if (Next == End)

222 return nullptr;

223 const AnnotatedLine *Current = *Next;

224 IndentTracker.nextLine(*Current);

225 unsigned MergedLines = tryFitMultipleLinesInOne(IndentTracker, Next, End);

226 if (MergedLines > 0 && Style.ColumnLimit == 0) {

227

228

229 for (unsigned i = 0; i < MergedLines; ++i)

230 if (Next[i + 1]->First->NewlinesBefore > 0)

231 MergedLines = 0;

232 }

233 if (!DryRun)

234 for (unsigned i = 0; i < MergedLines; ++i)

235 join(*Next[0], *Next[i + 1]);

236 Next = Next + MergedLines + 1;

237 return Current;

238 }

239

240private:

241

242 unsigned

243 tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,

244 ArrayRef<AnnotatedLine *>::const_iterator I,

245 ArrayRef<AnnotatedLine *>::const_iterator E) {

246 const unsigned Indent = IndentTracker.getIndent();

247

248

249 if (I + 1 == E)

250 return 0;

251

252 const AnnotatedLine *TheLine = *I;

253 if (TheLine->Last->is(TT_LineComment))

254 return 0;

255 const auto &NextLine = *I[1];

256 if (NextLine.Type == LT_Invalid || NextLine.First->MustBreakBefore)

257 return 0;

258 if (TheLine->InPPDirective &&

259 (!NextLine.InPPDirective || NextLine.First->HasUnescapedNewline)) {

260 return 0;

261 }

262

263 if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)

264 return 0;

265

266 unsigned Limit =

267 Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent;

268

269

270 Limit = TheLine->Last->TotalLength > Limit

271 ? 0

272 : Limit - TheLine->Last->TotalLength;

273

274 if (TheLine->Last->is(TT_FunctionLBrace) &&

275 TheLine->First == TheLine->Last &&

276 !Style.BraceWrapping.SplitEmptyFunction &&

277 NextLine.First->is(tok::r_brace)) {

278 return tryMergeSimpleBlock(I, E, Limit);

279 }

280

281 const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1] : nullptr;

282

283 if (PreviousLine && TheLine->Last->is(tok::l_brace) &&

284 TheLine->First == TheLine->Last) {

285 bool EmptyBlock = NextLine.First->is(tok::r_brace);

286

287 const FormatToken *Tok = PreviousLine->First;

288 if (Tok && Tok->is(tok::comment))

289 Tok = Tok->getNextNonComment();

290

291 if (Tok && Tok->getNamespaceToken()) {

292 return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock

293 ? tryMergeSimpleBlock(I, E, Limit)

294 : 0;

295 }

296

297 if (Tok && Tok->is(tok::kw_typedef))

298 Tok = Tok->getNextNonComment();

299 if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,

300 tok::kw_extern, Keywords.kw_interface)) {

301 return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock

302 ? tryMergeSimpleBlock(I, E, Limit)

303 : 0;

304 }

305

306 if (Tok && Tok->is(tok::kw_template) &&

307 Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) {

308 return 0;

309 }

310 }

311

312 auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine,

313 TheLine]() {

315 return true;

317 NextLine.First->is(tok::r_brace)) {

318 return true;

319 }

320

321 if (Style.AllowShortFunctionsOnASingleLine &

323

324

325 if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace))

326 return true;

327

328 if (TheLine->Level != 0) {

329 if (!PreviousLine)

330 return false;

331

332

333

334 const AnnotatedLine *Line = nullptr;

335 for (auto J = I - 1; J >= AnnotatedLines.begin(); --J) {

336 assert(*J);

337 if (!(*J)->InPPDirective && !(*J)->isComment() &&

338 (*J)->Level < TheLine->Level) {

340 break;

341 }

342 }

343

345 return false;

346

347

348 const auto *LastNonComment = Line->getLastNonComment();

349

350

351 assert(LastNonComment);

352 return isRecordLBrace(*LastNonComment);

353 }

354 }

355

356 return false;

357 };

358

359 bool MergeShortFunctions = ShouldMergeShortFunctions();

360

361 const auto *FirstNonComment = TheLine->getFirstNonComment();

362 if (!FirstNonComment)

363 return 0;

364

365

366

367

368 if (Style.AllowShortNamespacesOnASingleLine &&

369 TheLine->First->is(tok::kw_namespace) &&

370 TheLine->Last->is(tok::l_brace)) {

371 const auto result = tryMergeNamespace(I, E, Limit);

372 if (result > 0)

373 return result;

374 }

375

376 if (Style.CompactNamespaces) {

377 if (const auto *NSToken = TheLine->First->getNamespaceToken()) {

378 int J = 1;

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;

386

387

388

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;

393 ++CompactedLine) {

394 if (!(*CompactedLine)->InPPDirective) {

395 const int Level = (*CompactedLine)->Level;

396 (*CompactedLine)->Level = std::max(Level - OutdentBy, 0);

397 }

398 }

399 }

400 return J - 1;

401 }

402

403 if (auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) {

404 int i = 0;

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) {

411

412 I[i + 1]->First->SpacesRequiredBefore =

413 I[i]->Last->isNot(tok::r_brace);

414

415

416 IndentTracker.nextLine(*I[i + 1]);

417 }

418 return i;

419 }

420 }

421

422 const auto *LastNonComment = TheLine->getLastNonComment();

423 assert(LastNonComment);

424

425

426

427

428 if (LastNonComment->is(TT_FunctionLBrace) &&

429 TheLine->First != LastNonComment) {

430 return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;

431 }

432

433

434 if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&

435 (FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,

436 TT_ForEachMacro) ||

437 TheLine->startsWithExportBlock())) {

439 ? tryMergeSimpleBlock(I, E, Limit)

440 : 0;

441 }

442

443 if (NextLine.First->is(tok::l_brace)) {

444 if ((TheLine->First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,

445 tok::kw_for, tok::kw_switch, tok::kw_try,

446 tok::kw_do, TT_ForEachMacro) ||

447 (TheLine->First->is(tok::r_brace) && TheLine->First->Next &&

448 TheLine->First->Next->isOneOf(tok::kw_else, tok::kw_catch))) &&

449 Style.BraceWrapping.AfterControlStatement ==

451

452

453

454 return (Style.ColumnLimit == 0 || TheLine->Level * Style.IndentWidth +

455 TheLine->Last->TotalLength <=

456 Style.ColumnLimit)

457 ? 1

458 : 0;

459 }

460 if (TheLine->First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,

461 tok::kw_for, TT_ForEachMacro)) {

462 return (Style.BraceWrapping.AfterControlStatement ==

464 ? tryMergeSimpleBlock(I, E, Limit)

465 : 0;

466 }

467 if (TheLine->First->isOneOf(tok::kw_else, tok::kw_catch) &&

468 Style.BraceWrapping.AfterControlStatement ==

470

471

472

473

474

475 return (Style.ColumnLimit == 0 ||

476 TheLine->Last->TotalLength <= Style.ColumnLimit)

477 ? 1

478 : 0;

479 }

480 }

481 if (PreviousLine && TheLine->First->is(tok::l_brace)) {

482 switch (PreviousLine->First->Tok.getKind()) {

483 case tok::at:

484

485 if (PreviousLine->First->Next) {

487 PreviousLine->First->Next->Tok.getObjCKeywordID();

488 if (kwId == tok::objc_autoreleasepool ||

489 kwId == tok::objc_synchronized) {

490 return 0;

491 }

492 }

493 break;

494

495 case tok::kw_case:

496 case tok::kw_default:

497

498 return 0;

499

500 default:

501 break;

502 }

503 }

504

505

506

507 if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord &&

508 TheLine->Last->is(tok::l_brace) && PreviousLine->Last) {

509 const FormatToken *Previous = PreviousLine->Last;

511 if (Previous->is(tok::comment))

514 if (Previous->is(tok::greater) && !PreviousLine->InPPDirective)

515 return 0;

516 if (Previous->is(tok::identifier)) {

517 const FormatToken *PreviousPrevious =

518 Previous->getPreviousNonComment();

519 if (PreviousPrevious &&

520 PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct)) {

521 return 0;

522 }

523 }

524 }

525 }

526 }

527

528 if (TheLine->First->is(TT_SwitchExpressionLabel)) {

529 return Style.AllowShortCaseExpressionOnASingleLine

530 ? tryMergeShortCaseLabels(I, E, Limit)

531 : 0;

532 }

533

534 if (TheLine->Last->is(tok::l_brace)) {

535 bool ShouldMerge = false;

536

537 if (TheLine->Last->is(TT_EnumLBrace)) {

538 ShouldMerge = Style.AllowShortEnumsOnASingleLine;

539 } else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {

540 ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;

541 } else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) {

542

543

544

545 ShouldMerge = !Style.BraceWrapping.AfterClass ||

546 (NextLine.First->is(tok::r_brace) &&

547 !Style.BraceWrapping.SplitEmptyRecord);

548 } else if (TheLine->InPPDirective ||

549 !TheLine->First->isOneOf(tok::kw_class, tok::kw_enum,

550 tok::kw_struct)) {

551

552

553 ShouldMerge = !Style.BraceWrapping.AfterFunction ||

554 (NextLine.First->is(tok::r_brace) &&

555 !Style.BraceWrapping.SplitEmptyFunction);

556 }

557 return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit) : 0;

558 }

559

560

561 if (NextLine.First->is(TT_FunctionLBrace) &&

562 Style.BraceWrapping.AfterFunction) {

563 if (NextLine.Last->is(TT_LineComment))

564 return 0;

565

566

567 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))

568 return 0;

569 Limit -= 2;

570

571 unsigned MergedLines = 0;

572 if (MergeShortFunctions ||

574 NextLine.First == NextLine.Last && I + 2 != E &&

575 I[2]->First->is(tok::r_brace))) {

576 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);

577

578

579 if (MergedLines > 0)

580 ++MergedLines;

581 }

582 return MergedLines;

583 }

584 auto IsElseLine = [&TheLine]() -> bool {

585 const FormatToken *First = TheLine->First;

586 if (First->is(tok::kw_else))

587 return true;

588

589 return First->is(tok::r_brace) && First->Next &&

590 First->Next->is(tok::kw_else);

591 };

592 if (TheLine->First->is(tok::kw_if) ||

593 (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine ==

595 return Style.AllowShortIfStatementsOnASingleLine

596 ? tryMergeSimpleControlStatement(I, E, Limit)

597 : 0;

598 }

599 if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do,

600 TT_ForEachMacro)) {

601 return Style.AllowShortLoopsOnASingleLine

602 ? tryMergeSimpleControlStatement(I, E, Limit)

603 : 0;

604 }

605 if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) {

606 return Style.AllowShortCaseLabelsOnASingleLine

607 ? tryMergeShortCaseLabels(I, E, Limit)

608 : 0;

609 }

610 if (TheLine->InPPDirective &&

611 (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {

612 return tryMergeSimplePPDirective(I, E, Limit);

613 }

614 return 0;

615 }

616

617 unsigned

618 tryMergeSimplePPDirective(ArrayRef<AnnotatedLine *>::const_iterator I,

619 ArrayRef<AnnotatedLine *>::const_iterator E,

620 unsigned Limit) {

621 if (Limit == 0)

622 return 0;

623 if (I + 2 != E && I[2]->InPPDirective && !I[2]->First->HasUnescapedNewline)

624 return 0;

625 if (1 + I[1]->Last->TotalLength > Limit)

626 return 0;

627 return 1;

628 }

629

630 unsigned tryMergeNamespace(ArrayRef<AnnotatedLine *>::const_iterator I,

631 ArrayRef<AnnotatedLine *>::const_iterator E,

632 unsigned Limit) {

633 if (Limit == 0)

634 return 0;

635

636 assert(I[1]);

637 const auto &L1 = *I[1];

638 if (L1.InPPDirective != (*I)->InPPDirective ||

639 (L1.InPPDirective && L1.First->HasUnescapedNewline)) {

640 return 0;

641 }

642

643 if (std::distance(I, E) <= 2)

644 return 0;

645

646 assert(I[2]);

647 const auto &L2 = *I[2];

649 return 0;

650

651 Limit = limitConsideringMacros(I + 1, E, Limit);

652

653 if (!nextTwoLinesFitInto(I, Limit))

654 return 0;

655

656

657

658 if (L1.First->is(tok::kw_namespace)) {

659 if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)

660 return 0;

661

662 assert(Limit >= L1.Last->TotalLength + 3);

663 const auto InnerLimit = Limit - L1.Last->TotalLength - 3;

664 const auto MergedLines = tryMergeNamespace(I + 1, E, InnerLimit);

665 if (MergedLines == 0)

666 return 0;

667 const auto N = MergedLines + 2;

668

669 if (std::distance(I, E) <= N)

670 return 0;

671

672

673 if (I[N]->First->is(tok::r_brace) && !I[N]->First->MustBreakBefore &&

674 I[MergedLines + 1]->Last->isNot(tok::comment) &&

675 nextNLinesFitInto(I, I + N + 1, Limit)) {

676 return N;

677 }

678 return 0;

679 }

680

681

682

683

684

685 if (L1.Last->isNot(tok::semi))

686 return 0;

687

688

689 if (L2.First->isNot(tok::r_brace) || L2.First->MustBreakBefore)

690 return 0;

691

692

693 return 2;

694 }

695

696 unsigned

697 tryMergeSimpleControlStatement(ArrayRef<AnnotatedLine *>::const_iterator I,

698 ArrayRef<AnnotatedLine *>::const_iterator E,

699 unsigned Limit) {

700 if (Limit == 0)

701 return 0;

702 if (Style.BraceWrapping.AfterControlStatement ==

704 I[1]->First->is(tok::l_brace) &&

706 return 0;

707 }

708 if (I[1]->InPPDirective != (*I)->InPPDirective ||

709 (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) {

710 return 0;

711 }

712 Limit = limitConsideringMacros(I + 1, E, Limit);

713 AnnotatedLine &Line = **I;

714 if (Line.First->isNot(tok::kw_do) && Line.First->isNot(tok::kw_else) &&

715 Line.Last->isNot(tok::kw_else) && Line.Last->isNot(tok::r_paren)) {

716 return 0;

717 }

718

719 if (Line.First->is(tok::kw_do) && Line.Last->isNot(tok::kw_do))

720 return 0;

721 if (1 + I[1]->Last->TotalLength > Limit)

722 return 0;

723

724 if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,

725 TT_ForEachMacro, TT_LineComment)) {

726 return 0;

727 }

728

729 if (Style.AllowShortIfStatementsOnASingleLine ==

731 if (I + 2 != E && Line.startsWith(tok::kw_if) &&

732 I[2]->First->is(tok::kw_else)) {

733 return 0;

734 }

735 }

736 return 1;

737 }

738

739 unsigned tryMergeShortCaseLabels(ArrayRef<AnnotatedLine *>::const_iterator I,

740 ArrayRef<AnnotatedLine *>::const_iterator E,

741 unsigned Limit) {

742 if (Limit == 0 || I + 1 == E ||

743 I[1]->First->isOneOf(tok::kw_case, tok::kw_default)) {

744 return 0;

745 }

746 if (I[0]->Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace))

747 return 0;

748 unsigned NumStmts = 0;

749 unsigned Length = 0;

750 bool EndsWithComment = false;

751 bool InPPDirective = I[0]->InPPDirective;

752 bool InMacroBody = I[0]->InMacroBody;

753 const unsigned Level = I[0]->Level;

754 for (; NumStmts < 3; ++NumStmts) {

755 if (I + 1 + NumStmts == E)

756 break;

757 const AnnotatedLine *Line = I[1 + NumStmts];

758 if (Line->InPPDirective != InPPDirective)

759 break;

760 if (Line->InMacroBody != InMacroBody)

761 break;

762 if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))

763 break;

764 if (Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,

765 tok::kw_while) ||

766 EndsWithComment) {

767 return 0;

768 }

769 if (Line->First->is(tok::comment)) {

770 if (Level != Line->Level)

771 return 0;

772 const auto *J = I + 2 + NumStmts;

773 for (; J != E; ++J) {

775 if (Line->InPPDirective != InPPDirective)

776 break;

777 if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))

778 break;

779 if (Line->First->isNot(tok::comment) || Level != Line->Level)

780 return 0;

781 }

782 break;

783 }

784 if (Line->Last->is(tok::comment))

785 EndsWithComment = true;

786 Length += I[1 + NumStmts]->Last->TotalLength + 1;

787 }

788 if (NumStmts == 0 || NumStmts == 3 || Length > Limit)

789 return 0;

790 return NumStmts;

791 }

792

793 unsigned tryMergeSimpleBlock(ArrayRef<AnnotatedLine *>::const_iterator I,

794 ArrayRef<AnnotatedLine *>::const_iterator E,

795 unsigned Limit) {

796

798 return 0;

799

800 AnnotatedLine &Line = **I;

801

802

803

804

806 Line.First->isOneOf(tok::at, tok::minus, tok::plus)) {

807 return 0;

808 }

809

810

811

812 if (Line.First->is(tok::kw_case) ||

813 (Line.First->Next && Line.First->Next->is(tok::kw_else))) {

814 return 0;

815 }

816

817 if (Line.First->is(tok::kw_default)) {

818 const FormatToken *Tok = Line.First->getNextNonComment();

819 if (Tok && Tok->is(tok::colon))

820 return 0;

821 }

822

823 auto IsCtrlStmt = [](const auto &Line) {

824 return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,

825 tok::kw_do, tok::kw_for, TT_ForEachMacro);

826 };

827

828 const bool IsSplitBlock =

831 I[1]->First->isNot(tok::r_brace));

832

833 if (IsCtrlStmt(Line) ||

834 Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,

835 tok::kw___finally, tok::r_brace,

836 Keywords.kw___except) ||

837 Line.startsWithExportBlock()) {

838 if (IsSplitBlock)

839 return 0;

840

841

842 if (!Style.AllowShortIfStatementsOnASingleLine &&

843 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&

844 !Style.BraceWrapping.AfterControlStatement &&

845 I[1]->First->isNot(tok::r_brace)) {

846 return 0;

847 }

848 if (!Style.AllowShortIfStatementsOnASingleLine &&

849 Line.First->isOneOf(tok::kw_if, tok::kw_else) &&

850 Style.BraceWrapping.AfterControlStatement ==

852 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {

853 return 0;

854 }

855 if (!Style.AllowShortLoopsOnASingleLine &&

856 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,

857 TT_ForEachMacro) &&

858 !Style.BraceWrapping.AfterControlStatement &&

859 I[1]->First->isNot(tok::r_brace)) {

860 return 0;

861 }

862 if (!Style.AllowShortLoopsOnASingleLine &&

863 Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for,

864 TT_ForEachMacro) &&

865 Style.BraceWrapping.AfterControlStatement ==

867 I + 2 != E && I[2]->First->isNot(tok::r_brace)) {

868 return 0;

869 }

870

871

872

873

874

875 if (Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,

876 Keywords.kw___except, tok::kw___finally)) {

877 return 0;

878 }

879 }

880

881 if (Line.endsWith(tok::l_brace)) {

883 Line.First->is(TT_BlockLBrace)) {

884 return 0;

885 }

886

887 if (IsSplitBlock && Line.First == Line.Last &&

888 I > AnnotatedLines.begin() &&

889 (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {

890 return 0;

891 }

892 FormatToken *Tok = I[1]->First;

893 auto ShouldMerge = [Tok]() {

894 if (Tok->isNot(tok::r_brace) || Tok->MustBreakBefore)

895 return false;

896 const FormatToken *Next = Tok->getNextNonComment();

897 return !Next || Next->is(tok::semi);

898 };

899

900 if (ShouldMerge()) {

901

902 Tok->SpacesRequiredBefore =

903 (Style.SpaceInEmptyBlock || Line.Last->is(tok::comment)) ? 1 : 0;

904 Tok->CanBreakBefore = true;

905 return 1;

906 } else if (Limit != 0 && Line.startsWithNamespace() &&

907 !startsExternCBlock(Line)) {

908

909 if (isRecordLBrace(*Line.Last))

910 return 0;

911

912

914 return 0;

915 Limit = limitConsideringMacros(I + 2, E, Limit);

916

917 if (!nextTwoLinesFitInto(I, Limit))

918 return 0;

919

920

921

922 if (I[1]->Last->is(TT_LineComment))

923 return 0;

924 do {

925 if (Tok->is(tok::l_brace) && Tok->isNot(BK_BracedInit))

926 return 0;

927 Tok = Tok->Next;

928 } while (Tok);

929

930

931 Tok = I[2]->First;

932 if (Tok->isNot(tok::r_brace))

933 return 0;

934

935

936 if (Tok->Next && Tok->Next->is(tok::kw_else))

937 return 0;

938

939

940

941

942

943

944

945 if (Line.First == Line.Last && Line.First->isNot(TT_FunctionLBrace) &&

946 Style.BraceWrapping.AfterControlStatement ==

948 return 0;

949 }

950

951 return 2;

952 }

953 } else if (I[1]->First->is(tok::l_brace)) {

954 if (I[1]->Last->is(TT_LineComment))

955 return 0;

956

957

958 if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)))

959 return 0;

960 Limit -= 2;

961 unsigned MergedLines = 0;

963 (I[1]->First == I[1]->Last && I + 2 != E &&

964 I[2]->First->is(tok::r_brace))) {

965 MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);

966

967

968 if (MergedLines > 0)

969 ++MergedLines;

970 }

971 return MergedLines;

972 }

973 return 0;

974 }

975

976

977

978 unsigned limitConsideringMacros(ArrayRef<AnnotatedLine *>::const_iterator I,

979 ArrayRef<AnnotatedLine *>::const_iterator E,

980 unsigned Limit) {

981 if (I[0]->InPPDirective && I + 1 != E &&

982 !I[1]->First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {

983 return Limit < 2 ? 0 : Limit - 2;

984 }

985 return Limit;

986 }

987

988 bool nextTwoLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I,

989 unsigned Limit) {

990 if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore)

991 return false;

992 return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;

993 }

994

995 bool nextNLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I,

996 ArrayRef<AnnotatedLine *>::const_iterator E,

997 unsigned Limit) {

998 unsigned JoinedLength = 0;

999 for (const auto *J = I + 1; J != E; ++J) {

1000 if ((*J)->First->MustBreakBefore)

1001 return false;

1002

1003 JoinedLength += 1 + (*J)->Last->TotalLength;

1004 if (JoinedLength > Limit)

1005 return false;

1006 }

1007 return true;

1008 }

1009

1010 bool containsMustBreak(const AnnotatedLine *Line) {

1011 assert(Line->First);

1012

1013

1014 for (const FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next)

1015 if (Tok->MustBreakBefore)

1016 return true;

1017 return false;

1018 }

1019

1020 void join(AnnotatedLine &A, const AnnotatedLine &B) {

1021 assert(!A.Last->Next);

1022 assert(!B.First->Previous);

1023 if (B.Affected)

1024 A.Affected = true;

1025 A.Last->Next = B.First;

1026 B.First->Previous = A.Last;

1027 B.First->CanBreakBefore = true;

1028 unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;

1029 for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {

1030 Tok->TotalLength += LengthA;

1031 A.Last = Tok;

1032 }

1033 }

1034

1035 const FormatStyle &Style;

1036 const AdditionalKeywords &Keywords;

1037 const ArrayRef<AnnotatedLine *>::const_iterator End;

1038

1039 ArrayRef<AnnotatedLine *>::const_iterator Next;

1040 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;

1041};

1042

1043static void markFinalized(FormatToken *Tok) {

1044 if (Tok->is(tok::hash) && !Tok->Previous && Tok->Next &&

1045 Tok->Next->isOneOf(tok::pp_if, tok::pp_ifdef, tok::pp_ifndef,

1046 tok::pp_elif, tok::pp_elifdef, tok::pp_elifndef,

1047 tok::pp_else, tok::pp_endif)) {

1048 Tok = Tok->Next;

1049 }

1050 for (; Tok; Tok = Tok->Next) {

1051 if (Tok->MacroCtx && Tok->MacroCtx->Role == MR_ExpandedArg) {

1052

1053

1054

1055

1057

1058

1059

1060

1061

1062

1063 Tok->SpacesRequiredBefore = 0;

1064 if (!Tok->MustBreakBeforeFinalized)

1065 Tok->MustBreakBefore = 0;

1066 } else {

1067 Tok->Finalized = true;

1068 }

1069 }

1070}

1071

1072#ifndef NDEBUG

1073static void printLineState(const LineState &State) {

1074 llvm::dbgs() << "State: ";

1075 for (const ParenState &P : State.Stack) {

1076 llvm::dbgs() << (P.Tok ? P.Tok->TokenText : "F") << "|" << P.Indent << "|"

1077 << P.LastSpace << "|" << P.NestedBlockIndent << " ";

1078 }

1079 llvm::dbgs() << State.NextToken->TokenText << "\n";

1080}

1081#endif

1082

1083

1084class LineFormatter {

1085public:

1086 LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,

1087 const FormatStyle &Style,

1088 UnwrappedLineFormatter *BlockFormatter)

1089 : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),

1090 BlockFormatter(BlockFormatter) {}

1091 virtual ~LineFormatter() {}

1092

1093

1094

1095

1096 virtual unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,

1097 unsigned FirstStartColumn, bool DryRun) = 0;

1098

1099protected:

1100

1101

1102

1103

1104

1105

1106

1107

1108

1109

1110

1111

1112

1113

1114

1115

1116

1117

1118

1119

1120 bool formatChildren(LineState &State, bool NewLine, bool DryRun,

1121 unsigned &Penalty) {

1122 const FormatToken *LBrace = State.NextToken->getPreviousNonComment();

1123 bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(BK_Block);

1124 FormatToken &Previous = *State.NextToken->Previous;

1125 if (Previous.Children.size() == 0 || (!HasLBrace && !LBrace->MacroParent)) {

1126

1127

1128 return true;

1129 }

1130

1132 const ParenState &P = State.Stack.back();

1133

1134 int AdditionalIndent =

1135 P.Indent - Previous.Children[0]->Level * Style.IndentWidth;

1136 Penalty +=

1137 BlockFormatter->format(Previous.Children, DryRun, AdditionalIndent,

1138 true);

1139 return true;

1140 }

1141

1142 if (Previous.Children[0]->First->MustBreakBefore)

1143 return false;

1144

1145

1146 if (Previous.is(tok::comment))

1147 return false;

1148

1149

1150 if (Previous.Children.size() > 1)

1151 return false;

1152

1153 const AnnotatedLine *Child = Previous.Children[0];

1154

1155 if (Child->Last->isTrailingComment())

1156 return false;

1157

1158

1159

1160 if (Style.ColumnLimit > 0 &&

1161 Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit) {

1162 return false;

1163 }

1164

1165 if (!DryRun) {

1166 Whitespaces->replaceWhitespace(

1167 *Child->First, 0, 1,

1168 State.Column, false,

1169 State.Line->InPPDirective);

1170 }

1171 Penalty +=

1172 formatLine(*Child, State.Column + 1, 0, DryRun);

1173 if (!DryRun)

1174 markFinalized(Child->First);

1175

1176 State.Column += 1 + Child->Last->TotalLength;

1177 return true;

1178 }

1179

1181

1182private:

1183 WhitespaceManager *Whitespaces;

1184 const FormatStyle &Style;

1185 UnwrappedLineFormatter *BlockFormatter;

1186};

1187

1188

1189class NoColumnLimitLineFormatter : public LineFormatter {

1190public:

1191 NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,

1192 WhitespaceManager *Whitespaces,

1193 const FormatStyle &Style,

1194 UnwrappedLineFormatter *BlockFormatter)

1195 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}

1196

1197

1198

1199 unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,

1200 unsigned FirstStartColumn, bool DryRun) override {

1201 assert(!DryRun);

1202 LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn,

1203 &Line, false);

1204 while (State.NextToken) {

1205 bool Newline =

1206 Indenter->mustBreak(State) ||

1207 (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);

1208 unsigned Penalty = 0;

1209 formatChildren(State, Newline, false, Penalty);

1210 Indenter->addTokenToState(State, Newline, false);

1211 }

1212 return 0;

1213 }

1214};

1215

1216

1217class NoLineBreakFormatter : public LineFormatter {

1218public:

1219 NoLineBreakFormatter(ContinuationIndenter *Indenter,

1220 WhitespaceManager *Whitespaces, const FormatStyle &Style,

1221 UnwrappedLineFormatter *BlockFormatter)

1222 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}

1223

1224

1225 unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,

1226 unsigned FirstStartColumn, bool DryRun) override {

1227 unsigned Penalty = 0;

1228 LineState State =

1229 Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun);

1230 while (State.NextToken) {

1231 formatChildren(State, false, DryRun, Penalty);

1233 State, State.NextToken->MustBreakBefore, DryRun);

1234 }

1235 return Penalty;

1236 }

1237};

1238

1239

1240class OptimizingLineFormatter : public LineFormatter {

1241public:

1242 OptimizingLineFormatter(ContinuationIndenter *Indenter,

1243 WhitespaceManager *Whitespaces,

1244 const FormatStyle &Style,

1245 UnwrappedLineFormatter *BlockFormatter)

1246 : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}

1247

1248

1249

1250 unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,

1251 unsigned FirstStartColumn, bool DryRun) override {

1252 LineState State =

1253 Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun);

1254

1255

1256

1258 State.Stack.back().BreakBeforeParameter = true;

1259

1260

1261 return analyzeSolutionSpace(State, DryRun);

1262 }

1263

1264private:

1265 struct CompareLineStatePointers {

1266 bool operator()(LineState *obj1, LineState *obj2) const {

1267 return *obj1 < *obj2;

1268 }

1269 };

1270

1271

1272

1273

1274

1275

1276 typedef std::pair<unsigned, unsigned> OrderedPenalty;

1277

1278

1279

1280 struct StateNode {

1281 StateNode(const LineState &State, bool NewLine, StateNode *Previous)

1283 LineState State;

1286 };

1287

1288

1289

1290 typedef std::pair<OrderedPenalty, StateNode *> QueueItem;

1291

1292

1293 typedef std::priority_queue<QueueItem, SmallVector,

1294 std::greater>

1295 QueueType;

1296

1297

1298

1299

1300

1301

1302

1303

1304

1305 unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun) {

1306 std::set<LineState *, CompareLineStatePointers> Seen;

1307

1308

1309

1310 unsigned Count = 0;

1311 QueueType Queue;

1312

1313

1314 StateNode *RootNode =

1315 new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);

1316 Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode));

1317 ++Count;

1318

1319 unsigned Penalty = 0;

1320

1321

1322 while (!Queue.empty()) {

1323

1324 if (Count > 25'000'000)

1325 return 0;

1326

1327 Penalty = Queue.top().first.first;

1328 StateNode *Node = Queue.top().second;

1329 if (Node->State.NextToken) {

1330 LLVM_DEBUG(llvm::dbgs()

1331 << "\n---\nPenalty for line: " << Penalty << "\n");

1332 break;

1333 }

1334 Queue.pop();

1335

1336

1337

1338 if (Count > 50'000)

1339 Node->State.IgnoreStackForComparison = true;

1340

1341 if (!Seen.insert(&Node->State).second) {

1342

1343 continue;

1344 }

1345

1348 addNextStateToQueue(Penalty, Node, false, &Count, &Queue);

1350 addNextStateToQueue(Penalty, Node, true, &Count, &Queue);

1351 }

1352

1353 if (Queue.empty()) {

1354

1355

1356 LLVM_DEBUG(llvm::dbgs() << "Could not find a solution.\n");

1357 return 0;

1358 }

1359

1360

1361 if (!DryRun)

1362 reconstructPath(InitialState, Queue.top().second);

1363

1364 LLVM_DEBUG(llvm::dbgs()

1365 << "Total number of analyzed states: " << Count << "\n");

1366 LLVM_DEBUG(llvm::dbgs() << "---\n");

1367

1368 return Penalty;

1369 }

1370

1371

1372

1373

1374

1375 void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,

1376 bool NewLine, unsigned *Count, QueueType *Queue) {

1377 if (NewLine && Indenter->canBreak(PreviousNode->State))

1378 return;

1379 if (NewLine && Indenter->mustBreak(PreviousNode->State))

1380 return;

1381

1382 StateNode *Node = new (Allocator.Allocate())

1383 StateNode(PreviousNode->State, NewLine, PreviousNode);

1384 if (!formatChildren(Node->State, NewLine, true, Penalty))

1385 return;

1386

1388

1389 Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));

1390 ++(*Count);

1391 }

1392

1393

1394

1395 void reconstructPath(LineState &State, StateNode *Best) {

1397

1398 while (Best->Previous) {

1399 Path.push_back(Best);

1400 Best = Best->Previous;

1401 }

1402 for (const auto &Node : llvm::reverse(Path)) {

1403 unsigned Penalty = 0;

1404 formatChildren(State, Node->NewLine, false, Penalty);

1405 Penalty += Indenter->addTokenToState(State, Node->NewLine, false);

1406

1407 LLVM_DEBUG({

1408 printLineState(Node->Previous->State);

1409 if (Node->NewLine) {

1410 llvm::dbgs() << "Penalty for placing "

1411 << Node->Previous->State.NextToken->Tok.getName()

1412 << " on a new line: " << Penalty << "\n";

1413 }

1414 });

1415 }

1416 }

1417

1418 llvm::SpecificBumpPtrAllocator Allocator;

1419};

1420

1421}

1422

1425 int AdditionalIndent, bool FixBadIndentation, unsigned FirstStartColumn,

1426 unsigned NextStartColumn, unsigned LastStartColumn) {

1427 LineJoiner Joiner(Style, Keywords, Lines);

1428

1429

1430 std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey(

1431 &Lines, AdditionalIndent);

1432 auto CacheIt = PenaltyCache.find(CacheKey);

1433 if (DryRun && CacheIt != PenaltyCache.end())

1434 return CacheIt->second;

1435

1436 assert(!Lines.empty());

1437 unsigned Penalty = 0;

1438 LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,

1439 AdditionalIndent);

1443

1444

1445 unsigned RangeMinLevel = UINT_MAX;

1446

1447 bool FirstLine = true;

1449 Joiner.getNextMergedLine(DryRun, IndentTracker);

1450 Line; PrevPrevLine = PreviousLine, PreviousLine = Line, Line = NextLine,

1451 FirstLine = false) {

1452 assert(Line->First);

1454 unsigned Indent = IndentTracker.getIndent();

1455

1456

1457

1458

1459

1460 bool PreviousRBrace =

1461 PreviousLine && PreviousLine->startsWith(tok::r_brace);

1462 bool ContinueFormatting =

1463 TheLine.Level > RangeMinLevel ||

1464 (TheLine.Level == RangeMinLevel && !PreviousRBrace &&

1465 !TheLine.startsWith(TT_NamespaceRBrace));

1466

1467 bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&

1469 bool ShouldFormat = TheLine.Affected || FixIndentation;

1470

1471

1474 Status->Line =

1476 }

1477

1479 if (!DryRun) {

1480 bool LastLine = TheLine.First->is(tok::eof);

1481 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines, Indent,

1482 LastLine ? LastStartColumn : NextStartColumn + Indent);

1483 }

1484

1485 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);

1486 unsigned ColumnLimit = getColumnLimit(TheLine.InPPDirective, NextLine);

1487 bool FitsIntoOneLine =

1491 (!Style.isJavaScript() || !Style.JavaScriptWrapImports)) ||

1492 (Style.isCSharp() &&

1493 TheLine.InPPDirective));

1494 if (Style.ColumnLimit == 0) {

1495 NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this)

1496 .formatLine(TheLine, NextStartColumn + Indent,

1497 FirstLine ? FirstStartColumn : 0, DryRun);

1498 } else if (FitsIntoOneLine) {

1499 Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style, this)

1500 .formatLine(TheLine, NextStartColumn + Indent,

1501 FirstLine ? FirstStartColumn : 0, DryRun);

1502 } else {

1503 Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this)

1504 .formatLine(TheLine, NextStartColumn + Indent,

1505 FirstLine ? FirstStartColumn : 0, DryRun);

1506 }

1507 RangeMinLevel = std::min(RangeMinLevel, TheLine.Level);

1508 } else {

1509

1510

1513 if (!Tok->Children.empty())

1514 format(Tok->Children, DryRun);

1515 }

1516

1517

1518

1519 bool StartsNewLine =

1521 if (StartsNewLine)

1522 IndentTracker.adjustToUnmodifiedLine(TheLine);

1523 if (!DryRun) {

1524 bool ReformatLeadingWhitespace =

1525 StartsNewLine && ((PreviousLine && PreviousLine->Affected) ||

1527

1528 if (ReformatLeadingWhitespace) {

1529 formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,

1532 } else {

1533 Whitespaces->addUntouchableToken(*TheLine.First,

1535 }

1536

1537

1539 Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);

1540 }

1541 NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);

1543 }

1544 if (!DryRun)

1545 markFinalized(TheLine.First);

1546 }

1547 PenaltyCache[CacheKey] = Penalty;

1548 return Penalty;

1549}

1550

1556 const auto &RootToken = *Line.First;

1557 auto Newlines =

1559

1560 if (RootToken.is(tok::r_brace) &&

1561 (!RootToken.Next ||

1562 (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)) &&

1563

1565 Newlines = std::min(Newlines, 1u);

1566 }

1567

1568 if (!PreviousLine && Line.Level > 0)

1569 Newlines = std::min(Newlines, 1u);

1570 if (Newlines == 0 && !RootToken.IsFirst)

1571 Newlines = 1;

1572 if (RootToken.IsFirst &&

1574 Newlines = 0;

1575 }

1576

1577

1579 PreviousLine->Last->is(tok::l_brace) &&

1582 PreviousLine->startsWith(tok::l_brace)) &&

1583 !startsExternCBlock(*PreviousLine)) {

1584 Newlines = 1;

1585 }

1586

1588

1589 if (PreviousLine && PreviousLine->endsWith(TT_NamespaceLBrace)) {

1591 Newlines = 1;

1592 else if (Line.startsWithNamespace())

1593 Newlines = std::max(Newlines, 2u);

1594 }

1595

1596 if (Line.startsWith(TT_NamespaceRBrace)) {

1598 Newlines = 1;

1599 else if (!PreviousLine->startsWith(TT_NamespaceRBrace))

1600 Newlines = std::max(Newlines, 2u);

1601 }

1602 }

1603

1604

1605 if (PreviousLine && RootToken.isAccessSpecifier()) {

1608 if (Newlines > 1)

1609 Newlines = 1;

1610 break;

1612 Newlines = std::max(RootToken.NewlinesBefore, 1u);

1613 break;

1615 if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) && Newlines <= 1)

1616 Newlines = 2;

1618 Newlines = 1;

1619 break;

1622 if (PreviousLine->Last->is(tok::comment))

1624 else

1625 previousToken = PreviousLine->Last;

1626 if ((!previousToken || previousToken->isNot(tok::l_brace)) &&

1627 Newlines <= 1) {

1628 Newlines = 2;

1629 }

1630 } break;

1631 }

1632 }

1633

1634

1636 (!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline)) {

1637

1638

1639 if (!RootToken.isAccessSpecifier()) {

1642 Newlines = 1;

1643 break;

1645 Newlines = std::max(Newlines, 1u);

1646 break;

1648 if (RootToken.is(tok::r_brace))

1649 Newlines = 1u;

1650 else

1651 Newlines = std::max(Newlines, 2u);

1652 break;

1653 }

1654 }

1655 }

1656

1657 return Newlines;

1658}

1659

1660void UnwrappedLineFormatter::formatFirstToken(

1661 const AnnotatedLine &Line, const AnnotatedLine *PreviousLine,

1662 const AnnotatedLine *PrevPrevLine,

1664 unsigned NewlineIndent) {

1665 FormatToken &RootToken = *Line.First;

1666 if (RootToken.is(tok::eof)) {

1667 unsigned Newlines = std::min(

1668 RootToken.NewlinesBefore,

1669 Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);

1670 unsigned TokenIndent = Newlines ? NewlineIndent : 0;

1671 Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent,

1672 TokenIndent);

1673 return;

1674 }

1675

1676 if (RootToken.Newlines < 0) {

1677 RootToken.Newlines =

1679 assert(RootToken.Newlines >= 0);

1680 }

1681

1682 if (RootToken.Newlines > 0)

1683 Indent = NewlineIndent;

1684

1685

1686

1687 if (!Style.isJavaScript() &&

1691 Indent = 0;

1692 }

1693

1694 Whitespaces->replaceWhitespace(RootToken, RootToken.Newlines, Indent, Indent,

1695 false,

1696 Line.InPPDirective &&

1697 !RootToken.HasUnescapedNewline);

1698}

1699

1700unsigned

1701UnwrappedLineFormatter::getColumnLimit(bool InPPDirective,

1702 const AnnotatedLine *NextLine) const {

1703

1704

1705 bool ContinuesPPDirective =

1706 InPPDirective &&

1707

1708

1709 (!NextLine ||

1710 (NextLine->InPPDirective &&

1711

1712

1713 !NextLine->First->HasUnescapedNewline));

1714 return Style.ColumnLimit - (ContinuesPPDirective ? 2 : 0);

1715}

1716

1717}

1718}

This file contains the declaration of the FormatToken, a wrapper around Token with additional informa...

ContinuationIndenter * Indenter

Implements a combinatorial exploration of all the different linebreaks unwrapped lines can be formatt...

WhitespaceManager class manages whitespace around tokens and their replacements.

unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const

SourceLocation getLocation() const

Return a source location identifier for the specified offset in the current file.

bool LeadingEmptyLinesAffected

True if the leading empty lines of this line intersect with one of the input ranges.

bool Affected

True if this line should be formatted, i.e.

bool ContainsMacroCall

True if this line contains a macro call for which an expansion exists.

bool ChildrenAffected

True if one of this line's children intersects with an input range.

bool startsWithNamespace() const

true if this line starts a namespace definition.

bool endsWith(Ts... Tokens) const

true if this line ends with the given tokens in reversed order, ignoring comments.

bool startsWith(Ts... Tokens) const

true if this line starts with the given tokens in order, ignoring comments.

unsigned format(const SmallVectorImpl< AnnotatedLine * > &Lines, bool DryRun=false, int AdditionalIndent=0, bool FixBadIndentation=false, unsigned FirstStartColumn=0, unsigned NextStartColumn=0, unsigned LastStartColumn=0)

Format the current block and return the penalty.

@ MR_UnexpandedArg

The token is part of a macro argument that was previously formatted as expansion when formatting the ...

@ MR_ExpandedArg

The token was expanded from a macro argument when formatting the expanded token sequence.

const FormatToken * getNamespaceToken(const AnnotatedLine *Line, const SmallVectorImpl< AnnotatedLine * > &AnnotatedLines)

static auto computeNewlines(const AnnotatedLine &Line, const AnnotatedLine *PreviousLine, const AnnotatedLine *PrevPrevLine, const SmallVectorImpl< AnnotatedLine * > &Lines, const FormatStyle &Style)

StringRef getNamespaceTokenText(const AnnotatedLine *Line, const SmallVectorImpl< AnnotatedLine * > &AnnotatedLines)

@ LT_CommentAbovePPDirective

@ LT_PreprocessorDirective

ObjCKeywordKind

Provides a namespace for Objective-C keywords which start with an '@'.

The JSON file list parser is used to communicate input to InstallAPI.

if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))

bool AtStartOfFile

Keep empty lines at start of file.

bool AtStartOfBlock

Keep empty lines at start of a block.

The FormatStyle is used to configure the formatting to follow specific guidelines.

@ LK_Java

Should be used for Java.

@ ELBAMS_LogicalBlock

Add empty line only when access modifier starts a new logical block.

@ ELBAMS_Never

Remove all empty lines before access modifiers.

@ ELBAMS_Always

Always add empty line before access modifiers unless access modifier is at the start of struct or cla...

@ ELBAMS_Leave

Keep existing empty lines before access modifiers.

WrapNamespaceBodyWithEmptyLinesStyle WrapNamespaceBodyWithEmptyLines

Wrap namespace body with empty lines.

@ PPDIS_BeforeHash

Indents directives before the hash.

@ PPDIS_None

Does not indent any directives.

@ SBS_Empty

Only merge empty blocks.

@ SBS_Never

Never merge blocks into a single line.

@ SIS_WithoutElse

Put short ifs on the same line only if there is no else statement.

@ SIS_AllIfsAndElse

Always put short ifs, else ifs and else statements on the same line.

@ BWACS_Always

Always wrap braces after a control statement.

@ BWACS_MultiLine

Only wrap braces after a multi-line control statement.

@ WNBWELS_Leave

Keep existing newlines at the beginning and the end of namespace body.

@ WNBWELS_Never

Remove all empty lines at the beginning and the end of namespace body.

@ SFS_All

Merge all functions fitting on a single line.

@ SFS_Empty

Only merge empty functions.

@ SFS_InlineOnly

Only merge functions defined inside a class.

KeepEmptyLinesStyle KeepEmptyLines

Which empty lines are kept.

unsigned MaxEmptyLinesToKeep

The maximum number of consecutive empty lines to keep.

@ ELAAMS_Always

Always add empty line after access modifiers if there are none.

@ ELAAMS_Never

Remove all empty lines after access modifiers.

@ ELAAMS_Leave

Keep existing empty lines after access modifiers.

EmptyLineBeforeAccessModifierStyle EmptyLineBeforeAccessModifier

Defines in which cases to put empty line before access modifiers.

EmptyLineAfterAccessModifierStyle EmptyLineAfterAccessModifier

Defines when to put an empty line after access modifiers.

A wrapper around a Token storing information about the whitespace characters preceding it.

unsigned OriginalColumn

The original 0-based column of this token, including expanded tabs.

FormatToken * getPreviousNonComment() const

Returns the previous token ignoring comments.

FormatToken * Next

The next token in the unwrapped line.

unsigned NewlinesBefore

The number of newlines immediately before the Token.

bool is(tok::TokenKind Kind) const

unsigned TotalLength

The total length of the unwrapped line up to and including this token.

bool isOneOf(A K1, B K2) const

unsigned IsFirst

Indicates that this is the first token of the file.

bool isAccessSpecifier(bool ColonRequired=true) const

bool FormatComplete

A value of false means that any of the affected ranges were not formatted due to a non-recoverable sy...

unsigned Line

If FormatComplete is false, Line records a one-based original line number at which a syntax error mig...

static const size_t kInvalidIndex