可能OCLint官方提供的检测规则不能满足我们的日常需求,OCLint也是支持自定义规则滴。
OCLint环境安装
参考:OCLint 安装使用
OCLint源码下载
OCLint 源码下载
下载下来之后,直接在 oclint-0.15/oclint-scripts
下执行
./make
大概过程是下载LLVM、clang的源代码,编译LLVM、clang与OCLint预计OCLint的默认规则。
需要科学上网执行,即使是科学上网了也会有很大概率的失败。我的同事在家里科学上网失败了N次,好不容易成功一次,耗时小一天的时间。
为了大家快速方便,直接到gitHub下载我编译好的文件即可。大概5.8个G吧。大是大了点,比下不下来强。
https://github.com/yan998/oclint-0.15
开始开发
1、创建开发类
为了方便,OCLint提供了一个叫scaffoldRule
的脚本,它在oclint-scripts
目录下,我们通过他传入要生成的规则名,级别,类型,脚本就会在目录oclint-rules/rules/custom/
自动帮我们生成一个模板代码,并且加入编译路径中。
命名的时候,不用写rule后缀,他自己会给你加上。
# 生成一个名为 JRMethodLint 类型是ASTVisitor的规则模板
oclint-scripts/scaffoldRule JRMethodLint -t ASTVisitor
2、生成Xcode开发项目
2.1、新建oclint-xcoderules
文件夹
2.2、创建生成Xcode项目脚本
为了方便创建,我们新建脚本。
脚本使用cmake创建Xcode项目,cmake一款跨平台的编译工具,使用它构建的工程,既可以生成linux上的makefile,也可以生成Xcode的工程文件
#! /bin/sh -e
cmake -G Xcode -D CMAKE_CXX_COMPILER=../build/llvm-install/bin/clang++ -D CMAKE_C_COMPILER=../build/llvm-install/bin/clang -D OCLINT_BUILD_DIR=../build/oclint-core -D OCLINT_SOURCE_DIR=../oclint-core -D OCLINT_METRICS_SOURCE_DIR=../oclint-metrics -D OCLINT_METRICS_BUILD_DIR=../build/oclint-metrics -D LLVM_ROOT=../build/llvm-install/ ../oclint-rules
2.3、执行脚本生成Xcode项目
2.4、找到为我们创建的类和target
3、开始写代码了
3.1、简介
当前生成的类是一个cpp
文件,当然我们也要用 c++
进行开发。
W3C - C++ 教程 ,简单的看一下,能上手即可
也可以参考官方文档 OCLint 自定义规则文档
映入眼帘的是一堆被注释的方法。这些方法是干啥的呢?
这些以Visit开头的百十个函数都是OCLint提供给开发者的回调函数。
/* Visit ObjCMethodDecl
bool VisitObjCMethodDecl(ObjCMethodDecl *node)
{
return true;
}
*/
/* Visit ObjCContainerDecl
bool VisitObjCContainerDecl(ObjCContainerDecl *node)
{
return true;
}
*/
/* Visit ObjCCategoryDecl
bool VisitObjCCategoryDecl(ObjCCategoryDecl *node)
{
return true;
}
*/
。。。。。。。。
当OCLint分析到相关AST的时候就会调用相关的回调方法。
方法的返回值:
这些visit方法的返回布尔值用于控制遍历。AST访问者将在访问当前节点返回true时继续其子节点或同级节点,反之亦然,当当前visit方法返回false 时它将停止。
举个例子:
分析一个类所有的方法,如果在检测方法的回调方法返回false,那么就只会检测一个方法,不会继续往下检测。
我们来看下相关类的语法树,对应一下
clang -fmodules -fsyntax-only -Xclang -ast-dump student.m
可以看到AST中的节点,在OCLint中的回调方法都是可以找到的。
3.2、上手开发
bool VisitObjCMethodDecl(ObjCMethodDecl *node)
{
//检查名称的每部分,都不允许以大写字母开头
Selector sel = node -> getSelector();
int selectorPartCount = node -> getNumSelectorLocs();
for (int i = 0; i < selectorPartCount; i++) {
// 方法参数名称
StringRef selName = sel.getNameForSlot(i);
if (selName.size() == 0) {
return true;
}
char c = selName[0];
if (isUppercase(c)) {
// 提示
// 获取将要报错的位置
SourceLocation loc = node->getSelectorLoc(i);
addViolation(loc, loc, this, "方法名/方法参数 建议小写开头");
}
if (c == '_') {
// 提示
// 获取将要报错的位置
SourceLocation loc = node->getSelectorLoc(i);
addViolation(loc, loc, this, "方法名/方法参数 不要以下划线开头");
}
}
return true;
}
4、动态调试
代码编写完了,怎么知道好不好使呢?可以不可以打印相关属性或者直接打断点进行调试呢?
4.1、配置 Executable
Edit sheme -->info --> Executable
编译好的 OCLint 的可执行文件
oclint-0.15/build/oclint-release/bin/oclintexe
4.2、配置 Arguments Passed On Launch
选择我们自定义的 ClassNameLintRule,添加启动参数。-R 传入自定义的规则名,这里使用调试工程生成的 Debug 目录。接着传入一个随便写的测试用文档 student.m
,此文档所依赖的 Framework 等环境参数也需要传入。
-R /Users/a58/Desktop/Xcode_Plugin/oclint-0.15/oclint-xcoderules/rules.dl/Debug /Users/a58/Desktop/smallDemo/XcodePlugin/OCLint/OCLintDemo001/OCLintDemo001/student.m -- -x objective-c
-isystem /Users/a58/Desktop/Xcode_Plugin/oclint-0.15/build/oclint-release/lib/clang/9.0.0/include
-iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks
-isystem /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include
run
发现已经发生作用了
4.3、编译成dylib,放到OCLint规则目录下,进行检测,生成报告
我们正常编译我们的JRMethodLintRule,就会生成dylib。不过我们需要修改成release模式进行编译
编译完成之后,将dylib
放到/usr/local/lib/oclint/rules
中
4.4、编译项目的OClint
生成报告一样,也会跑我们自定义的规则
5、遇到的问题
5.1、.h
文件没有有被检测到
查询发现有网友也遇到了相关的问题
OCLint doesn't run rules against header files?
关于作者的回复
不检查头文件的原因是为了消除系统头带来的各种潜在问题。我们目前无法区分特定标头是来自Apple,来自第三方库/框架还是由用户编写。
还说他们是通过这句逻辑进行相关文件过滤的
https://github.com/oclint/oclint/blob/master/oclint-rules/include/oclint/AbstractASTVisitorRule.h#L31
那么我们可以把他的过滤条件给修改下,让他可以检测我们的.h
文件
重新将新生成的dylib
,放到/usr/local/lib/oclint/rules
搞定
5.2、在开发中遇到Expected unqualified-id
错误
刚开始开发项目能正常的运行,不知道操作了啥,就不行了。不管是重新生成Xcode项目还是怎么滴,就是不行了,查了很多的资料,也没有能解决。
然后就想可能是Xcode的某个配置的问题,但是又不好找。Xcode缓存也删了,没啥用。
最终重新下载了Xcode,用新版Xcode 重试好了。
5.3、有些检测规则不想用,怎么删除
可能有以下官方的检测规则,不想使用,这个根据个人的项目来。
5.3.1、首先根据规则的报错信息,找到相关规则的动态库
比如我们想干掉 unused method parameter
这个规则
因为一个方法里面有没有用到的参数,情况还是很多的,比如代理
来到我们的自定义规则开发项目,直接查询该警告的前面语句<他的这个报错内容是拼接起来的>
也就是这个类
UnusedMethodParameterRule
。他最终编译的动态库的名字,应该就是 libUnusedMethodParameterRule
进入
/usr/local/lib/oclint/rules
,删除即可再次检测,就看不到相关警告了