xref: /llvm-project/clang/lib/Format/QualifierAlignmentFixer.cpp (revision b92d6dd704d789240685a336ad8b25a9f381b4cc)
1 //===--- QualifierAlignmentFixer.cpp ----------------------------*- C++--*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements QualifierAlignmentFixer, a TokenAnalyzer that
11 /// enforces either left or right const depending on the style.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "QualifierAlignmentFixer.h"
16 
17 #define DEBUG_TYPE "format-qualifier-alignment-fixer"
18 
19 namespace clang {
20 namespace format {
21 
22 void addQualifierAlignmentFixerPasses(const FormatStyle &Style,
23                                       SmallVectorImpl<AnalyzerPass> &Passes) {
24   std::vector<std::string> LeftOrder;
25   std::vector<std::string> RightOrder;
26   std::vector<tok::TokenKind> ConfiguredQualifierTokens;
27   prepareLeftRightOrderingForQualifierAlignmentFixer(
28       Style.QualifierOrder, LeftOrder, RightOrder, ConfiguredQualifierTokens);
29 
30   // Handle the left and right alignment separately.
31   for (const auto &Qualifier : LeftOrder) {
32     Passes.emplace_back(
33         [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {
34           return LeftRightQualifierAlignmentFixer(Env, Style, Qualifier,
35                                                   ConfiguredQualifierTokens,
36                                                   /*RightAlign=*/false)
37               .process();
38         });
39   }
40   for (const auto &Qualifier : RightOrder) {
41     Passes.emplace_back(
42         [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {
43           return LeftRightQualifierAlignmentFixer(Env, Style, Qualifier,
44                                                   ConfiguredQualifierTokens,
45                                                   /*RightAlign=*/true)
46               .process();
47         });
48   }
49 }
50 
51 static void replaceToken(const SourceManager &SourceMgr,
52                          tooling::Replacements &Fixes,
53                          const CharSourceRange &Range, std::string NewText) {
54   auto Replacement = tooling::Replacement(SourceMgr, Range, NewText);
55   auto Err = Fixes.add(Replacement);
56 
57   if (Err) {
58     llvm::errs() << "Error while rearranging Qualifier : "
59                  << llvm::toString(std::move(Err)) << "\n";
60   }
61 }
62 
63 static void removeToken(const SourceManager &SourceMgr,
64                         tooling::Replacements &Fixes,
65                         const FormatToken *First) {
66   auto Range = CharSourceRange::getCharRange(First->getStartOfNonWhitespace(),
67                                              First->Tok.getEndLoc());
68   replaceToken(SourceMgr, Fixes, Range, "");
69 }
70 
71 static void insertQualifierAfter(const SourceManager &SourceMgr,
72                                  tooling::Replacements &Fixes,
73                                  const FormatToken *First,
74                                  const std::string &Qualifier) {
75   auto Range = CharSourceRange::getCharRange(First->Tok.getLocation(),
76                                              First->Tok.getEndLoc());
77 
78   std::string NewText{};
79   NewText += First->TokenText;
80   NewText += " " + Qualifier;
81   replaceToken(SourceMgr, Fixes, Range, NewText);
82 }
83 
84 static void insertQualifierBefore(const SourceManager &SourceMgr,
85                                   tooling::Replacements &Fixes,
86                                   const FormatToken *First,
87                                   const std::string &Qualifier) {
88   auto Range = CharSourceRange::getCharRange(First->getStartOfNonWhitespace(),
89                                              First->Tok.getEndLoc());
90 
91   std::string NewText = " " + Qualifier + " ";
92   NewText += First->TokenText;
93 
94   replaceToken(SourceMgr, Fixes, Range, NewText);
95 }
96 
97 static bool endsWithSpace(const std::string &s) {
98   if (s.empty())
99     return false;
100   return isspace(s.back());
101 }
102 
103 static bool startsWithSpace(const std::string &s) {
104   if (s.empty())
105     return false;
106   return isspace(s.front());
107 }
108 
109 static void rotateTokens(const SourceManager &SourceMgr,
110                          tooling::Replacements &Fixes, const FormatToken *First,
111                          const FormatToken *Last, bool Left) {
112   auto *End = Last;
113   auto *Begin = First;
114   if (!Left) {
115     End = Last->Next;
116     Begin = First->Next;
117   }
118 
119   std::string NewText;
120   // If we are rotating to the left we move the Last token to the front.
121   if (Left) {
122     NewText += Last->TokenText;
123     NewText += " ";
124   }
125 
126   // Then move through the other tokens.
127   auto *Tok = Begin;
128   while (Tok != End) {
129     if (!NewText.empty() && !endsWithSpace(NewText))
130       NewText += " ";
131 
132     NewText += Tok->TokenText;
133     Tok = Tok->Next;
134   }
135 
136   // If we are rotating to the right we move the first token to the back.
137   if (!Left) {
138     if (!NewText.empty() && !startsWithSpace(NewText))
139       NewText += " ";
140     NewText += First->TokenText;
141   }
142 
143   auto Range = CharSourceRange::getCharRange(First->getStartOfNonWhitespace(),
144                                              Last->Tok.getEndLoc());
145 
146   replaceToken(SourceMgr, Fixes, Range, NewText);
147 }
148 
149 static bool
150 isConfiguredQualifier(const FormatToken *const Tok,
151                       const std::vector<tok::TokenKind> &Qualifiers) {
152   return Tok && llvm::is_contained(Qualifiers, Tok->Tok.getKind());
153 }
154 
155 static bool isQualifier(const FormatToken *const Tok) {
156   if (!Tok)
157     return false;
158 
159   switch (Tok->Tok.getKind()) {
160   case tok::kw_const:
161   case tok::kw_volatile:
162   case tok::kw_static:
163   case tok::kw_inline:
164   case tok::kw_constexpr:
165   case tok::kw_restrict:
166   case tok::kw_friend:
167     return true;
168   default:
169     return false;
170   }
171 }
172 
173 const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
174     const SourceManager &SourceMgr, const AdditionalKeywords &Keywords,
175     tooling::Replacements &Fixes, const FormatToken *const Tok,
176     const std::string &Qualifier, tok::TokenKind QualifierType) {
177   // We only need to think about streams that begin with a qualifier.
178   if (Tok->isNot(QualifierType))
179     return Tok;
180   // Don't concern yourself if nothing follows the qualifier.
181   if (!Tok->Next)
182     return Tok;
183 
184   // Skip qualifiers to the left to find what preceeds the qualifiers.
185   // Use isQualifier rather than isConfiguredQualifier to cover all qualifiers.
186   const FormatToken *PreviousCheck = Tok->getPreviousNonComment();
187   while (isQualifier(PreviousCheck))
188     PreviousCheck = PreviousCheck->getPreviousNonComment();
189 
190   // Examples given in order of ['type', 'const', 'volatile']
191   const bool IsRightQualifier = PreviousCheck && [PreviousCheck]() {
192     // The cases:
193     // `Foo() const` -> `Foo() const`
194     // `Foo() const final` -> `Foo() const final`
195     // `Foo() const override` -> `Foo() const final`
196     // `Foo() const volatile override` -> `Foo() const volatile override`
197     // `Foo() volatile const final` -> `Foo() const volatile final`
198     if (PreviousCheck->is(tok::r_paren))
199       return true;
200 
201     // The cases:
202     // `struct {} volatile const a;` -> `struct {} const volatile a;`
203     // `class {} volatile const a;` -> `class {} const volatile a;`
204     if (PreviousCheck->is(tok::r_brace))
205       return true;
206 
207     // The case:
208     // `template <class T> const Bar Foo()` ->
209     // `template <class T> Bar const Foo()`
210     // The cases:
211     // `Foo<int> const foo` -> `Foo<int> const foo`
212     // `Foo<int> volatile const` -> `Foo<int> const volatile`
213     // The case:
214     // ```
215     // template <class T>
216     //   requires Concept1<T> && requires Concept2<T>
217     // const Foo f();
218     // ```
219     // ->
220     // ```
221     // template <class T>
222     //   requires Concept1<T> && requires Concept2<T>
223     // Foo const f();
224     // ```
225     if (PreviousCheck->is(TT_TemplateCloser)) {
226       // If the token closes a template<> or requires clause, then it is a left
227       // qualifier and should be moved to the right.
228       return !(PreviousCheck->ClosesTemplateDeclaration ||
229                PreviousCheck->ClosesRequiresClause);
230     }
231 
232     // The case  `Foo* const` -> `Foo* const`
233     // The case  `Foo* volatile const` -> `Foo* const volatile`
234     // The case  `int32_t const` -> `int32_t const`
235     // The case  `auto volatile const` -> `auto const volatile`
236     if (PreviousCheck->isOneOf(TT_PointerOrReference, tok::identifier,
237                                tok::kw_auto)) {
238       return true;
239     }
240 
241     return false;
242   }();
243 
244   // Find the last qualifier to the right.
245   const FormatToken *LastQual = Tok;
246   while (isQualifier(LastQual->getNextNonComment()))
247     LastQual = LastQual->getNextNonComment();
248 
249   // If this qualifier is to the right of a type or pointer do a partial sort
250   // and return.
251   if (IsRightQualifier) {
252     if (LastQual != Tok)
253       rotateTokens(SourceMgr, Fixes, Tok, LastQual, /*Left=*/false);
254     return Tok;
255   }
256 
257   const FormatToken *TypeToken = LastQual->getNextNonComment();
258   if (!TypeToken)
259     return Tok;
260 
261   // Stay safe and don't move past macros, also don't bother with sorting.
262   if (isPossibleMacro(TypeToken))
263     return Tok;
264 
265   // The case `const long long int volatile` -> `long long int const volatile`
266   // The case `long const long int volatile` -> `long long int const volatile`
267   // The case `long long volatile int const` -> `long long int const volatile`
268   // The case `const long long volatile int` -> `long long int const volatile`
269   if (TypeToken->isTypeName()) {
270     // The case `const decltype(foo)` -> `const decltype(foo)`
271     // The case `const typeof(foo)` -> `const typeof(foo)`
272     // The case `const _Atomic(foo)` -> `const _Atomic(foo)`
273     if (TypeToken->isOneOf(tok::kw_decltype, tok::kw_typeof, tok::kw__Atomic))
274       return Tok;
275 
276     const FormatToken *LastSimpleTypeSpecifier = TypeToken;
277     while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment()))
278       LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();
279 
280     rotateTokens(SourceMgr, Fixes, Tok, LastSimpleTypeSpecifier,
281                  /*Left=*/false);
282     return LastSimpleTypeSpecifier;
283   }
284 
285   // The case  `unsigned short const` -> `unsigned short const`
286   // The case:
287   // `unsigned short volatile const` -> `unsigned short const volatile`
288   if (PreviousCheck && PreviousCheck->isTypeName()) {
289     if (LastQual != Tok)
290       rotateTokens(SourceMgr, Fixes, Tok, LastQual, /*Left=*/false);
291     return Tok;
292   }
293 
294   // Skip the typename keyword.
295   // The case `const typename C::type` -> `typename C::type const`
296   if (TypeToken->is(tok::kw_typename))
297     TypeToken = TypeToken->getNextNonComment();
298 
299   // Skip the initial :: of a global-namespace type.
300   // The case `const ::...` -> `::... const`
301   if (TypeToken->is(tok::coloncolon)) {
302     // The case `const ::template Foo...` -> `::template Foo... const`
303     TypeToken = TypeToken->getNextNonComment();
304     if (TypeToken && TypeToken->is(tok::kw_template))
305       TypeToken = TypeToken->getNextNonComment();
306   }
307 
308   // Don't change declarations such as
309   // `foo(const struct Foo a);` -> `foo(const struct Foo a);`
310   // as they would currently change code such as
311   // `const struct my_struct_t {} my_struct;` -> `struct my_struct_t const {}
312   // my_struct;`
313   if (TypeToken->isOneOf(tok::kw_struct, tok::kw_class))
314     return Tok;
315 
316   if (TypeToken->isOneOf(tok::kw_auto, tok::identifier)) {
317     // The case  `const auto` -> `auto const`
318     // The case  `const Foo` -> `Foo const`
319     // The case  `const ::Foo` -> `::Foo const`
320     // The case  `const Foo *` -> `Foo const *`
321     // The case  `const Foo &` -> `Foo const &`
322     // The case  `const Foo &&` -> `Foo const &&`
323     // The case  `const std::Foo &&` -> `std::Foo const &&`
324     // The case  `const std::Foo<T> &&` -> `std::Foo<T> const &&`
325     // The case  `const ::template Foo` -> `::template Foo const`
326     // The case  `const T::template Foo` -> `T::template Foo const`
327     const FormatToken *Next = nullptr;
328     while ((Next = TypeToken->getNextNonComment()) &&
329            (Next->is(TT_TemplateOpener) ||
330             Next->startsSequence(tok::coloncolon, tok::identifier) ||
331             Next->startsSequence(tok::coloncolon, tok::kw_template,
332                                  tok::identifier))) {
333       if (Next->is(TT_TemplateOpener)) {
334         assert(Next->MatchingParen && "Missing template closer");
335         TypeToken = Next->MatchingParen;
336       } else if (Next->startsSequence(tok::coloncolon, tok::identifier)) {
337         TypeToken = Next->getNextNonComment();
338       } else {
339         TypeToken = Next->getNextNonComment()->getNextNonComment();
340       }
341     }
342 
343     if (Next->is(tok::kw_auto))
344       TypeToken = Next;
345 
346     // Place the Qualifier at the end of the list of qualifiers.
347     while (isQualifier(TypeToken->getNextNonComment())) {
348       // The case `volatile Foo::iter const` -> `Foo::iter const volatile`
349       TypeToken = TypeToken->getNextNonComment();
350     }
351 
352     insertQualifierAfter(SourceMgr, Fixes, TypeToken, Qualifier);
353     // Remove token and following whitespace.
354     auto Range = CharSourceRange::getCharRange(
355         Tok->getStartOfNonWhitespace(), Tok->Next->getStartOfNonWhitespace());
356     replaceToken(SourceMgr, Fixes, Range, "");
357   }
358 
359   return Tok;
360 }
361 
362 const FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft(
363     const SourceManager &SourceMgr, const AdditionalKeywords &Keywords,
364     tooling::Replacements &Fixes, const FormatToken *const Tok,
365     const std::string &Qualifier, tok::TokenKind QualifierType) {
366   // We only need to think about streams that begin with a qualifier.
367   if (Tok->isNot(QualifierType))
368     return Tok;
369   // Don't concern yourself if nothing preceeds the qualifier.
370   if (!Tok->getPreviousNonComment())
371     return Tok;
372 
373   // Skip qualifiers to the left to find what preceeds the qualifiers.
374   const FormatToken *TypeToken = Tok->getPreviousNonComment();
375   while (isQualifier(TypeToken))
376     TypeToken = TypeToken->getPreviousNonComment();
377 
378   // For left qualifiers preceeded by nothing, a template declaration, or *,&,&&
379   // we only perform sorting.
380   if (!TypeToken || TypeToken->isPointerOrReference() ||
381       TypeToken->ClosesRequiresClause || TypeToken->ClosesTemplateDeclaration) {
382 
383     // Don't sort past a non-configured qualifier token.
384     const FormatToken *FirstQual = Tok;
385     while (isConfiguredQualifier(FirstQual->getPreviousNonComment(),
386                                  ConfiguredQualifierTokens)) {
387       FirstQual = FirstQual->getPreviousNonComment();
388     }
389 
390     if (FirstQual != Tok)
391       rotateTokens(SourceMgr, Fixes, FirstQual, Tok, /*Left=*/true);
392     return Tok;
393   }
394 
395   // Stay safe and don't move past macros, also don't bother with sorting.
396   if (isPossibleMacro(TypeToken))
397     return Tok;
398 
399   // Examples given in order of ['const', 'volatile', 'type']
400 
401   // The case `volatile long long int const` -> `const volatile long long int`
402   // The case `volatile long long const int` -> `const volatile long long int`
403   // The case `const long long volatile int` -> `const volatile long long int`
404   // The case `long volatile long int const` -> `const volatile long long int`
405   if (TypeToken->isTypeName()) {
406     const FormatToken *LastSimpleTypeSpecifier = TypeToken;
407     while (isConfiguredQualifierOrType(
408         LastSimpleTypeSpecifier->getPreviousNonComment(),
409         ConfiguredQualifierTokens)) {
410       LastSimpleTypeSpecifier =
411           LastSimpleTypeSpecifier->getPreviousNonComment();
412     }
413 
414     rotateTokens(SourceMgr, Fixes, LastSimpleTypeSpecifier, Tok,
415                  /*Left=*/true);
416     return Tok;
417   }
418 
419   if (TypeToken->isOneOf(tok::kw_auto, tok::identifier, TT_TemplateCloser)) {
420     const auto IsStartOfType = [](const FormatToken *const Tok) -> bool {
421       if (!Tok)
422         return true;
423 
424       // A template closer is not the start of a type.
425       // The case `?<> const` -> `const ?<>`
426       if (Tok->is(TT_TemplateCloser))
427         return false;
428 
429       const FormatToken *const Previous = Tok->getPreviousNonComment();
430       if (!Previous)
431         return true;
432 
433       // An identifier preceeded by :: is not the start of a type.
434       // The case `?::Foo const` -> `const ?::Foo`
435       if (Tok->is(tok::identifier) && Previous->is(tok::coloncolon))
436         return false;
437 
438       const FormatToken *const PrePrevious = Previous->getPreviousNonComment();
439       // An identifier preceeded by ::template is not the start of a type.
440       // The case `?::template Foo const` -> `const ?::template Foo`
441       if (Tok->is(tok::identifier) && Previous->is(tok::kw_template) &&
442           PrePrevious && PrePrevious->is(tok::coloncolon)) {
443         return false;
444       }
445 
446       if (Tok->endsSequence(tok::kw_auto, tok::identifier))
447         return false;
448 
449       return true;
450     };
451 
452     while (!IsStartOfType(TypeToken)) {
453       // The case `?<>`
454       if (TypeToken->is(TT_TemplateCloser)) {
455         assert(TypeToken->MatchingParen && "Missing template opener");
456         TypeToken = TypeToken->MatchingParen->getPreviousNonComment();
457       } else {
458         // The cases
459         // `::Foo`
460         // `?>::Foo`
461         // `?Bar::Foo`
462         // `::template Foo`
463         // `?>::template Foo`
464         // `?Bar::template Foo`
465         if (TypeToken->getPreviousNonComment()->is(tok::kw_template))
466           TypeToken = TypeToken->getPreviousNonComment();
467 
468         const FormatToken *const ColonColon =
469             TypeToken->getPreviousNonComment();
470         const FormatToken *const PreColonColon =
471             ColonColon->getPreviousNonComment();
472         if (PreColonColon &&
473             PreColonColon->isOneOf(TT_TemplateCloser, tok::identifier)) {
474           TypeToken = PreColonColon;
475         } else {
476           TypeToken = ColonColon;
477         }
478       }
479     }
480 
481     assert(TypeToken && "Should be auto or identifier");
482 
483     // Place the Qualifier at the start of the list of qualifiers.
484     const FormatToken *Previous = nullptr;
485     while ((Previous = TypeToken->getPreviousNonComment()) &&
486            (isConfiguredQualifier(Previous, ConfiguredQualifierTokens) ||
487             Previous->is(tok::kw_typename))) {
488       // The case `volatile Foo::iter const` -> `const volatile Foo::iter`
489       // The case `typename C::type const` -> `const typename C::type`
490       TypeToken = Previous;
491     }
492 
493     // Don't change declarations such as
494     // `foo(struct Foo const a);` -> `foo(struct Foo const a);`
495     if (!Previous || !Previous->isOneOf(tok::kw_struct, tok::kw_class)) {
496       insertQualifierBefore(SourceMgr, Fixes, TypeToken, Qualifier);
497       removeToken(SourceMgr, Fixes, Tok);
498     }
499   }
500 
501   return Tok;
502 }
503 
504 tok::TokenKind LeftRightQualifierAlignmentFixer::getTokenFromQualifier(
505     const std::string &Qualifier) {
506   // Don't let 'type' be an identifier, but steal typeof token.
507   return llvm::StringSwitch<tok::TokenKind>(Qualifier)
508       .Case("type", tok::kw_typeof)
509       .Case("const", tok::kw_const)
510       .Case("volatile", tok::kw_volatile)
511       .Case("static", tok::kw_static)
512       .Case("inline", tok::kw_inline)
513       .Case("constexpr", tok::kw_constexpr)
514       .Case("restrict", tok::kw_restrict)
515       .Case("friend", tok::kw_friend)
516       .Default(tok::identifier);
517 }
518 
519 LeftRightQualifierAlignmentFixer::LeftRightQualifierAlignmentFixer(
520     const Environment &Env, const FormatStyle &Style,
521     const std::string &Qualifier,
522     const std::vector<tok::TokenKind> &QualifierTokens, bool RightAlign)
523     : TokenAnalyzer(Env, Style), Qualifier(Qualifier), RightAlign(RightAlign),
524       ConfiguredQualifierTokens(QualifierTokens) {
525   IsCpp = Style.isCpp();
526 }
527 
528 std::pair<tooling::Replacements, unsigned>
529 LeftRightQualifierAlignmentFixer::analyze(
530     TokenAnnotator & /*Annotator*/,
531     SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
532     FormatTokenLexer &Tokens) {
533   tooling::Replacements Fixes;
534   AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
535   fixQualifierAlignment(AnnotatedLines, Tokens, Fixes);
536   return {Fixes, 0};
537 }
538 
539 void LeftRightQualifierAlignmentFixer::fixQualifierAlignment(
540     SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, FormatTokenLexer &Tokens,
541     tooling::Replacements &Fixes) {
542   const AdditionalKeywords &Keywords = Tokens.getKeywords();
543   const SourceManager &SourceMgr = Env.getSourceManager();
544   tok::TokenKind QualifierToken = getTokenFromQualifier(Qualifier);
545   assert(QualifierToken != tok::identifier && "Unrecognised Qualifier");
546 
547   for (AnnotatedLine *Line : AnnotatedLines) {
548     fixQualifierAlignment(Line->Children, Tokens, Fixes);
549     if (!Line->Affected || Line->InPPDirective)
550       continue;
551     FormatToken *First = Line->First;
552     assert(First);
553     if (First->Finalized)
554       continue;
555 
556     const auto *Last = Line->Last;
557 
558     for (const auto *Tok = First; Tok && Tok != Last && Tok->Next;
559          Tok = Tok->Next) {
560       if (Tok->MustBreakBefore)
561         break;
562       if (Tok->is(tok::comment))
563         continue;
564       if (RightAlign) {
565         Tok = analyzeRight(SourceMgr, Keywords, Fixes, Tok, Qualifier,
566                            QualifierToken);
567       } else {
568         Tok = analyzeLeft(SourceMgr, Keywords, Fixes, Tok, Qualifier,
569                           QualifierToken);
570       }
571     }
572   }
573 }
574 
575 void prepareLeftRightOrderingForQualifierAlignmentFixer(
576     const std::vector<std::string> &Order, std::vector<std::string> &LeftOrder,
577     std::vector<std::string> &RightOrder,
578     std::vector<tok::TokenKind> &Qualifiers) {
579 
580   // Depending on the position of type in the order you need
581   // To iterate forward or backward through the order list as qualifier
582   // can push through each other.
583   // The Order list must define the position of "type" to signify
584   assert(llvm::is_contained(Order, "type") &&
585          "QualifierOrder must contain type");
586   // Split the Order list by type and reverse the left side.
587 
588   bool left = true;
589   for (const auto &s : Order) {
590     if (s == "type") {
591       left = false;
592       continue;
593     }
594 
595     tok::TokenKind QualifierToken =
596         LeftRightQualifierAlignmentFixer::getTokenFromQualifier(s);
597     if (QualifierToken != tok::kw_typeof && QualifierToken != tok::identifier)
598       Qualifiers.push_back(QualifierToken);
599 
600     if (left) {
601       // Reverse the order for left aligned items.
602       LeftOrder.insert(LeftOrder.begin(), s);
603     } else {
604       RightOrder.push_back(s);
605     }
606   }
607 }
608 
609 bool LeftRightQualifierAlignmentFixer::isQualifierOrType(
610     const FormatToken *Tok) {
611   return Tok &&
612          (Tok->isTypeName() || Tok->is(tok::kw_auto) || isQualifier(Tok));
613 }
614 
615 bool LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType(
616     const FormatToken *Tok, const std::vector<tok::TokenKind> &Qualifiers) {
617   return Tok && (Tok->isTypeName() || Tok->is(tok::kw_auto) ||
618                  isConfiguredQualifier(Tok, Qualifiers));
619 }
620 
621 // If a token is an identifier and it's upper case, it could
622 // be a macro and hence we need to be able to ignore it.
623 bool LeftRightQualifierAlignmentFixer::isPossibleMacro(const FormatToken *Tok) {
624   if (!Tok)
625     return false;
626   if (Tok->isNot(tok::identifier))
627     return false;
628   if (Tok->TokenText.upper() == Tok->TokenText.str()) {
629     // T,K,U,V likely could be template arguments
630     return Tok->TokenText.size() != 1;
631   }
632   return false;
633 }
634 
635 } // namespace format
636 } // namespace clang
637