陈江川

邮箱:jiangchuanc@gmail.com

Code Review-OCLint系列开篇

为什么要在团队中加入Code Review的环节?现在公司iOS团队中共8人,每个人的水平不同,导致编程风格各异,代码中出现一些容易犯错的问题。很多问题都可以在Code Review环节中解决,而不是到测试环节才解决。

初衷并没有想做得这么深入,只想简单把代码风格统一,方案是利用git的合并分支请求,然后人工进行对比。但想到“人工”两字,完全不符合程序员的风格。于是搜Objective-C Code Review的工具,看到OCLint这玩意,然后就入坑了。

OCLint

以下内容截取官网:

OCLint is a static code analysis tool for improving quality and reducing defects by inspecting C, C++ and Objective-C code and looking for potential problems.

Relying on the abstract syntax tree of the source code for better accuracy and efficiency.

安装

官方提供了两种方法:1.Homebrew;2.源代码安装

Homebrew安装

1. brew tap oclint/formulae
2. brew install oclint

源代码安装

如果你想自己写rule,那么必须使用源码进行安装:

  1. 在GitHub下载OCLint源码:OCLint

    git clone https://github.com/oclint/oclint.git
    
  2. 进入oclint-scripts目录执行:

    ./make
    

    这里下载和编译的时间可能较长,如果你不想自己编译,我这有份已经编译好的,是写这边文章时OCLint最新的版本:OCLint-0.12已编译好

  3. 编译成功后,会有以下路径:

    oclint/build/oclint-release
    

    这个就是编译好的oclint,我们还需要把这个路径添加到系统的PATH中, 在.bash_profile中添加:

    OCLINT_HOME=/path/to/oclint-release
    export PATH=$OCLINT_HOME/bin:$PATH
    
  4. 进入oclint/build/oclint-release目录,执行:

    cp bin/oclint* /usr/local/bin/
    ln -s /path/to/oclint-release/lib/oclint /usr/local/lib
    ln -s /path/to/oclint-release/lib/clang /usr/local/lib
    

    官方文档里是执行下面两条命令(不建议):

    cp bin/oclint* /usr/local/bin/
    cp -rp lib/* /usr/local/lib/
    

    这里我使用ln -s,把lib中的clang和oclint软链接到/usr/local/lib中,是为了后面自己编写rule能快速的更新/usr/local/lib中对应的oclint库,而不需要每次更新自定义rule库,又要手动copy到/usr/local/lib。

    注意,文中涉及到的/path/to/oclint-release路径是你电脑的oclint-release目录的绝对路径!

  5. 重启启动终端,然后输入:

    oclint --version
    

    出现以下打印信息说明安装成功:

自定义Rule

OCLint提供了70+的检查规则,但是如果这些还不能满足?那么就需要我们自定义Rule。

  1. 进入oclint目录,执行:

    oclint-scripts/scaffoldRule HoriObjectiveC -t ASTVisitor
    

    其中“HoriObjectiveC”是你定义的检查规则名字;“ASTVisitor”是你继承的Rule。

    这里可以继承如下规则:SourceCodeReader、ASTVisitor、ASTMatcher,具体的含义我还没有研究。

  2. 执行完上述命令后,分别在以下路径生成对应的文件:

    oclint-rules/rules/custom
    oclint-rules/test/custom
    
  3. 为了方便开发,可以生成xcodeproj文件,回到oclint目录,执行以下命令:

    • mkdir oclint-xcoderules
    • cd oclint-xcoderules
    • touch create-xcode-rules.sh
    • chmod 777 create-xcode-rules.sh

    打开create-xcode-rules.sh并添加以下内容

    #! /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
    
  4. 执行:./create-xcode-rules.sh

    出现下面log说明生成xcodeproj成功

    并且在oclint-xcoderules目录下生成了以下文件:

  5. 打开OCLINT_RULES.xcodeproj,会发现Sources目录下面有很多文件夹,自定义的Rule一般都是在最下面:

    在Scheme中选择对应的schme:

  6. 我们修改并build自定义的Rule后,会生成对应的:libHoriObjectiveCRule.dylib,要立即使用新生成的Rule,就要把新生成的Rule.dylib文件复制到:/path/to/oclint-release/lib/oclint/rules

    因为我们在“源代码安装 -> 第4步骤”中使用了软链接的方式,所以这里不再需要手动更新/usr/local/lib/路径中对应的oclint库。

    但是每次build自定义的Rule,又要手动的copy到/path/to/oclint-release/lib/oclint/rules目录,也是麻烦。所以为了把这步也省掉,在自定义Rule的Target中添加如下命令:

    cp /path/to/oclint/oclint-xcoderules/rules.dl/Debug/libHoriObjectiveCRule.dylib /path/to/oclint-release/lib/oclint/rules/libHoriObjectiveCRule.dylib
    

oclint-xcoderules文件夹的工程:oclint-xcoderules

使用OCLint

  1. 创建一个"Command Line Tool"项目:AST-Test;
  2. 添加一个Target:OCLint;
  3. 选择“Build Phases”,点“+”,选择“New Run Script Phase”;
  4. 添加如下代码:

    source ~/.bash_profile
    cd ${SRCROOT}
    xcodebuild clean
    xcodebuild | xcpretty -r json-compilation-database
    cp build/reports/compilation_db.json compile_commands.json
    oclint-json-compilation-database -e Pods   -- -rc=LONG_LINE=200 -rc=NCSS_METHOD=100  -report-type xcode
    

  5. Scheme选择OCLint,然后Build,最终出现:

    这两个警告是OCLint给出的

    AST-Test工程:AST-Test

参考文献

关于OCLint自定义规则
OClint学习笔记
静态代码分析之OCLint的那些事儿
OCLint官网

以上就是这两天的研究所得,所有的准备工作已完成,后续需要花费更多的精力去学习AST方面的知识。如有任何疑问发送邮件到:jiangchuanc@gmail.com