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#include
21#include
22
23#define DEBUG_TYPE "format-qualifier-alignment-fixer"
24
26namespace format {
27
30 std::vectorstd::string LeftOrder;
31 std::vectorstd::string RightOrder;
32 std::vectortok::TokenKind ConfiguredQualifierTokens;
34 Style.QualifierOrder, LeftOrder, RightOrder, ConfiguredQualifierTokens);
35
36
37 for (const auto &Qualifier : LeftOrder) {
38 Passes.emplace_back(
39 [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {
41 ConfiguredQualifierTokens,
42 false)
44 });
45 }
46 for (const auto &Qualifier : RightOrder) {
47 Passes.emplace_back(
48 [&, Qualifier, ConfiguredQualifierTokens](const Environment &Env) {
50 ConfiguredQualifierTokens,
51 true)
53 });
54 }
55}
56
61 auto Err = Fixes.add(Replacement);
62
63 if (Err) {
64 llvm::errs() << "Error while rearranging Qualifier : "
65 << llvm::toString(std::move(Err)) << "\n";
66 }
67}
68
73 First->Tok.getEndLoc());
75}
76
80 const std::string &Qualifier) {
82 First->Tok.getEndLoc());
83
84 std::string NewText{};
85 NewText += First->TokenText;
86 NewText += " " + Qualifier;
88}
89
93 const std::string &Qualifier) {
95 First->Tok.getEndLoc());
96
97 std::string NewText = " " + Qualifier + " ";
98 NewText += First->TokenText;
99
101}
102
104 if (s.empty())
105 return false;
106 return isspace(s.back());
107}
108
110 if (s.empty())
111 return false;
112 return isspace(s.front());
113}
114
118 auto *End = Last;
120 if (!Left) {
121 End = Last->Next;
123 }
124
125 std::string NewText;
126
127 if (Left) {
128 NewText += Last->TokenText;
129 NewText += " ";
130 }
131
132
133 auto *Tok = Begin;
134 while (Tok != End) {
136 NewText += " ";
137
138 NewText += Tok->TokenText;
139 Tok = Tok->Next;
140 }
141
142
143 if (!Left) {
145 NewText += " ";
146 NewText += First->TokenText;
147 }
148
150 Last->Tok.getEndLoc());
151
153}
154
155static bool
157 const std::vectortok::TokenKind &Qualifiers) {
159}
160
162 if (!Tok)
163 return false;
164
166 case tok::kw_const:
167 case tok::kw_volatile:
168 case tok::kw_static:
169 case tok::kw_inline:
170 case tok::kw_constexpr:
171 case tok::kw_restrict:
172 case tok::kw_friend:
173 return true;
174 default:
175 return false;
176 }
177}
178
182 const std::string &Qualifier, tok::TokenKind QualifierType) {
183
184 if (Tok->isNot(QualifierType))
185 return Tok;
186
187 if (!Tok->Next)
188 return Tok;
189
190
191
195
196
197 const bool IsRightQualifier = PreviousCheck && [PreviousCheck]() {
198
199
200
201
202
203
204 if (PreviousCheck->is(tok::r_paren))
205 return true;
206
207
208
209
210 if (PreviousCheck->is(tok::r_brace))
211 return true;
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231 if (PreviousCheck->is(TT_TemplateCloser)) {
232
233
236 }
237
238
239
240
241
242 if (PreviousCheck->isOneOf(TT_PointerOrReference, tok::identifier,
243 tok::kw_auto)) {
244 return true;
245 }
246
247 return false;
248 }();
249
250
254
255
256
257 if (IsRightQualifier) {
258 if (LastQual != Tok)
259 rotateTokens(SourceMgr, Fixes, Tok, LastQual, false);
260 return Tok;
261 }
262
264 if (!TypeToken)
265 return Tok;
266
267
269 return Tok;
270
271
272
273
274
276
277
278
279 if (TypeToken->isOneOf(tok::kw_decltype, tok::kw_typeof, tok::kw__Atomic))
280 return Tok;
281
282 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
285 LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();
286 }
287
288 rotateTokens(SourceMgr, Fixes, Tok, LastSimpleTypeSpecifier,
289 false);
290 return LastSimpleTypeSpecifier;
291 }
292
293
294
295
297 if (LastQual != Tok)
298 rotateTokens(SourceMgr, Fixes, Tok, LastQual, false);
299 return Tok;
300 }
301
302
303
304 if (TypeToken->is(tok::kw_typename))
306
307
308
309 if (TypeToken->is(tok::coloncolon)) {
310
312 if (TypeToken && TypeToken->is(tok::kw_template))
314 }
315
316
317
318
319
320
321 if (TypeToken->isOneOf(tok::kw_struct, tok::kw_class))
322 return Tok;
323
324 if (TypeToken->isOneOf(tok::kw_auto, tok::identifier)) {
325
326
327
328
329
330
331
332
333
334
337 (Next->is(TT_TemplateOpener) ||
338 Next->startsSequence(tok::coloncolon, tok::identifier) ||
339 Next->startsSequence(tok::coloncolon, tok::kw_template,
340 tok::identifier))) {
341 if (Next->is(TT_TemplateOpener)) {
342 assert(Next->MatchingParen && "Missing template closer");
343 TypeToken = Next->MatchingParen;
344 } else if (Next->startsSequence(tok::coloncolon, tok::identifier)) {
345 TypeToken = Next->getNextNonComment();
346 } else {
347 TypeToken = Next->getNextNonComment()->getNextNonComment();
348 }
349 }
350
351 if (Next && Next->is(tok::kw_auto))
352 TypeToken = Next;
353
354
356
358 }
359
361
365 }
366
367 return Tok;
368}
369
373 const std::string &Qualifier, tok::TokenKind QualifierType) {
374
375 if (Tok->isNot(QualifierType))
376 return Tok;
377
379 return Tok;
380
381
385
386
387
390 TypeToken->is(tok::r_square)) {
391
392
395 ConfiguredQualifierTokens)) {
397 }
398
399 if (FirstQual != Tok)
400 rotateTokens(SourceMgr, Fixes, FirstQual, Tok, true);
401 return Tok;
402 }
403
404
406 return Tok;
407
408
409
410
411
412
413
415 const FormatToken *LastSimpleTypeSpecifier = TypeToken;
418 ConfiguredQualifierTokens, LangOpts)) {
419 LastSimpleTypeSpecifier =
421 }
422
423 rotateTokens(SourceMgr, Fixes, LastSimpleTypeSpecifier, Tok,
424 true);
425 return Tok;
426 }
427
428 if (TypeToken->isOneOf(tok::kw_auto, tok::identifier, TT_TemplateCloser)) {
429 const auto IsStartOfType = [](const FormatToken *const Tok) -> bool {
430 if (!Tok)
431 return true;
432
433
434
435 if (Tok->is(TT_TemplateCloser))
436 return false;
437
440 return true;
441
442
443
444 if (Tok->is(tok::identifier) && Previous->is(tok::coloncolon))
445 return false;
446
447 const FormatToken *const PrePrevious = Previous->getPreviousNonComment();
448
449
450 if (Tok->is(tok::identifier) && Previous->is(tok::kw_template) &&
451 PrePrevious && PrePrevious->is(tok::coloncolon)) {
452 return false;
453 }
454
455 if (Tok->endsSequence(tok::kw_auto, tok::identifier))
456 return false;
457
458 return true;
459 };
460
461 while (!IsStartOfType(TypeToken)) {
462
463 if (TypeToken->is(TT_TemplateCloser)) {
464 assert(TypeToken->MatchingParen && "Missing template opener");
466 } else {
467
468
469
470
471
472
473
476
481 if (PreColonColon &&
482 PreColonColon->isOneOf(TT_TemplateCloser, tok::identifier)) {
483 TypeToken = PreColonColon;
484 } else {
485 TypeToken = ColonColon;
486 }
487 }
488 }
489
490 assert(TypeToken && "Should be auto or identifier");
491
492
496 Previous->is(tok::kw_typename))) {
497
498
500 }
501
502
503
504 if ( ||
->isOneOf(tok::kw_struct, tok::kw_class)) {
507 }
508 }
509
510 return Tok;
511}
512
514 const std::string &Qualifier) {
515
516 return llvm::StringSwitchtok::TokenKind(Qualifier)
517 .Case("type", tok::kw_typeof)
518 .Case("const", tok::kw_const)
519 .Case("volatile", tok::kw_volatile)
520 .Case("static", tok::kw_static)
521 .Case("inline", tok::kw_inline)
522 .Case("constexpr", tok::kw_constexpr)
523 .Case("restrict", tok::kw_restrict)
524 .Case("friend", tok::kw_friend)
525 .Default(tok::identifier);
526}
527
530 const std::string &Qualifier,
531 const std::vectortok::TokenKind &QualifierTokens, bool RightAlign)
532 : TokenAnalyzer(Env, Style), Qualifier(Qualifier), RightAlign(RightAlign),
533 ConfiguredQualifierTokens(QualifierTokens) {}
534
535std::pair<tooling::Replacements, unsigned>
543 return {Fixes, 0};
544}
545
552 assert(QualifierToken != tok::identifier && "Unrecognised Qualifier");
553
556 if (->Affected || Line->InPPDirective)
557 continue;
560 if (First->Finalized)
561 continue;
562
563 const auto *Last = Line->Last;
564
565 for (const auto *Tok = First; Tok && Tok != Last && Tok->Next;
566 Tok = Tok->Next) {
567 if (Tok->MustBreakBefore)
568 break;
569 if (Tok->is(tok::comment))
570 continue;
571 if (RightAlign) {
572 Tok = analyzeRight(SourceMgr, Keywords, Fixes, Tok, Qualifier,
573 QualifierToken);
574 } else {
575 Tok = analyzeLeft(SourceMgr, Keywords, Fixes, Tok, Qualifier,
576 QualifierToken);
577 }
578 }
579 }
580}
581
583 const std::vectorstd::string &Order, std::vectorstd::string &LeftOrder,
584 std::vectorstd::string &RightOrder,
585 std::vectortok::TokenKind &Qualifiers) {
586
587
588
589
590
591 assert(llvm::is_contained(Order, "type") &&
592 "QualifierOrder must contain type");
593
594
595 bool left = true;
596 for (const auto &s : Order) {
597 if (s == "type") {
598 left = false;
599 continue;
600 }
601
604 if (QualifierToken != tok::kw_typeof && QualifierToken != tok::identifier)
605 Qualifiers.push_back(QualifierToken);
606
607 if (left) {
608
609 LeftOrder.insert(LeftOrder.begin(), s);
610 } else {
611 RightOrder.push_back(s);
612 }
613 }
614}
615
617 return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||
619}
620
622 const std::vectortok::TokenKind &Qualifiers,
624 return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||
626}
627
628
629
631 if (!Tok)
632 return false;
633 if (Tok->isNot(tok::identifier))
634 return false;
636
637 return Tok->TokenText.size() != 1;
638 }
639 return false;
640}
641
642}
643}
This file contains the declaration of the FormatToken, a wrapper around Token with additional informa...
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.
tok::TokenKind getKind() const
bool computeAffectedLines(SmallVectorImpl< AnnotatedLine * > &Lines)
SourceManager & getSourceManager() const
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
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)
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 isPossibleMacro(const FormatToken *Tok)
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.
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...
The FormatStyle is used to configure the formatting to follow specific guidelines.
std::vector< std::string > QualifierOrder
The order in which the qualifiers appear.
A wrapper around a Token storing information about the whitespace characters preceding it.
bool isTypeName(const LangOptions &LangOpts) const
unsigned ClosesTemplateDeclaration
true if this is the ">" of "template<..>".
StringRef TokenText
The raw text of the token.
SourceLocation getStartOfNonWhitespace() const
Returns actual token start location without leading escaped newlines and whitespace.
bool isPointerOrReference() const
FormatToken * getNextNonComment() const
Returns the next token ignoring comments.
FormatToken * getPreviousNonComment() const
Returns the previous token ignoring comments.
FormatToken * Next
The next token in the unwrapped line.
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.
bool endsSequence(A K1, Ts... Tokens) const
true if this token ends a sequence with the given tokens in order, following the Previous pointers,...