11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 #include "llvm/ADT/StringExtras.h" 14 #include "llvm/ADT/StringRef.h" 27 FixItHint generateFixItHint(
const VarDecl *Decl,
bool IsConst) {
28 char FC = Decl->getName()[0];
29 if (!llvm::isAlpha(FC) || Decl->getName().size() == 1) {
36 char SC = Decl->getName()[1];
37 if ((FC ==
'k' || FC ==
'g') && !llvm::isAlpha(SC)) {
43 auto NewName = (IsConst ?
"k" :
"g") +
44 llvm::StringRef(std::string(1, FC)).upper() +
45 Decl->getName().substr(1).str();
46 return FixItHint::CreateReplacement(
47 CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())),
48 llvm::StringRef(NewName));
52 void GlobalVariableDeclarationCheck::registerMatchers(MatchFinder *Finder) {
54 if (!getLangOpts().ObjC1 && !getLangOpts().ObjC2) {
61 varDecl(hasGlobalStorage(), unless(hasType(isConstQualified())),
62 unless(matchesName(
"::g[A-Z]")))
65 Finder->addMatcher(varDecl(hasGlobalStorage(), hasType(isConstQualified()),
66 unless(matchesName(
"::k[A-Z]")))
67 .bind(
"global_const"),
71 void GlobalVariableDeclarationCheck::check(
72 const MatchFinder::MatchResult &Result) {
73 if (
const auto *Decl = Result.Nodes.getNodeAs<VarDecl>(
"global_var")) {
74 diag(Decl->getLocation(),
75 "non-const global variable '%0' must have a name which starts with " 77 << Decl->getName() << generateFixItHint(Decl,
false);
79 if (
const auto *Decl = Result.Nodes.getNodeAs<VarDecl>(
"global_const")) {
80 diag(Decl->getLocation(),
81 "const global variable '%0' must have a name which starts with " 83 << Decl->getName() << generateFixItHint(Decl,
true);