iOS之LLVM 八

117 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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修饰"));
        }
    }
}
  • CIgetDiagnostics函数,获取诊断引擎,需要传入位置和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 SettingsOther C Flags

image-24.png

//-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中新增两项用户自定义设置

image-25.png 分别添加CCCXX

image-26.png

  • 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

image-27.png 测试插件

image-28.png