17#include "llvm/Support/Debug.h"
18#include "llvm/Support/Regex.h"
23#define DEBUG_TYPE "format-qualifier-alignment-fixer"
31 unsigned NextStartColumn,
unsigned LastStartColumn, StringRef FileName)
33 FirstStartColumn(FirstStartColumn), NextStartColumn(NextStartColumn),
34 LastStartColumn(LastStartColumn), FileName(FileName) {
35 std::vector<std::string> LeftOrder;
36 std::vector<std::string> RightOrder;
37 std::vector<tok::TokenKind> ConfiguredQualifierTokens;
39 ConfiguredQualifierTokens);
42 for (
const auto &Qualifier : LeftOrder) {
44 [&, Qualifier, ConfiguredQualifierTokens](
const Environment &
Env) {
46 ConfiguredQualifierTokens,
51 for (
const auto &Qualifier : RightOrder) {
53 [&, Qualifier, ConfiguredQualifierTokens](
const Environment &
Env) {
55 ConfiguredQualifierTokens,
67 NextStartColumn, LastStartColumn);
70 std::optional<std::string> CurrentCode;
72 for (
size_t I = 0, E = Passes.size(); I < E; ++I) {
73 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
74 auto NewCode = applyAllReplacements(
75 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
77 Fixes = Fixes.
merge(PassFixes.first);
79 CurrentCode = std::move(*NewCode);
81 *CurrentCode, FileName,
83 FirstStartColumn, NextStartColumn, LastStartColumn);
94 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
96 if (!OriginalCode.equals(Fix.getReplacementText())) {
97 auto Err = NonNoOpFixes.
add(Fix);
99 llvm::errs() <<
"Error adding replacements : "
100 << llvm::toString(std::move(Err)) <<
"\n";
104 return {NonNoOpFixes, 0};
111 auto Err = Fixes.
add(Replacement);
114 llvm::errs() <<
"Error while rearranging Qualifier : "
115 << llvm::toString(std::move(Err)) <<
"\n";
123 First->Tok.getEndLoc());
130 const std::string &Qualifier) {
132 First->Tok.getEndLoc());
134 std::string NewText{};
135 NewText +=
First->TokenText;
136 NewText +=
" " + Qualifier;
143 const std::string &Qualifier) {
145 First->Tok.getEndLoc());
147 std::string NewText =
" " + Qualifier +
" ";
148 NewText +=
First->TokenText;
156 return isspace(
s.back());
162 return isspace(
s.front());
178 NewText +=
Last->TokenText;
188 NewText += Tok->TokenText;
196 NewText +=
First->TokenText;
200 Last->Tok.getEndLoc());
207 const std::vector<tok::TokenKind> &
Qualifiers) {
217 case tok::kw_volatile:
220 case tok::kw_constexpr:
221 case tok::kw_restrict:
234 if (!Tok->
is(QualifierType))
247 const bool IsRightQualifier = PreviousCheck && [PreviousCheck]() {
254 if (PreviousCheck->
is(tok::r_paren))
260 if (PreviousCheck->
is(tok::r_brace))
281 if (PreviousCheck->
is(TT_TemplateCloser)) {
292 if (PreviousCheck->
isOneOf(TT_PointerOrReference, tok::identifier,
307 if (IsRightQualifier) {
329 if (TypeToken->
isOneOf(tok::kw_decltype, tok::kw_typeof, tok::kw__Atomic))
332 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
336 rotateTokens(SourceMgr, Fixes, Tok, LastSimpleTypeSpecifier,
338 return LastSimpleTypeSpecifier;
352 if (TypeToken->
is(tok::kw_typename))
357 if (TypeToken->
is(tok::coloncolon)) {
360 if (TypeToken && TypeToken->
is(tok::kw_template))
369 if (TypeToken->
isOneOf(tok::kw_struct, tok::kw_class))
372 if (TypeToken->
isOneOf(tok::kw_auto, tok::identifier)) {
385 (Next->is(TT_TemplateOpener) ||
386 Next->startsSequence(tok::coloncolon, tok::identifier) ||
387 Next->startsSequence(tok::coloncolon, tok::kw_template,
389 if (Next->is(TT_TemplateOpener)) {
390 assert(Next->MatchingParen &&
"Missing template closer");
391 TypeToken = Next->MatchingParen;
392 }
else if (Next->startsSequence(tok::coloncolon, tok::identifier)) {
393 TypeToken = Next->getNextNonComment();
395 TypeToken = Next->getNextNonComment()->getNextNonComment();
420 if (!Tok->
is(QualifierType))
433 if (!TypeToken || TypeToken->
isOneOf(tok::star, tok::amp, tok::ampamp) ||
439 ConfiguredQualifierTokens)) {
443 if (FirstQual != Tok)
459 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
462 ConfiguredQualifierTokens)) {
463 LastSimpleTypeSpecifier =
467 rotateTokens(SourceMgr, Fixes, LastSimpleTypeSpecifier, Tok,
472 if (TypeToken->
isOneOf(tok::kw_auto, tok::identifier, TT_TemplateCloser)) {
473 const auto IsStartOfType = [](
const FormatToken *
const Tok) ->
bool {
479 if (Tok->
is(TT_TemplateCloser))
488 if (Tok->
is(tok::identifier) &&
Previous->is(tok::coloncolon))
494 if (Tok->
is(tok::identifier) &&
Previous->is(tok::kw_template) &&
495 PrePrevious && PrePrevious->
is(tok::coloncolon)) {
502 while (!IsStartOfType(TypeToken)) {
504 if (TypeToken->
is(TT_TemplateCloser)) {
505 assert(TypeToken->
MatchingParen &&
"Missing template opener");
523 PreColonColon->
isOneOf(TT_TemplateCloser, tok::identifier)) {
524 TypeToken = PreColonColon;
526 TypeToken = ColonColon;
531 assert(TypeToken &&
"Should be auto or identifier");
555 const std::string &Qualifier) {
557 return llvm::StringSwitch<tok::TokenKind>(Qualifier)
558 .Case(
"type", tok::kw_typeof)
559 .Case(
"const", tok::kw_const)
560 .Case(
"volatile", tok::kw_volatile)
561 .Case(
"static", tok::kw_static)
562 .Case(
"inline", tok::kw_inline)
563 .Case(
"constexpr", tok::kw_constexpr)
564 .Case(
"restrict", tok::kw_restrict)
565 .Case(
"friend", tok::kw_friend)
566 .Default(tok::identifier);
571 const std::string &Qualifier,
572 const std::vector<tok::TokenKind> &QualifierTokens,
bool RightAlign)
573 :
TokenAnalyzer(Env, Style), Qualifier(Qualifier), RightAlign(RightAlign),
574 ConfiguredQualifierTokens(QualifierTokens) {}
576std::pair<tooling::Replacements, unsigned>
587 assert(QualifierToken != tok::identifier &&
"Unrecognised Qualifier");
590 if (Line->InPPDirective)
594 if (
First->Finalized)
597 const auto *
Last = Line->Last;
599 for (
const auto *Tok =
First; Tok && Tok !=
Last && Tok->Next;
601 if (Tok->is(tok::comment))
604 Tok =
analyzeRight(SourceMgr, Keywords, Fixes, Tok, Qualifier,
607 Tok =
analyzeLeft(SourceMgr, Keywords, Fixes, Tok, Qualifier,
616 const std::vector<std::string> &Order, std::vector<std::string> &LeftOrder,
617 std::vector<std::string> &RightOrder,
624 assert(llvm::is_contained(Order,
"type") &&
625 "QualifierOrder must contain type");
629 for (
const auto &
s : Order) {
637 if (QualifierToken != tok::kw_typeof && QualifierToken != tok::identifier)
642 LeftOrder.insert(LeftOrder.begin(),
s);
644 RightOrder.push_back(
s);
657 const std::vector<tok::TokenKind> &
Qualifiers) {
667 if (!Tok->
is(tok::identifier))
This file declares LeftRightQualifierAlignmentFixer, a TokenAnalyzer that enforces either east or wes...
__device__ __2f16 float bool s
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
The collection of all-type qualifiers we support.
This class handles loading and caching of source files into memory.
tok::TokenKind getKind() const
TokenKind
Provides a simple uniform namespace for tokens from all C languages.