xref: /llvm-project/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp (revision ec5f4be4521c3b28d6bb14f34f39a87c36fe8c00)
15529a244SHaojian Wu //===--- GlobalVariableDeclarationCheck.cpp - clang-tidy-------------------===//
25529a244SHaojian Wu //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65529a244SHaojian Wu //
75529a244SHaojian Wu //===----------------------------------------------------------------------===//
85529a244SHaojian Wu 
95529a244SHaojian Wu #include "GlobalVariableDeclarationCheck.h"
105529a244SHaojian Wu #include "clang/AST/ASTContext.h"
115529a244SHaojian Wu #include "clang/ASTMatchers/ASTMatchFinder.h"
125529a244SHaojian Wu #include "llvm/ADT/StringExtras.h"
135529a244SHaojian Wu #include "llvm/ADT/StringRef.h"
145529a244SHaojian Wu 
155529a244SHaojian Wu #include <string>
165529a244SHaojian Wu 
175529a244SHaojian Wu using namespace clang::ast_matchers;
185529a244SHaojian Wu 
197d2ea6c4SCarlos Galvez namespace clang::tidy::google::objc {
205529a244SHaojian Wu 
215529a244SHaojian Wu namespace {
225529a244SHaojian Wu 
AST_MATCHER(VarDecl,isLocalVariable)23ec1982f0SStephane Moore AST_MATCHER(VarDecl, isLocalVariable) { return Node.isLocalVarDecl(); }
2412e3726fSStephane Moore 
generateFixItHint(const VarDecl * Decl,bool IsConst)259ac757bfSStephane Moore FixItHint generateFixItHint(const VarDecl *Decl, bool IsConst) {
262fd11e0bSThorsten Schütt   if (IsConst && (Decl->getStorageClass() != SC_Static)) {
27ec1982f0SStephane Moore     // No fix available if it is not a static constant, since it is difficult
28ec1982f0SStephane Moore     // to determine the proper fix in this case.
29*ec5f4be4SPiotr Zegar     return {};
30ec1982f0SStephane Moore   }
31ec1982f0SStephane Moore 
325529a244SHaojian Wu   char FC = Decl->getName()[0];
335529a244SHaojian Wu   if (!llvm::isAlpha(FC) || Decl->getName().size() == 1) {
345529a244SHaojian Wu     // No fix available if first character is not alphabetical character, or it
355529a244SHaojian Wu     // is a single-character variable, since it is difficult to determine the
365529a244SHaojian Wu     // proper fix in this case. Users should create a proper variable name by
375529a244SHaojian Wu     // their own.
38*ec5f4be4SPiotr Zegar     return {};
395529a244SHaojian Wu   }
405529a244SHaojian Wu   char SC = Decl->getName()[1];
415529a244SHaojian Wu   if ((FC == 'k' || FC == 'g') && !llvm::isAlpha(SC)) {
42ec1982f0SStephane Moore     // No fix available if the prefix is correct but the second character is
43ec1982f0SStephane Moore     // not alphabetical, since it is difficult to determine the proper fix in
44ec1982f0SStephane Moore     // this case.
45*ec5f4be4SPiotr Zegar     return {};
465529a244SHaojian Wu   }
47ec1982f0SStephane Moore 
485529a244SHaojian Wu   auto NewName = (IsConst ? "k" : "g") +
495529a244SHaojian Wu                  llvm::StringRef(std::string(1, FC)).upper() +
505529a244SHaojian Wu                  Decl->getName().substr(1).str();
51ec1982f0SStephane Moore 
525529a244SHaojian Wu   return FixItHint::CreateReplacement(
535529a244SHaojian Wu       CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())),
545529a244SHaojian Wu       llvm::StringRef(NewName));
555529a244SHaojian Wu }
565529a244SHaojian Wu }  // namespace
575529a244SHaojian Wu 
registerMatchers(MatchFinder * Finder)585529a244SHaojian Wu void GlobalVariableDeclarationCheck::registerMatchers(MatchFinder *Finder) {
595529a244SHaojian Wu   // need to add two matchers since we need to bind different ids to distinguish
605529a244SHaojian Wu   // constants and variables. Since bind() can only be called on node matchers,
615529a244SHaojian Wu   // we cannot make it in one matcher.
62490811ecSBen Hamilton   //
63490811ecSBen Hamilton   // Note that hasGlobalStorage() matches static variables declared locally
64490811ecSBen Hamilton   // inside a function or method, so we need to exclude those with
65490811ecSBen Hamilton   // isLocalVariable().
665529a244SHaojian Wu   Finder->addMatcher(
675529a244SHaojian Wu       varDecl(hasGlobalStorage(), unless(hasType(isConstQualified())),
68490811ecSBen Hamilton               unless(isLocalVariable()), unless(matchesName("::g[A-Z]")))
695529a244SHaojian Wu           .bind("global_var"),
705529a244SHaojian Wu       this);
715529a244SHaojian Wu   Finder->addMatcher(varDecl(hasGlobalStorage(), hasType(isConstQualified()),
72490811ecSBen Hamilton                              unless(isLocalVariable()),
73ec1982f0SStephane Moore                              unless(matchesName("::(k[A-Z])|([A-Z][A-Z0-9])")))
745529a244SHaojian Wu                          .bind("global_const"),
755529a244SHaojian Wu                      this);
765529a244SHaojian Wu }
775529a244SHaojian Wu 
check(const MatchFinder::MatchResult & Result)785529a244SHaojian Wu void GlobalVariableDeclarationCheck::check(
795529a244SHaojian Wu     const MatchFinder::MatchResult &Result) {
805529a244SHaojian Wu   if (const auto *Decl = Result.Nodes.getNodeAs<VarDecl>("global_var")) {
81787a7734SYan Zhang     if (Decl->isStaticDataMember())
82787a7734SYan Zhang       return;
835529a244SHaojian Wu     diag(Decl->getLocation(),
845529a244SHaojian Wu          "non-const global variable '%0' must have a name which starts with "
855529a244SHaojian Wu          "'g[A-Z]'")
865529a244SHaojian Wu         << Decl->getName() << generateFixItHint(Decl, false);
875529a244SHaojian Wu   }
885529a244SHaojian Wu   if (const auto *Decl = Result.Nodes.getNodeAs<VarDecl>("global_const")) {
89787a7734SYan Zhang     if (Decl->isStaticDataMember())
90787a7734SYan Zhang       return;
915529a244SHaojian Wu     diag(Decl->getLocation(),
925529a244SHaojian Wu          "const global variable '%0' must have a name which starts with "
932d836470SYan Zhang          "an appropriate prefix")
945529a244SHaojian Wu         << Decl->getName() << generateFixItHint(Decl, true);
955529a244SHaojian Wu   }
965529a244SHaojian Wu }
975529a244SHaojian Wu 
987d2ea6c4SCarlos Galvez } // namespace clang::tidy::google::objc
99