12 #include "../utils/OptionsUtils.h" 13 #include "clang/AST/ASTContext.h" 14 #include "clang/ASTMatchers/ASTMatchFinder.h" 15 #include "clang/Basic/CharInfo.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/Support/Regex.h" 41 constexpr llvm::StringLiteral DefaultSpecialAcronyms[] = {
126 FixItHint generateFixItHint(
const ObjCPropertyDecl *Decl,
NamingStyle Style) {
127 auto Name = Decl->getName();
128 auto NewName = Decl->getName().str();
130 if (Style == CategoryProperty) {
131 Index =
Name.find_first_of(
'_') + 1;
132 NewName.replace(0, Index - 1,
Name.substr(0, Index - 1).lower());
134 if (Index <
Name.size()) {
135 NewName[Index] = tolower(NewName[Index]);
136 if (NewName !=
Name) {
137 return FixItHint::CreateReplacement(
138 CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())),
139 llvm::StringRef(NewName));
145 std::string AcronymsGroupRegex(llvm::ArrayRef<std::string> EscapedAcronyms) {
147 llvm::join(EscapedAcronyms.begin(), EscapedAcronyms.end(),
"s?|") +
151 std::string validPropertyNameRegex(llvm::ArrayRef<std::string> EscapedAcronyms,
152 bool UsedInMatcher) {
161 std::string StartMatcher = UsedInMatcher ?
"::" :
"^";
162 std::string AcronymsMatcher = AcronymsGroupRegex(EscapedAcronyms);
163 return StartMatcher +
"(" + AcronymsMatcher +
"[A-Z]?)?[a-z]+[a-z0-9]*(" +
164 AcronymsMatcher +
"|([A-Z][a-z0-9]+)|A|I)*$";
167 bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
168 auto RegexExp = llvm::Regex(
"^[a-zA-Z]+_[a-zA-Z0-9][a-zA-Z0-9_]+$");
169 return RegexExp.match(PropertyName);
172 bool prefixedPropertyNameValid(llvm::StringRef PropertyName,
173 llvm::ArrayRef<std::string> Acronyms) {
174 size_t Start = PropertyName.find_first_of(
'_');
175 assert(Start != llvm::StringRef::npos && Start + 1 < PropertyName.size());
176 auto Prefix = PropertyName.substr(0, Start);
177 if (Prefix.lower() != Prefix) {
181 llvm::Regex(llvm::StringRef(validPropertyNameRegex(Acronyms,
false)));
182 return RegexExp.match(PropertyName.substr(Start + 1));
186 PropertyDeclarationCheck::PropertyDeclarationCheck(StringRef
Name,
191 IncludeDefaultAcronyms(Options.get(
"IncludeDefaultAcronyms", true)),
199 if (IncludeDefaultAcronyms) {
200 EscapedAcronyms.reserve(llvm::array_lengthof(DefaultSpecialAcronyms) +
201 SpecialAcronyms.size());
203 EscapedAcronyms.insert(EscapedAcronyms.end(),
204 std::begin(DefaultSpecialAcronyms),
205 std::end(DefaultSpecialAcronyms));
207 EscapedAcronyms.reserve(SpecialAcronyms.size());
211 std::transform(SpecialAcronyms.begin(), SpecialAcronyms.end(),
212 std::back_inserter(EscapedAcronyms),
213 [](
const std::string &s) {
return llvm::Regex::escape(s); });
218 unless(matchesName(validPropertyNameRegex(EscapedAcronyms,
true))))
224 const auto *MatchedDecl =
225 Result.Nodes.getNodeAs<ObjCPropertyDecl>(
"property");
226 assert(MatchedDecl->getName().size() > 0);
227 auto *DeclContext = MatchedDecl->getDeclContext();
228 auto *CategoryDecl = llvm::dyn_cast<ObjCCategoryDecl>(DeclContext);
231 llvm::Regex(
"^" + AcronymsGroupRegex(EscapedAcronyms) +
"$");
232 if (AcronymsRegex.match(MatchedDecl->getName())) {
235 if (CategoryDecl !=
nullptr &&
236 hasCategoryPropertyPrefix(MatchedDecl->getName())) {
237 if (!prefixedPropertyNameValid(MatchedDecl->getName(), EscapedAcronyms) ||
238 CategoryDecl->IsClassExtension()) {
239 NamingStyle Style = CategoryDecl->IsClassExtension() ? StandardProperty
241 diag(MatchedDecl->getLocation(),
242 "property name '%0' not using lowerCamelCase style or not prefixed " 243 "in a category, according to the Apple Coding Guidelines")
244 << MatchedDecl->getName() << generateFixItHint(MatchedDecl, Style);
248 diag(MatchedDecl->getLocation(),
249 "property name '%0' not using lowerCamelCase style or not prefixed in " 250 "a category, according to the Apple Coding Guidelines")
251 << MatchedDecl->getName()
252 << generateFixItHint(MatchedDecl, StandardProperty);
258 Options.
store(Opts,
"IncludeDefaultAcronyms", IncludeDefaultAcronyms);
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
void storeOptions(ClangTidyOptions::OptionMap &Options) override
Should store all options supported by this check with their current values or default values for opti...
std::string serializeStringList(ArrayRef< std::string > Strings)
Serialize a sequence of names that can be parsed by parseStringList.
LangOptions getLangOpts() const
Returns the language options from the context.
Base class for all clang-tidy checks.
std::vector< std::string > parseStringList(StringRef Option)
Parse a semicolon separated list of strings.
std::map< std::string, std::string > OptionMap
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
static std::string join(ArrayRef< SpecialMemberFunctionsCheck::SpecialMemberFunctionKind > SMFS, llvm::StringRef AndOr)
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.