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))
193 PreviousCheck = PreviousCheck->getPreviousNonComment();
196 const bool IsRightQualifier = PreviousCheck && [PreviousCheck]() {
203 if (PreviousCheck->
is(tok::r_paren))
209 if (PreviousCheck->
is(tok::r_brace))
230 if (PreviousCheck->
is(TT_TemplateCloser)) {
241 if (PreviousCheck->
isOneOf(TT_PointerOrReference, tok::identifier,
252 LastQual = LastQual->getNextNonComment();
256 if (IsRightQualifier) {
262 const FormatToken *TypeToken = LastQual->getNextNonComment();
274 if (TypeToken->isTypeName(
LangOpts)) {
278 if (TypeToken->
isOneOf(tok::kw_decltype, tok::kw_typeof, tok::kw__Atomic))
281 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
284 LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();
289 return LastSimpleTypeSpecifier;
295 if (PreviousCheck && PreviousCheck->isTypeName(
LangOpts)) {
303 if (TypeToken->
is(tok::kw_typename))
304 TypeToken = TypeToken->getNextNonComment();
308 if (TypeToken->
is(tok::coloncolon)) {
310 TypeToken = TypeToken->getNextNonComment();
311 if (TypeToken && TypeToken->
is(tok::kw_template))
312 TypeToken = TypeToken->getNextNonComment();
320 if (TypeToken->
isOneOf(tok::kw_struct, tok::kw_class))
323 if (TypeToken->
isOneOf(tok::kw_auto, tok::identifier)) {
335 while ((
Next = TypeToken->getNextNonComment()) &&
336 (
Next->is(TT_TemplateOpener) ||
337 Next->startsSequence(tok::coloncolon, tok::identifier) ||
338 Next->startsSequence(tok::coloncolon, tok::kw_template,
340 if (
Next->is(TT_TemplateOpener)) {
341 assert(
Next->MatchingParen &&
"Missing template closer");
342 TypeToken =
Next->MatchingParen;
343 }
else if (
Next->startsSequence(tok::coloncolon, tok::identifier)) {
344 TypeToken =
Next->getNextNonComment();
346 TypeToken =
Next->getNextNonComment()->getNextNonComment();
354 while (
isQualifier(TypeToken->getNextNonComment())) {
356 TypeToken = TypeToken->getNextNonComment();
362 Tok->getStartOfNonWhitespace(),
Tok->Next->getStartOfNonWhitespace());
374 if (
Tok->isNot(QualifierType))
377 if (!
Tok->getPreviousNonComment())
383 TypeToken = TypeToken->getPreviousNonComment();
387 if (!TypeToken || TypeToken->isPointerOrReference() ||
389 TypeToken->
is(tok::r_square)) {
394 ConfiguredQualifierTokens)) {
395 FirstQual = FirstQual->getPreviousNonComment();
398 if (FirstQual !=
Tok)
413 if (TypeToken->isTypeName(
LangOpts)) {
414 for (
const auto *Prev = TypeToken->
Previous;
415 Prev && Prev->
is(tok::coloncolon); Prev = Prev->Previous) {
418 if (!(Prev && Prev->is(tok::identifier)))
422 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
424 LastSimpleTypeSpecifier->getPreviousNonComment(),
425 ConfiguredQualifierTokens,
LangOpts)) {
426 LastSimpleTypeSpecifier =
427 LastSimpleTypeSpecifier->getPreviousNonComment();
435 if (TypeToken->
isOneOf(tok::kw_auto, tok::identifier, TT_TemplateCloser)) {
436 const auto IsStartOfType = [](
const FormatToken *
const Tok) ->
bool {
442 if (
Tok->is(TT_TemplateCloser))
451 if (
Tok->is(tok::identifier) &&
Previous->is(tok::coloncolon))
457 if (
Tok->is(tok::identifier) &&
Previous->is(tok::kw_template) &&
458 PrePrevious && PrePrevious->
is(tok::coloncolon)) {
462 if (
Tok->endsSequence(tok::kw_auto, tok::identifier))
468 while (!IsStartOfType(TypeToken)) {
470 if (TypeToken->
is(TT_TemplateCloser)) {
471 assert(TypeToken->
MatchingParen &&
"Missing template opener");
472 TypeToken = TypeToken->
MatchingParen->getPreviousNonComment();
481 if (TypeToken->getPreviousNonComment()->
is(tok::kw_template))
482 TypeToken = TypeToken->getPreviousNonComment();
485 TypeToken->getPreviousNonComment();
487 ColonColon->getPreviousNonComment();
489 PreColonColon->
isOneOf(TT_TemplateCloser, tok::identifier)) {
490 TypeToken = PreColonColon;
492 TypeToken = ColonColon;
497 assert(TypeToken &&
"Should be auto or identifier");
501 while ((
Previous = TypeToken->getPreviousNonComment()) &&
521 const std::string &Qualifier) {
523 return llvm::StringSwitch<tok::TokenKind>(Qualifier)
524 .Case(
"type", tok::kw_typeof)
525 .Case(
"const", tok::kw_const)
526 .Case(
"volatile", tok::kw_volatile)
527 .Case(
"static", tok::kw_static)
528 .Case(
"inline", tok::kw_inline)
529 .Case(
"constexpr", tok::kw_constexpr)
530 .Case(
"restrict", tok::kw_restrict)
531 .Case(
"friend", tok::kw_friend)
532 .Default(tok::identifier);
537 const std::string &Qualifier,
538 const std::vector<tok::TokenKind> &QualifierTokens,
bool RightAlign)
540 ConfiguredQualifierTokens(QualifierTokens) {}
542std::pair<tooling::Replacements, unsigned>
559 assert(QualifierToken != tok::identifier &&
"Unrecognised Qualifier");
563 if (!
Line->Affected ||
Line->InPPDirective)
567 if (
First->Finalized)
574 if (
Tok->MustBreakBefore)
576 if (
Tok->is(tok::comment))
590 const std::vector<std::string> &Order, std::vector<std::string> &LeftOrder,
591 std::vector<std::string> &RightOrder,
598 assert(llvm::is_contained(Order,
"type") &&
599 "QualifierOrder must contain type");
603 for (
const auto &
s : Order) {
611 if (QualifierToken != tok::kw_typeof && QualifierToken != tok::identifier)
616 LeftOrder.insert(LeftOrder.begin(),
s);
618 RightOrder.push_back(
s);
624 return Tok && (
Tok->isTypeName(LangOpts) ||
Tok->is(tok::kw_auto) ||
629 const std::vector<tok::TokenKind> &
Qualifiers,
631 return Tok && (
Tok->isTypeName(LangOpts) ||
Tok->is(tok::kw_auto) ||
639 if (
Tok->isNot(tok::identifier))
642 const auto Text =
Tok->TokenText;
643 assert(!
Text.empty());
646 if (
Text.size() == 1)
650 const auto *Prev =
Tok->getPreviousNonComment();
651 if (Prev && Prev->is(tok::coloncolon))
653 const auto *
Next =
Tok->getNextNonComment();
654 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...