10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "llvm/Support/Regex.h"
23 std::string validFunctionNameRegex(
bool RequirePrefix) {
42 std::string FunctionNameMatcher =
43 std::string(RequirePrefix ?
"[A-Z][A-Z0-9]+" :
"") +
"[A-Z][a-zA-Z0-9]*";
44 return std::string(
"::(") + FunctionNameMatcher +
")$";
50 FixItHint generateFixItHint(
const FunctionDecl *
Decl) {
54 if (
Decl->getStorageClass() != SC_Static)
58 std::string NewName =
Decl->getName().str();
61 bool AtWordBoundary =
true;
62 while (
Index < NewName.size()) {
63 char ch = NewName[
Index];
68 AtWordBoundary =
false;
75 NewName.erase(
Index, 1);
76 AtWordBoundary =
true;
82 return FixItHint::CreateReplacement(
83 CharSourceRange::getTokenRange(SourceRange(
Decl->getLocation())),
84 llvm::StringRef(NewName));
91 void FunctionNamingCheck::registerMatchers(MatchFinder *Finder) {
100 unless(anyOf(isExpansionInSystemHeader(), cxxMethodDecl(),
101 hasAncestor(namespaceDecl()), isMain(), isImplicit(),
102 matchesName(validFunctionNameRegex(
true)),
103 allOf(isStaticStorageClass(),
104 matchesName(validFunctionNameRegex(
false))))))
109 void FunctionNamingCheck::check(
const MatchFinder::MatchResult &Result) {
110 const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>(
"function");
112 bool IsGlobal = MatchedDecl->getStorageClass() != SC_Static;
113 diag(MatchedDecl->getLocation(),
114 "%select{static function|function in global namespace}1 named %0 must "
115 "%select{be in|have an appropriate prefix followed by}1 Pascal case as "
116 "required by Google Objective-C style guide")
117 << MatchedDecl << IsGlobal << generateFixItHint(MatchedDecl);