一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
判断属性的类型
实现isShouldUseCopy
函数,传入属性类型,判断当前类型是否为必须使用copy
修饰的类型
class HKMatchHandler:public MatchFinder::MatchCallback{
private:
CompilerInstance &CI;
bool isUserSourceCode(const string fileName){
if(fileName.empty()){
return false;
}
if(fileName.find("/Applications/Xcode.app/")==0){
return false;
}
return true;
}
bool isShouldUseCopy(const string typeStr){
if(typeStr.find("NSString") != string::npos ||
typeStr.find("NSArray") != string::npos ||
typeStr.find("NSDictionary") != string::npos){
return true;
}
return false;
}
public:
HKMatchHandler(CompilerInstance &CI):CI(CI){
}
void run(const MatchFinder::MatchResult &Result) {
const ObjCPropertyDecl *propertyDecl = Result.Nodes.getNodeAs<ObjCPropertyDecl>("objcPropertyDecl");
string fileName = CI.getSourceManager().getFilename(propertyDecl->getSourceRange().getBegin()).str();
if(propertyDecl && isUserSourceCode(fileName)){
string typeStr = propertyDecl->getType().getAsString();
if(isShouldUseCopy(typeStr)){
cout<<"------拿到了:"<<typeStr<<endl;
}
}
}
};
在ViewController.m
中,增加其他类型的属性声明
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic, strong) NSString* name;
@property(nonatomic, strong) NSArray* arrs;
@property(nonatomic, strong) id objc;
@property(nonatomic, strong) NSSet *sets;
@property(nonatomic, strong) NSDictionary * dict;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
@end
测试插件
文件解析完成...
------拿到了:NSString *
------拿到了:NSArray *
------拿到了:NSDictionary *
- 成功过滤其他类型的属性
判断属性的修饰符
通过propertyDecl->getPropertyAttributes()
获取属性修饰符,和OBJC_PR_copy
进行位与运算
void run(const MatchFinder::MatchResult &Result) {
const ObjCPropertyDecl *propertyDecl = Result.Nodes.getNodeAs<ObjCPropertyDecl>("objcPropertyDecl");
string fileName = CI.getSourceManager().getFilename(propertyDecl->getSourceRange().getBegin()).str();
if(propertyDecl && isUserSourceCode(fileName)){
string typeStr = propertyDecl->getType().getAsString();
ObjCPropertyDecl::PropertyAttributeKind attr = propertyDecl->getPropertyAttributes();
if(isShouldUseCopy(typeStr) && !(attr & ObjCPropertyDecl::OBJC_PR_copy)){
cout<<"------请使用copy修饰:"<<typeStr<<endl;
}
}
}
测试插件:
文件解析完成...
------请使用copy修饰:NSString *
------请使用copy修饰:NSArray *
------请使用copy修饰:NSDictionary *
提示警告信息
当判断目标类型使用非copy
修饰,目前只是内容打印,正确的做法在Xcode
中提示警告信息
使用编译器实例对象CI
提示警告信息
void run(const MatchFinder::MatchResult &Result) {
const ObjCPropertyDecl *propertyDecl = Result.Nodes.getNodeAs<ObjCPropertyDecl>("objcPropertyDecl");
string fileName = CI.getSourceManager().getFilename(propertyDecl->getSourceRange().getBegin()).str();
if(propertyDecl && isUserSourceCode(fileName)){
string typeStr = propertyDecl->getType().getAsString();
ObjCPropertyDecl::PropertyAttributeKind attr = propertyDecl->getPropertyAttributes();
if(isShouldUseCopy(typeStr) && !(attr & ObjCPropertyDecl::OBJC_PR_copy)){
DiagnosticsEngine &diag = CI.getDiagnostics();
diag.Report(propertyDecl->getLocation(), diag.getCustomDiagID(DiagnosticsEngine::Warning, "请使用copy修饰"));
}
}
}
CI
的getDiagnostics
函数,获取诊断引擎,需要传入位置和DiagID
- 通过节点获取位置,使用
propertyDecl->getLocation()
获得当前节点的位置 - 通过
diag.getCustomDiagID
获取DiagID
,设置提示级别和文案 测试插件
文件解析完成...
ViewController.m:12:40: warning: 请使用copy修饰
@property(nonatomic, strong) NSString* name;
^
ViewController.m:13:39: warning: 请使用copy修饰
@property(nonatomic, strong) NSArray* arrs;
^
ViewController.m:16:45: warning: 请使用copy修饰
@property(nonatomic, strong) NSDictionary * dict;
^
3 warnings generated.
Xcode
集成插件
打开测试项目,在Xcode
中注册插件,来到Build Settings
→Other C Flags
//-Xclang -load -Xclang (.dylib)插件路径 -Xclang -add-plugin -Xclang 插件名称
-Xclang -load -Xclang /Volumes/study/Source/llvm-hk/build_xcode/Debug/lib/HKPlugin.dylib -Xclang -add-plugin -Xclang HKPlugin
在Xcode
中替换Clang
,来到Build Settings
中新增两项用户自定义设置
分别添加CC
和CXX
CC
对应自己编译的Clang
绝对路径CXX
对应自己编译的Clang++
绝对路径
/Volumes/study/Source/llvm-hk/build_xcode/Debug/bin/clang
/Volumes/study/Source/llvm-hk/build_xcode/Debug/bin/clang++
在Build Settings
中,将Enable Index-Wihle-Building Functionality
设置为NO
测试插件