底层探索--CodeReview值OCLint

安装

  • 建议使用Homebrew安装:

    //依次执行
    brew tap oclint/formulae //设置第三方仓库
    brew install oclint //安装
    
    //如未安装Homebrew
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    
    //安装和OCLint配合使用的xcpretty
    gem install xcpretty
    

规则

OCLint是根据一系列定制的规则进行静态分析的,
OCLint所有规则

  • 默认情况下,OCLint会使用所有的规则,但我们可以编写脚本配置规则:
    • -disable-rule 规则名命令:不使用该规则
    • -rc 规则名=新值命令:重新设置新的规则值
    • 如何自定义规则:参考文章

命令解释

  • oclint :是 OCLint 工具集最主要的指令,主要作用是规则加载、编译分析选项以及生成分析报告

  • oclint-json-compilation-database: 的作用是在 JSON Compilation Database format 类型的编译文件 compile_commands.json 中提取必要的信息。

  • oclint-xcodebuild:用于将 xcodebuild 生成的 log 文件 xcodebuild.log 转换为 JSON Compilation Database format类型

  • xcodebuild是苹果发布自动构建的工具,可以通过命令行脚本的方式编译、打包Xcode工程。
    可以在终端输入man xcodebuild来查询相关用法

  • 一个常见的分析命令如下:

    oclint-json-compilation-database  -v \
    -e Pods \
    -- -report-type html -o oclint_result.html \
    -rc LONG_LINE=200 \
    -rc=NCSS_METHOD=100 \
    -max-priority-1=100000 \
    -max-priority-2=100000 \
    -max-priority-3=100000; \
    
    解释:
    \:用于表示后面的代码追加在本行,这样避免了一行命令过长的情况
    -e:忽略某个文件、目录
    -report-type:输出类型,支持HTML、XML等类型
    -rc:表示某个规则,可以在后面具体制定
    

OCLint in 控制台

//控制台编译:如果你没有开发者证书,可加-sdk iphonesimulator编译
xcodebuild -workspace 项目名.xcworkspace -scheme 项目名 -sdk iphonesimulator -configuration Debug

//编译,增强可读性
xcodebuild -workspace 项目名.xcworkspace -scheme 项目名 -sdk iphonesimulator -configuration Debug | xcpretty -r json-compilation-database -o compile_commands.json

  • 参数说明:
    • -r--report 输出格式,可以是:Junit、html、json-compilation-database
    • -o--output输出路径
    • -sdk:编译环境

OCLint in Xcode 使用--重点

  • 步骤一:点击项目新增 new target,选择Aggregate作为模板:

    OCLint之新建Target.png

  • 步骤二:为 new target进行命名:

    OCLint之命名Target.png

  • 步骤三:点击build phase,选择Add Run Script

    OCLint之新增runscript.png

  • 步骤四:输入规则如下图和代码:


    OCLint之run Script新增规则.png
    # workspace的名字(需要手动修改)
    WORKSPACE=ProjectApp.xcworkspace
    
    # scheme的名字(需要手动修改)
    SCHEME=ProjectApp
    
    #编译
    xcodebuild -workspace $WORKSPACE -scheme $SCHEME clean&&
    xcodebuild -workspace $WORKSPACE -scheme $SCHEME \
    -configuration Debug \
    COMPILER_INDEX_STORE_ENABLE=NO \
    
    #xcpretty生成compile_commands.json
    #oclint分析并生成指定格式报告(html) -report-type命令指定报告类型
    #-e参数指定需要忽略的文件,即这些文件不用分析
    | xcpretty -r json-compilation-database -o compile_commands.json&&
    oclint-json-compilation-database -e Pods -e Vender -- \
    -report-type xcode \
    
    #设置规则
    -disable-rule ProblematicBaseClassDestructor \
    -disable-rule DestructorOfVirtualClass \
    -disable-rule AssignIvarOutsideAccessors \
    -disable-rule ParameterReassignment \
    -disable-rule ShortVariableName \
    -disable-rule RedundantLocalVariable \
    -disable-rule TooManyFields \
    -disable-rule TooManyMethods \
    -disable-rule UnusedLocalVariable \
    -disable-rule UnusedMethodParameter \
    -disable-rule HighCyclomaticComplexity \
    -disable-rule HighNcssMethod \
    -rc LongClass=1000 \
    -rc LONG_LINE=200 \
    -rc LongMethod=100 \
    -rc TooManyParameters=8 \
    -rc DeepNestedBlock=5 \
    
    -max-priority-1=100000 \
    -max-priority-2=100000 \
    -max-priority-3=100000; \
    rm compile_commands.json
    
    
    or
    
    source ~/.bash_profile
    cd ${SRCROOT}
    xcodebuild clean
    xcodebuild  -workspace demo.xcworkspace -scheme demo | xcpretty -r json-compilation-database --output compile_commands.json
    oclint-json-compilation-database -v \
    -e Pods \
    -e MGLivenessDetection \
    -e MGBaseKit \
    -e MGIDCard \
    oclint_args -- -report-type xcode \
    -disable-rule ObjCAssignIvarOutsideAccessors \
    -disable-rule ShortVariableName \
    -rc=MINIMUM_CASES_IN_SWITCH=3 \
    -rc=CYCLOMATIC_COMPLEXITY=10 \
    -rc=LONG_CLASS=700 \
    -rc=LONG_LINE=200 \
    -rc=NCSS_METHOD=40 \
    -rc=NESTED_BLOCK_DEPTH=5 \
    -rc=TOO_MANY_FIELDS=20 \
    -rc=TOO_MANY_METHODS=30 \
    -rc=TOO_MANY_PARAMETERS=6
    exit
    
    
  • 步骤五:运行,静态分析Command + B

    OCLint之Scheme分析.png

封装成脚本

实例1:

#! /bin/sh
#source ~/.bash_profile
export LC_ALL=en_US.UTF-8
source /etc/profile
if which oclint 2>/dev/null; then
    echo 'oclint exist'
else
    brew tap oclint/formulae
    brew install oclint
fi
if which xcpretty 2>/dev/null; then
    echo 'xcpretty exist'
else
    gem install xcpretty
fi
rm compile_commands.json;
xcodebuild clean
xcodebuild -workspace 自己的项目名.xcworkspace -scheme 自己的项目名Scheme \
-configuration Debug \
| xcpretty -r json-compilation-database -o compile_commands.json
oclint-json-compilation-database  -v \
-e Pods \
-- -report-type html -o oclint_result.html \
-rc LONG_LINE=200 \
-rc=NCSS_METHOD=100 \
-max-priority-1=100000 \
-max-priority-2=100000 \
-max-priority-3=100000; \

实例2:

#!/bin/bash

# 指定编码
export LANG="zh_CN.UTF-8"
export LC_COLLATE="zh_CN.UTF-8"
export LC_CTYPE="zh_CN.UTF-8"
export LC_MESSAGES="zh_CN.UTF-8"
export LC_MONETARY="zh_CN.UTF-8"
export LC_NUMERIC="zh_CN.UTF-8"
export LC_TIME="zh_CN.UTF-8"


function checkDepend () {
command -v xcpretty >/dev/null 2>&1 || {
echo >&2 "I require xcpretty but it's not installed.  Install:gem install xcpretty";
exit
}
command -v oclint-json-compilation-database >/dev/null 2>&1 || {
echo >&2 "I require oclint-json-compilation-database but it's not installed.  Install:brew install oclint";
exit
}
}

function oclintForProject () {

# 检测依赖
checkDepend

projectName=$1
scheme=$2
reportType=$3

REPORT_PMD="pmd"
REPORT_XCODE="Xcode"

myworkspace=${projectName}
myscheme=${scheme}
echo "myworkspace是:${myworkspace}"
echo "myscheme是:${myscheme}"
echo "reportType为:${reportType}"

# 清除上次编译数据
if [ -d ./build/derivedData ]; then
echo '-----清除上次编译数据derivedData-----'
rm -rf ./build/derivedData
fi

# xcodebuild -workspace $myworkspace -scheme $myscheme clean
xcodebuild clean

echo '-----开始编译-----'

# 生成编译数据
xcodebuild -workspace ${myworkspace} -scheme ${myscheme} -UseModernBuildSystem=NO -derivedDataPath ./build/derivedData -configuration Debug COMPILER_INDEX_STORE_ENABLE=NO | xcpretty -r json-compilation-database -o compile_commands.json


if [ -f ./compile_commands.json ]
then
echo '-----编译数据生成完毕-----'
else
echo "-----生成编译数据失败-----"
return -1
fi

echo '-----分析中-----'

# 自定义排除警告的目录,将目录字符串加到数组里面
# 转化为:-e Debug.m -e Port.m -e Test
exclude_files=("Pods")

exclude=""
for i in ${exclude_files[@]}; do
exclude=${exclude}"-e "${i}" "
done
echo "排除目录:${exclude}"

# 分析reportType =~判断子字符串包含关系
if [[ ${reportType} =~ ${REPORT_PMD} ]]
then
nowReportType="-report-type html -o pmd.html"
else
nowReportType="-report-type Xcode"
fi
# 自定义report 如:
# nowReportType="-report-type html -o oclint_result.html"

echo "**************${nowReportType}"

# 生成报表
oclint-json-compilation-database ${exclude} -- \
${nowReportType} \
-rc=LONG_CLASS=1500 \
-rc=NESTED_BLOCK_DEPTH=5 \
-rc=LONG_VARIABLE_NAME=80 \
-rc=LONG_METHOD=200 \
-rc=LONG_LINE=300 \
-disable-rule ShortVariableName \
-disable-rule ObjCAssignIvarOutsideAccessors \
-disable-rule AssignIvarOutsideAccessors \
-disable-rule TooManyMethods \
-disable-rule BitwiseOperatorInConditional \
-max-priority-1=100000 \
-max-priority-2=100000 \
-max-priority-3=100000

#rm compile_commands.json
if [[ ${reportType} =~ ${REPORT_PMD} ]] && [ ! -f ./pmd.html ]
then
echo "-----分析失败-----"
return -1
else
echo '-----分析完毕-----'
return 0
fi
}

# 替换workspace的名字
myworkspace="Project.xcworkspace"
# 替换scheme的名字
myscheme="Project"
# 输出方式 Xcode/pmdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
reportType="pmd"

oclintForProject ${myworkspace} ${myscheme} ${reportType}

保存oclint.sh文件在同项目的顶级目录里面,然后控制台执行:sh oclint.sh or ./oclint.sh

参照

参考文章

参考文章1

参考文章2

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容