10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Basic/LangOptions.h"
13 #include "clang/Basic/SourceLocation.h"
14 #include "clang/Basic/SourceManager.h"
15 #include "clang/Lex/Lexer.h"
16 #include "llvm/Support/FormatVariadic.h"
28 SourceLocation ReceiverLocation = Expr->getReceiverRange().getBegin();
29 if (ReceiverLocation.isMacroID())
32 SourceLocation SelectorLocation = Expr->getSelectorStartLoc();
33 if (SelectorLocation.isMacroID())
42 while (ClassDecl !=
nullptr) {
43 for (
const auto *MethodDecl : ClassDecl->instance_methods()) {
44 if (MethodDecl->getSelector().getAsString() ==
"init")
45 return !MethodDecl->isUnavailable();
47 ClassDecl = ClassDecl->getSuperClass();
62 const SourceManager &SM,
63 const LangOptions &LangOpts) {
64 CharSourceRange CharRange = Lexer::makeFileCharRange(
65 CharSourceRange::getTokenRange(ReceiverRange), SM, LangOpts);
66 return Lexer::getSourceText(CharRange, SM, LangOpts);
70 const SourceManager &SM,
71 const LangOptions &LangOpts) {
77 std::map<StringRef, StringRef> ClassToFactoryMethodMap = {{
"NSDate",
"date"},
79 auto FoundClassFactory = ClassToFactoryMethodMap.find(Receiver);
80 if (FoundClassFactory != ClassToFactoryMethodMap.end()) {
81 StringRef ClassName = FoundClassFactory->first;
82 StringRef FactorySelector = FoundClassFactory->second;
84 std::string(llvm::formatv(
"[{0} {1}]", ClassName, FactorySelector));
85 return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall);
90 std::string(llvm::formatv(
"[[{0} alloc] init]", Receiver));
91 return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall);
97 void AvoidNSObjectNewCheck::registerMatchers(MatchFinder *Finder) {
100 objcMessageExpr(isClassMessage(), hasSelector(
"new")).bind(
"new_call"),
103 objcMethodDecl(isClassMethod(), isDefinition(), hasName(
"new"))
104 .bind(
"new_override"),
108 void AvoidNSObjectNewCheck::check(
const MatchFinder::MatchResult &Result) {
109 if (
const auto *CallExpr =
110 Result.Nodes.getNodeAs<ObjCMessageExpr>(
"new_call")) {
115 diag(CallExpr->getExprLoc(),
"do not create objects with +new")
117 Result.Context->getLangOpts());
120 if (
const auto *DeclExpr =
121 Result.Nodes.getNodeAs<ObjCMethodDecl>(
"new_override")) {
122 diag(DeclExpr->getBeginLoc(),
"classes should not override +new");