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#include

21#include

22

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

24

26namespace format {

27

30 std::vectorstd::string LeftOrder;

31 std::vectorstd::string RightOrder;

32 std::vectortok::TokenKind ConfiguredQualifierTokens;

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

35

36

37 for (const auto &Qualifier : LeftOrder) {

38 Passes.emplace_back(

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

41 ConfiguredQualifierTokens,

42 false)

44 });

45 }

46 for (const auto &Qualifier : RightOrder) {

47 Passes.emplace_back(

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

50 ConfiguredQualifierTokens,

51 true)

53 });

54 }

55}

56

61 auto Err = Fixes.add(Replacement);

62

63 if (Err) {

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

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

66 }

67}

68

73 First->Tok.getEndLoc());

75}

76

80 const std::string &Qualifier) {

82 First->Tok.getEndLoc());

83

84 std::string NewText{};

85 NewText += First->TokenText;

86 NewText += " " + Qualifier;

88}

89

93 const std::string &Qualifier) {

95 First->Tok.getEndLoc());

96

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

98 NewText += First->TokenText;

99

101}

102

104 if (s.empty())

105 return false;

106 return isspace(s.back());

107}

108

110 if (s.empty())

111 return false;

112 return isspace(s.front());

113}

114

118 auto *End = Last;

120 if (!Left) {

121 End = Last->Next;

123 }

124

125 std::string NewText;

126

127 if (Left) {

128 NewText += Last->TokenText;

129 NewText += " ";

130 }

131

132

133 auto *Tok = Begin;

134 while (Tok != End) {

136 NewText += " ";

137

138 NewText += Tok->TokenText;

139 Tok = Tok->Next;

140 }

141

142

143 if (!Left) {

145 NewText += " ";

146 NewText += First->TokenText;

147 }

148

150 Last->Tok.getEndLoc());

151

153}

154

155static bool

157 const std::vectortok::TokenKind &Qualifiers) {

159}

160

162 if (!Tok)

163 return false;

164

166 case tok::kw_const:

167 case tok::kw_volatile:

168 case tok::kw_static:

169 case tok::kw_inline:

170 case tok::kw_constexpr:

171 case tok::kw_restrict:

172 case tok::kw_friend:

173 return true;

174 default:

175 return false;

176 }

177}

178

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

183

184 if (Tok->isNot(QualifierType))

185 return Tok;

186

187 if (!Tok->Next)

188 return Tok;

189

190

191

195

196

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

198

199

200

201

202

203

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

205 return true;

206

207

208

209

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

211 return true;

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

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

232

233

236 }

237

238

239

240

241

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

243 tok::kw_auto)) {

244 return true;

245 }

246

247 return false;

248 }();

249

250

254

255

256

257 if (IsRightQualifier) {

258 if (LastQual != Tok)

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

260 return Tok;

261 }

262

264 if (!TypeToken)

265 return Tok;

266

267

269 return Tok;

270

271

272

273

274

276

277

278

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

280 return Tok;

281

282 const FormatToken *LastSimpleTypeSpecifier = TypeToken;

285 LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();

286 }

287

288 rotateTokens(SourceMgr, Fixes, Tok, LastSimpleTypeSpecifier,

289 false);

290 return LastSimpleTypeSpecifier;

291 }

292

293

294

295

297 if (LastQual != Tok)

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

299 return Tok;

300 }

301

302

303

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

306

307

308

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

310

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

314 }

315

316

317

318

319

320

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

322 return Tok;

323

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

325

326

327

328

329

330

331

332

333

334

337 (Next->is(TT_TemplateOpener) ||

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

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

340 tok::identifier))) {

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

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

343 TypeToken = Next->MatchingParen;

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

345 TypeToken = Next->getNextNonComment();

346 } else {

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

348 }

349 }

350

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

352 TypeToken = Next;

353

354

356

358 }

359

361

365 }

366

367 return Tok;

368}

369

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

374

375 if (Tok->isNot(QualifierType))

376 return Tok;

377

379 return Tok;

380

381

385

386

387

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

391

392

395 ConfiguredQualifierTokens)) {

397 }

398

399 if (FirstQual != Tok)

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

401 return Tok;

402 }

403

404

406 return Tok;

407

408

409

410

411

412

413

415 const FormatToken *LastSimpleTypeSpecifier = TypeToken;

418 ConfiguredQualifierTokens, LangOpts)) {

419 LastSimpleTypeSpecifier =

421 }

422

423 rotateTokens(SourceMgr, Fixes, LastSimpleTypeSpecifier, Tok,

424 true);

425 return Tok;

426 }

427

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

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

430 if (!Tok)

431 return true;

432

433

434

435 if (Tok->is(TT_TemplateCloser))

436 return false;

437

440 return true;

441

442

443

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

445 return false;

446

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

448

449

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

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

452 return false;

453 }

454

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

456 return false;

457

458 return true;

459 };

460

461 while (!IsStartOfType(TypeToken)) {

462

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

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

466 } else {

467

468

469

470

471

472

473

476

481 if (PreColonColon &&

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

483 TypeToken = PreColonColon;

484 } else {

485 TypeToken = ColonColon;

486 }

487 }

488 }

489

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

491

492

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

497

498

500 }

501

502

503

504 if (Previous || Previous->isOneOf(tok::kw_struct, tok::kw_class)) {

507 }

508 }

509

510 return Tok;

511}

512

514 const std::string &Qualifier) {

515

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

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

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

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

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

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

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

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

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

525 .Default(tok::identifier);

526}

527

530 const std::string &Qualifier,

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

532 : TokenAnalyzer(Env, Style), Qualifier(Qualifier), RightAlign(RightAlign),

533 ConfiguredQualifierTokens(QualifierTokens) {}

534

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

543 return {Fixes, 0};

544}

545

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

553

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

557 continue;

560 if (First->Finalized)

561 continue;

562

563 const auto *Last = Line->Last;

564

565 for (const auto *Tok = First; Tok && Tok != Last && Tok->Next;

566 Tok = Tok->Next) {

567 if (Tok->MustBreakBefore)

568 break;

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

570 continue;

571 if (RightAlign) {

572 Tok = analyzeRight(SourceMgr, Keywords, Fixes, Tok, Qualifier,

573 QualifierToken);

574 } else {

575 Tok = analyzeLeft(SourceMgr, Keywords, Fixes, Tok, Qualifier,

576 QualifierToken);

577 }

578 }

579 }

580}

581

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

584 std::vectorstd::string &RightOrder,

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

586

587

588

589

590

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

592 "QualifierOrder must contain type");

593

594

595 bool left = true;

596 for (const auto &s : Order) {

597 if (s == "type") {

598 left = false;

599 continue;

600 }

601

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

605 Qualifiers.push_back(QualifierToken);

606

607 if (left) {

608

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

610 } else {

611 RightOrder.push_back(s);

612 }

613 }

614}

615

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

619}

620

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

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

626}

627

628

629

631 if (!Tok)

632 return false;

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

634 return false;

636

637 return Tok->TokenText.size() != 1;

638 }

639 return false;

640}

641

642}

643}

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

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.

tok::TokenKind getKind() const

bool computeAffectedLines(SmallVectorImpl< AnnotatedLine * > &Lines)

SourceManager & getSourceManager() const

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

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

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

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

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

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

AffectedRangeManager AffectedRangeMgr

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)

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

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

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

bool isPossibleMacro(const FormatToken *Tok)

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

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

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

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

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

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

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

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

static bool isQualifier(const FormatToken *const Tok)

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...

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

std::vector< std::string > QualifierOrder

The order in which the qualifiers appear.

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

bool isTypeName(const LangOptions &LangOpts) const

unsigned ClosesTemplateDeclaration

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

StringRef TokenText

The raw text of the token.

SourceLocation getStartOfNonWhitespace() const

Returns actual token start location without leading escaped newlines and whitespace.

bool isPointerOrReference() const

FormatToken * getNextNonComment() const

Returns the next token ignoring comments.

FormatToken * getPreviousNonComment() const

Returns the previous token ignoring comments.

FormatToken * Next

The next token in the unwrapped line.

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.

bool endsSequence(A K1, Ts... Tokens) const

true if this token ends a sequence with the given tokens in order, following the Previous pointers,...