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 
9 #include "IdentifierNamingCheck.h"
10 
11 #include "../GlobList.h"
12 #include "clang/AST/CXXInheritance.h"
13 #include "clang/Lex/PPCallbacks.h"
14 #include "clang/Lex/Preprocessor.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/DenseMapInfo.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/FormatVariadic.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/Regex.h"
22 
23 #define DEBUG_TYPE "clang-tidy"
24 
25 // FixItHint
26 
27 using namespace clang::ast_matchers;
28 
29 namespace clang {
30 namespace tidy {
31 
32 llvm::ArrayRef<
33     std::pair<readability::IdentifierNamingCheck::CaseType, StringRef>>
34 OptionEnumMapping<
getEnumMapping()35     readability::IdentifierNamingCheck::CaseType>::getEnumMapping() {
36   static constexpr std::pair<readability::IdentifierNamingCheck::CaseType,
37                              StringRef>
38       Mapping[] = {
39           {readability::IdentifierNamingCheck::CT_AnyCase, "aNy_CasE"},
40           {readability::IdentifierNamingCheck::CT_LowerCase, "lower_case"},
41           {readability::IdentifierNamingCheck::CT_UpperCase, "UPPER_CASE"},
42           {readability::IdentifierNamingCheck::CT_CamelBack, "camelBack"},
43           {readability::IdentifierNamingCheck::CT_CamelCase, "CamelCase"},
44           {readability::IdentifierNamingCheck::CT_CamelSnakeCase,
45            "Camel_Snake_Case"},
46           {readability::IdentifierNamingCheck::CT_CamelSnakeBack,
47            "camel_Snake_Back"}};
48   return llvm::makeArrayRef(Mapping);
49 }
50 
51 namespace readability {
52 
53 // clang-format off
54 #define NAMING_KEYS(m) \
55     m(Namespace) \
56     m(InlineNamespace) \
57     m(EnumConstant) \
58     m(ScopedEnumConstant) \
59     m(ConstexprVariable) \
60     m(ConstantMember) \
61     m(PrivateMember) \
62     m(ProtectedMember) \
63     m(PublicMember) \
64     m(Member) \
65     m(ClassConstant) \
66     m(ClassMember) \
67     m(GlobalConstant) \
68     m(GlobalConstantPointer) \
69     m(GlobalPointer) \
70     m(GlobalVariable) \
71     m(LocalConstant) \
72     m(LocalConstantPointer) \
73     m(LocalPointer) \
74     m(LocalVariable) \
75     m(StaticConstant) \
76     m(StaticVariable) \
77     m(Constant) \
78     m(Variable) \
79     m(ConstantParameter) \
80     m(ParameterPack) \
81     m(Parameter) \
82     m(PointerParameter) \
83     m(ConstantPointerParameter) \
84     m(AbstractClass) \
85     m(Struct) \
86     m(Class) \
87     m(Union) \
88     m(Enum) \
89     m(GlobalFunction) \
90     m(ConstexprFunction) \
91     m(Function) \
92     m(ConstexprMethod) \
93     m(VirtualMethod) \
94     m(ClassMethod) \
95     m(PrivateMethod) \
96     m(ProtectedMethod) \
97     m(PublicMethod) \
98     m(Method) \
99     m(Typedef) \
100     m(TypeTemplateParameter) \
101     m(ValueTemplateParameter) \
102     m(TemplateTemplateParameter) \
103     m(TemplateParameter) \
104     m(TypeAlias) \
105     m(MacroDefinition) \
106     m(ObjcIvar) \
107 
108 enum StyleKind {
109 #define ENUMERATE(v) SK_ ## v,
110   NAMING_KEYS(ENUMERATE)
111 #undef ENUMERATE
112   SK_Count,
113   SK_Invalid
114 };
115 
116 static StringRef const StyleNames[] = {
117 #define STRINGIZE(v) #v,
118   NAMING_KEYS(STRINGIZE)
119 #undef STRINGIZE
120 };
121 
122 #undef NAMING_KEYS
123 // clang-format on
124 
NamingStyle(llvm::Optional<IdentifierNamingCheck::CaseType> Case,const std::string & Prefix,const std::string & Suffix,const std::string & IgnoredRegexpStr)125 IdentifierNamingCheck::NamingStyle::NamingStyle(
126     llvm::Optional<IdentifierNamingCheck::CaseType> Case,
127     const std::string &Prefix, const std::string &Suffix,
128     const std::string &IgnoredRegexpStr)
129     : Case(Case), Prefix(Prefix), Suffix(Suffix),
130       IgnoredRegexpStr(IgnoredRegexpStr) {
131   if (!IgnoredRegexpStr.empty()) {
132     IgnoredRegexp =
133         llvm::Regex(llvm::SmallString<128>({"^", IgnoredRegexpStr, "$"}));
134     if (!IgnoredRegexp.isValid())
135       llvm::errs() << "Invalid IgnoredRegexp regular expression: "
136                    << IgnoredRegexpStr;
137   }
138 }
139 
140 static IdentifierNamingCheck::FileStyle
getFileStyleFromOptions(const ClangTidyCheck::OptionsView & Options)141 getFileStyleFromOptions(const ClangTidyCheck::OptionsView &Options) {
142   SmallVector<llvm::Optional<IdentifierNamingCheck::NamingStyle>, 0> Styles;
143   Styles.resize(SK_Count);
144   SmallString<64> StyleString;
145   for (unsigned I = 0; I < SK_Count; ++I) {
146     StyleString = StyleNames[I];
147     size_t StyleSize = StyleString.size();
148     StyleString.append("IgnoredRegexp");
149     std::string IgnoredRegexpStr = Options.get(StyleString, "");
150     StyleString.resize(StyleSize);
151     StyleString.append("Prefix");
152     std::string Prefix(Options.get(StyleString, ""));
153     // Fast replacement of [Pre]fix -> [Suf]fix.
154     memcpy(&StyleString[StyleSize], "Suf", 3);
155     std::string Postfix(Options.get(StyleString, ""));
156     memcpy(&StyleString[StyleSize], "Case", 4);
157     StyleString.pop_back();
158     StyleString.pop_back();
159     auto CaseOptional =
160         Options.getOptional<IdentifierNamingCheck::CaseType>(StyleString);
161 
162     if (CaseOptional || !Prefix.empty() || !Postfix.empty() ||
163         !IgnoredRegexpStr.empty())
164       Styles[I].emplace(std::move(CaseOptional), std::move(Prefix),
165                         std::move(Postfix), std::move(IgnoredRegexpStr));
166   }
167   bool IgnoreMainLike = Options.get("IgnoreMainLikeFunctions", false);
168   return {std::move(Styles), IgnoreMainLike};
169 }
170 
IdentifierNamingCheck(StringRef Name,ClangTidyContext * Context)171 IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name,
172                                              ClangTidyContext *Context)
173     : RenamerClangTidyCheck(Name, Context), Context(Context), CheckName(Name),
174       GetConfigPerFile(Options.get("GetConfigPerFile", true)),
175       IgnoreFailedSplit(Options.get("IgnoreFailedSplit", false)) {
176 
177   auto IterAndInserted = NamingStylesCache.try_emplace(
178       llvm::sys::path::parent_path(Context->getCurrentFile()),
179       getFileStyleFromOptions(Options));
180   assert(IterAndInserted.second && "Couldn't insert Style");
181   // Holding a reference to the data in the vector is safe as it should never
182   // move.
183   MainFileStyle = &IterAndInserted.first->getValue();
184 }
185 
186 IdentifierNamingCheck::~IdentifierNamingCheck() = default;
187 
storeOptions(ClangTidyOptions::OptionMap & Opts)188 void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
189   RenamerClangTidyCheck::storeOptions(Opts);
190   SmallString<64> StyleString;
191   ArrayRef<llvm::Optional<NamingStyle>> Styles = MainFileStyle->getStyles();
192   for (size_t I = 0; I < SK_Count; ++I) {
193     if (!Styles[I])
194       continue;
195     StyleString = StyleNames[I];
196     size_t StyleSize = StyleString.size();
197     StyleString.append("IgnoredRegexp");
198     Options.store(Opts, StyleString, Styles[I]->IgnoredRegexpStr);
199     StyleString.resize(StyleSize);
200     StyleString.append("Prefix");
201     Options.store(Opts, StyleString, Styles[I]->Prefix);
202     // Fast replacement of [Pre]fix -> [Suf]fix.
203     memcpy(&StyleString[StyleSize], "Suf", 3);
204     Options.store(Opts, StyleString, Styles[I]->Suffix);
205     if (Styles[I]->Case) {
206       memcpy(&StyleString[StyleSize], "Case", 4);
207       StyleString.pop_back();
208       StyleString.pop_back();
209       Options.store(Opts, StyleString, *Styles[I]->Case);
210     }
211   }
212   Options.store(Opts, "GetConfigPerFile", GetConfigPerFile);
213   Options.store(Opts, "IgnoreFailedSplit", IgnoreFailedSplit);
214   Options.store(Opts, "IgnoreMainLikeFunctions",
215                 MainFileStyle->isIgnoringMainLikeFunction());
216 }
217 
matchesStyle(StringRef Name,const IdentifierNamingCheck::NamingStyle & Style)218 static bool matchesStyle(StringRef Name,
219                          const IdentifierNamingCheck::NamingStyle &Style) {
220   static llvm::Regex Matchers[] = {
221       llvm::Regex("^.*$"),
222       llvm::Regex("^[a-z][a-z0-9_]*$"),
223       llvm::Regex("^[a-z][a-zA-Z0-9]*$"),
224       llvm::Regex("^[A-Z][A-Z0-9_]*$"),
225       llvm::Regex("^[A-Z][a-zA-Z0-9]*$"),
226       llvm::Regex("^[A-Z]([a-z0-9]*(_[A-Z])?)*"),
227       llvm::Regex("^[a-z]([a-z0-9]*(_[A-Z])?)*"),
228   };
229 
230   if (!Name.consume_front(Style.Prefix))
231     return false;
232   if (!Name.consume_back(Style.Suffix))
233     return false;
234 
235   // Ensure the name doesn't have any extra underscores beyond those specified
236   // in the prefix and suffix.
237   if (Name.startswith("_") || Name.endswith("_"))
238     return false;
239 
240   if (Style.Case && !Matchers[static_cast<size_t>(*Style.Case)].match(Name))
241     return false;
242 
243   return true;
244 }
245 
fixupWithCase(StringRef Name,IdentifierNamingCheck::CaseType Case)246 static std::string fixupWithCase(StringRef Name,
247                                  IdentifierNamingCheck::CaseType Case) {
248   static llvm::Regex Splitter(
249       "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)");
250 
251   SmallVector<StringRef, 8> Substrs;
252   Name.split(Substrs, "_", -1, false);
253 
254   SmallVector<StringRef, 8> Words;
255   SmallVector<StringRef, 8> Groups;
256   for (auto Substr : Substrs) {
257     while (!Substr.empty()) {
258       Groups.clear();
259       if (!Splitter.match(Substr, &Groups))
260         break;
261 
262       if (Groups[2].size() > 0) {
263         Words.push_back(Groups[1]);
264         Substr = Substr.substr(Groups[0].size());
265       } else if (Groups[3].size() > 0) {
266         Words.push_back(Groups[3]);
267         Substr = Substr.substr(Groups[0].size() - Groups[4].size());
268       } else if (Groups[5].size() > 0) {
269         Words.push_back(Groups[5]);
270         Substr = Substr.substr(Groups[0].size() - Groups[6].size());
271       }
272     }
273   }
274 
275   if (Words.empty())
276     return Name.str();
277 
278   SmallString<128> Fixup;
279   switch (Case) {
280   case IdentifierNamingCheck::CT_AnyCase:
281     return Name.str();
282     break;
283 
284   case IdentifierNamingCheck::CT_LowerCase:
285     for (auto const &Word : Words) {
286       if (&Word != &Words.front())
287         Fixup += "_";
288       Fixup += Word.lower();
289     }
290     break;
291 
292   case IdentifierNamingCheck::CT_UpperCase:
293     for (auto const &Word : Words) {
294       if (&Word != &Words.front())
295         Fixup += "_";
296       Fixup += Word.upper();
297     }
298     break;
299 
300   case IdentifierNamingCheck::CT_CamelCase:
301     for (auto const &Word : Words) {
302       Fixup += toupper(Word.front());
303       Fixup += Word.substr(1).lower();
304     }
305     break;
306 
307   case IdentifierNamingCheck::CT_CamelBack:
308     for (auto const &Word : Words) {
309       if (&Word == &Words.front()) {
310         Fixup += Word.lower();
311       } else {
312         Fixup += toupper(Word.front());
313         Fixup += Word.substr(1).lower();
314       }
315     }
316     break;
317 
318   case IdentifierNamingCheck::CT_CamelSnakeCase:
319     for (auto const &Word : Words) {
320       if (&Word != &Words.front())
321         Fixup += "_";
322       Fixup += toupper(Word.front());
323       Fixup += Word.substr(1).lower();
324     }
325     break;
326 
327   case IdentifierNamingCheck::CT_CamelSnakeBack:
328     for (auto const &Word : Words) {
329       if (&Word != &Words.front()) {
330         Fixup += "_";
331         Fixup += toupper(Word.front());
332       } else {
333         Fixup += tolower(Word.front());
334       }
335       Fixup += Word.substr(1).lower();
336     }
337     break;
338   }
339 
340   return Fixup.str().str();
341 }
342 
isParamInMainLikeFunction(const ParmVarDecl & ParmDecl,bool IncludeMainLike)343 static bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl,
344                                       bool IncludeMainLike) {
345   const auto *FDecl =
346       dyn_cast_or_null<FunctionDecl>(ParmDecl.getParentFunctionOrMethod());
347   if (!FDecl)
348     return false;
349   if (FDecl->isMain())
350     return true;
351   if (!IncludeMainLike)
352     return false;
353   if (FDecl->getAccess() != AS_public && FDecl->getAccess() != AS_none)
354     return false;
355   // If the function doesn't have a name thats an identifier, can occur of the
356   // function is an operator overload, bail out early.
357   if (!FDecl->getDeclName().isIdentifier())
358     return false;
359   enum MainType { None, Main, WMain };
360   auto IsCharPtrPtr = [](QualType QType) -> MainType {
361     if (QType.isNull())
362       return None;
363     if (QType = QType->getPointeeType(), QType.isNull())
364       return None;
365     if (QType = QType->getPointeeType(), QType.isNull())
366       return None;
367     if (QType->isCharType())
368       return Main;
369     if (QType->isWideCharType())
370       return WMain;
371     return None;
372   };
373   auto IsIntType = [](QualType QType) {
374     if (QType.isNull())
375       return false;
376     if (const auto *Builtin =
377             dyn_cast<BuiltinType>(QType->getUnqualifiedDesugaredType())) {
378       return Builtin->getKind() == BuiltinType::Int;
379     }
380     return false;
381   };
382   if (!IsIntType(FDecl->getReturnType()))
383     return false;
384   if (FDecl->getNumParams() < 2 || FDecl->getNumParams() > 3)
385     return false;
386   if (!IsIntType(FDecl->parameters()[0]->getType()))
387     return false;
388   MainType Type = IsCharPtrPtr(FDecl->parameters()[1]->getType());
389   if (Type == None)
390     return false;
391   if (FDecl->getNumParams() == 3 &&
392       IsCharPtrPtr(FDecl->parameters()[2]->getType()) != Type)
393     return false;
394 
395   if (Type == Main) {
396     static llvm::Regex Matcher(
397         "(^[Mm]ain([_A-Z]|$))|([a-z0-9_]Main([_A-Z]|$))|(_main(_|$))");
398     assert(Matcher.isValid() && "Invalid Matcher for main like functions.");
399     return Matcher.match(FDecl->getName());
400   } else {
401     static llvm::Regex Matcher("(^((W[Mm])|(wm))ain([_A-Z]|$))|([a-z0-9_]W[Mm]"
402                                "ain([_A-Z]|$))|(_wmain(_|$))");
403     assert(Matcher.isValid() && "Invalid Matcher for wmain like functions.");
404     return Matcher.match(FDecl->getName());
405   }
406 }
407 
408 static std::string
fixupWithStyle(StringRef Name,const IdentifierNamingCheck::NamingStyle & Style)409 fixupWithStyle(StringRef Name,
410                const IdentifierNamingCheck::NamingStyle &Style) {
411   const std::string Fixed = fixupWithCase(
412       Name, Style.Case.getValueOr(IdentifierNamingCheck::CaseType::CT_AnyCase));
413   StringRef Mid = StringRef(Fixed).trim("_");
414   if (Mid.empty())
415     Mid = "_";
416   return (Style.Prefix + Mid + Style.Suffix).str();
417 }
418 
findStyleKind(const NamedDecl * D,ArrayRef<llvm::Optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,bool IgnoreMainLikeFunctions)419 static StyleKind findStyleKind(
420     const NamedDecl *D,
421     ArrayRef<llvm::Optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
422     bool IgnoreMainLikeFunctions) {
423   assert(D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit() &&
424          "Decl must be an explicit identifier with a name.");
425 
426   if (isa<ObjCIvarDecl>(D) && NamingStyles[SK_ObjcIvar])
427     return SK_ObjcIvar;
428 
429   if (isa<TypedefDecl>(D) && NamingStyles[SK_Typedef])
430     return SK_Typedef;
431 
432   if (isa<TypeAliasDecl>(D) && NamingStyles[SK_TypeAlias])
433     return SK_TypeAlias;
434 
435   if (const auto *Decl = dyn_cast<NamespaceDecl>(D)) {
436     if (Decl->isAnonymousNamespace())
437       return SK_Invalid;
438 
439     if (Decl->isInline() && NamingStyles[SK_InlineNamespace])
440       return SK_InlineNamespace;
441 
442     if (NamingStyles[SK_Namespace])
443       return SK_Namespace;
444   }
445 
446   if (isa<EnumDecl>(D) && NamingStyles[SK_Enum])
447     return SK_Enum;
448 
449   if (const auto *EnumConst = dyn_cast<EnumConstantDecl>(D)) {
450     if (cast<EnumDecl>(EnumConst->getDeclContext())->isScoped() &&
451         NamingStyles[SK_ScopedEnumConstant])
452       return SK_ScopedEnumConstant;
453 
454     if (NamingStyles[SK_EnumConstant])
455       return SK_EnumConstant;
456 
457     if (NamingStyles[SK_Constant])
458       return SK_Constant;
459 
460     return SK_Invalid;
461   }
462 
463   if (const auto *Decl = dyn_cast<CXXRecordDecl>(D)) {
464     if (Decl->isAnonymousStructOrUnion())
465       return SK_Invalid;
466 
467     if (!Decl->getCanonicalDecl()->isThisDeclarationADefinition())
468       return SK_Invalid;
469 
470     if (Decl->hasDefinition() && Decl->isAbstract() &&
471         NamingStyles[SK_AbstractClass])
472       return SK_AbstractClass;
473 
474     if (Decl->isStruct() && NamingStyles[SK_Struct])
475       return SK_Struct;
476 
477     if (Decl->isStruct() && NamingStyles[SK_Class])
478       return SK_Class;
479 
480     if (Decl->isClass() && NamingStyles[SK_Class])
481       return SK_Class;
482 
483     if (Decl->isClass() && NamingStyles[SK_Struct])
484       return SK_Struct;
485 
486     if (Decl->isUnion() && NamingStyles[SK_Union])
487       return SK_Union;
488 
489     if (Decl->isEnum() && NamingStyles[SK_Enum])
490       return SK_Enum;
491 
492     return SK_Invalid;
493   }
494 
495   if (const auto *Decl = dyn_cast<FieldDecl>(D)) {
496     QualType Type = Decl->getType();
497 
498     if (!Type.isNull() && Type.isConstQualified()) {
499       if (NamingStyles[SK_ConstantMember])
500         return SK_ConstantMember;
501 
502       if (NamingStyles[SK_Constant])
503         return SK_Constant;
504     }
505 
506     if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMember])
507       return SK_PrivateMember;
508 
509     if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMember])
510       return SK_ProtectedMember;
511 
512     if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMember])
513       return SK_PublicMember;
514 
515     if (NamingStyles[SK_Member])
516       return SK_Member;
517 
518     return SK_Invalid;
519   }
520 
521   if (const auto *Decl = dyn_cast<ParmVarDecl>(D)) {
522     if (isParamInMainLikeFunction(*Decl, IgnoreMainLikeFunctions))
523       return SK_Invalid;
524     QualType Type = Decl->getType();
525 
526     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable])
527       return SK_ConstexprVariable;
528 
529     if (!Type.isNull() && Type.isConstQualified()) {
530       if (Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_ConstantPointerParameter])
531         return SK_ConstantPointerParameter;
532 
533       if (NamingStyles[SK_ConstantParameter])
534         return SK_ConstantParameter;
535 
536       if (NamingStyles[SK_Constant])
537         return SK_Constant;
538     }
539 
540     if (Decl->isParameterPack() && NamingStyles[SK_ParameterPack])
541       return SK_ParameterPack;
542 
543     if (!Type.isNull() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_PointerParameter])
544         return SK_PointerParameter;
545 
546     if (NamingStyles[SK_Parameter])
547       return SK_Parameter;
548 
549     return SK_Invalid;
550   }
551 
552   if (const auto *Decl = dyn_cast<VarDecl>(D)) {
553     QualType Type = Decl->getType();
554 
555     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable])
556       return SK_ConstexprVariable;
557 
558     if (!Type.isNull() && Type.isConstQualified()) {
559       if (Decl->isStaticDataMember() && NamingStyles[SK_ClassConstant])
560         return SK_ClassConstant;
561 
562       if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_GlobalConstantPointer])
563         return SK_GlobalConstantPointer;
564 
565       if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalConstant])
566         return SK_GlobalConstant;
567 
568       if (Decl->isStaticLocal() && NamingStyles[SK_StaticConstant])
569         return SK_StaticConstant;
570 
571       if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_LocalConstantPointer])
572         return SK_LocalConstantPointer;
573 
574       if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalConstant])
575         return SK_LocalConstant;
576 
577       if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalConstant])
578         return SK_LocalConstant;
579 
580       if (NamingStyles[SK_Constant])
581         return SK_Constant;
582     }
583 
584     if (Decl->isStaticDataMember() && NamingStyles[SK_ClassMember])
585       return SK_ClassMember;
586 
587     if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_GlobalPointer])
588       return SK_GlobalPointer;
589 
590     if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalVariable])
591       return SK_GlobalVariable;
592 
593     if (Decl->isStaticLocal() && NamingStyles[SK_StaticVariable])
594       return SK_StaticVariable;
595 
596     if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_LocalPointer])
597       return SK_LocalPointer;
598 
599     if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalVariable])
600       return SK_LocalVariable;
601 
602     if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalVariable])
603       return SK_LocalVariable;
604 
605     if (NamingStyles[SK_Variable])
606       return SK_Variable;
607 
608     return SK_Invalid;
609   }
610 
611   if (const auto *Decl = dyn_cast<CXXMethodDecl>(D)) {
612     if (Decl->isMain() || !Decl->isUserProvided() ||
613         Decl->size_overridden_methods() > 0)
614       return SK_Invalid;
615 
616     // If this method has the same name as any base method, this is likely
617     // necessary even if it's not an override. e.g. CRTP.
618     for (const CXXBaseSpecifier &Base : Decl->getParent()->bases())
619       if (const auto *RD = Base.getType()->getAsCXXRecordDecl())
620         if (RD->hasMemberName(Decl->getDeclName()))
621           return SK_Invalid;
622 
623     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprMethod])
624       return SK_ConstexprMethod;
625 
626     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
627       return SK_ConstexprFunction;
628 
629     if (Decl->isStatic() && NamingStyles[SK_ClassMethod])
630       return SK_ClassMethod;
631 
632     if (Decl->isVirtual() && NamingStyles[SK_VirtualMethod])
633       return SK_VirtualMethod;
634 
635     if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMethod])
636       return SK_PrivateMethod;
637 
638     if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMethod])
639       return SK_ProtectedMethod;
640 
641     if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMethod])
642       return SK_PublicMethod;
643 
644     if (NamingStyles[SK_Method])
645       return SK_Method;
646 
647     if (NamingStyles[SK_Function])
648       return SK_Function;
649 
650     return SK_Invalid;
651   }
652 
653   if (const auto *Decl = dyn_cast<FunctionDecl>(D)) {
654     if (Decl->isMain())
655       return SK_Invalid;
656 
657     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
658       return SK_ConstexprFunction;
659 
660     if (Decl->isGlobal() && NamingStyles[SK_GlobalFunction])
661       return SK_GlobalFunction;
662 
663     if (NamingStyles[SK_Function])
664       return SK_Function;
665   }
666 
667   if (isa<TemplateTypeParmDecl>(D)) {
668     if (NamingStyles[SK_TypeTemplateParameter])
669       return SK_TypeTemplateParameter;
670 
671     if (NamingStyles[SK_TemplateParameter])
672       return SK_TemplateParameter;
673 
674     return SK_Invalid;
675   }
676 
677   if (isa<NonTypeTemplateParmDecl>(D)) {
678     if (NamingStyles[SK_ValueTemplateParameter])
679       return SK_ValueTemplateParameter;
680 
681     if (NamingStyles[SK_TemplateParameter])
682       return SK_TemplateParameter;
683 
684     return SK_Invalid;
685   }
686 
687   if (isa<TemplateTemplateParmDecl>(D)) {
688     if (NamingStyles[SK_TemplateTemplateParameter])
689       return SK_TemplateTemplateParameter;
690 
691     if (NamingStyles[SK_TemplateParameter])
692       return SK_TemplateParameter;
693 
694     return SK_Invalid;
695   }
696 
697   return SK_Invalid;
698 }
699 
getFailureInfo(StringRef Name,SourceLocation Location,ArrayRef<llvm::Optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,StyleKind SK,const SourceManager & SM,bool IgnoreFailedSplit)700 static llvm::Optional<RenamerClangTidyCheck::FailureInfo> getFailureInfo(
701     StringRef Name, SourceLocation Location,
702     ArrayRef<llvm::Optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
703     StyleKind SK, const SourceManager &SM, bool IgnoreFailedSplit) {
704   if (SK == SK_Invalid || !NamingStyles[SK])
705     return None;
706 
707   const IdentifierNamingCheck::NamingStyle &Style = *NamingStyles[SK];
708   if (Style.IgnoredRegexp.isValid() && Style.IgnoredRegexp.match(Name))
709     return None;
710 
711   if (matchesStyle(Name, Style))
712     return None;
713 
714   std::string KindName =
715       fixupWithCase(StyleNames[SK], IdentifierNamingCheck::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(Location.print(llvm::dbgs(), SM);
722                  llvm::dbgs()
723                  << llvm::formatv(": unable to split words for {0} '{1}'\n",
724                                   KindName, Name));
725     }
726     return None;
727   }
728   return RenamerClangTidyCheck::FailureInfo{std::move(KindName),
729                                             std::move(Fixup)};
730 }
731 
732 llvm::Optional<RenamerClangTidyCheck::FailureInfo>
GetDeclFailureInfo(const NamedDecl * Decl,const SourceManager & SM) const733 IdentifierNamingCheck::GetDeclFailureInfo(const NamedDecl *Decl,
734                                           const SourceManager &SM) const {
735   SourceLocation Loc = Decl->getLocation();
736   const FileStyle &FileStyle = getStyleForFile(SM.getFilename(Loc));
737   if (!FileStyle.isActive())
738     return llvm::None;
739 
740   return getFailureInfo(Decl->getName(), Loc, FileStyle.getStyles(),
741                         findStyleKind(Decl, FileStyle.getStyles(),
742                                       FileStyle.isIgnoringMainLikeFunction()),
743                         SM, IgnoreFailedSplit);
744 }
745 
746 llvm::Optional<RenamerClangTidyCheck::FailureInfo>
GetMacroFailureInfo(const Token & MacroNameTok,const SourceManager & SM) const747 IdentifierNamingCheck::GetMacroFailureInfo(const Token &MacroNameTok,
748                                            const SourceManager &SM) const {
749   SourceLocation Loc = MacroNameTok.getLocation();
750   const FileStyle &Style = getStyleForFile(SM.getFilename(Loc));
751   if (!Style.isActive())
752     return llvm::None;
753 
754   return getFailureInfo(MacroNameTok.getIdentifierInfo()->getName(), Loc,
755                         Style.getStyles(), SK_MacroDefinition, SM,
756                         IgnoreFailedSplit);
757 }
758 
759 RenamerClangTidyCheck::DiagInfo
GetDiagInfo(const NamingCheckId & ID,const NamingCheckFailure & Failure) const760 IdentifierNamingCheck::GetDiagInfo(const NamingCheckId &ID,
761                                    const NamingCheckFailure &Failure) const {
762   return DiagInfo{"invalid case style for %0 '%1'",
763                   [&](DiagnosticBuilder &Diag) {
764                     Diag << Failure.Info.KindName << ID.second;
765                   }};
766 }
767 
768 const IdentifierNamingCheck::FileStyle &
getStyleForFile(StringRef FileName) const769 IdentifierNamingCheck::getStyleForFile(StringRef FileName) const {
770   if (!GetConfigPerFile)
771     return *MainFileStyle;
772   StringRef Parent = llvm::sys::path::parent_path(FileName);
773   auto Iter = NamingStylesCache.find(Parent);
774   if (Iter != NamingStylesCache.end())
775     return Iter->getValue();
776 
777   ClangTidyOptions Options = Context->getOptionsForFile(FileName);
778   if (Options.Checks && GlobList(*Options.Checks).contains(CheckName)) {
779     auto It = NamingStylesCache.try_emplace(
780         Parent,
781         getFileStyleFromOptions({CheckName, Options.CheckOptions, Context}));
782     assert(It.second);
783     return It.first->getValue();
784   }
785   // Default construction gives an empty style.
786   auto It = NamingStylesCache.try_emplace(Parent);
787   assert(It.second);
788   return It.first->getValue();
789 }
790 
791 } // namespace readability
792 } // namespace tidy
793 } // namespace clang
794