clang-tools  11.0.0git
IdentifierNamingCheck.cpp
Go to the documentation of this file.
1 //===--- IdentifierNamingCheck.cpp - clang-tidy ---------------------------===//
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 
10 
11 #include "clang/AST/CXXInheritance.h"
12 #include "clang/Lex/PPCallbacks.h"
13 #include "clang/Lex/Preprocessor.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/DenseMapInfo.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/Error.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/Regex.h"
20 
21 #define DEBUG_TYPE "clang-tidy"
22 
23 // FixItHint
24 
25 using namespace clang::ast_matchers;
26 
27 namespace clang {
28 namespace tidy {
29 namespace readability {
30 
31 // clang-format off
32 #define NAMING_KEYS(m) \
33  m(Namespace) \
34  m(InlineNamespace) \
35  m(EnumConstant) \
36  m(ConstexprVariable) \
37  m(ConstantMember) \
38  m(PrivateMember) \
39  m(ProtectedMember) \
40  m(PublicMember) \
41  m(Member) \
42  m(ClassConstant) \
43  m(ClassMember) \
44  m(GlobalConstant) \
45  m(GlobalConstantPointer) \
46  m(GlobalPointer) \
47  m(GlobalVariable) \
48  m(LocalConstant) \
49  m(LocalConstantPointer) \
50  m(LocalPointer) \
51  m(LocalVariable) \
52  m(StaticConstant) \
53  m(StaticVariable) \
54  m(Constant) \
55  m(Variable) \
56  m(ConstantParameter) \
57  m(ParameterPack) \
58  m(Parameter) \
59  m(PointerParameter) \
60  m(ConstantPointerParameter) \
61  m(AbstractClass) \
62  m(Struct) \
63  m(Class) \
64  m(Union) \
65  m(Enum) \
66  m(GlobalFunction) \
67  m(ConstexprFunction) \
68  m(Function) \
69  m(ConstexprMethod) \
70  m(VirtualMethod) \
71  m(ClassMethod) \
72  m(PrivateMethod) \
73  m(ProtectedMethod) \
74  m(PublicMethod) \
75  m(Method) \
76  m(Typedef) \
77  m(TypeTemplateParameter) \
78  m(ValueTemplateParameter) \
79  m(TemplateTemplateParameter) \
80  m(TemplateParameter) \
81  m(TypeAlias) \
82  m(MacroDefinition) \
83  m(ObjcIvar) \
84 
85 enum StyleKind {
86 #define ENUMERATE(v) SK_ ## v,
88 #undef ENUMERATE
91 };
92 
93 static StringRef const StyleNames[] = {
94 #define STRINGIZE(v) #v,
96 #undef STRINGIZE
97 };
98 
99 #undef NAMING_KEYS
100 // clang-format on
101 
102 static constexpr std::pair<StringRef, IdentifierNamingCheck::CaseType>
103  Mapping[] = {
104  {"aNy_CasE", IdentifierNamingCheck::CT_AnyCase},
105  {"lower_case", IdentifierNamingCheck::CT_LowerCase},
106  {"UPPER_CASE", IdentifierNamingCheck::CT_UpperCase},
107  {"camelBack", IdentifierNamingCheck::CT_CamelBack},
108  {"CamelCase", IdentifierNamingCheck::CT_CamelCase},
109  {"Camel_Snake_Case", IdentifierNamingCheck::CT_CamelSnakeCase},
110  {"camel_Snake_Back", IdentifierNamingCheck::CT_CamelSnakeBack}};
111 
112 namespace {
113 /// Callback supplies macros to IdentifierNamingCheck::checkMacro
114 class IdentifierNamingCheckPPCallbacks : public PPCallbacks {
115 public:
116  IdentifierNamingCheckPPCallbacks(Preprocessor *PP,
117  IdentifierNamingCheck *Check)
118  : PP(PP), Check(Check) {}
119 
120  /// MacroDefined calls checkMacro for macros in the main file
121  void MacroDefined(const Token &MacroNameTok,
122  const MacroDirective *MD) override {
123  Check->checkMacro(PP->getSourceManager(), MacroNameTok, MD->getMacroInfo());
124  }
125 
126  /// MacroExpands calls expandMacro for macros in the main file
127  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
128  SourceRange /*Range*/,
129  const MacroArgs * /*Args*/) override {
130  Check->expandMacro(MacroNameTok, MD.getMacroInfo());
131  }
132 
133 private:
134  Preprocessor *PP;
135  IdentifierNamingCheck *Check;
136 };
137 } // namespace
138 
139 IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name,
140  ClangTidyContext *Context)
141  : RenamerClangTidyCheck(Name, Context),
142  IgnoreFailedSplit(Options.get("IgnoreFailedSplit", false)),
143  IgnoreMainLikeFunctions(Options.get("IgnoreMainLikeFunctions", false)) {
144 
145  for (auto const &Name : StyleNames) {
146  auto CaseOptional = [&]() -> llvm::Optional<CaseType> {
147  auto ValueOr = Options.get((Name + "Case").str(), makeArrayRef(Mapping));
148  if (ValueOr)
149  return *ValueOr;
150  llvm::logAllUnhandledErrors(
151  llvm::handleErrors(ValueOr.takeError(),
152  [](const MissingOptionError &) -> llvm::Error {
153  return llvm::Error::success();
154  }),
155  llvm::errs(), "warning: ");
156  return llvm::None;
157  }();
158 
159  auto prefix = Options.get((Name + "Prefix").str(), "");
160  auto postfix = Options.get((Name + "Suffix").str(), "");
161 
162  if (CaseOptional || !prefix.empty() || !postfix.empty()) {
163  NamingStyles.push_back(NamingStyle(CaseOptional, prefix, postfix));
164  } else {
165  NamingStyles.push_back(llvm::None);
166  }
167  }
168 }
169 
171 
174  for (size_t i = 0; i < SK_Count; ++i) {
175  if (NamingStyles[i]) {
176  if (NamingStyles[i]->Case) {
177  Options.store(Opts, (StyleNames[i] + "Case").str(),
178  *NamingStyles[i]->Case, llvm::makeArrayRef(Mapping));
179  }
180  Options.store(Opts, (StyleNames[i] + "Prefix").str(),
181  NamingStyles[i]->Prefix);
182  Options.store(Opts, (StyleNames[i] + "Suffix").str(),
183  NamingStyles[i]->Suffix);
184  }
185  }
186 
187  Options.store(Opts, "IgnoreFailedSplit", IgnoreFailedSplit);
188  Options.store(Opts, "IgnoreMainLikeFunctions", IgnoreMainLikeFunctions);
189 }
190 
191 static bool matchesStyle(StringRef Name,
193  static llvm::Regex Matchers[] = {
194  llvm::Regex("^.*$"),
195  llvm::Regex("^[a-z][a-z0-9_]*$"),
196  llvm::Regex("^[a-z][a-zA-Z0-9]*$"),
197  llvm::Regex("^[A-Z][A-Z0-9_]*$"),
198  llvm::Regex("^[A-Z][a-zA-Z0-9]*$"),
199  llvm::Regex("^[A-Z]([a-z0-9]*(_[A-Z])?)*"),
200  llvm::Regex("^[a-z]([a-z0-9]*(_[A-Z])?)*"),
201  };
202 
203  if (Name.startswith(Style.Prefix))
204  Name = Name.drop_front(Style.Prefix.size());
205  else
206  return false;
207 
208  if (Name.endswith(Style.Suffix))
209  Name = Name.drop_back(Style.Suffix.size());
210  else
211  return false;
212 
213  // Ensure the name doesn't have any extra underscores beyond those specified
214  // in the prefix and suffix.
215  if (Name.startswith("_") || Name.endswith("_"))
216  return false;
217 
218  if (Style.Case && !Matchers[static_cast<size_t>(*Style.Case)].match(Name))
219  return false;
220 
221  return true;
222 }
223 
224 static std::string fixupWithCase(StringRef Name,
226  static llvm::Regex Splitter(
227  "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)");
228 
229  SmallVector<StringRef, 8> Substrs;
230  Name.split(Substrs, "_", -1, false);
231 
232  SmallVector<StringRef, 8> Words;
233  for (auto Substr : Substrs) {
234  while (!Substr.empty()) {
235  SmallVector<StringRef, 8> Groups;
236  if (!Splitter.match(Substr, &Groups))
237  break;
238 
239  if (Groups[2].size() > 0) {
240  Words.push_back(Groups[1]);
241  Substr = Substr.substr(Groups[0].size());
242  } else if (Groups[3].size() > 0) {
243  Words.push_back(Groups[3]);
244  Substr = Substr.substr(Groups[0].size() - Groups[4].size());
245  } else if (Groups[5].size() > 0) {
246  Words.push_back(Groups[5]);
247  Substr = Substr.substr(Groups[0].size() - Groups[6].size());
248  }
249  }
250  }
251 
252  if (Words.empty())
253  return std::string(Name);
254 
255  std::string Fixup;
256  switch (Case) {
258  Fixup += Name;
259  break;
260 
262  for (auto const &Word : Words) {
263  if (&Word != &Words.front())
264  Fixup += "_";
265  Fixup += Word.lower();
266  }
267  break;
268 
270  for (auto const &Word : Words) {
271  if (&Word != &Words.front())
272  Fixup += "_";
273  Fixup += Word.upper();
274  }
275  break;
276 
278  for (auto const &Word : Words) {
279  Fixup += Word.substr(0, 1).upper();
280  Fixup += Word.substr(1).lower();
281  }
282  break;
283 
285  for (auto const &Word : Words) {
286  if (&Word == &Words.front()) {
287  Fixup += Word.lower();
288  } else {
289  Fixup += Word.substr(0, 1).upper();
290  Fixup += Word.substr(1).lower();
291  }
292  }
293  break;
294 
296  for (auto const &Word : Words) {
297  if (&Word != &Words.front())
298  Fixup += "_";
299  Fixup += Word.substr(0, 1).upper();
300  Fixup += Word.substr(1).lower();
301  }
302  break;
303 
305  for (auto const &Word : Words) {
306  if (&Word != &Words.front()) {
307  Fixup += "_";
308  Fixup += Word.substr(0, 1).upper();
309  } else {
310  Fixup += Word.substr(0, 1).lower();
311  }
312  Fixup += Word.substr(1).lower();
313  }
314  break;
315  }
316 
317  return Fixup;
318 }
319 
320 static bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl,
321  bool IncludeMainLike) {
322  const auto *FDecl =
323  dyn_cast_or_null<FunctionDecl>(ParmDecl.getParentFunctionOrMethod());
324  if (!FDecl)
325  return false;
326  if (FDecl->isMain())
327  return true;
328  if (!IncludeMainLike)
329  return false;
330  if (FDecl->getAccess() != AS_public && FDecl->getAccess() != AS_none)
331  return false;
332  enum MainType { None, Main, WMain };
333  auto IsCharPtrPtr = [](QualType QType) -> MainType {
334  if (QType.isNull())
335  return None;
336  if (QType = QType->getPointeeType(), QType.isNull())
337  return None;
338  if (QType = QType->getPointeeType(), QType.isNull())
339  return None;
340  if (QType->isCharType())
341  return Main;
342  if (QType->isWideCharType())
343  return WMain;
344  return None;
345  };
346  auto IsIntType = [](QualType QType) {
347  if (QType.isNull())
348  return false;
349  if (const auto *Builtin =
350  dyn_cast<BuiltinType>(QType->getUnqualifiedDesugaredType())) {
351  return Builtin->getKind() == BuiltinType::Int;
352  }
353  return false;
354  };
355  if (!IsIntType(FDecl->getReturnType()))
356  return false;
357  if (FDecl->getNumParams() < 2 || FDecl->getNumParams() > 3)
358  return false;
359  if (!IsIntType(FDecl->parameters()[0]->getType()))
360  return false;
361  MainType Type = IsCharPtrPtr(FDecl->parameters()[1]->getType());
362  if (Type == None)
363  return false;
364  if (FDecl->getNumParams() == 3 &&
365  IsCharPtrPtr(FDecl->parameters()[2]->getType()) != Type)
366  return false;
367 
368  if (Type == Main) {
369  static llvm::Regex Matcher(
370  "(^[Mm]ain([_A-Z]|$))|([a-z0-9_]Main([_A-Z]|$))|(_main(_|$))");
371  assert(Matcher.isValid() && "Invalid Matcher for main like functions.");
372  return Matcher.match(FDecl->getName());
373  } else {
374  static llvm::Regex Matcher("(^((W[Mm])|(wm))ain([_A-Z]|$))|([a-z0-9_]W[Mm]"
375  "ain([_A-Z]|$))|(_wmain(_|$))");
376  assert(Matcher.isValid() && "Invalid Matcher for wmain like functions.");
377  return Matcher.match(FDecl->getName());
378  }
379 }
380 
381 static std::string
383  const IdentifierNamingCheck::NamingStyle &Style) {
384  const std::string Fixed = fixupWithCase(
385  Name, Style.Case.getValueOr(IdentifierNamingCheck::CaseType::CT_AnyCase));
386  StringRef Mid = StringRef(Fixed).trim("_");
387  if (Mid.empty())
388  Mid = "_";
389  return (Style.Prefix + Mid + Style.Suffix).str();
390 }
391 
393  const NamedDecl *D,
394  const std::vector<llvm::Optional<IdentifierNamingCheck::NamingStyle>>
395  &NamingStyles,
396  bool IgnoreMainLikeFunctions) {
397  assert(D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit() &&
398  "Decl must be an explicit identifier with a name.");
399 
400  if (isa<ObjCIvarDecl>(D) && NamingStyles[SK_ObjcIvar])
401  return SK_ObjcIvar;
402 
403  if (isa<TypedefDecl>(D) && NamingStyles[SK_Typedef])
404  return SK_Typedef;
405 
406  if (isa<TypeAliasDecl>(D) && NamingStyles[SK_TypeAlias])
407  return SK_TypeAlias;
408 
409  if (const auto *Decl = dyn_cast<NamespaceDecl>(D)) {
410  if (Decl->isAnonymousNamespace())
411  return SK_Invalid;
412 
413  if (Decl->isInline() && NamingStyles[SK_InlineNamespace])
414  return SK_InlineNamespace;
415 
416  if (NamingStyles[SK_Namespace])
417  return SK_Namespace;
418  }
419 
420  if (isa<EnumDecl>(D) && NamingStyles[SK_Enum])
421  return SK_Enum;
422 
423  if (isa<EnumConstantDecl>(D)) {
424  if (NamingStyles[SK_EnumConstant])
425  return SK_EnumConstant;
426 
427  if (NamingStyles[SK_Constant])
428  return SK_Constant;
429 
430  return SK_Invalid;
431  }
432 
433  if (const auto *Decl = dyn_cast<CXXRecordDecl>(D)) {
434  if (Decl->isAnonymousStructOrUnion())
435  return SK_Invalid;
436 
437  if (!Decl->getCanonicalDecl()->isThisDeclarationADefinition())
438  return SK_Invalid;
439 
440  if (Decl->hasDefinition() && Decl->isAbstract() &&
441  NamingStyles[SK_AbstractClass])
442  return SK_AbstractClass;
443 
444  if (Decl->isStruct() && NamingStyles[SK_Struct])
445  return SK_Struct;
446 
447  if (Decl->isStruct() && NamingStyles[SK_Class])
448  return SK_Class;
449 
450  if (Decl->isClass() && NamingStyles[SK_Class])
451  return SK_Class;
452 
453  if (Decl->isClass() && NamingStyles[SK_Struct])
454  return SK_Struct;
455 
456  if (Decl->isUnion() && NamingStyles[SK_Union])
457  return SK_Union;
458 
459  if (Decl->isEnum() && NamingStyles[SK_Enum])
460  return SK_Enum;
461 
462  return SK_Invalid;
463  }
464 
465  if (const auto *Decl = dyn_cast<FieldDecl>(D)) {
466  QualType Type = Decl->getType();
467 
468  if (!Type.isNull() && Type.isConstQualified()) {
469  if (NamingStyles[SK_ConstantMember])
470  return SK_ConstantMember;
471 
472  if (NamingStyles[SK_Constant])
473  return SK_Constant;
474  }
475 
476  if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMember])
477  return SK_PrivateMember;
478 
479  if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMember])
480  return SK_ProtectedMember;
481 
482  if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMember])
483  return SK_PublicMember;
484 
485  if (NamingStyles[SK_Member])
486  return SK_Member;
487 
488  return SK_Invalid;
489  }
490 
491  if (const auto *Decl = dyn_cast<ParmVarDecl>(D)) {
492  if (isParamInMainLikeFunction(*Decl, IgnoreMainLikeFunctions))
493  return SK_Invalid;
494  QualType Type = Decl->getType();
495 
496  if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable])
497  return SK_ConstexprVariable;
498 
499  if (!Type.isNull() && Type.isConstQualified()) {
500  if (Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_ConstantPointerParameter])
501  return SK_ConstantPointerParameter;
502 
503  if (NamingStyles[SK_ConstantParameter])
504  return SK_ConstantParameter;
505 
506  if (NamingStyles[SK_Constant])
507  return SK_Constant;
508  }
509 
510  if (Decl->isParameterPack() && NamingStyles[SK_ParameterPack])
511  return SK_ParameterPack;
512 
513  if (!Type.isNull() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_PointerParameter])
514  return SK_PointerParameter;
515 
516  if (NamingStyles[SK_Parameter])
517  return SK_Parameter;
518 
519  return SK_Invalid;
520  }
521 
522  if (const auto *Decl = dyn_cast<VarDecl>(D)) {
523  QualType Type = Decl->getType();
524 
525  if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable])
526  return SK_ConstexprVariable;
527 
528  if (!Type.isNull() && Type.isConstQualified()) {
529  if (Decl->isStaticDataMember() && NamingStyles[SK_ClassConstant])
530  return SK_ClassConstant;
531 
532  if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_GlobalConstantPointer])
533  return SK_GlobalConstantPointer;
534 
535  if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalConstant])
536  return SK_GlobalConstant;
537 
538  if (Decl->isStaticLocal() && NamingStyles[SK_StaticConstant])
539  return SK_StaticConstant;
540 
541  if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_LocalConstantPointer])
542  return SK_LocalConstantPointer;
543 
544  if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalConstant])
545  return SK_LocalConstant;
546 
547  if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalConstant])
548  return SK_LocalConstant;
549 
550  if (NamingStyles[SK_Constant])
551  return SK_Constant;
552  }
553 
554  if (Decl->isStaticDataMember() && NamingStyles[SK_ClassMember])
555  return SK_ClassMember;
556 
557  if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_GlobalPointer])
558  return SK_GlobalPointer;
559 
560  if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalVariable])
561  return SK_GlobalVariable;
562 
563  if (Decl->isStaticLocal() && NamingStyles[SK_StaticVariable])
564  return SK_StaticVariable;
565 
566  if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_LocalPointer])
567  return SK_LocalPointer;
568 
569  if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalVariable])
570  return SK_LocalVariable;
571 
572  if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalVariable])
573  return SK_LocalVariable;
574 
575  if (NamingStyles[SK_Variable])
576  return SK_Variable;
577 
578  return SK_Invalid;
579  }
580 
581  if (const auto *Decl = dyn_cast<CXXMethodDecl>(D)) {
582  if (Decl->isMain() || !Decl->isUserProvided() ||
583  Decl->size_overridden_methods() > 0)
584  return SK_Invalid;
585 
586  // If this method has the same name as any base method, this is likely
587  // necessary even if it's not an override. e.g. CRTP.
588  auto FindHidden = [&](const CXXBaseSpecifier *S, clang::CXXBasePath &P) {
589  return CXXRecordDecl::FindOrdinaryMember(S, P, Decl->getDeclName());
590  };
591  CXXBasePaths UnusedPaths;
592  if (Decl->getParent()->lookupInBases(FindHidden, UnusedPaths))
593  return SK_Invalid;
594 
595  if (Decl->isConstexpr() && NamingStyles[SK_ConstexprMethod])
596  return SK_ConstexprMethod;
597 
598  if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
599  return SK_ConstexprFunction;
600 
601  if (Decl->isStatic() && NamingStyles[SK_ClassMethod])
602  return SK_ClassMethod;
603 
604  if (Decl->isVirtual() && NamingStyles[SK_VirtualMethod])
605  return SK_VirtualMethod;
606 
607  if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMethod])
608  return SK_PrivateMethod;
609 
610  if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMethod])
611  return SK_ProtectedMethod;
612 
613  if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMethod])
614  return SK_PublicMethod;
615 
616  if (NamingStyles[SK_Method])
617  return SK_Method;
618 
619  if (NamingStyles[SK_Function])
620  return SK_Function;
621 
622  return SK_Invalid;
623  }
624 
625  if (const auto *Decl = dyn_cast<FunctionDecl>(D)) {
626  if (Decl->isMain())
627  return SK_Invalid;
628 
629  if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
630  return SK_ConstexprFunction;
631 
632  if (Decl->isGlobal() && NamingStyles[SK_GlobalFunction])
633  return SK_GlobalFunction;
634 
635  if (NamingStyles[SK_Function])
636  return SK_Function;
637  }
638 
639  if (isa<TemplateTypeParmDecl>(D)) {
640  if (NamingStyles[SK_TypeTemplateParameter])
641  return SK_TypeTemplateParameter;
642 
643  if (NamingStyles[SK_TemplateParameter])
644  return SK_TemplateParameter;
645 
646  return SK_Invalid;
647  }
648 
649  if (isa<NonTypeTemplateParmDecl>(D)) {
650  if (NamingStyles[SK_ValueTemplateParameter])
651  return SK_ValueTemplateParameter;
652 
653  if (NamingStyles[SK_TemplateParameter])
654  return SK_TemplateParameter;
655 
656  return SK_Invalid;
657  }
658 
659  if (isa<TemplateTemplateParmDecl>(D)) {
660  if (NamingStyles[SK_TemplateTemplateParameter])
661  return SK_TemplateTemplateParameter;
662 
663  if (NamingStyles[SK_TemplateParameter])
664  return SK_TemplateParameter;
665 
666  return SK_Invalid;
667  }
668 
669  return SK_Invalid;
670 }
671 
672 llvm::Optional<RenamerClangTidyCheck::FailureInfo>
673 IdentifierNamingCheck::GetDeclFailureInfo(const NamedDecl *Decl,
674  const SourceManager &SM) const {
675  StyleKind SK = findStyleKind(Decl, NamingStyles, IgnoreMainLikeFunctions);
676  if (SK == SK_Invalid)
677  return None;
678 
679  if (!NamingStyles[SK])
680  return None;
681 
682  const NamingStyle &Style = *NamingStyles[SK];
683  StringRef Name = Decl->getName();
684  if (matchesStyle(Name, Style))
685  return None;
686 
687  std::string KindName = fixupWithCase(StyleNames[SK], CT_LowerCase);
688  std::replace(KindName.begin(), KindName.end(), '_', ' ');
689 
690  std::string Fixup = fixupWithStyle(Name, Style);
691  if (StringRef(Fixup).equals(Name)) {
692  if (!IgnoreFailedSplit) {
693  LLVM_DEBUG(llvm::dbgs()
694  << Decl->getBeginLoc().printToString(SM)
695  << llvm::format(": unable to split words for %s '%s'\n",
696  KindName.c_str(), Name.str().c_str()));
697  }
698  return None;
699  }
700  return FailureInfo{std::move(KindName), std::move(Fixup)};
701 }
702 
703 llvm::Optional<RenamerClangTidyCheck::FailureInfo>
704 IdentifierNamingCheck::GetMacroFailureInfo(const Token &MacroNameTok,
705  const SourceManager &SM) const {
706  if (!NamingStyles[SK_MacroDefinition])
707  return None;
708 
709  StringRef Name = MacroNameTok.getIdentifierInfo()->getName();
710  const NamingStyle &Style = *NamingStyles[SK_MacroDefinition];
711  if (matchesStyle(Name, Style))
712  return None;
713 
714  std::string KindName =
715  fixupWithCase(StyleNames[SK_MacroDefinition], CT_LowerCase);
716  std::replace(KindName.begin(), KindName.end(), '_', ' ');
717 
718  std::string Fixup = fixupWithStyle(Name, Style);
719  if (StringRef(Fixup).equals(Name)) {
720  if (!IgnoreFailedSplit) {
721  LLVM_DEBUG(llvm::dbgs()
722  << MacroNameTok.getLocation().printToString(SM)
723  << llvm::format(": unable to split words for %s '%s'\n",
724  KindName.c_str(), Name.str().c_str()));
725  }
726  return None;
727  }
728  return FailureInfo{std::move(KindName), std::move(Fixup)};
729 }
730 
732 IdentifierNamingCheck::GetDiagInfo(const NamingCheckId &ID,
733  const NamingCheckFailure &Failure) const {
734  return DiagInfo{"invalid case style for %0 '%1'",
735  [&](DiagnosticBuilder &diag) {
736  diag << Failure.Info.KindName << ID.second;
737  }};
738 }
739 
740 } // namespace readability
741 } // namespace tidy
742 } // namespace clang
void expandMacro(const Token &MacroNameTok, const MacroInfo *MI)
Add a usage of a macro if it already has a violation.
#define ENUMERATE(v)
const FunctionDecl * Decl
static bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl, bool IncludeMainLike)
std::string Suffix
Definition: AddUsing.cpp:96
static StyleKind findStyleKind(const NamedDecl *D, const std::vector< llvm::Optional< IdentifierNamingCheck::NamingStyle >> &NamingStyles, bool IgnoreMainLikeFunctions)
static constexpr std::pair< StringRef, IdentifierNamingCheck::CaseType > Mapping[]
llvm::Expected< std::string > get(StringRef LocalName) const
Read a named option from the Context.
static bool matchesStyle(StringRef Name, IdentifierNamingCheck::NamingStyle Style)
Represents customized diagnostic text and how arguments should be applied.
std::pair< SourceLocation, std::string > NamingCheckId
static std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle, llvm::StringRef Repl)
Definition: TestIndex.cpp:30
void handleErrors(llvm::ArrayRef< ClangTidyError > Errors, ClangTidyContext &Context, bool Fix, unsigned &WarningsAsErrorsCount, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS)
Displays the found Errors to the users.
Definition: ClangTidy.cpp:572
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
static constexpr llvm::StringLiteral Name
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Derived classes that override this function should call this method from the overridden method...
Base class for clang-tidy checks that want to flag declarations and/or macros for renaming based on c...
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
static std::string fixupWithCase(StringRef Name, IdentifierNamingCheck::CaseType Case)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static std::string fixupWithStyle(StringRef Name, const IdentifierNamingCheck::NamingStyle &Style)
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
void checkMacro(SourceManager &sourceMgr, const Token &MacroNameTok, const MacroInfo *MI)
Check Macros for style violations.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
#define STRINGIZE(v)
static StringRef const StyleNames[]
std::map< std::string, ClangTidyValue > OptionMap
#define NAMING_KEYS(m)
std::string Word
NodeType Type
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check&#39;s name.
Checks for identifiers naming style mismatch.