forked from OSchip/llvm-project
116 lines
3.6 KiB
C++
116 lines
3.6 KiB
C++
//===--- PropertyDeclarationCheck.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 "PropertyDeclarationCheck.h"
|
|
#include "../utils/OptionsUtils.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/Support/Regex.h"
|
|
#include <algorithm>
|
|
|
|
using namespace clang::ast_matchers;
|
|
|
|
namespace clang {
|
|
namespace tidy {
|
|
namespace objc {
|
|
|
|
namespace {
|
|
/// The acronyms are from
|
|
/// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html#//apple_ref/doc/uid/20001285-BCIHCGAE
|
|
constexpr char DefaultSpecialAcronyms[] =
|
|
"ASCII;"
|
|
"PDF;"
|
|
"XML;"
|
|
"HTML;"
|
|
"URL;"
|
|
"RTF;"
|
|
"HTTP;"
|
|
"TIFF;"
|
|
"JPG;"
|
|
"PNG;"
|
|
"GIF;"
|
|
"LZW;"
|
|
"ROM;"
|
|
"RGB;"
|
|
"CMYK;"
|
|
"MIDI;"
|
|
"FTP";
|
|
|
|
/// For now we will only fix 'CamelCase' property to
|
|
/// 'camelCase'. For other cases the users need to
|
|
/// come up with a proper name by their own.
|
|
/// FIXME: provide fix for snake_case to snakeCase
|
|
FixItHint generateFixItHint(const ObjCPropertyDecl *Decl) {
|
|
if (isupper(Decl->getName()[0])) {
|
|
auto NewName = Decl->getName().str();
|
|
NewName[0] = tolower(NewName[0]);
|
|
return FixItHint::CreateReplacement(
|
|
CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())),
|
|
llvm::StringRef(NewName));
|
|
}
|
|
return FixItHint();
|
|
}
|
|
|
|
std::string validPropertyNameRegex(const std::vector<std::string> &Prefixes) {
|
|
std::vector<std::string> EscapedPrefixes;
|
|
EscapedPrefixes.reserve(Prefixes.size());
|
|
// In case someone defines a custom prefix which includes a regex
|
|
// special character, escape all the prefixes.
|
|
std::transform(Prefixes.begin(), Prefixes.end(),
|
|
std::back_inserter(EscapedPrefixes), [](const std::string& s) {
|
|
return llvm::Regex::escape(s); });
|
|
// Allow any of these names:
|
|
// foo
|
|
// fooBar
|
|
// url
|
|
// urlString
|
|
// URL
|
|
// URLString
|
|
return std::string("::((") +
|
|
llvm::join(EscapedPrefixes.begin(), EscapedPrefixes.end(), "|") +
|
|
")[A-Z]?)?[a-z]+[a-z0-9]*([A-Z][a-z0-9]+)*$";
|
|
}
|
|
} // namespace
|
|
|
|
PropertyDeclarationCheck::PropertyDeclarationCheck(StringRef Name,
|
|
ClangTidyContext *Context)
|
|
: ClangTidyCheck(Name, Context),
|
|
SpecialAcronyms(utils::options::parseStringList(
|
|
Options.get("Acronyms", DefaultSpecialAcronyms))) {}
|
|
|
|
void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
|
|
Finder->addMatcher(
|
|
objcPropertyDecl(
|
|
// the property name should be in Lower Camel Case like
|
|
// 'lowerCamelCase'
|
|
unless(matchesName(validPropertyNameRegex(SpecialAcronyms))))
|
|
.bind("property"),
|
|
this);
|
|
}
|
|
|
|
void PropertyDeclarationCheck::check(const MatchFinder::MatchResult &Result) {
|
|
const auto *MatchedDecl =
|
|
Result.Nodes.getNodeAs<ObjCPropertyDecl>("property");
|
|
assert(MatchedDecl->getName().size() > 0);
|
|
diag(MatchedDecl->getLocation(),
|
|
"property name '%0' should use lowerCamelCase style, according to "
|
|
"the Apple Coding Guidelines")
|
|
<< MatchedDecl->getName() << generateFixItHint(MatchedDecl);
|
|
}
|
|
|
|
void PropertyDeclarationCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
|
|
Options.store(Opts, "Acronyms",
|
|
utils::options::serializeStringList(SpecialAcronyms));
|
|
}
|
|
|
|
} // namespace objc
|
|
} // namespace tidy
|
|
} // namespace clang
|