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:
172 case tok::kw__Nonnull:
173 case tok::kw__Nullable:
174 case tok::kw__Null_unspecified:
175 case tok::kw___ptr32:
176 case tok::kw___ptr64:
177 case tok::kw___funcref:
189 if (
Tok->isNot(QualifierType))
192 const auto *
Next =
Tok->getNextNonComment();
202 PreviousCheck = PreviousCheck->getPreviousNonComment();
205 const bool IsRightQualifier = PreviousCheck && [PreviousCheck]() {
212 if (PreviousCheck->
is(tok::r_paren))
218 if (PreviousCheck->
is(tok::r_brace))
239 if (PreviousCheck->
is(TT_TemplateCloser)) {
250 if (PreviousCheck->
isOneOf(TT_PointerOrReference, tok::identifier,
259 const auto *LastQual =
Tok;
263 if (!LastQual || !
Next ||
264 (LastQual->isOneOf(tok::kw_const, tok::kw_volatile) &&
271 if (IsRightQualifier) {
277 const FormatToken *TypeToken = LastQual->getNextNonComment();
282 if (TypeToken->isPossibleMacro())
289 if (TypeToken->isTypeName(
LangOpts)) {
293 if (TypeToken->
isOneOf(tok::kw_decltype, tok::kw_typeof, tok::kw__Atomic))
296 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
299 LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();
304 return LastSimpleTypeSpecifier;
310 if (PreviousCheck && PreviousCheck->isTypeName(
LangOpts)) {
318 if (TypeToken->
is(tok::kw_typename))
319 TypeToken = TypeToken->getNextNonComment();
323 if (TypeToken->
is(tok::coloncolon)) {
325 TypeToken = TypeToken->getNextNonComment();
326 if (TypeToken && TypeToken->
is(tok::kw_template))
327 TypeToken = TypeToken->getNextNonComment();
335 if (TypeToken->
isOneOf(tok::kw_struct, tok::kw_class))
338 if (TypeToken->
isOneOf(tok::kw_auto, tok::identifier)) {
350 while ((
Next = TypeToken->getNextNonComment()) &&
351 (
Next->is(TT_TemplateOpener) ||
352 Next->startsSequence(tok::coloncolon, tok::identifier) ||
353 Next->startsSequence(tok::coloncolon, tok::kw_template,
355 if (
Next->is(TT_TemplateOpener)) {
356 assert(
Next->MatchingParen &&
"Missing template closer");
357 TypeToken =
Next->MatchingParen;
358 }
else if (
Next->startsSequence(tok::coloncolon, tok::identifier)) {
359 TypeToken =
Next->getNextNonComment();
361 TypeToken =
Next->getNextNonComment()->getNextNonComment();
369 while (
isQualifier(TypeToken->getNextNonComment())) {
371 TypeToken = TypeToken->getNextNonComment();
377 Tok->getStartOfNonWhitespace(),
Tok->Next->getStartOfNonWhitespace());
389 if (
Tok->isNot(QualifierType))
392 if (!
Tok->getPreviousNonComment())
398 TypeToken = TypeToken->getPreviousNonComment();
402 if (!TypeToken || TypeToken->isPointerOrReference() ||
404 TypeToken->
is(tok::r_square)) {
409 ConfiguredQualifierTokens)) {
410 FirstQual = FirstQual->getPreviousNonComment();
413 if (FirstQual !=
Tok)
419 if (TypeToken->isPossibleMacro())
428 if (TypeToken->isTypeName(
LangOpts)) {
429 for (
const auto *Prev = TypeToken->
Previous;
430 Prev && Prev->
is(tok::coloncolon); Prev = Prev->Previous) {
433 if (!(Prev && Prev->is(tok::identifier)))
437 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
439 LastSimpleTypeSpecifier->getPreviousNonComment(),
440 ConfiguredQualifierTokens,
LangOpts)) {
441 LastSimpleTypeSpecifier =
442 LastSimpleTypeSpecifier->getPreviousNonComment();
450 if (TypeToken->
isOneOf(tok::kw_auto, tok::identifier, TT_TemplateCloser)) {
451 const auto IsStartOfType = [](
const FormatToken *
const Tok) ->
bool {
457 if (
Tok->is(TT_TemplateCloser))
466 if (
Tok->is(tok::identifier) &&
Previous->is(tok::coloncolon))
472 if (
Tok->is(tok::identifier) &&
Previous->is(tok::kw_template) &&
473 PrePrevious && PrePrevious->
is(tok::coloncolon)) {
477 if (
Tok->endsSequence(tok::kw_auto, tok::identifier))
483 while (!IsStartOfType(TypeToken)) {
485 if (TypeToken->
is(TT_TemplateCloser)) {
486 assert(TypeToken->
MatchingParen &&
"Missing template opener");
487 TypeToken = TypeToken->
MatchingParen->getPreviousNonComment();
496 if (TypeToken->getPreviousNonComment()->
is(tok::kw_template))
497 TypeToken = TypeToken->getPreviousNonComment();
500 TypeToken->getPreviousNonComment();
502 ColonColon->getPreviousNonComment();
504 PreColonColon->
isOneOf(TT_TemplateCloser, tok::identifier)) {
505 TypeToken = PreColonColon;
507 TypeToken = ColonColon;
512 assert(TypeToken &&
"Should be auto or identifier");
516 while ((
Previous = TypeToken->getPreviousNonComment()) &&
536 const std::string &Qualifier) {
538 return llvm::StringSwitch<tok::TokenKind>(Qualifier)
539 .Case(
"type", tok::kw_typeof)
540 .Case(
"const", tok::kw_const)
541 .Case(
"volatile", tok::kw_volatile)
542 .Case(
"static", tok::kw_static)
543 .Case(
"inline", tok::kw_inline)
544 .Case(
"constexpr", tok::kw_constexpr)
545 .Case(
"restrict", tok::kw_restrict)
546 .Case(
"friend", tok::kw_friend)
547 .Default(tok::identifier);
552 const std::string &Qualifier,
553 const std::vector<tok::TokenKind> &QualifierTokens,
bool RightAlign)
555 ConfiguredQualifierTokens(QualifierTokens) {}
557std::pair<tooling::Replacements, unsigned>
574 assert(QualifierToken != tok::identifier &&
"Unrecognised Qualifier");
578 if (!
Line->Affected ||
Line->InPPDirective)
582 if (
First->Finalized)
591 if (
Tok->is(tok::comment))
605 const std::vector<std::string> &Order, std::vector<std::string> &LeftOrder,
606 std::vector<std::string> &RightOrder,
613 assert(llvm::is_contained(Order,
"type") &&
614 "QualifierOrder must contain type");
618 for (
const auto &
s : Order) {
626 if (QualifierToken != tok::kw_typeof && QualifierToken != tok::identifier)
631 LeftOrder.insert(LeftOrder.begin(),
s);
633 RightOrder.push_back(
s);
639 return Tok && (
Tok->isTypeName(LangOpts) ||
Tok->is(tok::kw_auto) ||
644 const std::vector<tok::TokenKind> &
Qualifiers,
646 return Tok && (
Tok->isTypeName(LangOpts) ||
Tok->is(tok::kw_auto) ||
This file declares QualifierAlignmentFixer, a TokenAnalyzer that enforces either east or west const d...
__device__ __2f16 float __ockl_bool s
Represents a byte-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