性能优化

OCLint 自定义规则

2020-07-03  本文已影响0人  踩坑小分队

可能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
image.png

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项目

image.png
2.4、找到为我们创建的类和target
image.png

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中的回调方法都是可以找到的。


image.png

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


image.png

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
image.png

run

image.png

发现已经发生作用了

4.3、编译成dylib,放到OCLint规则目录下,进行检测,生成报告
我们正常编译我们的JRMethodLintRule,就会生成dylib。不过我们需要修改成release模式进行编译

image.png

编译完成之后,将dylib放到/usr/local/lib/oclint/rules

image.png

4.4、编译项目的OClint

Xcode实现效果.png

生成报告一样,也会跑我们自定义的规则

5、遇到的问题

5.1、.h文件没有有被检测到

image.png

查询发现有网友也遇到了相关的问题
OCLint doesn't run rules against header files?

关于作者的回复

不检查头文件的原因是为了消除系统头带来的各种潜在问题。我们目前无法区分特定标头是来自Apple,来自第三方库/框架还是由用户编写。

还说他们是通过这句逻辑进行相关文件过滤的
https://github.com/oclint/oclint/blob/master/oclint-rules/include/oclint/AbstractASTVisitorRule.h#L31

那么我们可以把他的过滤条件给修改下,让他可以检测我们的.h文件

image.png

重新将新生成的dylib,放到/usr/local/lib/oclint/rules
搞定

image.png

5.2、在开发中遇到Expected unqualified-id错误

image.png
刚开始开发项目能正常的运行,不知道操作了啥,就不行了。不管是重新生成Xcode项目还是怎么滴,就是不行了,查了很多的资料,也没有能解决。
然后就想可能是Xcode的某个配置的问题,但是又不好找。Xcode缓存也删了,没啥用。
最终重新下载了Xcode,用新版Xcode 重试好了。

5.3、有些检测规则不想用,怎么删除
可能有以下官方的检测规则,不想使用,这个根据个人的项目来。
5.3.1、首先根据规则的报错信息,找到相关规则的动态库
比如我们想干掉 unused method parameter这个规则

image.png
因为一个方法里面有没有用到的参数,情况还是很多的,比如代理

来到我们的自定义规则开发项目,直接查询该警告的前面语句<他的这个报错内容是拼接起来的>

image.png
也就是这个类 UnusedMethodParameterRule。他最终编译的动态库的名字,应该就是 libUnusedMethodParameterRule
进入 /usr/local/lib/oclint/rules,删除即可
image.png
再次检测,就看不到相关警告了
上一篇 下一篇

猜你喜欢

热点阅读