11 #include "../utils/OptionsUtils.h" 12 #include "clang/AST/ASTContext.h" 13 #include "clang/ASTMatchers/ASTMatchFinder.h" 14 #include "clang/Basic/CharInfo.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/Support/Regex.h" 41 FixItHint generateFixItHint(
const ObjCPropertyDecl *
Decl,
NamingStyle Style) {
42 auto Name = Decl->getName();
43 auto NewName = Decl->getName().str();
45 if (Style == CategoryProperty) {
46 Index =
Name.find_first_of(
'_') + 1;
47 NewName.replace(0, Index - 1,
Name.substr(0, Index - 1).lower());
49 if (Index <
Name.size()) {
50 NewName[
Index] = tolower(NewName[Index]);
51 if (NewName !=
Name) {
52 return FixItHint::CreateReplacement(
54 llvm::StringRef(NewName));
60 std::string validPropertyNameRegex(
bool UsedInMatcher) {
78 std::string StartMatcher = UsedInMatcher ?
"::" :
"^";
79 return StartMatcher +
"([a-z]|[A-Z][A-Z0-9])[a-z0-9A-Z]*$";
82 bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
84 llvm::Regex(
"^[a-zA-Z][a-zA-Z0-9]*_[a-zA-Z0-9][a-zA-Z0-9_]+$");
85 return RegexExp.match(PropertyName);
88 bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
89 size_t Start = PropertyName.find_first_of(
'_');
90 assert(Start != llvm::StringRef::npos && Start + 1 < PropertyName.size());
91 auto Prefix = PropertyName.substr(0, Start);
92 if (Prefix.lower() != Prefix) {
95 auto RegexExp = llvm::Regex(llvm::StringRef(validPropertyNameRegex(
false)));
96 return RegexExp.match(PropertyName.substr(Start + 1));
100 void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
102 if (!getLangOpts().ObjC)
return;
104 Finder->addMatcher(objcPropertyDecl(
107 unless(matchesName(validPropertyNameRegex(
true))))
112 void PropertyDeclarationCheck::check(
const MatchFinder::MatchResult &Result) {
113 const auto *MatchedDecl =
114 Result.Nodes.getNodeAs<ObjCPropertyDecl>(
"property");
115 assert(MatchedDecl->getName().size() > 0);
116 auto *DeclContext = MatchedDecl->getDeclContext();
117 auto *CategoryDecl = llvm::dyn_cast<ObjCCategoryDecl>(DeclContext);
119 if (CategoryDecl !=
nullptr &&
120 hasCategoryPropertyPrefix(MatchedDecl->getName())) {
121 if (!prefixedPropertyNameValid(MatchedDecl->getName()) ||
122 CategoryDecl->IsClassExtension()) {
123 NamingStyle Style = CategoryDecl->IsClassExtension() ? StandardProperty
125 diag(MatchedDecl->getLocation(),
126 "property name '%0' not using lowerCamelCase style or not prefixed " 127 "in a category, according to the Apple Coding Guidelines")
128 << MatchedDecl->getName() << generateFixItHint(MatchedDecl, Style);
132 diag(MatchedDecl->getLocation(),
133 "property name '%0' not using lowerCamelCase style or not prefixed in " 134 "a category, according to the Apple Coding Guidelines")
135 << MatchedDecl->getName()
136 << generateFixItHint(MatchedDecl, StandardProperty);
const FunctionDecl * Decl
static constexpr llvm::StringLiteral Name
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
const SymbolIndex * Index