diff options
Diffstat (limited to 'clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp')
| -rw-r--r-- | clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp b/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp new file mode 100644 index 00000000000..a278be14958 --- /dev/null +++ b/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp @@ -0,0 +1,90 @@ +//===--- GlobalVariableDeclarationCheck.cpp - clang-tidy-------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "GlobalVariableDeclarationCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" + +#include <string> + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace google { +namespace objc { + +namespace { + +FixItHint generateFixItHint(const VarDecl *Decl, bool IsConst) { + char FC = Decl->getName()[0]; + if (!llvm::isAlpha(FC) || Decl->getName().size() == 1) { + // No fix available if first character is not alphabetical character, or it + // is a single-character variable, since it is difficult to determine the + // proper fix in this case. Users should create a proper variable name by + // their own. + return FixItHint(); + } + char SC = Decl->getName()[1]; + if ((FC == 'k' || FC == 'g') && !llvm::isAlpha(SC)) { + // No fix available if the prefix is correct but the second character is not + // alphabetical, since it is difficult to determine the proper fix in this + // case. + return FixItHint(); + } + auto NewName = (IsConst ? "k" : "g") + + llvm::StringRef(std::string(1, FC)).upper() + + Decl->getName().substr(1).str(); + return FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())), + llvm::StringRef(NewName)); +} +} // namespace + +void GlobalVariableDeclarationCheck::registerMatchers(MatchFinder *Finder) { + // The relevant Style Guide rule only applies to Objective-C. + if (!getLangOpts().ObjC1 && !getLangOpts().ObjC2) { + return; + } + // need to add two matchers since we need to bind different ids to distinguish + // constants and variables. Since bind() can only be called on node matchers, + // we cannot make it in one matcher. + Finder->addMatcher( + varDecl(hasGlobalStorage(), unless(hasType(isConstQualified())), + unless(matchesName("::g[A-Z]"))) + .bind("global_var"), + this); + Finder->addMatcher(varDecl(hasGlobalStorage(), hasType(isConstQualified()), + unless(matchesName("::k[A-Z]"))) + .bind("global_const"), + this); +} + +void GlobalVariableDeclarationCheck::check( + const MatchFinder::MatchResult &Result) { + if (const auto *Decl = Result.Nodes.getNodeAs<VarDecl>("global_var")) { + diag(Decl->getLocation(), + "non-const global variable '%0' must have a name which starts with " + "'g[A-Z]'") + << Decl->getName() << generateFixItHint(Decl, false); + } + if (const auto *Decl = Result.Nodes.getNodeAs<VarDecl>("global_const")) { + diag(Decl->getLocation(), + "const global variable '%0' must have a name which starts with " + "'k[A-Z]'") + << Decl->getName() << generateFixItHint(Decl, true); + } +} + +} // namespace objc +} // namespace google +} // namespace tidy +} // namespace clang |

