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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

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

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

21#include

22

23#define DEBUG_TYPE "format-token-breaker"

24

26namespace format {

27

28static constexpr StringRef Blanks(" \t\v\f\r");

29

31 const FormatStyle &Style) {

32 static constexpr StringRef KnownCStylePrefixes[] = {"///<", "//!<", "///",

33 "//!", "//:", "//"};

34 static constexpr StringRef KnownTextProtoPrefixes[] = {"####", "###", "##",

35 "//", "#"};

37 if (Style.isTextProto())

38 KnownPrefixes = KnownTextProtoPrefixes;

39

40 assert(

41 llvm::is_sorted(KnownPrefixes, [](StringRef Lhs, StringRef Rhs) noexcept {

42 return Lhs.size() > Rhs.size();

43 }));

44

45 for (StringRef KnownPrefix : KnownPrefixes) {

46 if (Comment.starts_with(KnownPrefix)) {

47 const auto PrefixLength =

48 Comment.find_first_not_of(' ', KnownPrefix.size());

49 return Comment.substr(0, PrefixLength);

50 }

51 }

52 return {};

53}

54

57 unsigned ColumnLimit, unsigned TabWidth,

59 bool DecorationEndsWithStar = false) {

60 LLVM_DEBUG(llvm::dbgs() << "Comment split: \"" << Text

61 << "\", Column limit: " << ColumnLimit

62 << ", Content start: " << ContentStartColumn << "\n");

63 if (ColumnLimit <= ContentStartColumn + 1)

65

66 unsigned MaxSplit = ColumnLimit - ContentStartColumn + 1;

67 unsigned MaxSplitBytes = 0;

68

69 for (unsigned NumChars = 0;

70 NumChars < MaxSplit && MaxSplitBytes < Text.size();) {

71 unsigned BytesInChar =

74 Text.substr(MaxSplitBytes, BytesInChar), ContentStartColumn + NumChars,

76 MaxSplitBytes += BytesInChar;

77 }

78

79

80

81

82 if (Style.isJavaScript()) {

83 StringRef::size_type SpaceOffset =

84 Text.find_first_of(Blanks, MaxSplitBytes);

85 if (SpaceOffset != StringRef::npos && SpaceOffset + 1 < Text.size() &&

86 Text[SpaceOffset + 1] == '{') {

87 MaxSplitBytes = SpaceOffset + 1;

88 }

89 }

90

91 StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);

92

93 static const auto kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\.");

94

95 while (SpaceOffset != StringRef::npos) {

96

97

98

99

100

101 if (Style.isCpp()) {

102 StringRef::size_type LastNonBlank =

103 Text.find_last_not_of(Blanks, SpaceOffset);

104 if (LastNonBlank != StringRef::npos && Text[LastNonBlank] == '\\') {

105 SpaceOffset = Text.find_last_of(Blanks, LastNonBlank);

106 continue;

107 }

108 }

109

110

111

112 if (kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks))) {

113 SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);

114 continue;

115 }

116

117

118 if (Style.isJavaScript() && SpaceOffset + 1 < Text.size() &&

119 (Text[SpaceOffset + 1] == '{' || Text[SpaceOffset + 1] == '@')) {

120 SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);

121 continue;

122 }

123

124 break;

125 }

126

127 if (SpaceOffset == StringRef::npos ||

128

129 Text.find_last_not_of(Blanks, SpaceOffset) == StringRef::npos) {

130

131

132 StringRef::size_type FirstNonWhitespace = Text.find_first_not_of(Blanks);

133 if (FirstNonWhitespace == StringRef::npos) {

134

136 }

137 SpaceOffset = Text.find_first_of(

138 Blanks, std::max(MaxSplitBytes, FirstNonWhitespace));

139 }

140 if (SpaceOffset != StringRef::npos && SpaceOffset != 0) {

141

142

143

144

145 if (SpaceOffset == 1 && Text[SpaceOffset - 1] == '*')

147 StringRef BeforeCut = Text.substr(0, SpaceOffset).rtrim(Blanks);

148 StringRef AfterCut = Text.substr(SpaceOffset);

149 if (!DecorationEndsWithStar)

150 AfterCut = AfterCut.ltrim(Blanks);

152 AfterCut.begin() - BeforeCut.end());

153 }

155}

156

160

161 if (Text.empty())

163 if (ColumnLimit <= UsedColumns)

165 unsigned MaxSplit = ColumnLimit - UsedColumns;

166 StringRef::size_type SpaceOffset = 0;

167 StringRef::size_type SlashOffset = 0;

168 StringRef::size_type WordStartOffset = 0;

169 StringRef::size_type SplitPoint = 0;

170 for (unsigned Chars = 0;;) {

171 unsigned Advance;

172 if (Text[0] == '\\') {

174 Chars += Advance;

175 } else {

178 Text.substr(0, Advance), UsedColumns + Chars, TabWidth, Encoding);

179 }

180

181 if (Chars > MaxSplit || Text.size() <= Advance)

182 break;

183

185 SpaceOffset = SplitPoint;

186 if (Text[0] == '/')

187 SlashOffset = SplitPoint;

189 WordStartOffset = SplitPoint;

190

191 SplitPoint += Advance;

193 }

194

195 if (SpaceOffset != 0)

197 if (SlashOffset != 0)

199 if (WordStartOffset != 0)

201 if (SplitPoint != 0)

204}

205

207 assert((Token.is(TT_BlockComment) || Token.is(TT_LineComment)) &&

208 "formatting regions are switched by comment tokens");

209 StringRef Content = Token.TokenText.substr(2).ltrim();

210 return Content.starts_with("clang-format on") ||

211 Content.starts_with("clang-format off");

212}

213

214unsigned

217

218

219

220

221

222

223

224

225

226

227

228 return RemainingTokenColumns + 1 - Split.second;

229}

230

232

234 unsigned Offset,

235 StringRef::size_type Length,

237 llvm_unreachable("Getting the length of a part of the string literal "

238 "indicates that the code tries to reflow it.");

239}

240

241unsigned

248

250 bool Break) const {

252}

253

265

267 unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,

268 unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const {

271}

272

275 unsigned ContentIndent,

280}

281

289 : "\"",

294

295

296

297

298

299

300

301 bool SignOnNewLine =

302 Style.isJavaScript() &&

303 Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;

304

306

307

308 assert(QuoteStyle == DoubleQuotes);

309 LeftBraceQuote =

310 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? "{\"" : "{ \"";

311 RightBraceQuote =

312 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? "\"}" : "\" }";

313 Postfix = "\",";

314 Prefix = "\"";

315 } else {

316

317

318 if (QuoteStyle == SingleQuotes) {

319 LeftBraceQuote = Style.SpacesInParensOptions.Other ? "( '" : "('";

320 RightBraceQuote = Style.SpacesInParensOptions.Other ? "' )" : "')";

321 Postfix = SignOnNewLine ? "'" : "' +";

322 Prefix = SignOnNewLine ? "+ '" : "'";

323 } else {

324 if (QuoteStyle == AtDoubleQuotes) {

325 LeftBraceQuote = Style.SpacesInParensOptions.Other ? "( @" : "(@";

326 Prefix = SignOnNewLine ? "+ @\"" : "@\"";

327 } else {

328 LeftBraceQuote = Style.SpacesInParensOptions.Other ? "( \"" : "(\"";

329 Prefix = SignOnNewLine ? "+ \"" : "\"";

330 }

332 Postfix = SignOnNewLine ? "\"" : "\" +";

333 }

334 }

335

336

337 ContinuationIndent = BracesNeeded ? LeftBraceQuote.size() - 1 : 0;

338

339

340 if (!Style.isVerilog() && SignOnNewLine && !BracesNeeded && UnindentPlus &&

341 Style.AlignOperands == FormatStyle::OAS_AlignAfterOperator) {

342 ContinuationIndent -= 2;

343 }

344}

345

347 unsigned LineIndex, unsigned Offset, unsigned StartColumn) const {

351}

352

353unsigned

355 bool Break) const {

356 return std::max(

357 0,

361 : 0) +

363}

364

376

379

381 return;

382

383

384

385

386

387

389 Tok, 0, 1, "",

391 0);

393 Tok, Tok.TokenText.size() - 1, 1,

395 "", InPPDirective, 0, 0);

396}

397

401 const FormatStyle &Style)

404

406

409 unsigned ColumnLimit, unsigned ContentStartColumn,

410 const llvm::Regex &CommentPragmasRegex) const {

411

413 return Split(StringRef::npos, 0);

415 ContentStartColumn, ColumnLimit, Style.TabWidth,

417}

418

420 unsigned LineIndex, unsigned TailOffset, Split Split,

422 StringRef Text = Content[LineIndex].substr(TailOffset);

423

424

425

426

427 unsigned BreakOffsetInToken =

429 unsigned CharsToRemove = Split.second;

431 tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "", "",

432 false, 0, 1);

433}

434

438

440 Content = Content.trim(Blanks);

441

442

443 bool hasSpecialMeaningPrefix = false;

444 for (StringRef Prefix :

445 {"@", "\\", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "}) {

446 if (Content.starts_with(Prefix)) {

447 hasSpecialMeaningPrefix = true;

448 break;

449 }

450 }

451

452

453

454

455 static const auto kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\. ");

456 hasSpecialMeaningPrefix =

457 hasSpecialMeaningPrefix || kNumberedListRegexp.match(Content);

458

459

460

461

462 return Content.size() >= 2 && !hasSpecialMeaningPrefix &&

463 !Content.ends_with("\\") &&

464

465

467}

468

471 unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,

474 DelimitersOnNewline(false),

475 UnbreakableTailLength(Token.UnbreakableTailLength) {

476 assert(Tok.is(TT_BlockComment) &&

477 "block comment section must start with a block comment");

478

482 .split(Lines, UseCRLF ? "\r\n" : "\n");

483

484 int IndentDelta = StartColumn - OriginalStartColumn;

488

491 for (size_t i = 1; i < Lines.size(); ++i)

492 adjustWhitespace(i, IndentDelta);

493

494

495

497

498

499

500

501

502

503 if (Lines.size() >= 2 && Content[1].starts_with("**") &&

506 }

507

508 Decoration = "* ";

509 if (Lines.size() == 1 && !FirstInLine) {

510

511

512

513

514

515 Decoration = "";

516 }

517 for (size_t i = 1, e = Content.size(); i < e && !Decoration.empty(); ++i) {

519 if (i + 1 == e) {

520

521 if (Text.empty())

522 break;

523 } else if (Text.empty() && Decoration.starts_with(Text)) {

524 continue;

525 }

526 while (Text.starts_with(Decoration))

527 Decoration = Decoration.drop_back(1);

528 }

529

530 LastLineNeedsDecoration = true;

532 for (size_t i = 1, e = Lines.size(); i < e; ++i) {

533 if (Content[i].empty()) {

534 if (i + 1 == e) {

535

536

537

538 LastLineNeedsDecoration = false;

539

540 if (e >= 2 && !Decoration.empty())

542 } else if (Decoration.empty()) {

543

544

546 }

547 continue;

548 }

549

550

551

552

553

554 unsigned DecorationSize = Decoration.starts_with(Content[i])

556 : Decoration.size();

557 if (DecorationSize)

558 ContentColumn[i] = DecorationColumn + DecorationSize;

560 if (!Decoration.starts_with(Content[i])) {

561 IndentAtLineBreak =

562 std::min(IndentAtLineBreak, std::max(0, ContentColumn[i]));

563 }

564 }

565 IndentAtLineBreak = std::max(IndentAtLineBreak, Decoration.size());

566

567

568 if (Style.isJavaScript() || Style.isJava()) {

569 if ((Lines[0] == "*" || Lines[0].starts_with("* ")) && Lines.size() > 1) {

570

571 DelimitersOnNewline = true;

572 } else if (Lines[0].starts_with("* ") && Lines.size() == 1) {

573

574

575

576 unsigned EndColumn =

580 2;

581 DelimitersOnNewline = EndColumn > Style.ColumnLimit;

582 }

583 }

584

585 LLVM_DEBUG({

586 llvm::dbgs() << "IndentAtLineBreak " << IndentAtLineBreak << "\n";

587 llvm::dbgs() << "DelimitersOnNewline " << DelimitersOnNewline << "\n";

588 for (size_t i = 0; i < Lines.size(); ++i) {

589 llvm::dbgs() << i << " |" << Content[i] << "| "

591 << "IN=" << (Content[i].data() - Lines[i].data()) << "\n";

592 }

593 });

594}

595

597 unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,

598 unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const {

599

601 return Split(StringRef::npos, 0);

603 ContentStartColumn, ColumnLimit, Style.TabWidth,

605}

606

607void BreakableBlockComment::adjustWhitespace(unsigned LineIndex,

608 int IndentDelta) {

609

610

611

612

613

614 size_t EndOfPreviousLine = Lines[LineIndex - 1].size();

616 --EndOfPreviousLine;

617

618

619 EndOfPreviousLine =

620 Lines[LineIndex - 1].find_last_not_of(Blanks, EndOfPreviousLine);

621 if (EndOfPreviousLine == StringRef::npos)

622 EndOfPreviousLine = 0;

623 else

624 ++EndOfPreviousLine;

625

626 size_t StartOfLine = Lines[LineIndex].find_first_not_of(Blanks);

627 if (StartOfLine == StringRef::npos)

628 StartOfLine = Lines[LineIndex].size();

629

630 StringRef Whitespace = Lines[LineIndex].substr(0, StartOfLine);

631

632 size_t PreviousContentOffset =

633 Content[LineIndex - 1].data() - Lines[LineIndex - 1].data();

634 Content[LineIndex - 1] = Lines[LineIndex - 1].substr(

635 PreviousContentOffset, EndOfPreviousLine - PreviousContentOffset);

636 Content[LineIndex] = Lines[LineIndex].substr(StartOfLine);

637

638

641 IndentDelta;

642}

643

645 unsigned Offset,

646 StringRef::size_type Length,

651}

652

654 unsigned Offset,

656 unsigned LineLength =

657 UnbreakableTailLength +

659 if (LineIndex + 1 == Lines.size()) {

660 LineLength += 2;

661

662 bool HasRemainingText = Offset < Content[LineIndex].size();

663 if (!HasRemainingText) {

664 bool HasDecoration = Lines[LineIndex].ltrim().starts_with(Decoration);

665 if (HasDecoration)

666 LineLength -= Decoration.size();

667 }

668 }

669 return LineLength;

670}

671

673 bool Break) const {

674 if (Break)

675 return IndentAtLineBreak;

677}

678

679const llvm::StringSet<>

681 "@param", "@return", "@returns", "@throws", "@type", "@template",

682 "@see", "@deprecated", "@define", "@exports", "@mods", "@private",

683};

684

686 if (Style.isJava() && Style.isJavaScript())

687 return 0;

688

689

690

691 StringRef ContentWithNoDecoration = Content[LineIndex];

692 if (LineIndex == 0 && ContentWithNoDecoration.starts_with("*"))

693 ContentWithNoDecoration = ContentWithNoDecoration.substr(1).ltrim(Blanks);

694 StringRef FirstWord = ContentWithNoDecoration.substr(

695 0, ContentWithNoDecoration.find_first_of(Blanks));

697 return Style.ContinuationIndentWidth;

698 return 0;

699}

700

704 StringRef Text = Content[LineIndex].substr(TailOffset);

705 StringRef Prefix = Decoration;

706

707

708

709 unsigned LocalIndentAtLineBreak = IndentAtLineBreak;

710 if (LineIndex + 1 == Lines.size() &&

712

713 Prefix = "";

714 if (LocalIndentAtLineBreak >= 2)

715 LocalIndentAtLineBreak -= 2;

716 }

717

718

719 unsigned BreakOffsetInToken =

721 unsigned CharsToRemove = Split.second;

722 assert(LocalIndentAtLineBreak >= Prefix.size());

723 std::string PrefixWithTrailingIndent = std::string(Prefix);

724 PrefixWithTrailingIndent.append(ContentIndent, ' ');

726 tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "",

727 PrefixWithTrailingIndent, InPPDirective, 1,

728 LocalIndentAtLineBreak + ContentIndent -

729 PrefixWithTrailingIndent.size());

730}

731

733 unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {

734 if (mayReflow(LineIndex, CommentPragmasRegex))

735 return Split(StringRef::npos, 0);

736

737

738

739 size_t Trimmed = Content[LineIndex].find_first_not_of(Blanks);

740 if (LineIndex) {

741 unsigned PreviousContentIndent = getContentIndent(LineIndex - 1);

742 if (PreviousContentIndent && Trimmed != StringRef::npos &&

743 Trimmed != PreviousContentIndent) {

744 return Split(StringRef::npos, 0);

745 }

746 }

747

748 return Split(0, Trimmed != StringRef::npos ? Trimmed : 0);

749}

750

752

753 return DelimitersOnNewline &&

754 Lines[0].substr(1).find_first_not_of(Blanks) != StringRef::npos;

755}

756

759 StringRef TrimmedContent = Content[LineIndex].ltrim(Blanks);

760

761 assert(Tokens[LineIndex - 1] == Tokens[LineIndex] &&

762 "Reflowing whitespace within a token");

763

764

765 unsigned WhitespaceOffsetInToken = Content[LineIndex - 1].data() +

766 Content[LineIndex - 1].size() -

768 unsigned WhitespaceLength = TrimmedContent.data() -

770 WhitespaceOffsetInToken;

772 tokenAt(LineIndex), WhitespaceOffsetInToken,

773 WhitespaceLength, "",

775 0);

776}

777

780 if (LineIndex == 0) {

781 if (DelimitersOnNewline) {

782

783

784

785

786 size_t BreakLength = Lines[0].substr(1).find_first_not_of(Blanks);

787 if (BreakLength != StringRef::npos) {

788 insertBreak(LineIndex, 0, Split(1, BreakLength), 0,

789 Whitespaces);

790 }

791 }

792 return;

793 }

794

795

796 StringRef Prefix = Decoration;

797 if (Content[LineIndex].empty()) {

798 if (LineIndex + 1 == Lines.size()) {

799 if (!LastLineNeedsDecoration) {

800

801

802 Prefix = "";

803 }

804 } else if (!Decoration.empty()) {

805

806

807 Prefix = Prefix.substr(0, 1);

808 }

810

811 Prefix = Prefix.substr(0, 1);

812 }

813

814

815 unsigned WhitespaceOffsetInToken = Content[LineIndex - 1].data() +

816 Content[LineIndex - 1].size() -

818 unsigned WhitespaceLength = Content[LineIndex].data() -

820 WhitespaceOffsetInToken;

822 tokenAt(LineIndex), WhitespaceOffsetInToken, WhitespaceLength, "", Prefix,

824}

825

828 if (DelimitersOnNewline) {

829

830

831

832 StringRef Line = Content.back().substr(TailOffset);

833 StringRef TrimmedLine = Line.rtrim(Blanks);

834 if (!TrimmedLine.empty())

835 return Split(TrimmedLine.size(), Line.size() - TrimmedLine.size());

836 }

837 return Split(StringRef::npos, 0);

838}

839

841 unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {

842

843

844 StringRef IndentContent = Content[LineIndex];

845 if (Lines[LineIndex].ltrim(Blanks).starts_with("*"))

846 IndentContent = Lines[LineIndex].ltrim(Blanks).substr(1);

848 !CommentPragmasRegex.match(IndentContent) &&

851}

852

857 assert(Tok.is(TT_LineComment) &&

858 "line comment section must start with a line comment");

860 const int Minimum = Style.SpacesInLineCommentPrefix.Minimum;

861

862

863 int FirstLineSpaceChange = 0;

865 CurrentTok && CurrentTok->is(TT_LineComment);

866 CurrentTok = CurrentTok->Next) {

867 LastLineTok = LineTok;

868 StringRef TokenText(CurrentTok->TokenText);

869 assert((TokenText.starts_with("//") || TokenText.starts_with("#")) &&

870 "unsupported line comment prefix, '//' and '#' are supported");

871 size_t FirstLineIndex = Lines.size();

875 PrefixSpaceChange.resize(Lines.size());

877 Prefix.resize(Lines.size());

878 OriginalPrefix.resize(Lines.size());

879 for (size_t i = FirstLineIndex, e = Lines.size(); i < e; ++i) {

882 OriginalPrefix[i] = IndentPrefix;

883 const int SpacesInPrefix = llvm::count(IndentPrefix, ' ');

884

885

886

887 const auto NoSpaceBeforeFirstCommentChar = [&]() {

888 assert(Lines[i].size() > IndentPrefix.size());

889 const char FirstCommentChar = Lines[i][IndentPrefix.size()];

890 const unsigned FirstCharByteSize =

893 Lines[i].substr(IndentPrefix.size(), FirstCharByteSize),

895 return false;

896 }

897

898

899

900

901

902

903

904

905

906 if (FirstCommentChar == '#' && TokenText.starts_with("#"))

907 return false;

908 return FirstCommentChar == '\\' || isPunctuation(FirstCommentChar) ||

910 };

911

912

913

914

915

916

917 if (i == 0 || OriginalPrefix[i].rtrim(Blanks) !=

918 OriginalPrefix[i - 1].rtrim(Blanks)) {

919 if (SpacesInPrefix < Minimum && Lines[i].size() > IndentPrefix.size() &&

920 !NoSpaceBeforeFirstCommentChar()) {

921 FirstLineSpaceChange = Minimum - SpacesInPrefix;

922 } else if (static_cast<unsigned>(SpacesInPrefix) >

923 Style.SpacesInLineCommentPrefix.Maximum) {

924 FirstLineSpaceChange =

925 Style.SpacesInLineCommentPrefix.Maximum - SpacesInPrefix;

926 } else {

927 FirstLineSpaceChange = 0;

928 }

929 }

930

931 if (Lines[i].size() != IndentPrefix.size()) {

932 assert(Lines[i].size() > IndentPrefix.size());

933

934 PrefixSpaceChange[i] = SpacesInPrefix + FirstLineSpaceChange < Minimum

935 ? Minimum - SpacesInPrefix

936 : FirstLineSpaceChange;

937

938 const auto FirstNonSpace = Lines[i][IndentPrefix.size()];

939 const bool IsFormatComment = LineTok && switchesFormatting(*LineTok);

940 const bool LineRequiresLeadingSpace =

941 !NoSpaceBeforeFirstCommentChar() ||

942 (FirstNonSpace == '}' && FirstLineSpaceChange != 0);

943 const bool AllowsSpaceChange =

944 !IsFormatComment &&

945 (SpacesInPrefix != 0 || LineRequiresLeadingSpace);

946

947 if (PrefixSpaceChange[i] > 0 && AllowsSpaceChange) {

948 Prefix[i] = IndentPrefix.str();

949 Prefix[i].append(PrefixSpaceChange[i], ' ');

950 } else if (PrefixSpaceChange[i] < 0 && AllowsSpaceChange) {

951 Prefix[i] = IndentPrefix

952 .drop_back(std::minstd::size\_t(

953 -PrefixSpaceChange[i], SpacesInPrefix))

954 .str();

955 } else {

956 Prefix[i] = IndentPrefix.str();

957 }

958 } else {

959

960

961 Prefix[i] = IndentPrefix.drop_back(SpacesInPrefix).str();

962 }

963

965 Content[i] = Lines[i].substr(IndentPrefix.size());

969

970

971 size_t EndOfLine = Content[i].find_last_not_of(Blanks);

972 if (EndOfLine == StringRef::npos)

973 EndOfLine = Content[i].size();

974 else

975 ++EndOfLine;

977 }

978 LineTok = CurrentTok->Next;

979 if (CurrentTok->Next && !CurrentTok->Next->ContinuesLineCommentSection) {

980

981

982

983

984

985

986

987

988

989

990

991

992

993

994 break;

995 }

996 }

997}

998

999unsigned

1001 StringRef::size_type Length,

1006}

1007

1008unsigned

1010 bool ) const {

1012}

1013

1015 unsigned LineIndex, unsigned TailOffset, Split Split,

1017 StringRef Text = Content[LineIndex].substr(TailOffset);

1018

1019

1020 unsigned BreakOffsetInToken =

1022 unsigned CharsToRemove = Split.second;

1024 tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "",

1025 Prefix[LineIndex], InPPDirective, 1,

1026 ContentColumn[LineIndex] - Prefix[LineIndex].size());

1027}

1028

1030 unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {

1031 if (mayReflow(LineIndex, CommentPragmasRegex))

1032 return Split(StringRef::npos, 0);

1033

1034 size_t Trimmed = Content[LineIndex].find_first_not_of(Blanks);

1035

1036

1037

1038

1039

1040 return Split(0, Trimmed != StringRef::npos ? Trimmed : 0);

1041}

1042

1045 if (LineIndex > 0 && Tokens[LineIndex] != Tokens[LineIndex - 1]) {

1046

1047

1049 *Tokens[LineIndex], 0, 0,

1050 StartColumn, true,

1051 false);

1052 } else if (LineIndex > 0) {

1053

1054

1055

1056

1057

1058

1059

1060

1061

1062

1063 unsigned Offset = Lines[LineIndex - 1].data() +

1064 Lines[LineIndex - 1].size() -

1066

1067

1068 unsigned WhitespaceLength =

1071 WhitespaceLength,

1072 "",

1073 "",

1074 false,

1075 0,

1076 0);

1077 }

1078

1079 unsigned Offset =

1081 unsigned WhitespaceLength =

1082 Content[LineIndex].data() - Lines[LineIndex].data();

1084 WhitespaceLength,

1085 "",

1087 false,

1088 0,

1089 0);

1090}

1091

1094

1095

1096

1097

1098

1099

1100 if (LineIndex > 0 && Tokens[LineIndex] != Tokens[LineIndex - 1]) {

1101

1102

1103

1104

1105

1106 unsigned LineColumn =

1108 (Content[LineIndex].data() - Lines[LineIndex].data()) +

1109 (OriginalPrefix[LineIndex].size() - Prefix[LineIndex].size());

1110

1111

1112

1113

1114

1116 1,

1117 LineColumn,

1118 LineColumn,

1119 true,

1120 false);

1121 }

1122 if (OriginalPrefix[LineIndex] != Prefix[LineIndex]) {

1123

1124 const auto SpacesToRemove = -std::min(PrefixSpaceChange[LineIndex], 0);

1125 const auto SpacesToAdd = std::max(PrefixSpaceChange[LineIndex], 0);

1127 tokenAt(LineIndex), OriginalPrefix[LineIndex].size() - SpacesToRemove,

1128 SpacesToRemove, "", "", false,

1129 0, SpacesToAdd);

1130 }

1131}

1132

1134 if (LastLineTok)

1135 State.NextToken = LastLineTok->Next;

1136}

1137

1139 unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {

1140

1141

1142 StringRef IndentContent = Content[LineIndex];

1143 if (Lines[LineIndex].starts_with("//"))

1144 IndentContent = Lines[LineIndex].substr(2);

1145

1146

1147

1148

1149

1150

1152 !CommentPragmasRegex.match(IndentContent) &&

1155 OriginalPrefix[LineIndex] == OriginalPrefix[LineIndex - 1];

1156}

1157

1158}

1159}

Declares BreakableToken, BreakableStringLiteral, BreakableComment, BreakableBlockComment and Breakabl...

This file implements an indenter that manages the indentation of continuations.

StringRef TokenText

The raw text of the token.

Various functions to configurably format source code.

Token - This structure provides full information about a lexed token.

bool is(tok::TokenKind K) const

is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....

BreakableStringLiteralUsingOperators(const FormatToken &Tok, QuoteStyleType QuoteStyle, bool UnindentPlus, unsigned StartColumn, unsigned UnbreakableTailLength, bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)

Creates a breakable token for a single line string literal for C#, Java, JavaScript,...

Definition BreakableToken.cpp:282

QuoteStyleType QuoteStyle

void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, unsigned ContentIndent, WhitespaceManager &Whitespaces) const override

Emits the previously retrieved Split via Whitespaces.

Definition BreakableToken.cpp:365

StringRef RightBraceQuote

unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override

Returns the column at which content in line LineIndex starts, assuming no reflow.

Definition BreakableToken.cpp:354

void updateAfterBroken(WhitespaceManager &Whitespaces) const override

Adds replacements that are needed when the token is broken.

Definition BreakableToken.cpp:377

unsigned getRemainingLength(unsigned LineIndex, unsigned Offset, unsigned StartColumn) const override

Returns the number of columns required to format the text following the byte Offset in the line LineI...

Definition BreakableToken.cpp:346

Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit, unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const override

Returns a range (offset, length) at which to break the line at LineIndex, if previously broken at Tai...

Definition BreakableToken.cpp:266

unsigned UnbreakableTailLength

unsigned getRangeLength(unsigned LineIndex, unsigned Offset, StringRef::size_type Length, unsigned StartColumn) const override

Returns the number of columns required to format the text in the byte range [Offset,...

Definition BreakableToken.cpp:233

unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override

Returns the column at which content in line LineIndex starts, assuming no reflow.

Definition BreakableToken.cpp:249

unsigned getLineCount() const override

Returns the number of lines in this token in the original code.

Definition BreakableToken.cpp:231

unsigned getRemainingLength(unsigned LineIndex, unsigned Offset, unsigned StartColumn) const override

Returns the number of columns required to format the text following the byte Offset in the line LineI...

Definition BreakableToken.cpp:242

BreakableStringLiteral(const FormatToken &Tok, unsigned StartColumn, StringRef Prefix, StringRef Postfix, unsigned UnbreakableTailLength, bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)

Creates a breakable token for a single line string literal.

Definition BreakableToken.cpp:254

void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, unsigned ContentIndent, WhitespaceManager &Whitespaces) const override

Emits the previously retrieved Split via Whitespaces.

Definition BreakableToken.cpp:273

std::pair< StringRef::size_type, unsigned > Split

Contains starting character index and length of split.

const FormatStyle & Style

unsigned getLengthAfterCompression(unsigned RemainingTokenColumns, Split Split) const

Returns the number of columns needed to format RemainingTokenColumns, assuming that Split is within t...

Definition BreakableToken.cpp:215

BreakableToken(const FormatToken &Tok, bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)

const encoding::Encoding Encoding

Manages the whitespaces around tokens and their replacements.

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.

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.

unsigned columnWidthWithTabs(StringRef Text, unsigned StartColumn, unsigned TabWidth, Encoding Encoding)

Returns the number of columns required to display the Text, starting from the StartColumn on a termin...

unsigned getEscapeSequenceLength(StringRef Text)

Gets the length of an escape sequence inside a C++ string literal.

unsigned getCodePointNumBytes(char FirstChar, Encoding Encoding)

Gets the number of bytes in a sequence representing a single codepoint and starting with FirstChar in...

unsigned columnWidth(StringRef Text, Encoding Encoding)

Returns the number of columns required to display the Text on a generic Unicode-capable terminal.

bool switchesFormatting(const FormatToken &Token)

Checks if Token switches formatting, like /* clang-format off *‍/.

Definition BreakableToken.cpp:206

static BreakableToken::Split getStringSplit(StringRef Text, unsigned UsedColumns, unsigned ColumnLimit, unsigned TabWidth, encoding::Encoding Encoding)

Definition BreakableToken.cpp:158

static StringRef getLineCommentIndentPrefix(StringRef Comment, const FormatStyle &Style)

Definition BreakableToken.cpp:30

static bool mayReflowContent(StringRef Content)

Definition BreakableToken.cpp:439

static constexpr StringRef Blanks(" \t\v\f\r")

static BreakableToken::Split getCommentSplit(StringRef Text, unsigned ContentStartColumn, unsigned ColumnLimit, unsigned TabWidth, encoding::Encoding Encoding, const FormatStyle &Style, bool DecorationEndsWithStar=false)

Definition BreakableToken.cpp:56

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

unsigned TabWidth

The number of columns used for tab stops.

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

LLVM_READONLY bool isAlphanumeric(unsigned char c)

Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].

LLVM_READONLY bool isHorizontalWhitespace(unsigned char c)

Returns true if this character is horizontal ASCII whitespace: ' ', '\t', '\f', '\v'.

LLVM_READONLY bool isPunctuation(unsigned char c)

Return true if this character is an ASCII punctuation character.

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

StringRef TokenText

The raw text of the token.

FormatToken * Next

The next token in the unwrapped line.

The current state when indenting a unwrapped line.