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