17#include "llvm/Support/Debug.h"
18#include "llvm/Support/Regex.h"
20#define DEBUG_TYPE "format-qualifier-alignment-fixer"
27 std::vector<std::string> LeftOrder;
28 std::vector<std::string> RightOrder;
29 std::vector<tok::TokenKind> ConfiguredQualifierTokens;
31 Style.QualifierOrder, LeftOrder, RightOrder, ConfiguredQualifierTokens);
34 for (
const auto &Qualifier : LeftOrder) {
36 [&, Qualifier, ConfiguredQualifierTokens](
const Environment &Env) {
38 ConfiguredQualifierTokens,
43 for (
const auto &Qualifier : RightOrder) {
45 [&, Qualifier, ConfiguredQualifierTokens](
const Environment &Env) {
47 ConfiguredQualifierTokens,
58 auto Err = Fixes.
add(Replacement);
61 llvm::errs() <<
"Error while rearranging Qualifier : "
62 << llvm::toString(std::move(Err)) <<
"\n";
70 First->Tok.getEndLoc());
77 const std::string &Qualifier) {
79 First->Tok.getEndLoc());
81 std::string NewText{};
82 NewText +=
First->TokenText;
83 NewText +=
" " + Qualifier;
90 const std::string &Qualifier) {
92 First->Tok.getEndLoc());
94 std::string NewText =
" " + Qualifier +
" ";
95 NewText +=
First->TokenText;
103 return isspace(
s.back());
109 return isspace(
s.front());
125 NewText +=
Last->TokenText;
133 Tok->isNot(tok::coloncolon)) {
137 NewText +=
Tok->TokenText;
145 NewText +=
First->TokenText;
149 Last->Tok.getEndLoc());
156 const std::vector<tok::TokenKind> &
Qualifiers) {
164 switch (
Tok->Tok.getKind()) {
166 case tok::kw_volatile:
169 case tok::kw_constexpr:
170 case tok::kw_restrict:
183 if (
Tok->isNot(QualifierType))
186 const auto *
Next =
Tok->getNextNonComment();
196 PreviousCheck = PreviousCheck->getPreviousNonComment();
199 const bool IsRightQualifier = PreviousCheck && [PreviousCheck]() {
206 if (PreviousCheck->
is(tok::r_paren))
212 if (PreviousCheck->
is(tok::r_brace))
233 if (PreviousCheck->
is(TT_TemplateCloser)) {
244 if (PreviousCheck->
isOneOf(TT_PointerOrReference, tok::identifier,
253 const auto *LastQual =
Tok;
257 if (!LastQual || !
Next ||
258 (LastQual->isOneOf(tok::kw_const, tok::kw_volatile) &&
265 if (IsRightQualifier) {
271 const FormatToken *TypeToken = LastQual->getNextNonComment();
283 if (TypeToken->isTypeName(
LangOpts)) {
287 if (TypeToken->
isOneOf(tok::kw_decltype, tok::kw_typeof, tok::kw__Atomic))
290 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
293 LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();
298 return LastSimpleTypeSpecifier;
304 if (PreviousCheck && PreviousCheck->isTypeName(
LangOpts)) {
312 if (TypeToken->
is(tok::kw_typename))
313 TypeToken = TypeToken->getNextNonComment();
317 if (TypeToken->
is(tok::coloncolon)) {
319 TypeToken = TypeToken->getNextNonComment();
320 if (TypeToken && TypeToken->
is(tok::kw_template))
321 TypeToken = TypeToken->getNextNonComment();
329 if (TypeToken->
isOneOf(tok::kw_struct, tok::kw_class))
332 if (TypeToken->
isOneOf(tok::kw_auto, tok::identifier)) {
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,
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();
355 TypeToken =
Next->getNextNonComment()->getNextNonComment();
363 while (
isQualifier(TypeToken->getNextNonComment())) {
365 TypeToken = TypeToken->getNextNonComment();
371 Tok->getStartOfNonWhitespace(),
Tok->Next->getStartOfNonWhitespace());
383 if (
Tok->isNot(QualifierType))
386 if (!
Tok->getPreviousNonComment())
392 TypeToken = TypeToken->getPreviousNonComment();
396 if (!TypeToken || TypeToken->isPointerOrReference() ||
398 TypeToken->
is(tok::r_square)) {
403 ConfiguredQualifierTokens)) {
404 FirstQual = FirstQual->getPreviousNonComment();
407 if (FirstQual !=
Tok)
422 if (TypeToken->isTypeName(
LangOpts)) {
423 for (
const auto *Prev = TypeToken->
Previous;
424 Prev && Prev->
is(tok::coloncolon); Prev = Prev->Previous) {
427 if (!(Prev && Prev->is(tok::identifier)))
431 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
433 LastSimpleTypeSpecifier->getPreviousNonComment(),
434 ConfiguredQualifierTokens,
LangOpts)) {
435 LastSimpleTypeSpecifier =
436 LastSimpleTypeSpecifier->getPreviousNonComment();
444 if (TypeToken->
isOneOf(tok::kw_auto, tok::identifier, TT_TemplateCloser)) {
445 const auto IsStartOfType = [](
const FormatToken *
const Tok) ->
bool {
451 if (
Tok->is(TT_TemplateCloser))
460 if (
Tok->is(tok::identifier) &&
Previous->is(tok::coloncolon))
466 if (
Tok->is(tok::identifier) &&
Previous->is(tok::kw_template) &&
467 PrePrevious && PrePrevious->
is(tok::coloncolon)) {
471 if (
Tok->endsSequence(tok::kw_auto, tok::identifier))
477 while (!IsStartOfType(TypeToken)) {
479 if (TypeToken->
is(TT_TemplateCloser)) {
480 assert(TypeToken->
MatchingParen &&
"Missing template opener");
481 TypeToken = TypeToken->
MatchingParen->getPreviousNonComment();
490 if (TypeToken->getPreviousNonComment()->
is(tok::kw_template))
491 TypeToken = TypeToken->getPreviousNonComment();
494 TypeToken->getPreviousNonComment();
496 ColonColon->getPreviousNonComment();
498 PreColonColon->
isOneOf(TT_TemplateCloser, tok::identifier)) {
499 TypeToken = PreColonColon;
501 TypeToken = ColonColon;
506 assert(TypeToken &&
"Should be auto or identifier");
510 while ((
Previous = TypeToken->getPreviousNonComment()) &&
530 const std::string &Qualifier) {
532 return llvm::StringSwitch<tok::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);
546 const std::string &Qualifier,
547 const std::vector<tok::TokenKind> &QualifierTokens,
bool RightAlign)
549 ConfiguredQualifierTokens(QualifierTokens) {}
551std::pair<tooling::Replacements, unsigned>
568 assert(QualifierToken != tok::identifier &&
"Unrecognised Qualifier");
572 if (!
Line->Affected ||
Line->InPPDirective)
576 if (
First->Finalized)
585 if (
Tok->is(tok::comment))
599 const std::vector<std::string> &Order, std::vector<std::string> &LeftOrder,
600 std::vector<std::string> &RightOrder,
607 assert(llvm::is_contained(Order,
"type") &&
608 "QualifierOrder must contain type");
612 for (
const auto &
s : Order) {
620 if (QualifierToken != tok::kw_typeof && QualifierToken != tok::identifier)
625 LeftOrder.insert(LeftOrder.begin(),
s);
627 RightOrder.push_back(
s);
633 return Tok && (
Tok->isTypeName(LangOpts) ||
Tok->is(tok::kw_auto) ||
638 const std::vector<tok::TokenKind> &
Qualifiers,
640 return Tok && (
Tok->isTypeName(LangOpts) ||
Tok->is(tok::kw_auto) ||
648 if (
Tok->isNot(tok::identifier))
651 const auto Text =
Tok->TokenText;
652 assert(!
Text.empty());
655 if (
Text.size() == 1)
659 const auto *Prev =
Tok->getPreviousNonComment();
660 if (Prev && Prev->is(tok::coloncolon))
662 const auto *
Next =
Tok->getNextNonComment();
663 if (
Next &&
Next->is(tok::coloncolon))
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.
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