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

1

2

3

4

5

6

7

8

9

10

11

12

13

15#include "llvm/ADT/STLExtras.h"

16#include "llvm/ADT/SmallVector.h"

17#include

18

21

24 return SourceMgr.isBeforeInTranslationUnit(

29 SourceMgr.isBeforeInTranslationUnit(

32}

33

54

56 unsigned Spaces,

57 unsigned StartOfTokenColumn,

58 bool IsAligned, bool InPPDirective,

59 unsigned IndentedFromColumn) {

61 return;

63 Changes.push_back(Change(Tok, true, Tok.WhitespaceRange,

64 Spaces, StartOfTokenColumn, IndentedFromColumn,

66 InPPDirective && Tok.IsFirst,

67 false));

68}

69

71 bool InPPDirective) {

73 return;

74 Changes.push_back(Change(

75 Tok, false, Tok.WhitespaceRange, 0,

76 Tok.OriginalColumn, 0, Tok.NewlinesBefore, "", "",

77 false, InPPDirective && Tok.IsFirst,

78 false));

79}

80

81llvm::Error

83 return Replaces.add(Replacement);

84}

85

87 size_t LF = Text.count('\n');

88 size_t CR = Text.count('\r') * 2;

89 return LF == CR ? DefaultToCRLF : CR > LF;

90}

91

93 const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars,

94 StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective,

95 unsigned Newlines, int Spaces) {

97 return;

98 SourceLocation Start = Tok.getStartOfNonWhitespace().getLocWithOffset(Offset);

99 Changes.push_back(

100 Change(Tok, true,

102 std::max(0, Spaces), 0, Newlines,

103 PreviousPostfix, CurrentPrefix,

104 true, InPPDirective && Tok.IsFirst,

105 true));

106}

107

109 if (Changes.empty())

110 return Replaces;

111

113 calculateLineBreakInformation();

114 alignConsecutiveMacros();

115 alignConsecutiveShortCaseStatements(true);

116 alignConsecutiveShortCaseStatements(false);

117 alignConsecutiveDeclarations();

118 alignConsecutiveBitFields();

119 alignConsecutiveAssignments();

120 if (Style.isTableGen()) {

121 alignConsecutiveTableGenBreakingDAGArgColons();

122 alignConsecutiveTableGenCondOperatorColons();

123 alignConsecutiveTableGenDefinitions();

124 }

125 alignChainedConditionals();

126 alignTrailingComments();

127 alignEscapedNewlines();

128 alignArrayInitializers();

129 generateChanges();

130

131 return Replaces;

132}

133

134void WhitespaceManager::calculateLineBreakInformation() {

135 Changes[0].PreviousEndOfTokenColumn = 0;

136 Change *LastOutsideTokenChange = &Changes[0];

137 for (unsigned I = 1, e = Changes.size(); I != e; ++I) {

138 auto &C = Changes[I];

139 auto &P = Changes[I - 1];

140 auto &PrevTokLength = P.TokenLength;

142 C.OriginalWhitespaceRange.getBegin();

144 P.OriginalWhitespaceRange.getEnd();

145 unsigned OriginalWhitespaceStartOffset =

146 SourceMgr.getFileOffset(OriginalWhitespaceStart);

147 unsigned PreviousOriginalWhitespaceEndOffset =

148 SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);

149 assert(PreviousOriginalWhitespaceEndOffset <=

150 OriginalWhitespaceStartOffset);

151 const char *const PreviousOriginalWhitespaceEndData =

152 SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd);

153 StringRef Text(PreviousOriginalWhitespaceEndData,

154 SourceMgr.getCharacterData(OriginalWhitespaceStart) -

155 PreviousOriginalWhitespaceEndData);

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177 auto NewlinePos = Text.find_first_of('\n');

178 if (NewlinePos == StringRef::npos) {

179 PrevTokLength = OriginalWhitespaceStartOffset -

180 PreviousOriginalWhitespaceEndOffset +

181 C.PreviousLinePostfix.size() + P.CurrentLinePrefix.size();

182 if (!P.IsInsideToken)

183 PrevTokLength = std::min(PrevTokLength, P.Tok->ColumnWidth);

184 } else {

185 PrevTokLength = NewlinePos + P.CurrentLinePrefix.size();

186 }

187

188

189

190 if (P.IsInsideToken && P.NewlinesBefore == 0)

191 LastOutsideTokenChange->TokenLength += PrevTokLength + P.Spaces;

192 else

193 LastOutsideTokenChange = &P;

194

195 C.PreviousEndOfTokenColumn = P.StartOfTokenColumn + PrevTokLength;

196

197 P.IsTrailingComment =

198 (C.NewlinesBefore > 0 || C.Tok->is(tok::eof) ||

199 (C.IsInsideToken && C.Tok->is(tok::comment))) &&

200 P.Tok->is(tok::comment) &&

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231 OriginalWhitespaceStart != PreviousOriginalWhitespaceEnd;

232 }

233

234

235 Changes.back().TokenLength = 0;

236 Changes.back().IsTrailingComment = Changes.back().Tok->is(tok::comment);

237

238 const WhitespaceManager::Change *LastBlockComment = nullptr;

239 for (auto &Change : Changes) {

240

241

242

249 LastBlockComment = &Change;

254 }

255 } else {

256 LastBlockComment = nullptr;

257 }

258 }

259

260

261

262

263

264 SmallVector<bool, 16> ScopeStack;

265 int ConditionalsLevel = 0;

266 for (auto &Change : Changes) {

268 bool isNestedConditional =

273 if (isNestedConditional)

274 ++ConditionalsLevel;

275 ScopeStack.push_back(isNestedConditional);

276 }

277

279

281 if (ScopeStack.pop_back_val())

282 --ConditionalsLevel;

283 }

284}

285

286

287

288

289

290static void

292 unsigned Column, bool RightJustify,

295 unsigned OriginalMatchColumn = 0;

296 int Shift = 0;

297

298

299 bool LineShifted = false;

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

325

326 for (unsigned i = Start; i != End; ++i) {

327 auto &CurrentChange = Changes[i];

328 if (!Matches.empty() && Matches[0] < i)

329 Matches.consume_front();

330 assert(Matches.empty() || Matches[0] >= i);

331 while (!ScopeStack.empty() &&

332 CurrentChange.indentAndNestingLevel() < ScopeStack.back()) {

333 ScopeStack.pop_back();

334 }

335

336

337 if (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore != 0u &&

338 CurrentChange.indentAndNestingLevel() > ScopeStack[0] &&

339 CurrentChange.IndentedFromColumn < OriginalMatchColumn) {

340 ScopeStack.push_back(CurrentChange.indentAndNestingLevel());

341 }

342

343 bool InsideNestedScope =

344 !ScopeStack.empty() &&

345 (CurrentChange.indentAndNestingLevel() > ScopeStack[0] ||

346 (CurrentChange.indentAndNestingLevel() == ScopeStack[0] &&

347 CurrentChange.IndentedFromColumn >= OriginalMatchColumn));

348

349 if (CurrentChange.NewlinesBefore > 0) {

350 LineShifted = false;

351 if (!InsideNestedScope)

352 Shift = 0;

353 }

354

355

356

357

358 if (!Matches.empty() && Matches[0] == i) {

359 OriginalMatchColumn = CurrentChange.StartOfTokenColumn;

360 Shift = Column - (RightJustify ? CurrentChange.TokenLength : 0) -

361 CurrentChange.StartOfTokenColumn;

362 ScopeStack = {CurrentChange.indentAndNestingLevel()};

363 }

364

365 if (Shift == 0)

366 continue;

367

368

369

370

371 if ((!Matches.empty() && Matches[0] == i) ||

372 (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore > 0 &&

373 InsideNestedScope)) {

374 LineShifted = true;

375 CurrentChange.Spaces += Shift;

376 }

377

378

380 CurrentChange.Spaces >=

381 static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||

382 CurrentChange.Tok->is(tok::eof));

383

384 if (LineShifted) {

385 CurrentChange.StartOfTokenColumn += Shift;

386 if (i + 1 != Changes.size())

387 Changes[i + 1].PreviousEndOfTokenColumn += Shift;

388 }

389

390

391

392 if ((Style.PointerAlignment == FormatStyle::PAS_Right ||

393 Style.ReferenceAlignment == FormatStyle::RAS_Right) &&

394 CurrentChange.Spaces != 0 &&

395 CurrentChange.Tok->isNoneOf(tok::equal, tok::r_paren,

396 TT_TemplateCloser)) {

397 const bool ReferenceNotRightAligned =

398 Style.ReferenceAlignment != FormatStyle::RAS_Right &&

399 Style.ReferenceAlignment != FormatStyle::RAS_Pointer;

401 Previous >= 0 && Changes[Previous].Tok->is(TT_PointerOrReference);

403 assert(Changes[Previous].Tok->isPointerOrReference());

404 if (Changes[Previous].Tok->isNot(tok::star)) {

405 if (ReferenceNotRightAligned)

406 continue;

407 } else if (Style.PointerAlignment != FormatStyle::PAS_Right) {

408 continue;

409 }

410 Changes[Previous + 1].Spaces -= Shift;

411 Changes[Previous].Spaces += Shift;

412 Changes[Previous].StartOfTokenColumn += Shift;

413 }

414 }

415 }

416}

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453template <typename F, bool SimpleCheck = false>

454static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,

456 unsigned StartAt,

457 const FormatStyle::AlignConsecutiveStyle &ACS = {},

458 bool RightJustify = false) {

459

460

461

462

463

464

465

466

467

468

469 unsigned WidthLeft = 0;

470

471

472 unsigned WidthAnchor = 0;

473

474

475 unsigned WidthRight = 0;

476

477

478 unsigned StartOfSequence = 0;

479 unsigned EndOfSequence = 0;

480

481

483

484

485

486 const auto IndentAndNestingLevel =

487 StartAt < Changes.size() ? Changes[StartAt].indentAndNestingLevel()

488 : std::tuple<unsigned, unsigned, unsigned>();

489

490

491

492

493 unsigned CommasBeforeLastMatch = 0;

494 unsigned CommasBeforeMatch = 0;

495

496

497 bool FoundMatchOnLine = false;

498

499

500 bool LineIsComment = true;

501

502

503

504

505

506

507

508

509 auto AlignCurrentSequence = [&] {

510 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {

512 WidthLeft + WidthAnchor, RightJustify, MatchedIndices,

513 Changes);

514 }

515 WidthLeft = 0;

516 WidthAnchor = 0;

517 WidthRight = 0;

518 StartOfSequence = 0;

519 EndOfSequence = 0;

520 MatchedIndices.clear();

521 };

522

523 unsigned I = StartAt;

524 const auto E = Changes.size();

525 for (; I != E; ++I) {

526 auto &CurrentChange = Changes[I];

527 if (CurrentChange.indentAndNestingLevel() < IndentAndNestingLevel)

528 break;

529

530 if (CurrentChange.NewlinesBefore != 0) {

531 CommasBeforeMatch = 0;

532 EndOfSequence = I;

533

534

535 bool EmptyLineBreak =

536 (CurrentChange.NewlinesBefore > 1) && !ACS.AcrossEmptyLines;

537

538

539

540 bool NoMatchBreak =

541 !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);

542

543 if (EmptyLineBreak || NoMatchBreak)

544 AlignCurrentSequence();

545

546

547

548 if (I == 0 || CurrentChange.Tok->isNot(tok::string_literal) ||

549 Changes[I - 1].Tok->isNot(tok::string_literal)) {

550 FoundMatchOnLine = false;

551 }

552 LineIsComment = true;

553 }

554

555 if (CurrentChange.Tok->isNot(tok::comment))

556 LineIsComment = false;

557

558 if (!SimpleCheck) {

559 if (CurrentChange.Tok->is(tok::comma)) {

560 ++CommasBeforeMatch;

561 } else if (CurrentChange.indentAndNestingLevel() >

562 IndentAndNestingLevel) {

563

564 const auto StoppedAt =

565 AlignTokens(Style, Matches, Changes, I, ACS, RightJustify);

566 I = StoppedAt - 1;

567 continue;

568 }

569 }

570

571 if (!Matches(CurrentChange))

572 continue;

573

574

575

576 if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch) {

577 MatchedIndices.push_back(I);

578 AlignCurrentSequence();

579 }

580

581 CommasBeforeLastMatch = CommasBeforeMatch;

582 FoundMatchOnLine = true;

583

584 if (StartOfSequence == 0)

585 StartOfSequence = I;

586

587 unsigned ChangeWidthLeft = CurrentChange.StartOfTokenColumn;

588 unsigned ChangeWidthAnchor = 0;

589 unsigned ChangeWidthRight = 0;

590 unsigned CurrentChangeWidthRight = 0;

591 if (RightJustify)

592 if (ACS.PadOperators)

593 ChangeWidthAnchor = CurrentChange.TokenLength;

594 else

595 ChangeWidthLeft += CurrentChange.TokenLength;

596 else

597 CurrentChangeWidthRight = CurrentChange.TokenLength;

598 const FormatToken *MatchingParenToEncounter = nullptr;

599 for (unsigned J = I + 1;

600 J != E && (Changes[J].NewlinesBefore == 0 ||

601 MatchingParenToEncounter || Changes[J].IsAligned);

602 ++J) {

603 const auto &Change = Changes[J];

605

606 if (Tok->MatchingParen) {

607 if (Tok->isOneOf(tok::l_paren, tok::l_brace, tok::l_square,

608 TT_TemplateOpener) &&

609 !MatchingParenToEncounter) {

610

611

612

613 if (J + 1 != E && Changes[J + 1].NewlinesBefore == 0)

614 MatchingParenToEncounter = Tok->MatchingParen;

615 } else if (MatchingParenToEncounter == Tok->MatchingParen) {

616 MatchingParenToEncounter = nullptr;

617 }

618 }

619

621 ChangeWidthRight = std::max(ChangeWidthRight, CurrentChangeWidthRight);

622 const auto ChangeWidthStart = ChangeWidthLeft + ChangeWidthAnchor;

623

624

625

626

627

628

629

630

632 break;

633 CurrentChangeWidthRight = Change.Spaces - ChangeWidthStart;

634 } else {

636 }

637

638

639

640

641

642

645 }

646

647 ChangeWidthRight = std::max(ChangeWidthRight, CurrentChangeWidthRight);

648

649

650 unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);

651 unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);

652 unsigned NewRight = std::max(ChangeWidthRight, WidthRight);

653

654 if (Style.ColumnLimit != 0 &&

655 Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {

656 AlignCurrentSequence();

657 StartOfSequence = I;

658 WidthLeft = ChangeWidthLeft;

659 WidthAnchor = ChangeWidthAnchor;

660 WidthRight = ChangeWidthRight;

661 } else {

662 WidthLeft = NewLeft;

663 WidthAnchor = NewAnchor;

664 WidthRight = NewRight;

665 }

666 MatchedIndices.push_back(I);

667 }

668

669

670

671 for (EndOfSequence = I;

672 EndOfSequence < E && Changes[EndOfSequence].NewlinesBefore == 0;

673 ++EndOfSequence) {

674 }

675 AlignCurrentSequence();

676

677

678 return I;

679}

680

681

682

683

684

685

686

687

689 unsigned &StartOfSequence, unsigned &EndOfSequence, unsigned &MinColumn,

692 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {

693 bool FoundMatchOnLine = false;

694 int Shift = 0;

695

696 for (unsigned I = StartOfSequence; I != EndOfSequence; ++I) {

698 Shift = 0;

699 FoundMatchOnLine = false;

700 }

701

702

703

704

705 if (!FoundMatchOnLine && Matches(Changes[I])) {

706 FoundMatchOnLine = true;

707 Shift = MinColumn - Changes[I].StartOfTokenColumn;

708 Changes[I].Spaces += Shift;

709 }

710

711 assert(Shift >= 0);

712 Changes[I].StartOfTokenColumn += Shift;

713 if (I + 1 != Changes.size())

714 Changes[I + 1].PreviousEndOfTokenColumn += Shift;

715 }

716 }

717

718 MinColumn = 0;

719 StartOfSequence = 0;

720 EndOfSequence = 0;

721}

722

723void WhitespaceManager::alignConsecutiveMacros() {

724 if (!Style.AlignConsecutiveMacros.Enabled)

725 return;

726

727 auto AlignMacrosMatches = [](const Change &C) {

729 assert(Current);

730

731 if (Current->SpacesRequiredBefore == 0 || !Current->Previous)

732 return false;

733

734 Current = Current->Previous;

735

736

737

738 if (Current->is(tok::r_paren)) {

739 const auto *MatchingParen = Current->MatchingParen;

740

741

744 return false;

745 }

747 } else if (Current->Next->SpacesRequiredBefore != 1) {

748

749

750 return false;

751 }

752

753 return Current->endsSequence(tok::identifier, tok::pp_define);

754 };

755

756 AlignTokens<decltype(AlignMacrosMatches) &, true>(

757 Style, AlignMacrosMatches, Changes, 0, Style.AlignConsecutiveMacros);

758}

759

760void WhitespaceManager::alignConsecutiveAssignments() {

761 if (!Style.AlignConsecutiveAssignments.Enabled)

762 return;

763

765 Style,

767

768 if (C.NewlinesBefore > 0)

769 return false;

770

771

772 if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)

773 return false;

774

775

778 return false;

779

780 return Style.AlignConsecutiveAssignments.AlignCompound

782 : (C.Tok->is(tok::equal) ||

783

784

785

786 (Style.isVerilog() && C.Tok->is(tok::lessequal) &&

788 },

789 Changes, 0, Style.AlignConsecutiveAssignments,

790 true);

791}

792

793void WhitespaceManager::alignConsecutiveBitFields() {

794 alignConsecutiveColons(Style.AlignConsecutiveBitFields, TT_BitFieldColon);

795}

796

797void WhitespaceManager::alignConsecutiveColons(

798 const FormatStyle::AlignConsecutiveStyle &AlignStyle, TokenType Type) {

799 if (!AlignStyle.Enabled)

800 return;

801

803 Style,

805

806 if (C.NewlinesBefore > 0)

807 return false;

808

809

810 if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)

811 return false;

812

813 return C.Tok->is(Type);

814 },

815 Changes, 0, AlignStyle);

816}

817

818void WhitespaceManager::alignConsecutiveShortCaseStatements(bool IsExpr) {

819 if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||

820 !(IsExpr ? Style.AllowShortCaseExpressionOnASingleLine

821 : Style.AllowShortCaseLabelsOnASingleLine)) {

822 return;

823 }

824

825 const auto Type = IsExpr ? TT_CaseLabelArrow : TT_CaseLabelColon;

826 const auto &Option = Style.AlignConsecutiveShortCaseStatements;

827 const bool AlignArrowOrColon =

828 IsExpr ? Option.AlignCaseArrows : Option.AlignCaseColons;

829

830 auto Matches = [&](const Change &C) {

831 if (AlignArrowOrColon)

832 return C.Tok->is(Type);

833

834

835

836

837

838 return C.IsInsideToken && C.Tok->Previous && C.Tok->Previous->is(Type);

839 };

840

841 unsigned MinColumn = 0;

842

843

844

845

846 unsigned MinEmptyCaseColumn = 0;

847

848

849 unsigned StartOfSequence = 0;

850 unsigned EndOfSequence = 0;

851

852

853 bool FoundMatchOnLine = false;

854

855 bool LineIsComment = true;

856 bool LineIsEmptyCase = false;

857

858 unsigned I = 0;

859 for (unsigned E = Changes.size(); I != E; ++I) {

861

862 bool EmptyLineBreak =

863 (Changes[I].NewlinesBefore > 1) &&

864 !Style.AlignConsecutiveShortCaseStatements.AcrossEmptyLines;

865

866

867

868 bool NoMatchBreak =

869 !FoundMatchOnLine &&

870 !(LineIsComment &&

871 Style.AlignConsecutiveShortCaseStatements.AcrossComments) &&

872 !LineIsEmptyCase;

873

874 if (EmptyLineBreak || NoMatchBreak) {

876 Matches, Changes);

877 MinEmptyCaseColumn = 0;

878 }

879

880

881 FoundMatchOnLine = false;

882 LineIsComment = true;

883 LineIsEmptyCase = false;

884 }

885

886 if (Changes[I].Tok->isNot(tok::comment))

887 LineIsComment = false;

888

889 if (Changes[I].Tok->is(Type)) {

890 LineIsEmptyCase =

891 !Changes[I].Tok->Next || Changes[I].Tok->Next->isTrailingComment();

892

893 if (LineIsEmptyCase) {

894 if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons) {

895 MinEmptyCaseColumn =

896 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn);

897 } else {

898 MinEmptyCaseColumn =

899 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn + 2);

900 }

901 }

902 }

903

904 if (!Matches(Changes[I]))

905 continue;

906

907 if (LineIsEmptyCase)

908 continue;

909

910 FoundMatchOnLine = true;

911

912 if (StartOfSequence == 0)

913 StartOfSequence = I;

914

915 EndOfSequence = I + 1;

916

917 MinColumn = std::max(MinColumn, Changes[I].StartOfTokenColumn);

918

919

920 MinColumn = std::max(MinColumn, MinEmptyCaseColumn);

921 }

922

924 Changes);

925}

926

927void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() {

928 alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons,

929 TT_TableGenDAGArgListColonToAlign);

930}

931

932void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() {

933 alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons,

934 TT_TableGenCondOperatorColon);

935}

936

937void WhitespaceManager::alignConsecutiveTableGenDefinitions() {

938 alignConsecutiveColons(Style.AlignConsecutiveTableGenDefinitionColons,

939 TT_InheritanceColon);

940}

941

942void WhitespaceManager::alignConsecutiveDeclarations() {

943 if (!Style.AlignConsecutiveDeclarations.Enabled)

944 return;

945

947 Style,

949 if (C.Tok->is(TT_FunctionTypeLParen))

950 return Style.AlignConsecutiveDeclarations.AlignFunctionPointers;

951 if (C.Tok->is(TT_FunctionDeclarationName))

952 return Style.AlignConsecutiveDeclarations.AlignFunctionDeclarations;

953 if (C.Tok->isNot(TT_StartOfName))

954 return false;

955 if (C.Tok->Previous &&

956 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))

957 return false;

958

960 if (Next->is(tok::comment))

961 continue;

962 if (Next->is(TT_PointerOrReference))

963 return false;

964 if (Next->Tok.getIdentifierInfo())

965 break;

966 if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,

967 tok::kw_operator)) {

968 return false;

969 }

970 }

971 return true;

972 },

973 Changes, 0, Style.AlignConsecutiveDeclarations);

974}

975

976void WhitespaceManager::alignChainedConditionals() {

977 if (Style.BreakBeforeTernaryOperators) {

979 Style,

981

982 return C.Tok->is(TT_ConditionalExpr) &&

983 ((C.Tok->is(tok::question) && C.NewlinesBefore) ||

984 (C.Tok->is(tok::colon) && C.Tok->Next &&

985 (C.Tok->Next->FakeLParens.empty() ||

987 },

988 Changes, 0);

989 } else {

990 static auto AlignWrappedOperand = [](Change const &C) {

992 return C.NewlinesBefore && Previous && Previous->is(TT_ConditionalExpr) &&

994 (C.Tok->FakeLParens.empty() ||

996 };

997

998

999

1000 for (Change &C : Changes)

1001 if (AlignWrappedOperand(C))

1002 C.StartOfTokenColumn -= 2;

1004 Style,

1005 [this](Change const &C) {

1006

1007

1008

1009 return (C.Tok->is(TT_ConditionalExpr) && C.Tok->is(tok::question) &&

1010 &C != &Changes.back() && (&C + 1)->NewlinesBefore == 0 &&

1011 !(&C + 1)->IsTrailingComment) ||

1012 AlignWrappedOperand(C);

1013 },

1014 Changes, 0);

1015 }

1016}

1017

1018void WhitespaceManager::alignTrailingComments() {

1019 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Never)

1020 return;

1021

1022 const int Size = Changes.size();

1023 if (Size == 0)

1024 return;

1025

1026 int MinColumn = 0;

1027 int StartOfSequence = 0;

1028 bool BreakBeforeNext = false;

1029 bool IsInPP = Changes.front().Tok->Tok.is(tok::hash);

1030 int NewLineThreshold = 1;

1031 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)

1032 NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;

1033

1035 auto &C = Changes[I];

1036 if (C.StartOfBlockComment)

1037 continue;

1038 if (C.NewlinesBefore != 0) {

1040 const bool WasInPP = std::exchange(

1041 IsInPP, C.Tok->Tok.is(tok::hash) || (IsInPP && C.IsTrailingComment) ||

1042 C.ContinuesPPDirective);

1043 if (IsInPP != WasInPP && !Style.AlignTrailingComments.AlignPPAndNotPP) {

1044 alignTrailingComments(StartOfSequence, I, MinColumn);

1045 MinColumn = 0;

1047 StartOfSequence = I;

1049 }

1050 }

1051 if (C.IsTrailingComment)

1052 continue;

1053

1054 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Leave) {

1055 const int OriginalSpaces =

1056 C.OriginalWhitespaceRange.getEnd().getRawEncoding() -

1057 C.OriginalWhitespaceRange.getBegin().getRawEncoding() -

1058 C.Tok->LastNewlineOffset;

1059 assert(OriginalSpaces >= 0);

1060 const auto RestoredLineLength =

1061 C.StartOfTokenColumn + C.TokenLength + OriginalSpaces;

1062

1063

1064 if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)

1065 break;

1066 C.Spaces = C.NewlinesBefore > 0 ? C.Tok->OriginalColumn : OriginalSpaces;

1067 continue;

1068 }

1069

1070 const int ChangeMinColumn = C.StartOfTokenColumn;

1071 int ChangeMaxColumn;

1072

1073

1074

1075 if (C.CreateReplacement)

1076 ChangeMaxColumn = ChangeMinColumn;

1077 else if (Style.ColumnLimit == 0)

1078 ChangeMaxColumn = INT_MAX;

1079 else if (Style.ColumnLimit >= C.TokenLength)

1080 ChangeMaxColumn = Style.ColumnLimit - C.TokenLength;

1081 else

1082 ChangeMaxColumn = ChangeMinColumn;

1083

1084 if (I + 1 < Size && Changes[I + 1].ContinuesPPDirective &&

1085 ChangeMaxColumn >= 2) {

1086 ChangeMaxColumn -= 2;

1087 }

1088

1089 bool WasAlignedWithStartOfNextLine = false;

1090 if (C.NewlinesBefore >= 1) {

1091 const auto CommentColumn =

1092 SourceMgr.getSpellingColumnNumber(C.OriginalWhitespaceRange.getEnd());

1093 for (int J = I + 1; J < Size; ++J) {

1094 if (Changes[J].Tok->is(tok::comment))

1095 continue;

1096

1097 const auto NextColumn = SourceMgr.getSpellingColumnNumber(

1098 Changes[J].OriginalWhitespaceRange.getEnd());

1099

1100

1101 WasAlignedWithStartOfNextLine =

1102 CommentColumn == NextColumn ||

1103 CommentColumn == NextColumn + Style.IndentWidth;

1104 break;

1105 }

1106 }

1107

1108

1109

1110 auto DontAlignThisComment = [](const auto *Tok) {

1111 if (Tok->is(tok::semi)) {

1112 Tok = Tok->getPreviousNonComment();

1113 if (Tok)

1114 return false;

1115 }

1116 if (Tok->is(tok::r_paren)) {

1117

1118 Tok = Tok->MatchingParen;

1119 if (Tok)

1120 return false;

1121 Tok = Tok->getPreviousNonComment();

1122 if (Tok)

1123 return false;

1124 if (Tok->is(TT_DoWhile)) {

1125 const auto *Prev = Tok->getPreviousNonComment();

1126 if (!Prev) {

1127

1128 return true;

1129 }

1130 Tok = Prev;

1131 }

1132 }

1133

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

1135 return false;

1136

1137 while (Tok->Previous && Tok->Previous->is(tok::r_brace))

1138 Tok = Tok->Previous;

1139 return Tok->NewlinesBefore > 0;

1140 };

1141

1142 if (I > 0 && C.NewlinesBefore == 0 &&

1143 DontAlignThisComment(Changes[I - 1].Tok)) {

1144 alignTrailingComments(StartOfSequence, I, MinColumn);

1145

1146

1147 MinColumn = 0;

1149 StartOfSequence = I + 1;

1150 } else if (BreakBeforeNext || Newlines > NewLineThreshold ||

1151 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||

1152

1153

1154 (C.NewlinesBefore == 1 && I > 0 &&

1155 !Changes[I - 1].IsTrailingComment) ||

1156 WasAlignedWithStartOfNextLine) {

1157 alignTrailingComments(StartOfSequence, I, MinColumn);

1158 MinColumn = ChangeMinColumn;

1159 MaxColumn = ChangeMaxColumn;

1160 StartOfSequence = I;

1161 } else {

1162 MinColumn = std::max(MinColumn, ChangeMinColumn);

1163 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);

1164 }

1165 BreakBeforeNext = (I == 0) || (C.NewlinesBefore > 1) ||

1166

1167

1168 (C.NewlinesBefore == 1 && StartOfSequence == I);

1170 }

1171 alignTrailingComments(StartOfSequence, Size, MinColumn);

1172}

1173

1174void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,

1176 for (unsigned i = Start; i != End; ++i) {

1178 if (Changes[i].IsTrailingComment)

1179 Shift = Column - Changes[i].StartOfTokenColumn;

1180 if (Changes[i].StartOfBlockComment) {

1181 Shift = Changes[i].IndentationOffset +

1182 Changes[i].StartOfBlockComment->StartOfTokenColumn -

1183 Changes[i].StartOfTokenColumn;

1184 }

1185 if (Shift <= 0)

1186 continue;

1187 Changes[i].Spaces += Shift;

1188 if (i + 1 != Changes.size())

1189 Changes[i + 1].PreviousEndOfTokenColumn += Shift;

1190 Changes[i].StartOfTokenColumn += Shift;

1191 }

1192}

1193

1194void WhitespaceManager::alignEscapedNewlines() {

1195 const auto Align = Style.AlignEscapedNewlines;

1196 if (Align == FormatStyle::ENAS_DontAlign)

1197 return;

1198

1199 const bool WithLastLine = Align == FormatStyle::ENAS_LeftWithLastLine;

1200 const bool AlignLeft = Align == FormatStyle::ENAS_Left || WithLastLine;

1201 const auto MaxColumn = Style.ColumnLimit;

1202 unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;

1203 unsigned StartOfMacro = 0;

1204 for (unsigned i = 1, e = Changes.size(); i < e; ++i) {

1206 if (C.NewlinesBefore == 0 && (!WithLastLine || C.Tok->isNot(tok::eof)))

1207 continue;

1209 const auto BackslashColumn = C.PreviousEndOfTokenColumn + 2;

1210 if (InPPDirective ||

1211 (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {

1212 MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);

1213 }

1214 if (!InPPDirective) {

1215 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);

1216 MaxEndOfLine = AlignLeft ? 0 : MaxColumn;

1217 StartOfMacro = i;

1218 }

1219 }

1220 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);

1221}

1222

1223void WhitespaceManager::alignEscapedNewlines(unsigned Start, unsigned End,

1225 for (unsigned i = Start; i < End; ++i) {

1227 if (C.NewlinesBefore > 0) {

1228 assert(C.ContinuesPPDirective);

1229 if (C.PreviousEndOfTokenColumn + 1 > Column)

1230 C.EscapedNewlineColumn = 0;

1231 else

1232 C.EscapedNewlineColumn = Column;

1233 }

1234 }

1235}

1236

1237void WhitespaceManager::alignArrayInitializers() {

1238 if (Style.AlignArrayOfStructures == FormatStyle::AIAS_None)

1239 return;

1240

1241 for (unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();

1242 ChangeIndex < ChangeEnd; ++ChangeIndex) {

1243 auto &C = Changes[ChangeIndex];

1244 if (C.Tok->IsArrayInitializer) {

1245 bool FoundComplete = false;

1246 for (unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;

1247 ++InsideIndex) {

1248 const auto *Tok = Changes[InsideIndex].Tok;

1249 if (Tok->is(tok::pp_define))

1250 break;

1251 if (Tok == C.Tok->MatchingParen) {

1252 alignArrayInitializers(ChangeIndex, InsideIndex + 1);

1253 ChangeIndex = InsideIndex + 1;

1254 FoundComplete = true;

1255 break;

1256 }

1257 }

1258 if (!FoundComplete)

1259 ChangeIndex = ChangeEnd;

1260 }

1261 }

1262}

1263

1264void WhitespaceManager::alignArrayInitializers(unsigned Start, unsigned End) {

1265

1266 if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Right)

1267 alignArrayInitializersRightJustified(getCells(Start, End));

1268 else if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Left)

1269 alignArrayInitializersLeftJustified(getCells(Start, End));

1270}

1271

1272void WhitespaceManager::alignArrayInitializersRightJustified(

1273 CellDescriptions &&CellDescs) {

1274 if (!CellDescs.isRectangular())

1275 return;

1276

1277 const int BracePadding =

1278 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? 0 : 1;

1279 auto &Cells = CellDescs.Cells;

1280

1281 auto *CellIter = Cells.begin();

1282 for (auto i = 0U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {

1283 unsigned NetWidth = 0U;

1284 if (isSplitCell(*CellIter))

1285 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);

1286 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);

1287

1288 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {

1289

1290

1291

1292 const auto *Next = CellIter;

1293 do {

1296 Changes[Next->Index].Spaces = BracePadding;

1297 Changes[Next->Index].NewlinesBefore = 0;

1298 }

1299 Next = Next->NextColumnElement;

1300 } while (Next);

1301

1302

1303 if (CellIter != Cells.begin()) {

1304 auto ThisNetWidth =

1305 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);

1306 auto MaxNetWidth = getMaximumNetWidth(

1307 Cells.begin(), CellIter, CellDescs.InitialSpaces,

1308 CellDescs.CellCounts[0], CellDescs.CellCounts.size());

1309 if (ThisNetWidth < MaxNetWidth)

1310 Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);

1311 auto RowCount = 1U;

1312 auto Offset = std::distance(Cells.begin(), CellIter);

1313 for (const auto *Next = CellIter->NextColumnElement; Next;

1314 Next = Next->NextColumnElement) {

1315 if (RowCount >= CellDescs.CellCounts.size())

1316 break;

1317 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);

1318 auto *End = Start + Offset;

1319 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);

1320 if (ThisNetWidth < MaxNetWidth)

1321 Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);

1322 ++RowCount;

1323 }

1324 }

1325 } else {

1326 auto ThisWidth =

1327 calculateCellWidth(CellIter->Index, CellIter->EndIndex, true) +

1328 NetWidth;

1329 if (Changes[CellIter->Index].NewlinesBefore == 0) {

1330 Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));

1331 Changes[CellIter->Index].Spaces += (i > 0) ? 1 : BracePadding;

1332 }

1333 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);

1334 for (const auto *Next = CellIter->NextColumnElement; Next;

1335 Next = Next->NextColumnElement) {

1336 ThisWidth =

1337 calculateCellWidth(Next->Index, Next->EndIndex, true) + NetWidth;

1338 if (Changes[Next->Index].NewlinesBefore == 0) {

1339 Changes[Next->Index].Spaces = (CellWidth - ThisWidth);

1340 Changes[Next->Index].Spaces += (i > 0) ? 1 : BracePadding;

1341 }

1342 alignToStartOfCell(Next->Index, Next->EndIndex);

1343 }

1344 }

1345 }

1346}

1347

1348void WhitespaceManager::alignArrayInitializersLeftJustified(

1349 CellDescriptions &&CellDescs) {

1350

1351 if (!CellDescs.isRectangular())

1352 return;

1353

1354 const int BracePadding =

1355 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? 0 : 1;

1356 auto &Cells = CellDescs.Cells;

1357

1358 auto *CellIter = Cells.begin();

1359

1360 for (const auto *Next = CellIter; Next; Next = Next->NextColumnElement) {

1361 auto &Change = Changes[Next->Index];

1364 }

1365 ++CellIter;

1366 for (auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {

1367 auto MaxNetWidth = getMaximumNetWidth(

1368 Cells.begin(), CellIter, CellDescs.InitialSpaces,

1369 CellDescs.CellCounts[0], CellDescs.CellCounts.size());

1370 auto ThisNetWidth =

1371 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);

1372 if (Changes[CellIter->Index].NewlinesBefore == 0) {

1373 Changes[CellIter->Index].Spaces =

1374 MaxNetWidth - ThisNetWidth +

1375 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1

1376 : BracePadding);

1377 }

1378 auto RowCount = 1U;

1379 auto Offset = std::distance(Cells.begin(), CellIter);

1380 for (const auto *Next = CellIter->NextColumnElement; Next;

1381 Next = Next->NextColumnElement) {

1382 if (RowCount >= CellDescs.CellCounts.size())

1383 break;

1384 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);

1385 auto *End = Start + Offset;

1386 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);

1387 if (Changes[Next->Index].NewlinesBefore == 0) {

1388 Changes[Next->Index].Spaces =

1389 MaxNetWidth - ThisNetWidth +

1390 (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : BracePadding);

1391 }

1392 ++RowCount;

1393 }

1394 }

1395}

1396

1397bool WhitespaceManager::isSplitCell(const CellDescription &Cell) {

1398 if (Cell.HasSplit)

1399 return true;

1400 for (const auto *Next = Cell.NextColumnElement; Next;

1401 Next = Next->NextColumnElement) {

1402 if (Next->HasSplit)

1403 return true;

1404 }

1405 return false;

1406}

1407

1408WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,

1409 unsigned End) {

1410

1411 unsigned Depth = 0;

1412 unsigned Cell = 0;

1413 SmallVector CellCounts;

1414 unsigned InitialSpaces = 0;

1415 unsigned InitialTokenLength = 0;

1416 unsigned EndSpaces = 0;

1417 SmallVector Cells;

1419 for (unsigned i = Start; i < End; ++i) {

1420 auto &C = Changes[i];

1421 if (C.Tok->is(tok::l_brace))

1422 ++Depth;

1423 else if (C.Tok->is(tok::r_brace))

1424 --Depth;

1425 if (Depth == 2) {

1426 if (C.Tok->is(tok::l_brace)) {

1427 Cell = 0;

1429 if (InitialSpaces == 0) {

1430 InitialSpaces = C.Spaces + C.TokenLength;

1431 InitialTokenLength = C.TokenLength;

1432 auto j = i - 1;

1433 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {

1434 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;

1435 InitialTokenLength += Changes[j].TokenLength;

1436 }

1437 if (C.NewlinesBefore == 0) {

1438 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;

1439 InitialTokenLength += Changes[j].TokenLength;

1440 }

1441 }

1442 } else if (C.Tok->is(tok::comma)) {

1443 if (!Cells.empty())

1444 Cells.back().EndIndex = i;

1445 if (const auto *Next = C.Tok->getNextNonComment();

1446 Next && Next->isNot(tok::r_brace)) {

1447 ++Cell;

1448 }

1449 }

1450 } else if (Depth == 1) {

1452 if (!Cells.empty())

1453 Cells.back().EndIndex = i;

1454 Cells.push_back(CellDescription{i, ++Cell, i + 1, false, nullptr});

1455 CellCounts.push_back(C.Tok->Previous->isNot(tok::comma) ? Cell + 1

1456 : Cell);

1457

1458 const auto *NextNonComment = C.Tok->getNextNonComment();

1459 while (NextNonComment && NextNonComment->is(tok::comma))

1460 NextNonComment = NextNonComment->getNextNonComment();

1461 auto j = i;

1462 while (j < End && Changes[j].Tok != NextNonComment)

1463 ++j;

1465 Changes[j].Tok->isNot(tok::r_brace)) {

1466 Changes[j].NewlinesBefore = 1;

1467

1468 Changes[j].Spaces = InitialSpaces - InitialTokenLength;

1469 }

1470 } else if (C.Tok->is(tok::comment) && C.Tok->NewlinesBefore == 0) {

1471

1472 C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;

1473 } else if (C.Tok->is(tok::l_brace)) {

1474

1475

1476 auto j = i - 1;

1477 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)

1478 ;

1479 EndSpaces = Changes[j].Spaces;

1480 }

1481 } else if (Depth == 0 && C.Tok->is(tok::r_brace)) {

1482 C.NewlinesBefore = 1;

1483 C.Spaces = EndSpaces;

1484 }

1485 if (C.Tok->StartsColumn) {

1486

1487

1488 bool HasSplit = false;

1490

1491

1492

1493

1494

1495

1496

1497

1498

1499

1500

1501

1502

1503

1504 auto j = i - 1;

1505 if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&

1506 Changes[j - 1].NewlinesBefore > 0) {

1507 --j;

1508 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;

1509 if (LineLimit < Style.ColumnLimit) {

1510 Changes[i].NewlinesBefore = 0;

1511 Changes[i].Spaces = 1;

1512 }

1513 }

1514 }

1516 Changes[i].Spaces = InitialSpaces;

1517 ++i;

1518 HasSplit = true;

1519 }

1520 if (Changes[i].Tok != C.Tok)

1521 --i;

1522 Cells.push_back(CellDescription{i, Cell, i, HasSplit, nullptr});

1523 }

1524 }

1525

1526 return linkCells({Cells, CellCounts, InitialSpaces});

1527}

1528

1529unsigned WhitespaceManager::calculateCellWidth(unsigned Start, unsigned End,

1530 bool WithSpaces) const {

1531 unsigned CellWidth = 0;

1532 for (auto i = Start; i < End; i++) {

1534 CellWidth = 0;

1535 CellWidth += Changes[i].TokenLength;

1536 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);

1537 }

1538 return CellWidth;

1539}

1540

1541void WhitespaceManager::alignToStartOfCell(unsigned Start, unsigned End) {

1542 if ((End - Start) <= 1)

1543 return;

1544

1545

1546 for (auto i = Start + 1; i < End; i++)

1548 Changes[i].Spaces = Changes[Start].Spaces;

1549}

1550

1551WhitespaceManager::CellDescriptions

1552WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {

1553 auto &Cells = CellDesc.Cells;

1554 for (auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {

1555 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {

1556 for (auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {

1557 if (NextIter->Cell == CellIter->Cell) {

1558 CellIter->NextColumnElement = &(*NextIter);

1559 break;

1560 }

1561 }

1562 }

1563 }

1564 return std::move(CellDesc);

1565}

1566

1567void WhitespaceManager::generateChanges() {

1568 for (unsigned i = 0, e = Changes.size(); i != e; ++i) {

1569 const Change &C = Changes[i];

1570 if (i > 0) {

1571 auto Last = Changes[i - 1].OriginalWhitespaceRange;

1572 auto New = Changes[i].OriginalWhitespaceRange;

1573

1574

1575

1576

1577

1578

1579

1580

1581

1582

1583

1584

1585

1586

1587

1588

1589

1590

1591

1592

1593

1594

1595

1596

1597

1598

1599

1600

1601

1602

1603

1604

1605

1606

1607

1608

1609

1610

1611

1612

1613

1614 if (Last.getBegin() == New.getBegin() &&

1615 (Last.getEnd() != Last.getBegin() ||

1616 New.getEnd() == New.getBegin())) {

1617 continue;

1618 }

1619 }

1620 if (C.CreateReplacement) {

1621 std::string ReplacementText = C.PreviousLinePostfix;

1622 if (C.ContinuesPPDirective) {

1623 appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,

1624 C.PreviousEndOfTokenColumn,

1625 C.EscapedNewlineColumn);

1626 } else {

1627 appendNewlineText(ReplacementText, C);

1628 }

1629

1630

1631 appendIndentText(

1632 ReplacementText, C.Tok->IndentLevel, std::max(0, C.Spaces),

1633 std::max((int)C.StartOfTokenColumn, C.Spaces) - std::max(0, C.Spaces),

1634 C.IsAligned);

1635 ReplacementText.append(C.CurrentLinePrefix);

1636 storeReplacement(C.OriginalWhitespaceRange, ReplacementText);

1637 }

1638 }

1639}

1640

1641void WhitespaceManager::storeReplacement(SourceRange Range, StringRef Text) {

1642 unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.getEnd()) -

1643 SourceMgr.getFileOffset(Range.getBegin());

1644

1645 if (StringRef(SourceMgr.getCharacterData(Range.getBegin()),

1646 WhitespaceLength) == Text) {

1647 return;

1648 }

1649 auto Err = Replaces.add(tooling::Replacement(

1651

1652

1653 if (Err) {

1654 llvm::errs() << llvm::toString(std::move(Err)) << "\n";

1655 assert(false);

1656 }

1657}

1658

1659void WhitespaceManager::appendNewlineText(std::string &Text, const Change &C) {

1660 if (C.NewlinesBefore <= 0)

1661 return;

1662

1663 StringRef Newline = UseCRLF ? "\r\n" : "\n";

1664 Text.append(Newline);

1665

1666 if (C.Tok->HasFormFeedBefore)

1667 Text.append("\f");

1668

1669 for (unsigned I = 1; I < C.NewlinesBefore; ++I)

1670 Text.append(Newline);

1671}

1672

1673void WhitespaceManager::appendEscapedNewlineText(

1674 std::string &Text, unsigned Newlines, unsigned PreviousEndOfTokenColumn,

1675 unsigned EscapedNewlineColumn) {

1677 unsigned Spaces =

1678 std::max(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);

1679 for (unsigned i = 0; i < Newlines; ++i) {

1680 Text.append(Spaces, ' ');

1681 Text.append(UseCRLF ? "\\\r\n" : "\\\n");

1682 Spaces = std::max(0, EscapedNewlineColumn - 1);

1683 }

1684 }

1685}

1686

1687void WhitespaceManager::appendIndentText(std::string &Text,

1689 unsigned WhitespaceStartColumn,

1690 bool IsAligned) {

1691 switch (Style.UseTab) {

1692 case FormatStyle::UT_Never:

1693 Text.append(Spaces, ' ');

1694 break;

1695 case FormatStyle::UT_Always: {

1696 if (Style.TabWidth) {

1697 unsigned FirstTabWidth =

1698 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;

1699

1700

1701 if (Spaces < FirstTabWidth || Spaces == 1) {

1702 Text.append(Spaces, ' ');

1703 break;

1704 }

1705

1706 Spaces -= FirstTabWidth;

1707 Text.append("\t");

1708

1709 Text.append(Spaces / Style.TabWidth, '\t');

1710 Text.append(Spaces % Style.TabWidth, ' ');

1711 } else if (Spaces == 1) {

1712 Text.append(Spaces, ' ');

1713 }

1714 break;

1715 }

1716 case FormatStyle::UT_ForIndentation:

1717 if (WhitespaceStartColumn == 0) {

1718 unsigned Indentation = IndentLevel * Style.IndentWidth;

1719 Spaces = appendTabIndent(Text, Spaces, Indentation);

1720 }

1721 Text.append(Spaces, ' ');

1722 break;

1723 case FormatStyle::UT_ForContinuationAndIndentation:

1724 if (WhitespaceStartColumn == 0)

1725 Spaces = appendTabIndent(Text, Spaces, Spaces);

1726 Text.append(Spaces, ' ');

1727 break;

1728 case FormatStyle::UT_AlignWithSpaces:

1729 if (WhitespaceStartColumn == 0) {

1730 unsigned Indentation =

1731 IsAligned ? IndentLevel * Style.IndentWidth : Spaces;

1732 Spaces = appendTabIndent(Text, Spaces, Indentation);

1733 }

1734 Text.append(Spaces, ' ');

1735 break;

1736 }

1737}

1738

1739unsigned WhitespaceManager::appendTabIndent(std::string &Text, unsigned Spaces,

1740 unsigned Indentation) {

1741

1742

1743 if (Indentation > Spaces)

1744 Indentation = Spaces;

1745 if (Style.TabWidth) {

1746 unsigned Tabs = Indentation / Style.TabWidth;

1747 Text.append(Tabs, '\t');

1748 Spaces -= Tabs * Style.TabWidth;

1749 }

1750 return Spaces;

1751}

1752

1753}

1754}

int Newlines

The number of newlines immediately before the Token after formatting.

unsigned NewlinesBefore

The number of newlines immediately before the Token.

FormatToken * MatchingParen

If this is a bracket, this points to the matching one.

unsigned IndentLevel

The indent level of this token. Copied from the surrounding line.

FormatToken * Previous

The previous token in the unwrapped line.

FormatToken * Next

The next token in the unwrapped line.

WhitespaceManager class manages whitespace around tokens and their replacements.

static CharSourceRange getCharRange(SourceRange R)

Encodes a location in the source.

SourceLocation getLocWithOffset(IntTy Offset) const

Return a source location with the specified offset from this SourceLocation.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getBegin() const

Functor to sort changes in original source order.

bool operator()(const Change &C1, const Change &C2) const

Definition WhitespaceManager.cpp:22

void replaceWhitespaceInToken(const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars, StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective, unsigned Newlines, int Spaces)

Inserts or replaces whitespace in the middle of a token.

Definition WhitespaceManager.cpp:92

void replaceWhitespace(FormatToken &Tok, unsigned Newlines, unsigned Spaces, unsigned StartOfTokenColumn, bool IsAligned=false, bool InPPDirective=false, unsigned IndentedFromColumn=0)

Replaces the whitespace in front of Tok.

Definition WhitespaceManager.cpp:55

void addUntouchableToken(const FormatToken &Tok, bool InPPDirective)

Adds information about an unchangeable token's whitespace.

Definition WhitespaceManager.cpp:70

static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF)

Infers whether the input is using CRLF.

Definition WhitespaceManager.cpp:86

llvm::Error addReplacement(const tooling::Replacement &Replacement)

Definition WhitespaceManager.cpp:82

const tooling::Replacements & generateReplacements()

Returns all the Replacements created during formatting.

Definition WhitespaceManager.cpp:108

@ MR_ExpandedArg

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

static void AlignMatchingTokenSequence(unsigned &StartOfSequence, unsigned &EndOfSequence, unsigned &MinColumn, std::function< bool(const WhitespaceManager::Change &C)> Matches, SmallVector< WhitespaceManager::Change, 16 > &Changes)

Definition WhitespaceManager.cpp:688

static void AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, unsigned Column, bool RightJustify, ArrayRef< unsigned > Matches, SmallVector< WhitespaceManager::Change, 16 > &Changes)

Definition WhitespaceManager.cpp:291

TokenType

Determines the semantic type of a syntactic token, e.g.

static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, SmallVector< WhitespaceManager::Change, 16 > &Changes, unsigned StartAt, const FormatStyle::AlignConsecutiveStyle &ACS={}, bool RightJustify=false)

Definition WhitespaceManager.cpp:454

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

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

@ Type

The name was classified as a type.

int const char * function

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

unsigned FakeRParens

Insert this many fake ) after this token for correct indentation.

SmallVector< prec::Level, 4 > FakeLParens

Stores the number of required fake parentheses and the corresponding operator precedence.

bool is(tok::TokenKind Kind) const

FormatToken * Previous

The previous token in the unwrapped line.

Represents a change before a token, a break inside a token, or the layout of an unchanged token (or w...

const Change * StartOfBlockComment

SourceRange OriginalWhitespaceRange

unsigned IndentedFromColumn

std::string PreviousLinePostfix

std::string CurrentLinePrefix

unsigned StartOfTokenColumn

unsigned PreviousEndOfTokenColumn

unsigned EscapedNewlineColumn

bool ContinuesPPDirective

Change(const FormatToken &Tok, bool CreateReplacement, SourceRange OriginalWhitespaceRange, int Spaces, unsigned StartOfTokenColumn, unsigned IndentedFromColumn, unsigned NewlinesBefore, StringRef PreviousLinePostfix, StringRef CurrentLinePrefix, bool IsAligned, bool ContinuesPPDirective, bool IsInsideToken)

Creates a Change.

Definition WhitespaceManager.cpp:34