10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
26 AST_MATCHER(VarDecl, isLocalVariable) {
return Node.isLocalVarDecl(); }
28 FixItHint generateFixItHint(
const VarDecl *
Decl,
bool IsConst) {
29 if (IsConst && (
Decl->getStorageClass() != SC_Static)) {
35 char FC =
Decl->getName()[0];
36 if (!llvm::isAlpha(FC) ||
Decl->getName().size() == 1) {
43 char SC =
Decl->getName()[1];
44 if ((FC ==
'k' || FC ==
'g') && !llvm::isAlpha(SC)) {
51 auto NewName = (IsConst ?
"k" :
"g") +
52 llvm::StringRef(std::string(1, FC)).upper() +
53 Decl->getName().substr(1).str();
55 return FixItHint::CreateReplacement(
56 CharSourceRange::getTokenRange(SourceRange(
Decl->getLocation())),
57 llvm::StringRef(NewName));
61 void GlobalVariableDeclarationCheck::registerMatchers(MatchFinder *Finder) {
70 varDecl(hasGlobalStorage(), unless(hasType(isConstQualified())),
71 unless(isLocalVariable()), unless(matchesName(
"::g[A-Z]")))
74 Finder->addMatcher(varDecl(hasGlobalStorage(), hasType(isConstQualified()),
75 unless(isLocalVariable()),
76 unless(matchesName(
"::(k[A-Z])|([A-Z][A-Z0-9])")))
77 .bind(
"global_const"),
81 void GlobalVariableDeclarationCheck::check(
82 const MatchFinder::MatchResult &Result) {
83 if (
const auto *
Decl = Result.Nodes.getNodeAs<VarDecl>(
"global_var")) {
84 if (
Decl->isStaticDataMember())
86 diag(
Decl->getLocation(),
87 "non-const global variable '%0' must have a name which starts with "
89 <<
Decl->getName() << generateFixItHint(
Decl,
false);
91 if (
const auto *
Decl = Result.Nodes.getNodeAs<VarDecl>(
"global_const")) {
92 if (
Decl->isStaticDataMember())
94 diag(
Decl->getLocation(),
95 "const global variable '%0' must have a name which starts with "
96 "an appropriate prefix")
97 <<
Decl->getName() << generateFixItHint(
Decl,
true);