iOS代码静态分析平台搭建(二)之OCLint规则

OCLint内置了72条检测规则,如果对这些规则不加以自定义的话很可能会出现上万条不规范的内容,代码是为了实现功能,规范也一定要注意,但是不能本末倒置,我找了一个比较老的工程进行了测试,输出的报告如下:



这个工程的代码量其实还算不上很大,已经出现了这么多不符合规则的内容,粗略整理了一下,大概有三十多条检测规则是代码中比较常用的。

OCLint常见规则

规则名称 自定义规则所对应KEY值 含义 备注
long variable name LongVariableName 过长的变量名称
long line LongLine 一行代码包含过多的字符
empty else block EmptyElseBlock else语句中是空的
unused method parameter UnusedMethodParameter 未使用的参数
prefer early exits and continue PreferEarlyExit 如果存在退出语句,让满足退出条件的选项尽早退出 代码示例
empty catch statement EmptyCatchStatement try-catchy语句中catch代码块为空
too many methods TooManyMethods 一个类中包含了过多的方法
collapsible if statements CollapsibleIfStatements 如果可以尽量合并if语句 代码示例
ivar assignment outside accessors or init AssignIvarOutsideAccessors 某些成员变量的初始化不在get,set,init方法中 代码示例
redundant nil check RedundantNilCheck 非必要的nil检查 代码示例
high ncss method HighNcssMethod “非注释的源语句”过多,其实说的就是一个方法不包含注释,有效的代码量过大 代码示例
high npath complexity HighNpathComplexity 一个方法中可能执行的路径总和过多 代码示例
long method LongMethod 一个方法过于庞大,做了太多事情
high cyclomatic complexity HighCyclomaticComplexity 代码圈度过高,包含了很多if else while等语句 代码示例
empty if statement EmptyIfStatement if语句内容为空
useless parentheses UselessParentheses 无用的括号 代码示例
redundant conditional operator RedundantConditionalOperator 冗余的条件判断 代码示例
redundant local variable RedundantLocalVariable 多余的变量创建 代码示例
unnecessary else statement UnnecessaryElseStatement 不必要的else判断 代码示例
unused local variable UnusedLocalVariable 定义了一个变量但未使用 代码示例
dead code DeadCode 顾名思义,死代码,所写的逻辑不影响最终的执行结果或者代码不会被执行 代码示例
inverted logic InvertedLogic 逆逻辑,代码的逻辑很难被理解 代码示例
constant if expression ConstantIfExpression if语句的判断总是true或者false 代码示例
too few branches in switch statement TooFewBranchesInSwitchStatement switch语句的分支太少 代码示例
missing default in switch statements MissingDefaultStatement switch语句却少default 代码示例
bitwise operator in conditional BitwiseOperatorInConditional 条件语句中使用了位运算,位运算很高效,但有时难以理解 代码示例
unnecessary default statement in covered switch statement UnnecessaryDefaultStatement 不必要的default,switch已经罗列出所有的case分支 代码示例
redundant if statement RedundantIfStatement 没必要的条件判断 代码示例
long class LongClass 太大的类,超过了1000行代码 代码示例
deep nested block DeepNestedBlock 太深的嵌套 代码示例
missing break in switch statement MissingBreakInSwitchStatement switch语句缺少break 代码示例
constant conditional operator ConstantConditionalOperator 常量条件运算符,结果总为true或者false 代码示例
broken oddness check BrokenOddnessCheck 奇数检查不正确,出现这个问题大概率是使用%运算进行判断 代码示例
use number literal UseNumberLiteral 推荐直接使用数字来进行初始化,而不是调用类方法 代码示例
short variable name ShortVariableName 过短的变量名称 代码示例
use container literal UseContainerLiteral 推荐使用容器语法初始化数组字典等 代码示例
parameter reassignment ParameterReassignment 参数被重新定义了,这是不标准的写法 代码示例
use object subscripting UseObjectSubscripting 不推荐使用下标在数组或者字典中取值 代码示例

定义具体检测规则

上面所列出来的规则是可以根据我们的项目需要进行自定义的,比如设置每行代码最多200个字符。

-rc=LONG_LINE=200

设置变量名称最长40个字符

-rc=LONG_VARIABLE_NAME=40

忽略某些检测规则

-disable-rule ShortVariableName 
-disable-rule UseContainerLiteral
-disable-rule ParameterReassignment 
-disable-rule UseObjectSubscripting 

完整的检测语句如下:

oclint-json-compilation-database -e Pods -e Applications -- -extra-arg=-Wno-everything -report-type html -o oclintReport.html \-rc=LONG_LINE=200 \-rc=LONG_VARIABLE_NAME=40 \-disable-rule ShortVariableName \-disable-rule UseContainerLiteral \-disable-rule ParameterReassignment \-disable-rule UseObjectSubscripting 

生成报告

可以选择输出html格式的报告,直接使用浏览器就可以查看结果。


结果查看起来还是非常方便的,会定位到具体的类以及对应的行,还会将具体的错误类别展示出来。有一个点要注意,在生成编译文件的时候要加上一句GCC_PRECOMPILE_PREFIX_HEADER=YES,预先编译prefix文件,不然最终展示出来的报告会出现很多编译问题,完整编译语句如下:

xcodebuild clean build -scheme <your_scheme> -workspace <your_workspace>.xcworkspace -configuration Debug GCC_PRECOMPILE_PREFIX_HEADER=YES COMPILER_INDEX_STORE_ENABLE=NO -sdk iphoneos16.2 | xcpretty -r json-compilation-database -o compile_commands.json

脚本文件

每次都使用命令行进行代码的扫描,其实是很费劲的一件事情,可以直接使用脚本文件进行检测。

#!/bin/bash

COLOR_ERR="\033[1;31m"    #出错提示
COLOR_SUCC="\033[0;32m"  #成功提示
COLOR_QS="\033[1;37m"  #问题颜色
COLOR_AW="\033[0;37m"  #答案提示
COLOR_END="\033[1;34m"     #颜色结束符



# 寻找项目的 ProjectName
function searchProjectName () {
    # maxdepth 查找文件夹的深度
    find . -maxdepth 1 -name "*.xcodeproj"
}

function oclintForProject () {
    # 预先检测所需的安装包是否存在
    if which xcodebuild 2>/dev/null; then
    echo 'xcodebuild exist'
    else
    echo 'xcodebuild 未安装,请安装Xcode'
    fi
    
    if which oclint 2>/dev/null; then
    echo 'oclint exist'
    else
    export PATH="/Users/imac0823/Documents/Tools/oclint/bin:$PATH"
    source ~/.zshrc
    fi
    if which xcpretty 2>/dev/null; then
    echo 'xcpretty exist'
    else
    echo 'xcpretty 未安装,请安装xcpretty'
    fi
    
    
    # 指定编码
    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"
    export xcpretty=/usr/local/bin/xcpretty # xcpretty 的安装位置可以在终端用 which xcpretty找到
    
    searchFunctionName=`searchProjectName`
    path=${searchFunctionName}
    # 字符串替换函数。//表示全局替换 /表示匹配到的第一个结果替换。
    path=${path//.\//}  # ./BridgeLabiPhone.xcodeproj -> BridgeLabiPhone.xcodeproj
    path=${path//.xcodeproj/} # BridgeLabiPhone.xcodeproj -> BridgeLabiPhone
    
    myworkspace=$path".xcworkspace" # workspace名字
    myscheme=$path  # scheme名字
    
    # 清除上次编译数据
    DIR=~/Library/Developer/Xcode/DerivedData/
    echo -e $COLOR_SUCC'🚀🚀🚀🚀🚀清除上次编译数据🚀🚀🚀🚀🚀'$COLOR_SUCC
    rm -r -- "$DIR"*

     # # 生成编译数据
    xcodebuild GCC_PRECOMPILE_PREFIX_HEADER=YES COMPILER_INDEX_STORE_ENABLE=NO OTHER_CFLAGS="-DNS_FORMAT_ARGUMENT(A)= -D_Nullable_result=_Nullable" clean build -scheme $myscheme -workspace $myworkspace -configuration Debug -sdk iphoneos16.2 |tee xcodebuild.log|xcpretty -r json-compilation-database -o compile_commands.json

    if [ -f ./compile_commands.json ]; then
    echo -e $COLOR_SUCC'🚀🚀🚀🚀🚀xcpretty编译数据生成完毕🚀🚀🚀🚀🚀'$COLOR_SUCC
    else
    echo -e $COLOR_ERR'❌❌❌xcpretty编译数据生成失败❌❌❌'$COLOR_ERR
    return -1
    fi

    if [ -f ./compile_commands.json ]; then
    echo -e $COLOR_SUCC'🚀🚀🚀🚀🚀xcpretty编译数据生成完毕🚀🚀🚀🚀🚀'$COLOR_SUCC
    else
    echo -e $COLOR_ERR'❌❌❌xcpretty编译数据生成失败❌❌❌'$COLOR_ERR
    return -1
    fi

    echo -e $COLOR_SUCC'🚀🚀🚀🚀🚀OCLint代码分析开始🚀🚀🚀🚀🚀'$COLOR_SUCC
    # 生成报表
    oclint-json-compilation-database -e Pods -e Applications -- -extra-arg=-Wno-everything -report-type html -o oclintReport.html \-rc=LONG_LINE=200 \-rc=LONG_VARIABLE_NAME=40 \-disable-rule ShortVariableName \-disable-rule UseContainerLiteral \-disable-rule ParameterReassignment \-disable-rule UseObjectSubscripting \-disable-rule AssignIvarOutsideAccessors \-disable-rule UnusedMethodParameter
    
    if [ -f ./oclintReport.html ]; then
    echo -e $COLOR_SUCC'🚀🚀🚀🚀🚀oclint分析数据生成完毕🚀🚀🚀🚀🚀'$COLOR_SUCC
    else
    echo -e $COLOR_ERR'❌❌❌oclint分析数据生成失败❌❌❌'$COLOR_ERR
    return -1
    fi
  
}

oclintForProject $1


OCLint的不足之处

OCLint可以检测出来许许多多代码不规范的地方,这些不规范会影响代码的可读性问题,不易于维护,时间长了会造成很多技术债,但是更深层次的问题比如资源泄漏,内存泄漏这类问题OCLint是无法检测出来的,需要借助其他工具,比如FacebookInfer,这个放到下一篇再去分享。

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

推荐阅读更多精彩内容