clang: lib/Format/QualifierAlignmentFixer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
17#include "llvm/Support/Debug.h"
18#include "llvm/Support/Regex.h"
19
20#define DEBUG_TYPE "format-qualifier-alignment-fixer"
21
23namespace format {
24
27 std::vectorstd::string LeftOrder;
28 std::vectorstd::string RightOrder;
29 std::vectortok::TokenKind ConfiguredQualifierTokens;
31 Style.QualifierOrder, LeftOrder, RightOrder, ConfiguredQualifierTokens);
32
33
34 for (const auto &Qualifier : LeftOrder) {
35 Passes.emplace_back(
36 [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {
38 ConfiguredQualifierTokens,
39 false)
41 });
42 }
43 for (const auto &Qualifier : RightOrder) {
44 Passes.emplace_back(
45 [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {
47 ConfiguredQualifierTokens,
48 true)
50 });
51 }
52}
53
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
70 First->Tok.getEndLoc());
72}
73
77 const std::string &Qualifier) {
79 First->Tok.getEndLoc());
80
81 std::string NewText{};
82 NewText += First->TokenText;
83 NewText += " " + Qualifier;
84 replaceToken(SourceMgr, Fixes, Range, NewText);
85}
86
90 const std::string &Qualifier) {
92 First->Tok.getEndLoc());
93
94 std::string NewText = " " + Qualifier + " ";
95 NewText += First->TokenText;
96
97 replaceToken(SourceMgr, Fixes, Range, NewText);
98}
99
101 if (s.empty())
102 return false;
103 return isspace(s.back());
104}
105
107 if (s.empty())
108 return false;
109 return isspace(s.front());
110}
111
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
124 if (Left) {
125 NewText += Last->TokenText;
126 NewText += " ";
127 }
128
129
130 auto *Tok = Begin;
131 while (Tok != End) {
132 if (!NewText.empty() && (NewText) &&
133 Tok->isNot(tok::coloncolon)) {
134 NewText += " ";
135 }
136
137 NewText += Tok->TokenText;
139 }
140
141
142 if (!Left) {
144 NewText += " ";
145 NewText += First->TokenText;
146 }
147
149 Last->Tok.getEndLoc());
150
151 replaceToken(SourceMgr, Fixes, Range, NewText);
152}
153
154static bool
159
161 if ()
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 return true;
173 default:
174 return false;
175 }
176}
177
181 const std::string &Qualifier, tok::TokenKind QualifierType) {
182
183 if (Tok->isNot(QualifierType))
184 return Tok;
185
186 const auto *Next = Tok->getNextNonComment();
187
188
190 return Tok;
191
192
193
194 const FormatToken *PreviousCheck = Tok->getPreviousNonComment();
196 PreviousCheck = PreviousCheck->getPreviousNonComment();
197
198
199 const bool IsRightQualifier = PreviousCheck && [PreviousCheck]() {
200
201
202
203
204
205
206 if (PreviousCheck->is(tok::r_paren))
207 return true;
208
209
210
211
212 if (PreviousCheck->is(tok::r_brace))
213 return true;
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233 if (PreviousCheck->is(TT_TemplateCloser)) {
234
235
238 }
239
240
241
242
243
244 if (PreviousCheck->isOneOf(TT_PointerOrReference, tok::identifier,
245 tok::kw_auto)) {
246 return true;
247 }
248
249 return false;
250 }();
251
252
253 const auto *LastQual = Tok;
255 LastQual = Next;
256
257 if (!LastQual || ||
258 (LastQual->isOneOf(tok::kw_const, tok::kw_volatile) &&
260 return Tok;
261 }
262
263
264
265 if (IsRightQualifier) {
266 if (LastQual != Tok)
267 rotateTokens(SourceMgr, Fixes, Tok, LastQual, false);
268 return Tok;
269 }
270
271 const FormatToken *TypeToken = LastQual->getNextNonComment();
272 if (!TypeToken)
273 return Tok;
274
275
277 return Tok;
278
279
280
281
282
283 if (TypeToken->isTypeName(LangOpts)) {
284
285
286
287 if (TypeToken->isOneOf(tok::kw_decltype, tok::kw_typeof, tok::kw__Atomic))
288 return Tok;
289
290 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
291 while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment(),
293 LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();
294 }
295
296 rotateTokens(SourceMgr, Fixes, Tok, LastSimpleTypeSpecifier,
297 false);
298 return LastSimpleTypeSpecifier;
299 }
300
301
302
303
304 if (PreviousCheck && PreviousCheck->isTypeName(LangOpts)) {
305 if (LastQual != Tok)
306 rotateTokens(SourceMgr, Fixes, Tok, LastQual, false);
307 return Tok;
308 }
309
310
311
312 if (TypeToken->is(tok::kw_typename))
313 TypeToken = TypeToken->getNextNonComment();
314
315
316
317 if (TypeToken->is(tok::coloncolon)) {
318
319 TypeToken = TypeToken->getNextNonComment();
320 if (TypeToken && TypeToken->is(tok::kw_template))
321 TypeToken = TypeToken->getNextNonComment();
322 }
323
324
325
326
327
328
329 if (TypeToken->isOneOf(tok::kw_struct, tok::kw_class))
330 return Tok;
331
332 if (TypeToken->isOneOf(tok::kw_auto, tok::identifier)) {
333
334
335
336
337
338
339
340
341
342
344 while ((Next = TypeToken->getNextNonComment()) &&
345 (Next->is(TT_TemplateOpener) ||
346 Next->startsSequence(tok::coloncolon, tok::identifier) ||
347 Next->startsSequence(tok::coloncolon, tok::kw_template,
348 tok::identifier))) {
349 if (Next->is(TT_TemplateOpener)) {
350 assert(Next->MatchingParen && "Missing template closer");
351 TypeToken = Next->MatchingParen;
352 } else if (Next->startsSequence(tok::coloncolon, tok::identifier)) {
353 TypeToken = Next->getNextNonComment();
354 } else {
355 TypeToken = Next->getNextNonComment()->getNextNonComment();
356 }
357 }
358
359 if (Next && Next->is(tok::kw_auto))
360 TypeToken = Next;
361
362
363 while (isQualifier(TypeToken->getNextNonComment())) {
364
365 TypeToken = TypeToken->getNextNonComment();
366 }
367
369
371 Tok->getStartOfNonWhitespace(), Tok->Next->getStartOfNonWhitespace());
373 }
374
375 return Tok;
376}
377
381 const std::string &Qualifier, tok::TokenKind QualifierType) {
382
383 if (Tok->isNot(QualifierType))
384 return Tok;
385
386 if (->getPreviousNonComment())
387 return Tok;
388
389
390 const FormatToken *TypeToken = Tok->getPreviousNonComment();
392 TypeToken = TypeToken->getPreviousNonComment();
393
394
395
396 if (!TypeToken || TypeToken->isPointerOrReference() ||
398 TypeToken->is(tok::r_square)) {
399
400
403 ConfiguredQualifierTokens)) {
404 FirstQual = FirstQual->getPreviousNonComment();
405 }
406
407 if (FirstQual != Tok)
408 rotateTokens(SourceMgr, Fixes, FirstQual, Tok, true);
409 return Tok;
410 }
411
412
414 return Tok;
415
416
417
418
419
420
421
422 if (TypeToken->isTypeName(LangOpts)) {
423 for (const auto *Prev = TypeToken->Previous;
424 Prev && Prev->is(tok::coloncolon); Prev = Prev->Previous) {
425 TypeToken = Prev;
427 if (!(Prev && Prev->is(tok::identifier)))
428 break;
429 TypeToken = Prev;
430 }
431 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
433 LastSimpleTypeSpecifier->getPreviousNonComment(),
434 ConfiguredQualifierTokens, LangOpts)) {
435 LastSimpleTypeSpecifier =
436 LastSimpleTypeSpecifier->getPreviousNonComment();
437 }
438
439 rotateTokens(SourceMgr, Fixes, LastSimpleTypeSpecifier, Tok,
440 true);
441 return Tok;
442 }
443
444 if (TypeToken->isOneOf(tok::kw_auto, tok::identifier, TT_TemplateCloser)) {
445 const auto IsStartOfType = [](const FormatToken *const Tok) -> bool {
446 if ()
447 return true;
448
449
450
451 if (Tok->is(TT_TemplateCloser))
452 return false;
453
456 return true;
457
458
459
460 if (Tok->is(tok::identifier) && Previous->is(tok::coloncolon))
461 return false;
462
463 const FormatToken *const PrePrevious = Previous->getPreviousNonComment();
464
465
466 if (Tok->is(tok::identifier) && Previous->is(tok::kw_template) &&
467 PrePrevious && PrePrevious->is(tok::coloncolon)) {
468 return false;
469 }
470
471 if (Tok->endsSequence(tok::kw_auto, tok::identifier))
472 return false;
473
474 return true;
475 };
476
477 while (!IsStartOfType(TypeToken)) {
478
479 if (TypeToken->is(TT_TemplateCloser)) {
480 assert(TypeToken->MatchingParen && "Missing template opener");
481 TypeToken = TypeToken->MatchingParen->getPreviousNonComment();
482 } else {
483
484
485
486
487
488
489
490 if (TypeToken->getPreviousNonComment()->is(tok::kw_template))
491 TypeToken = TypeToken->getPreviousNonComment();
492
494 TypeToken->getPreviousNonComment();
496 ColonColon->getPreviousNonComment();
497 if (PreColonColon &&
498 PreColonColon->isOneOf(TT_TemplateCloser, tok::identifier)) {
499 TypeToken = PreColonColon;
500 } else {
501 TypeToken = ColonColon;
502 }
503 }
504 }
505
506 assert(TypeToken && "Should be auto or identifier");
507
508
510 while ((Previous = TypeToken->getPreviousNonComment()) &&
512 Previous->is(tok::kw_typename))) {
513
514
516 }
517
518
519
520 if ( || Previous->isNoneOf(tok::kw_struct, tok::kw_class)) {
523 }
524 }
525
526 return Tok;
527}
528
530 const std::string &Qualifier) {
531
532 return llvm::StringSwitchtok::TokenKind(Qualifier)
533 .Case("type", tok::kw_typeof)
534 .Case("const", tok::kw_const)
535 .Case("volatile", tok::kw_volatile)
536 .Case("static", tok::kw_static)
537 .Case("inline", tok::kw_inline)
538 .Case("constexpr", tok::kw_constexpr)
539 .Case("restrict", tok::kw_restrict)
540 .Case("friend", tok::kw_friend)
541 .Default(tok::identifier);
542}
543
546 const std::string &Qualifier,
547 const std::vectortok::TokenKind &QualifierTokens, bool RightAlign)
549 ConfiguredQualifierTokens(QualifierTokens) {}
550
551std::pair<tooling::Replacements, unsigned>
559 return {Fixes, 0};
560}
561
568 assert(QualifierToken != tok::identifier && "Unrecognised Qualifier");
569
572 if (->Affected || Line->InPPDirective)
573 continue;
576 if (First->Finalized)
577 continue;
578
579 const auto *Last = Line->Last;
580
583 if (Tok->MustBreakBefore && Tok != First)
584 break;
585 if (Tok->is(tok::comment))
586 continue;
587 if (RightAlign) {
589 QualifierToken);
590 } else {
592 QualifierToken);
593 }
594 }
595 }
596}
597
599 const std::vectorstd::string &Order, std::vectorstd::string &LeftOrder,
600 std::vectorstd::string &RightOrder,
601 std::vectortok::TokenKind &Qualifiers) {
602
603
604
605
606
607 assert(llvm::is_contained(Order, "type") &&
608 "QualifierOrder must contain type");
609
610
611 bool left = true;
612 for (const auto &s : Order) {
613 if (s == "type") {
614 left = false;
615 continue;
616 }
617
620 if (QualifierToken != tok::kw_typeof && QualifierToken != tok::identifier)
621 Qualifiers.push_back(QualifierToken);
622
623 if (left) {
624
625 LeftOrder.insert(LeftOrder.begin(), s);
626 } else {
627 RightOrder.push_back(s);
628 }
629 }
630}
631
633 return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||
635}
636
638 const std::vectortok::TokenKind &Qualifiers,
640 return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||
642}
643
644
645
647 assert(Tok);
648 if (Tok->isNot(tok::identifier))
649 return false;
650
651 const auto Text = Tok->TokenText;
652 assert(.empty());
653
654
655 if (Text.size() == 1)
656 return false;
657
658
659 const auto *Prev = Tok->getPreviousNonComment();
660 if (Prev && Prev->is(tok::coloncolon))
661 return false;
662 const auto *Next = Tok->getNextNonComment();
663 if (Next && Next->is(tok::coloncolon))
664 return false;
665
667}
668
669}
670}
This file contains the declaration of the FormatToken, a wrapper around Token with additional informa...
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 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.
const AdditionalKeywords & getKeywords()
LeftRightQualifierAlignmentFixer(const Environment &Env, const FormatStyle &Style, const std::string &Qualifier, const std::vector< tok::TokenKind > &ConfiguredQualifierTokens, bool RightAlign)
Definition QualifierAlignmentFixer.cpp:544
const FormatToken * analyzeLeft(const SourceManager &SourceMgr, const AdditionalKeywords &Keywords, tooling::Replacements &Fixes, const FormatToken *Tok, const std::string &Qualifier, tok::TokenKind QualifierType)
Definition QualifierAlignmentFixer.cpp:378
const FormatToken * analyzeRight(const SourceManager &SourceMgr, const AdditionalKeywords &Keywords, tooling::Replacements &Fixes, const FormatToken *Tok, const std::string &Qualifier, tok::TokenKind QualifierType)
Definition QualifierAlignmentFixer.cpp:178
std::pair< tooling::Replacements, unsigned > analyze(TokenAnnotator &Annotator, SmallVectorImpl< AnnotatedLine * > &AnnotatedLines, FormatTokenLexer &Tokens) override
Definition QualifierAlignmentFixer.cpp:552
void fixQualifierAlignment(SmallVectorImpl< AnnotatedLine * > &AnnotatedLines, FormatTokenLexer &Tokens, tooling::Replacements &Fixes)
Definition QualifierAlignmentFixer.cpp:562
static tok::TokenKind getTokenFromQualifier(const std::string &Qualifier)
Definition QualifierAlignmentFixer.cpp:529
AffectedRangeManager AffectedRangeMgr
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.
void addQualifierAlignmentFixerPasses(const FormatStyle &Style, SmallVectorImpl< AnalyzerPass > &Passes)
Definition QualifierAlignmentFixer.cpp:25
bool isConfiguredQualifierOrType(const FormatToken *Tok, const std::vector< tok::TokenKind > &Qualifiers, const LangOptions &LangOpts)
Definition QualifierAlignmentFixer.cpp:637
static void replaceToken(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const CharSourceRange &Range, std::string NewText)
Definition QualifierAlignmentFixer.cpp:54
static bool endsWithSpace(const std::string &s)
Definition QualifierAlignmentFixer.cpp:100
bool isPossibleMacro(const FormatToken *Tok)
Definition QualifierAlignmentFixer.cpp:646
bool isQualifierOrType(const FormatToken *Tok, const LangOptions &LangOpts)
Definition QualifierAlignmentFixer.cpp:632
static void insertQualifierAfter(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const FormatToken *First, const std::string &Qualifier)
Definition QualifierAlignmentFixer.cpp:74
static void insertQualifierBefore(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const FormatToken *First, const std::string &Qualifier)
Definition QualifierAlignmentFixer.cpp:87
static void rotateTokens(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const FormatToken *First, const FormatToken *Last, bool Left)
Definition QualifierAlignmentFixer.cpp:112
static void removeToken(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const FormatToken *First)
Definition QualifierAlignmentFixer.cpp:66
static bool isConfiguredQualifier(const FormatToken *const Tok, const std::vector< tok::TokenKind > &Qualifiers)
Definition QualifierAlignmentFixer.cpp:155
void prepareLeftRightOrderingForQualifierAlignmentFixer(const std::vector< std::string > &Order, std::vector< std::string > &LeftOrder, std::vector< std::string > &RightOrder, std::vector< tok::TokenKind > &Qualifiers)
Definition QualifierAlignmentFixer.cpp:598
static bool startsWithSpace(const std::string &s)
Definition QualifierAlignmentFixer.cpp:106
static bool isQualifier(const FormatToken *const Tok)
Definition QualifierAlignmentFixer.cpp:160
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
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.