1 //===--- LeftRightQualifierAlignmentFixer.cpp -------------------*- C++--*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file implements LeftRightQualifierAlignmentFixer, a TokenAnalyzer that
11 /// enforces either left or right const depending on the style.
13 //===----------------------------------------------------------------------===//
15 #include "QualifierAlignmentFixer.h"
16 #include "FormatToken.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/Regex.h"
23 #define DEBUG_TYPE "format-qualifier-alignment-fixer"
28 QualifierAlignmentFixer::QualifierAlignmentFixer(
29 const Environment
&Env
, const FormatStyle
&Style
, StringRef
&Code
,
30 ArrayRef
<tooling::Range
> Ranges
, unsigned FirstStartColumn
,
31 unsigned NextStartColumn
, unsigned LastStartColumn
, StringRef FileName
)
32 : TokenAnalyzer(Env
, Style
), Code(Code
), Ranges(Ranges
),
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
;
38 PrepareLeftRightOrdering(Style
.QualifierOrder
, LeftOrder
, RightOrder
,
39 ConfiguredQualifierTokens
);
41 // Handle the left and right alignment separately.
42 for (const auto &Qualifier
: LeftOrder
) {
44 [&, Qualifier
, ConfiguredQualifierTokens
](const Environment
&Env
) {
45 return LeftRightQualifierAlignmentFixer(Env
, Style
, Qualifier
,
46 ConfiguredQualifierTokens
,
51 for (const auto &Qualifier
: RightOrder
) {
53 [&, Qualifier
, ConfiguredQualifierTokens
](const Environment
&Env
) {
54 return LeftRightQualifierAlignmentFixer(Env
, Style
, Qualifier
,
55 ConfiguredQualifierTokens
,
62 std::pair
<tooling::Replacements
, unsigned> QualifierAlignmentFixer::analyze(
63 TokenAnnotator
& /*Annotator*/,
64 SmallVectorImpl
<AnnotatedLine
*> & /*AnnotatedLines*/,
65 FormatTokenLexer
& /*Tokens*/) {
66 auto Env
= Environment::make(Code
, FileName
, Ranges
, FirstStartColumn
,
67 NextStartColumn
, LastStartColumn
);
70 std::optional
<std::string
> CurrentCode
;
71 tooling::Replacements Fixes
;
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
);
80 Env
= Environment::make(
81 *CurrentCode
, FileName
,
82 tooling::calculateRangesAfterReplacements(Fixes
, Ranges
),
83 FirstStartColumn
, NextStartColumn
, LastStartColumn
);
90 // Don't make replacements that replace nothing.
91 tooling::Replacements NonNoOpFixes
;
93 for (const tooling::Replacement
&Fix
: Fixes
) {
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};
107 static void replaceToken(const SourceManager
&SourceMgr
,
108 tooling::Replacements
&Fixes
,
109 const CharSourceRange
&Range
, std::string NewText
) {
110 auto Replacement
= tooling::Replacement(SourceMgr
, Range
, NewText
);
111 auto Err
= Fixes
.add(Replacement
);
114 llvm::errs() << "Error while rearranging Qualifier : "
115 << llvm::toString(std::move(Err
)) << "\n";
119 static void removeToken(const SourceManager
&SourceMgr
,
120 tooling::Replacements
&Fixes
,
121 const FormatToken
*First
) {
122 auto Range
= CharSourceRange::getCharRange(First
->getStartOfNonWhitespace(),
123 First
->Tok
.getEndLoc());
124 replaceToken(SourceMgr
, Fixes
, Range
, "");
127 static void insertQualifierAfter(const SourceManager
&SourceMgr
,
128 tooling::Replacements
&Fixes
,
129 const FormatToken
*First
,
130 const std::string
&Qualifier
) {
131 auto Range
= CharSourceRange::getCharRange(First
->Tok
.getLocation(),
132 First
->Tok
.getEndLoc());
134 std::string NewText
{};
135 NewText
+= First
->TokenText
;
136 NewText
+= " " + Qualifier
;
137 replaceToken(SourceMgr
, Fixes
, Range
, NewText
);
140 static void insertQualifierBefore(const SourceManager
&SourceMgr
,
141 tooling::Replacements
&Fixes
,
142 const FormatToken
*First
,
143 const std::string
&Qualifier
) {
144 auto Range
= CharSourceRange::getCharRange(First
->getStartOfNonWhitespace(),
145 First
->Tok
.getEndLoc());
147 std::string NewText
= " " + Qualifier
+ " ";
148 NewText
+= First
->TokenText
;
150 replaceToken(SourceMgr
, Fixes
, Range
, NewText
);
153 static bool endsWithSpace(const std::string
&s
) {
156 return isspace(s
.back());
159 static bool startsWithSpace(const std::string
&s
) {
162 return isspace(s
.front());
165 static void rotateTokens(const SourceManager
&SourceMgr
,
166 tooling::Replacements
&Fixes
, const FormatToken
*First
,
167 const FormatToken
*Last
, bool Left
) {
176 // If we are rotating to the left we move the Last token to the front.
178 NewText
+= Last
->TokenText
;
182 // Then move through the other tokens.
185 if (!NewText
.empty() && !endsWithSpace(NewText
))
188 NewText
+= Tok
->TokenText
;
192 // If we are rotating to the right we move the first token to the back.
194 if (!NewText
.empty() && !startsWithSpace(NewText
))
196 NewText
+= First
->TokenText
;
199 auto Range
= CharSourceRange::getCharRange(First
->getStartOfNonWhitespace(),
200 Last
->Tok
.getEndLoc());
202 replaceToken(SourceMgr
, Fixes
, Range
, NewText
);
206 isConfiguredQualifier(const FormatToken
*const Tok
,
207 const std::vector
<tok::TokenKind
> &Qualifiers
) {
208 return Tok
&& llvm::is_contained(Qualifiers
, Tok
->Tok
.getKind());
211 static bool isQualifier(const FormatToken
*const Tok
) {
215 switch (Tok
->Tok
.getKind()) {
217 case tok::kw_volatile
:
220 case tok::kw_constexpr
:
221 case tok::kw_restrict
:
229 const FormatToken
*LeftRightQualifierAlignmentFixer::analyzeRight(
230 const SourceManager
&SourceMgr
, const AdditionalKeywords
&Keywords
,
231 tooling::Replacements
&Fixes
, const FormatToken
*const Tok
,
232 const std::string
&Qualifier
, tok::TokenKind QualifierType
) {
233 // We only need to think about streams that begin with a qualifier.
234 if (!Tok
->is(QualifierType
))
236 // Don't concern yourself if nothing follows the qualifier.
240 // Skip qualifiers to the left to find what preceeds the qualifiers.
241 // Use isQualifier rather than isConfiguredQualifier to cover all qualifiers.
242 const FormatToken
*PreviousCheck
= Tok
->getPreviousNonComment();
243 while (isQualifier(PreviousCheck
))
244 PreviousCheck
= PreviousCheck
->getPreviousNonComment();
246 // Examples given in order of ['type', 'const', 'volatile']
247 const bool IsRightQualifier
= PreviousCheck
&& [PreviousCheck
]() {
249 // `Foo() const` -> `Foo() const`
250 // `Foo() const final` -> `Foo() const final`
251 // `Foo() const override` -> `Foo() const final`
252 // `Foo() const volatile override` -> `Foo() const volatile override`
253 // `Foo() volatile const final` -> `Foo() const volatile final`
254 if (PreviousCheck
->is(tok::r_paren
))
258 // `struct {} volatile const a;` -> `struct {} const volatile a;`
259 // `class {} volatile const a;` -> `class {} const volatile a;`
260 if (PreviousCheck
->is(tok::r_brace
))
264 // `template <class T> const Bar Foo()` ->
265 // `template <class T> Bar const Foo()`
267 // `Foo<int> const foo` -> `Foo<int> const foo`
268 // `Foo<int> volatile const` -> `Foo<int> const volatile`
271 // template <class T>
272 // requires Concept1<T> && requires Concept2<T>
277 // template <class T>
278 // requires Concept1<T> && requires Concept2<T>
281 if (PreviousCheck
->is(TT_TemplateCloser
)) {
282 // If the token closes a template<> or requires clause, then it is a left
283 // qualifier and should be moved to the right.
284 return !(PreviousCheck
->ClosesTemplateDeclaration
||
285 PreviousCheck
->ClosesRequiresClause
);
288 // The case `Foo* const` -> `Foo* const`
289 // The case `Foo* volatile const` -> `Foo* const volatile`
290 // The case `int32_t const` -> `int32_t const`
291 // The case `auto volatile const` -> `auto const volatile`
292 if (PreviousCheck
->isOneOf(TT_PointerOrReference
, tok::identifier
,
300 // Find the last qualifier to the right.
301 const FormatToken
*LastQual
= Tok
;
302 while (isQualifier(LastQual
->getNextNonComment()))
303 LastQual
= LastQual
->getNextNonComment();
305 // If this qualifier is to the right of a type or pointer do a partial sort
307 if (IsRightQualifier
) {
309 rotateTokens(SourceMgr
, Fixes
, Tok
, LastQual
, /*Left=*/false);
313 const FormatToken
*TypeToken
= LastQual
->getNextNonComment();
317 // Stay safe and don't move past macros, also don't bother with sorting.
318 if (isPossibleMacro(TypeToken
))
321 // The case `const long long int volatile` -> `long long int const volatile`
322 // The case `long const long int volatile` -> `long long int const volatile`
323 // The case `long long volatile int const` -> `long long int const volatile`
324 // The case `const long long volatile int` -> `long long int const volatile`
325 if (TypeToken
->isSimpleTypeSpecifier()) {
326 // The case `const decltype(foo)` -> `const decltype(foo)`
327 // The case `const typeof(foo)` -> `const typeof(foo)`
328 // The case `const _Atomic(foo)` -> `const _Atomic(foo)`
329 if (TypeToken
->isOneOf(tok::kw_decltype
, tok::kw_typeof
, tok::kw__Atomic
))
332 const FormatToken
*LastSimpleTypeSpecifier
= TypeToken
;
333 while (isQualifierOrType(LastSimpleTypeSpecifier
->getNextNonComment()))
334 LastSimpleTypeSpecifier
= LastSimpleTypeSpecifier
->getNextNonComment();
336 rotateTokens(SourceMgr
, Fixes
, Tok
, LastSimpleTypeSpecifier
,
338 return LastSimpleTypeSpecifier
;
341 // The case `unsigned short const` -> `unsigned short const`
343 // `unsigned short volatile const` -> `unsigned short const volatile`
344 if (PreviousCheck
&& PreviousCheck
->isSimpleTypeSpecifier()) {
346 rotateTokens(SourceMgr
, Fixes
, Tok
, LastQual
, /*Left=*/false);
350 // Skip the typename keyword.
351 // The case `const typename C::type` -> `typename C::type const`
352 if (TypeToken
->is(tok::kw_typename
))
353 TypeToken
= TypeToken
->getNextNonComment();
355 // Skip the initial :: of a global-namespace type.
356 // The case `const ::...` -> `::... const`
357 if (TypeToken
->is(tok::coloncolon
)) {
358 // The case `const ::template Foo...` -> `::template Foo... const`
359 TypeToken
= TypeToken
->getNextNonComment();
360 if (TypeToken
&& TypeToken
->is(tok::kw_template
))
361 TypeToken
= TypeToken
->getNextNonComment();
364 // Don't change declarations such as
365 // `foo(const struct Foo a);` -> `foo(const struct Foo a);`
366 // as they would currently change code such as
367 // `const struct my_struct_t {} my_struct;` -> `struct my_struct_t const {}
369 if (TypeToken
->isOneOf(tok::kw_struct
, tok::kw_class
))
372 if (TypeToken
->isOneOf(tok::kw_auto
, tok::identifier
)) {
373 // The case `const auto` -> `auto const`
374 // The case `const Foo` -> `Foo const`
375 // The case `const ::Foo` -> `::Foo const`
376 // The case `const Foo *` -> `Foo const *`
377 // The case `const Foo &` -> `Foo const &`
378 // The case `const Foo &&` -> `Foo const &&`
379 // The case `const std::Foo &&` -> `std::Foo const &&`
380 // The case `const std::Foo<T> &&` -> `std::Foo<T> const &&`
381 // The case `const ::template Foo` -> `::template Foo const`
382 // The case `const T::template Foo` -> `T::template Foo const`
383 const FormatToken
*Next
= nullptr;
384 while ((Next
= TypeToken
->getNextNonComment()) &&
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();
399 // Place the Qualifier at the end of the list of qualifiers.
400 while (isQualifier(TypeToken
->getNextNonComment())) {
401 // The case `volatile Foo::iter const` -> `Foo::iter const volatile`
402 TypeToken
= TypeToken
->getNextNonComment();
405 insertQualifierAfter(SourceMgr
, Fixes
, TypeToken
, Qualifier
);
406 // Remove token and following whitespace.
407 auto Range
= CharSourceRange::getCharRange(
408 Tok
->getStartOfNonWhitespace(), Tok
->Next
->getStartOfNonWhitespace());
409 replaceToken(SourceMgr
, Fixes
, Range
, "");
415 const FormatToken
*LeftRightQualifierAlignmentFixer::analyzeLeft(
416 const SourceManager
&SourceMgr
, const AdditionalKeywords
&Keywords
,
417 tooling::Replacements
&Fixes
, const FormatToken
*const Tok
,
418 const std::string
&Qualifier
, tok::TokenKind QualifierType
) {
419 // We only need to think about streams that begin with a qualifier.
420 if (!Tok
->is(QualifierType
))
422 // Don't concern yourself if nothing preceeds the qualifier.
423 if (!Tok
->getPreviousNonComment())
426 // Skip qualifiers to the left to find what preceeds the qualifiers.
427 const FormatToken
*TypeToken
= Tok
->getPreviousNonComment();
428 while (isQualifier(TypeToken
))
429 TypeToken
= TypeToken
->getPreviousNonComment();
431 // For left qualifiers preceeded by nothing, a template declaration, or *,&,&&
432 // we only perform sorting.
433 if (!TypeToken
|| TypeToken
->isOneOf(tok::star
, tok::amp
, tok::ampamp
) ||
434 TypeToken
->ClosesRequiresClause
|| TypeToken
->ClosesTemplateDeclaration
) {
436 // Don't sort past a non-configured qualifier token.
437 const FormatToken
*FirstQual
= Tok
;
438 while (isConfiguredQualifier(FirstQual
->getPreviousNonComment(),
439 ConfiguredQualifierTokens
)) {
440 FirstQual
= FirstQual
->getPreviousNonComment();
443 if (FirstQual
!= Tok
)
444 rotateTokens(SourceMgr
, Fixes
, FirstQual
, Tok
, /*Left=*/true);
448 // Stay safe and don't move past macros, also don't bother with sorting.
449 if (isPossibleMacro(TypeToken
))
452 // Examples given in order of ['const', 'volatile', 'type']
454 // The case `volatile long long int const` -> `const volatile long long int`
455 // The case `volatile long long const int` -> `const volatile long long int`
456 // The case `const long long volatile int` -> `const volatile long long int`
457 // The case `long volatile long int const` -> `const volatile long long int`
458 if (TypeToken
->isSimpleTypeSpecifier()) {
459 const FormatToken
*LastSimpleTypeSpecifier
= TypeToken
;
460 while (isConfiguredQualifierOrType(
461 LastSimpleTypeSpecifier
->getPreviousNonComment(),
462 ConfiguredQualifierTokens
)) {
463 LastSimpleTypeSpecifier
=
464 LastSimpleTypeSpecifier
->getPreviousNonComment();
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 {
477 // A template closer is not the start of a type.
478 // The case `?<> const` -> `const ?<>`
479 if (Tok
->is(TT_TemplateCloser
))
482 const FormatToken
*const Previous
= Tok
->getPreviousNonComment();
486 // An identifier preceeded by :: is not the start of a type.
487 // The case `?::Foo const` -> `const ?::Foo`
488 if (Tok
->is(tok::identifier
) && Previous
->is(tok::coloncolon
))
491 const FormatToken
*const PrePrevious
= Previous
->getPreviousNonComment();
492 // An identifier preceeded by ::template is not the start of a type.
493 // The case `?::template Foo const` -> `const ?::template Foo`
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");
506 TypeToken
= TypeToken
->MatchingParen
->getPreviousNonComment();
513 // `?>::template Foo`
514 // `?Bar::template Foo`
515 if (TypeToken
->getPreviousNonComment()->is(tok::kw_template
))
516 TypeToken
= TypeToken
->getPreviousNonComment();
518 const FormatToken
*const ColonColon
=
519 TypeToken
->getPreviousNonComment();
520 const FormatToken
*const PreColonColon
=
521 ColonColon
->getPreviousNonComment();
523 PreColonColon
->isOneOf(TT_TemplateCloser
, tok::identifier
)) {
524 TypeToken
= PreColonColon
;
526 TypeToken
= ColonColon
;
531 assert(TypeToken
&& "Should be auto or identifier");
533 // Place the Qualifier at the start of the list of qualifiers.
534 const FormatToken
*Previous
= nullptr;
535 while ((Previous
= TypeToken
->getPreviousNonComment()) &&
536 (isConfiguredQualifier(Previous
, ConfiguredQualifierTokens
) ||
537 Previous
->is(tok::kw_typename
))) {
538 // The case `volatile Foo::iter const` -> `const volatile Foo::iter`
539 // The case `typename C::type const` -> `const typename C::type`
540 TypeToken
= Previous
;
543 // Don't change declarations such as
544 // `foo(struct Foo const a);` -> `foo(struct Foo const a);`
545 if (!Previous
|| !Previous
->isOneOf(tok::kw_struct
, tok::kw_class
)) {
546 insertQualifierBefore(SourceMgr
, Fixes
, TypeToken
, Qualifier
);
547 removeToken(SourceMgr
, Fixes
, Tok
);
554 tok::TokenKind
LeftRightQualifierAlignmentFixer::getTokenFromQualifier(
555 const std::string
&Qualifier
) {
556 // Don't let 'type' be an identifier, but steal typeof token.
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
);
569 LeftRightQualifierAlignmentFixer::LeftRightQualifierAlignmentFixer(
570 const Environment
&Env
, const FormatStyle
&Style
,
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
) {}
576 std::pair
<tooling::Replacements
, unsigned>
577 LeftRightQualifierAlignmentFixer::analyze(
578 TokenAnnotator
& /*Annotator*/,
579 SmallVectorImpl
<AnnotatedLine
*> &AnnotatedLines
,
580 FormatTokenLexer
&Tokens
) {
581 tooling::Replacements Fixes
;
582 const AdditionalKeywords
&Keywords
= Tokens
.getKeywords();
583 const SourceManager
&SourceMgr
= Env
.getSourceManager();
584 AffectedRangeMgr
.computeAffectedLines(AnnotatedLines
);
586 tok::TokenKind QualifierToken
= getTokenFromQualifier(Qualifier
);
587 assert(QualifierToken
!= tok::identifier
&& "Unrecognised Qualifier");
589 for (AnnotatedLine
*Line
: AnnotatedLines
) {
590 if (!Line
->Affected
|| Line
->InPPDirective
)
592 FormatToken
*First
= Line
->First
;
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
,
615 void QualifierAlignmentFixer::PrepareLeftRightOrdering(
616 const std::vector
<std::string
> &Order
, std::vector
<std::string
> &LeftOrder
,
617 std::vector
<std::string
> &RightOrder
,
618 std::vector
<tok::TokenKind
> &Qualifiers
) {
620 // Depending on the position of type in the order you need
621 // To iterate forward or backward through the order list as qualifier
622 // can push through each other.
623 // The Order list must define the position of "type" to signify
624 assert(llvm::is_contained(Order
, "type") &&
625 "QualifierOrder must contain type");
626 // Split the Order list by type and reverse the left side.
629 for (const auto &s
: Order
) {
635 tok::TokenKind QualifierToken
=
636 LeftRightQualifierAlignmentFixer::getTokenFromQualifier(s
);
637 if (QualifierToken
!= tok::kw_typeof
&& QualifierToken
!= tok::identifier
)
638 Qualifiers
.push_back(QualifierToken
);
641 // Reverse the order for left aligned items.
642 LeftOrder
.insert(LeftOrder
.begin(), s
);
644 RightOrder
.push_back(s
);
649 bool LeftRightQualifierAlignmentFixer::isQualifierOrType(
650 const FormatToken
*const Tok
) {
651 return Tok
&& (Tok
->isSimpleTypeSpecifier() || Tok
->is(tok::kw_auto
) ||
655 bool LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType(
656 const FormatToken
*const Tok
,
657 const std::vector
<tok::TokenKind
> &Qualifiers
) {
658 return Tok
&& (Tok
->isSimpleTypeSpecifier() || Tok
->is(tok::kw_auto
) ||
659 isConfiguredQualifier(Tok
, Qualifiers
));
662 // If a token is an identifier and it's upper case, it could
663 // be a macro and hence we need to be able to ignore it.
664 bool LeftRightQualifierAlignmentFixer::isPossibleMacro(const FormatToken
*Tok
) {
667 if (!Tok
->is(tok::identifier
))
669 if (Tok
->TokenText
.upper() == Tok
->TokenText
.str()) {
670 // T,K,U,V likely could be template arguments
671 return (Tok
->TokenText
.size() != 1);
676 } // namespace format