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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

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

18#include "llvm/Support/Regex.h"

19

20#define DEBUG_TYPE "format-qualifier-alignment-fixer"

21

23namespace format {

24

27 std::vectorstd::string LeftOrder;

28 std::vectorstd::string RightOrder;

29 std::vectortok::TokenKind ConfiguredQualifierTokens;

31 Style.QualifierOrder, LeftOrder, RightOrder, ConfiguredQualifierTokens);

32

33

34 for (const auto &Qualifier : LeftOrder) {

35 Passes.emplace_back(

36 [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {

38 ConfiguredQualifierTokens,

39 false)

41 });

42 }

43 for (const auto &Qualifier : RightOrder) {

44 Passes.emplace_back(

45 [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {

47 ConfiguredQualifierTokens,

48 true)

50 });

51 }

52}

53

58 auto Err = Fixes.add(Replacement);

59

60 if (Err) {

61 llvm::errs() << "Error while rearranging Qualifier : "

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

63 }

64}

65

70 First->Tok.getEndLoc());

72}

73

77 const std::string &Qualifier) {

79 First->Tok.getEndLoc());

80

81 std::string NewText{};

82 NewText += First->TokenText;

83 NewText += " " + Qualifier;

84 replaceToken(SourceMgr, Fixes, Range, NewText);

85}

86

90 const std::string &Qualifier) {

92 First->Tok.getEndLoc());

93

94 std::string NewText = " " + Qualifier + " ";

95 NewText += First->TokenText;

96

97 replaceToken(SourceMgr, Fixes, Range, NewText);

98}

99

101 if (s.empty())

102 return false;

103 return isspace(s.back());

104}

105

107 if (s.empty())

108 return false;

109 return isspace(s.front());

110}

111

115 auto *End = Last;

116 auto *Begin = First;

117 if (!Left) {

118 End = Last->Next;

119 Begin = First->Next;

120 }

121

122 std::string NewText;

123

124 if (Left) {

125 NewText += Last->TokenText;

126 NewText += " ";

127 }

128

129

130 auto *Tok = Begin;

131 while (Tok != End) {

132 if (!NewText.empty() && endsWithSpace(NewText) &&

133 Tok->isNot(tok::coloncolon)) {

134 NewText += " ";

135 }

136

137 NewText += Tok->TokenText;

139 }

140

141

142 if (!Left) {

144 NewText += " ";

145 NewText += First->TokenText;

146 }

147

149 Last->Tok.getEndLoc());

150

151 replaceToken(SourceMgr, Fixes, Range, NewText);

152}

153

154static bool

159

161 if (Tok)

162 return false;

163

164 switch (Tok->Tok.getKind()) {

165 case tok::kw_const:

166 case tok::kw_volatile:

167 case tok::kw_static:

168 case tok::kw_inline:

169 case tok::kw_constexpr:

170 case tok::kw_restrict:

171 case tok::kw_friend:

172 return true;

173 default:

174 return false;

175 }

176}

177

181 const std::string &Qualifier, tok::TokenKind QualifierType) {

182

183 if (Tok->isNot(QualifierType))

184 return Tok;

185

186 const auto *Next = Tok->getNextNonComment();

187

188

190 return Tok;

191

192

193

194 const FormatToken *PreviousCheck = Tok->getPreviousNonComment();

196 PreviousCheck = PreviousCheck->getPreviousNonComment();

197

198

199 const bool IsRightQualifier = PreviousCheck && [PreviousCheck]() {

200

201

202

203

204

205

206 if (PreviousCheck->is(tok::r_paren))

207 return true;

208

209

210

211

212 if (PreviousCheck->is(tok::r_brace))

213 return true;

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233 if (PreviousCheck->is(TT_TemplateCloser)) {

234

235

238 }

239

240

241

242

243

244 if (PreviousCheck->isOneOf(TT_PointerOrReference, tok::identifier,

245 tok::kw_auto)) {

246 return true;

247 }

248

249 return false;

250 }();

251

252

253 const auto *LastQual = Tok;

255 LastQual = Next;

256

257 if (!LastQual || Next ||

258 (LastQual->isOneOf(tok::kw_const, tok::kw_volatile) &&

260 return Tok;

261 }

262

263

264

265 if (IsRightQualifier) {

266 if (LastQual != Tok)

267 rotateTokens(SourceMgr, Fixes, Tok, LastQual, false);

268 return Tok;

269 }

270

271 const FormatToken *TypeToken = LastQual->getNextNonComment();

272 if (!TypeToken)

273 return Tok;

274

275

277 return Tok;

278

279

280

281

282

283 if (TypeToken->isTypeName(LangOpts)) {

284

285

286

287 if (TypeToken->isOneOf(tok::kw_decltype, tok::kw_typeof, tok::kw__Atomic))

288 return Tok;

289

290 const FormatToken *LastSimpleTypeSpecifier = TypeToken;

291 while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment(),

293 LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();

294 }

295

296 rotateTokens(SourceMgr, Fixes, Tok, LastSimpleTypeSpecifier,

297 false);

298 return LastSimpleTypeSpecifier;

299 }

300

301

302

303

304 if (PreviousCheck && PreviousCheck->isTypeName(LangOpts)) {

305 if (LastQual != Tok)

306 rotateTokens(SourceMgr, Fixes, Tok, LastQual, false);

307 return Tok;

308 }

309

310

311

312 if (TypeToken->is(tok::kw_typename))

313 TypeToken = TypeToken->getNextNonComment();

314

315

316

317 if (TypeToken->is(tok::coloncolon)) {

318

319 TypeToken = TypeToken->getNextNonComment();

320 if (TypeToken && TypeToken->is(tok::kw_template))

321 TypeToken = TypeToken->getNextNonComment();

322 }

323

324

325

326

327

328

329 if (TypeToken->isOneOf(tok::kw_struct, tok::kw_class))

330 return Tok;

331

332 if (TypeToken->isOneOf(tok::kw_auto, tok::identifier)) {

333

334

335

336

337

338

339

340

341

342

344 while ((Next = TypeToken->getNextNonComment()) &&

345 (Next->is(TT_TemplateOpener) ||

346 Next->startsSequence(tok::coloncolon, tok::identifier) ||

347 Next->startsSequence(tok::coloncolon, tok::kw_template,

348 tok::identifier))) {

349 if (Next->is(TT_TemplateOpener)) {

350 assert(Next->MatchingParen && "Missing template closer");

351 TypeToken = Next->MatchingParen;

352 } else if (Next->startsSequence(tok::coloncolon, tok::identifier)) {

353 TypeToken = Next->getNextNonComment();

354 } else {

355 TypeToken = Next->getNextNonComment()->getNextNonComment();

356 }

357 }

358

359 if (Next && Next->is(tok::kw_auto))

360 TypeToken = Next;

361

362

363 while (isQualifier(TypeToken->getNextNonComment())) {

364

365 TypeToken = TypeToken->getNextNonComment();

366 }

367

369

371 Tok->getStartOfNonWhitespace(), Tok->Next->getStartOfNonWhitespace());

373 }

374

375 return Tok;

376}

377

381 const std::string &Qualifier, tok::TokenKind QualifierType) {

382

383 if (Tok->isNot(QualifierType))

384 return Tok;

385

386 if (Tok->getPreviousNonComment())

387 return Tok;

388

389

390 const FormatToken *TypeToken = Tok->getPreviousNonComment();

392 TypeToken = TypeToken->getPreviousNonComment();

393

394

395

396 if (!TypeToken || TypeToken->isPointerOrReference() ||

398 TypeToken->is(tok::r_square)) {

399

400

403 ConfiguredQualifierTokens)) {

404 FirstQual = FirstQual->getPreviousNonComment();

405 }

406

407 if (FirstQual != Tok)

408 rotateTokens(SourceMgr, Fixes, FirstQual, Tok, true);

409 return Tok;

410 }

411

412

414 return Tok;

415

416

417

418

419

420

421

422 if (TypeToken->isTypeName(LangOpts)) {

423 for (const auto *Prev = TypeToken->Previous;

424 Prev && Prev->is(tok::coloncolon); Prev = Prev->Previous) {

425 TypeToken = Prev;

427 if (!(Prev && Prev->is(tok::identifier)))

428 break;

429 TypeToken = Prev;

430 }

431 const FormatToken *LastSimpleTypeSpecifier = TypeToken;

433 LastSimpleTypeSpecifier->getPreviousNonComment(),

434 ConfiguredQualifierTokens, LangOpts)) {

435 LastSimpleTypeSpecifier =

436 LastSimpleTypeSpecifier->getPreviousNonComment();

437 }

438

439 rotateTokens(SourceMgr, Fixes, LastSimpleTypeSpecifier, Tok,

440 true);

441 return Tok;

442 }

443

444 if (TypeToken->isOneOf(tok::kw_auto, tok::identifier, TT_TemplateCloser)) {

445 const auto IsStartOfType = [](const FormatToken *const Tok) -> bool {

446 if (Tok)

447 return true;

448

449

450

451 if (Tok->is(TT_TemplateCloser))

452 return false;

453

456 return true;

457

458

459

460 if (Tok->is(tok::identifier) && Previous->is(tok::coloncolon))

461 return false;

462

463 const FormatToken *const PrePrevious = Previous->getPreviousNonComment();

464

465

466 if (Tok->is(tok::identifier) && Previous->is(tok::kw_template) &&

467 PrePrevious && PrePrevious->is(tok::coloncolon)) {

468 return false;

469 }

470

471 if (Tok->endsSequence(tok::kw_auto, tok::identifier))

472 return false;

473

474 return true;

475 };

476

477 while (!IsStartOfType(TypeToken)) {

478

479 if (TypeToken->is(TT_TemplateCloser)) {

480 assert(TypeToken->MatchingParen && "Missing template opener");

481 TypeToken = TypeToken->MatchingParen->getPreviousNonComment();

482 } else {

483

484

485

486

487

488

489

490 if (TypeToken->getPreviousNonComment()->is(tok::kw_template))

491 TypeToken = TypeToken->getPreviousNonComment();

492

494 TypeToken->getPreviousNonComment();

496 ColonColon->getPreviousNonComment();

497 if (PreColonColon &&

498 PreColonColon->isOneOf(TT_TemplateCloser, tok::identifier)) {

499 TypeToken = PreColonColon;

500 } else {

501 TypeToken = ColonColon;

502 }

503 }

504 }

505

506 assert(TypeToken && "Should be auto or identifier");

507

508

510 while ((Previous = TypeToken->getPreviousNonComment()) &&

512 Previous->is(tok::kw_typename))) {

513

514

516 }

517

518

519

520 if (Previous || Previous->isNoneOf(tok::kw_struct, tok::kw_class)) {

523 }

524 }

525

526 return Tok;

527}

528

530 const std::string &Qualifier) {

531

532 return llvm::StringSwitchtok::TokenKind(Qualifier)

533 .Case("type", tok::kw_typeof)

534 .Case("const", tok::kw_const)

535 .Case("volatile", tok::kw_volatile)

536 .Case("static", tok::kw_static)

537 .Case("inline", tok::kw_inline)

538 .Case("constexpr", tok::kw_constexpr)

539 .Case("restrict", tok::kw_restrict)

540 .Case("friend", tok::kw_friend)

541 .Default(tok::identifier);

542}

543

546 const std::string &Qualifier,

547 const std::vectortok::TokenKind &QualifierTokens, bool RightAlign)

549 ConfiguredQualifierTokens(QualifierTokens) {}

550

551std::pair<tooling::Replacements, unsigned>

559 return {Fixes, 0};

560}

561

568 assert(QualifierToken != tok::identifier && "Unrecognised Qualifier");

569

572 if (Line->Affected || Line->InPPDirective)

573 continue;

576 if (First->Finalized)

577 continue;

578

579 const auto *Last = Line->Last;

580

583 if (Tok->MustBreakBefore && Tok != First)

584 break;

585 if (Tok->is(tok::comment))

586 continue;

587 if (RightAlign) {

589 QualifierToken);

590 } else {

592 QualifierToken);

593 }

594 }

595 }

596}

597

599 const std::vectorstd::string &Order, std::vectorstd::string &LeftOrder,

600 std::vectorstd::string &RightOrder,

601 std::vectortok::TokenKind &Qualifiers) {

602

603

604

605

606

607 assert(llvm::is_contained(Order, "type") &&

608 "QualifierOrder must contain type");

609

610

611 bool left = true;

612 for (const auto &s : Order) {

613 if (s == "type") {

614 left = false;

615 continue;

616 }

617

620 if (QualifierToken != tok::kw_typeof && QualifierToken != tok::identifier)

621 Qualifiers.push_back(QualifierToken);

622

623 if (left) {

624

625 LeftOrder.insert(LeftOrder.begin(), s);

626 } else {

627 RightOrder.push_back(s);

628 }

629 }

630}

631

633 return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||

635}

636

638 const std::vectortok::TokenKind &Qualifiers,

640 return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||

642}

643

644

645

647 assert(Tok);

648 if (Tok->isNot(tok::identifier))

649 return false;

650

651 const auto Text = Tok->TokenText;

652 assert(Text.empty());

653

654

655 if (Text.size() == 1)

656 return false;

657

658

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

660 if (Prev && Prev->is(tok::coloncolon))

661 return false;

662 const auto *Next = Tok->getNextNonComment();

663 if (Next && Next->is(tok::coloncolon))

664 return false;

665

667}

668

669}

670}

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

FormatToken * Previous

The previous token in the unwrapped line.

FormatToken * Next

The next token in the unwrapped line.

This file declares QualifierAlignmentFixer, a TokenAnalyzer that enforces either east or west const d...

__device__ __2f16 float __ockl_bool s

Represents a character-granular source range.

static CharSourceRange getCharRange(SourceRange R)

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

The collection of all-type qualifiers we support.

This class handles loading and caching of source files into memory.

const AdditionalKeywords & getKeywords()

LeftRightQualifierAlignmentFixer(const Environment &Env, const FormatStyle &Style, const std::string &Qualifier, const std::vector< tok::TokenKind > &ConfiguredQualifierTokens, bool RightAlign)

Definition QualifierAlignmentFixer.cpp:544

const FormatToken * analyzeLeft(const SourceManager &SourceMgr, const AdditionalKeywords &Keywords, tooling::Replacements &Fixes, const FormatToken *Tok, const std::string &Qualifier, tok::TokenKind QualifierType)

Definition QualifierAlignmentFixer.cpp:378

const FormatToken * analyzeRight(const SourceManager &SourceMgr, const AdditionalKeywords &Keywords, tooling::Replacements &Fixes, const FormatToken *Tok, const std::string &Qualifier, tok::TokenKind QualifierType)

Definition QualifierAlignmentFixer.cpp:178

std::pair< tooling::Replacements, unsigned > analyze(TokenAnnotator &Annotator, SmallVectorImpl< AnnotatedLine * > &AnnotatedLines, FormatTokenLexer &Tokens) override

Definition QualifierAlignmentFixer.cpp:552

void fixQualifierAlignment(SmallVectorImpl< AnnotatedLine * > &AnnotatedLines, FormatTokenLexer &Tokens, tooling::Replacements &Fixes)

Definition QualifierAlignmentFixer.cpp:562

static tok::TokenKind getTokenFromQualifier(const std::string &Qualifier)

Definition QualifierAlignmentFixer.cpp:529

AffectedRangeManager AffectedRangeMgr

TokenAnalyzer(const Environment &Env, const FormatStyle &Style)

std::pair< tooling::Replacements, unsigned > process(bool SkipAnnotation=false)

Determines extra information about the tokens comprising an UnwrappedLine.

void addQualifierAlignmentFixerPasses(const FormatStyle &Style, SmallVectorImpl< AnalyzerPass > &Passes)

Definition QualifierAlignmentFixer.cpp:25

bool isConfiguredQualifierOrType(const FormatToken *Tok, const std::vector< tok::TokenKind > &Qualifiers, const LangOptions &LangOpts)

Definition QualifierAlignmentFixer.cpp:637

static void replaceToken(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const CharSourceRange &Range, std::string NewText)

Definition QualifierAlignmentFixer.cpp:54

static bool endsWithSpace(const std::string &s)

Definition QualifierAlignmentFixer.cpp:100

bool isPossibleMacro(const FormatToken *Tok)

Definition QualifierAlignmentFixer.cpp:646

bool isQualifierOrType(const FormatToken *Tok, const LangOptions &LangOpts)

Definition QualifierAlignmentFixer.cpp:632

static void insertQualifierAfter(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const FormatToken *First, const std::string &Qualifier)

Definition QualifierAlignmentFixer.cpp:74

static void insertQualifierBefore(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const FormatToken *First, const std::string &Qualifier)

Definition QualifierAlignmentFixer.cpp:87

static void rotateTokens(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const FormatToken *First, const FormatToken *Last, bool Left)

Definition QualifierAlignmentFixer.cpp:112

static void removeToken(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const FormatToken *First)

Definition QualifierAlignmentFixer.cpp:66

static bool isConfiguredQualifier(const FormatToken *const Tok, const std::vector< tok::TokenKind > &Qualifiers)

Definition QualifierAlignmentFixer.cpp:155

void prepareLeftRightOrderingForQualifierAlignmentFixer(const std::vector< std::string > &Order, std::vector< std::string > &LeftOrder, std::vector< std::string > &RightOrder, std::vector< tok::TokenKind > &Qualifiers)

Definition QualifierAlignmentFixer.cpp:598

static bool startsWithSpace(const std::string &s)

Definition QualifierAlignmentFixer.cpp:106

static bool isQualifier(const FormatToken *const Tok)

Definition QualifierAlignmentFixer.cpp:160

TokenKind

Provides a simple uniform namespace for tokens from all C languages.

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

Encapsulates keywords that are context sensitive or for languages not properly supported by Clang's l...

IdentifierInfo * kw_override

IdentifierInfo * kw_final

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

unsigned ClosesTemplateDeclaration

true if this is the ">" of "template<..>".

bool is(tok::TokenKind Kind) const

bool isOneOf(A K1, B K2) const

unsigned ClosesRequiresClause

true if this is the last token within requires clause.

FormatToken * MatchingParen

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

FormatToken * Previous

The previous token in the unwrapped line.