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"
25 SourceLocation ReceiverLocation = Expr->getReceiverRange().getBegin();
26 if (ReceiverLocation.isMacroID())
29 SourceLocation SelectorLocation = Expr->getSelectorStartLoc();
30 if (SelectorLocation.isMacroID())
39 while (ClassDecl !=
nullptr) {
40 for (
const auto *MethodDecl : ClassDecl->instance_methods()) {
41 if (MethodDecl->getSelector().getAsString() ==
"init")
42 return !MethodDecl->isUnavailable();
44 ClassDecl = ClassDecl->getSuperClass();
59 const SourceManager &SM,
60 const LangOptions &LangOpts) {
61 CharSourceRange CharRange = Lexer::makeFileCharRange(
62 CharSourceRange::getTokenRange(ReceiverRange), SM, LangOpts);
63 return Lexer::getSourceText(CharRange, SM, LangOpts);
67 const SourceManager &SM,
68 const LangOptions &LangOpts) {
74 std::map<StringRef, StringRef> ClassToFactoryMethodMap = {{
"NSDate",
"date"},
76 auto FoundClassFactory = ClassToFactoryMethodMap.find(Receiver);
77 if (FoundClassFactory != ClassToFactoryMethodMap.end()) {
78 StringRef ClassName = FoundClassFactory->first;
79 StringRef FactorySelector = FoundClassFactory->second;
81 std::string(llvm::formatv(
"[{0} {1}]", ClassName, FactorySelector));
82 return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall);
87 std::string(llvm::formatv(
"[[{0} alloc] init]", Receiver));
88 return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall);
97 objcMessageExpr(isClassMessage(), hasSelector(
"new")).bind(
"new_call"),
100 objcMethodDecl(isClassMethod(), isDefinition(), hasName(
"new"))
101 .bind(
"new_override"),
106 if (
const auto *CallExpr =
107 Result.Nodes.getNodeAs<ObjCMessageExpr>(
"new_call")) {
112 diag(CallExpr->getExprLoc(),
"do not create objects with +new")
114 Result.Context->getLangOpts());
117 if (
const auto *DeclExpr =
118 Result.Nodes.getNodeAs<ObjCMethodDecl>(
"new_override")) {
119 diag(DeclExpr->getBeginLoc(),
"classes should not override +new");
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
static bool isMessageExpressionInsideMacro(const ObjCMessageExpr *Expr)
static FixItHint getCallFixItHint(const ObjCMessageExpr *Expr, const SourceManager &SM, const LangOptions &LangOpts)
static StringRef getReceiverString(SourceRange ReceiverRange, const SourceManager &SM, const LangOptions &LangOpts)
static bool isInitMethodAvailable(const ObjCInterfaceDecl *ClassDecl)