iOS代碼靜態(tài)分析平臺(tái)搭建(二)之OCLint規(guī)則

OCLint內(nèi)置了72條檢測(cè)規(guī)則踩身,如果對(duì)這些規(guī)則不加以自定義的話(huà)很可能會(huì)出現(xiàn)上萬(wàn)條不規(guī)范的內(nèi)容稍浆,代碼是為了實(shí)現(xiàn)功能,規(guī)范也一定要注意试和,但是不能本末倒置讯泣,我找了一個(gè)比較老的工程進(jìn)行了測(cè)試,輸出的報(bào)告如下:



這個(gè)工程的代碼量其實(shí)還算不上很大阅悍,已經(jīng)出現(xiàn)了這么多不符合規(guī)則的內(nèi)容好渠,粗略整理了一下昨稼,大概有三十多條檢測(cè)規(guī)則是代碼中比較常用的。

OCLint常見(jiàn)規(guī)則

規(guī)則名稱(chēng) 自定義規(guī)則所對(duì)應(yīng)KEY值 含義 備注
long variable name LongVariableName 過(guò)長(zhǎng)的變量名稱(chēng)
long line LongLine 一行代碼包含過(guò)多的字符
empty else block EmptyElseBlock else語(yǔ)句中是空的
unused method parameter UnusedMethodParameter 未使用的參數(shù)
prefer early exits and continue PreferEarlyExit 如果存在退出語(yǔ)句拳锚,讓滿(mǎn)足退出條件的選項(xiàng)盡早退出 代碼示例
empty catch statement EmptyCatchStatement try-catchy語(yǔ)句中catch代碼塊為空
too many methods TooManyMethods 一個(gè)類(lèi)中包含了過(guò)多的方法
collapsible if statements CollapsibleIfStatements 如果可以盡量合并if語(yǔ)句 代碼示例
ivar assignment outside accessors or init AssignIvarOutsideAccessors 某些成員變量的初始化不在get假栓,set,init方法中 代碼示例
redundant nil check RedundantNilCheck 非必要的nil檢查 代碼示例
high ncss method HighNcssMethod “非注釋的源語(yǔ)句”過(guò)多霍掺,其實(shí)說(shuō)的就是一個(gè)方法不包含注釋?zhuān)行У拇a量過(guò)大 代碼示例
high npath complexity HighNpathComplexity 一個(gè)方法中可能執(zhí)行的路徑總和過(guò)多 代碼示例
long method LongMethod 一個(gè)方法過(guò)于龐大匾荆,做了太多事情
high cyclomatic complexity HighCyclomaticComplexity 代碼圈度過(guò)高,包含了很多if else while等語(yǔ)句 代碼示例
empty if statement EmptyIfStatement if語(yǔ)句內(nèi)容為空
useless parentheses UselessParentheses 無(wú)用的括號(hào) 代碼示例
redundant conditional operator RedundantConditionalOperator 冗余的條件判斷 代碼示例
redundant local variable RedundantLocalVariable 多余的變量創(chuàng)建 代碼示例
unnecessary else statement UnnecessaryElseStatement 不必要的else判斷 代碼示例
unused local variable UnusedLocalVariable 定義了一個(gè)變量但未使用 代碼示例
dead code DeadCode 顧名思義杆烁,死代碼牙丽,所寫(xiě)的邏輯不影響最終的執(zhí)行結(jié)果或者代碼不會(huì)被執(zhí)行 代碼示例
inverted logic InvertedLogic 逆邏輯,代碼的邏輯很難被理解 代碼示例
constant if expression ConstantIfExpression if語(yǔ)句的判斷總是true或者false 代碼示例
too few branches in switch statement TooFewBranchesInSwitchStatement switch語(yǔ)句的分支太少 代碼示例
missing default in switch statements MissingDefaultStatement switch語(yǔ)句卻少default 代碼示例
bitwise operator in conditional BitwiseOperatorInConditional 條件語(yǔ)句中使用了位運(yùn)算兔魂,位運(yùn)算很高效烤芦,但有時(shí)難以理解 代碼示例
unnecessary default statement in covered switch statement UnnecessaryDefaultStatement 不必要的default,switch已經(jīng)羅列出所有的case分支 代碼示例
redundant if statement RedundantIfStatement 沒(méi)必要的條件判斷 代碼示例
long class LongClass 太大的類(lèi)入热,超過(guò)了1000行代碼 代碼示例
deep nested block DeepNestedBlock 太深的嵌套 代碼示例
missing break in switch statement MissingBreakInSwitchStatement switch語(yǔ)句缺少break 代碼示例
constant conditional operator ConstantConditionalOperator 常量條件運(yùn)算符拍棕,結(jié)果總為true或者false 代碼示例
broken oddness check BrokenOddnessCheck 奇數(shù)檢查不正確晓铆,出現(xiàn)這個(gè)問(wèn)題大概率是使用%運(yùn)算進(jìn)行判斷 代碼示例
use number literal UseNumberLiteral 推薦直接使用數(shù)字來(lái)進(jìn)行初始化勺良,而不是調(diào)用類(lèi)方法 代碼示例
short variable name ShortVariableName 過(guò)短的變量名稱(chēng) 代碼示例
use container literal UseContainerLiteral 推薦使用容器語(yǔ)法初始化數(shù)組字典等 代碼示例
parameter reassignment ParameterReassignment 參數(shù)被重新定義了,這是不標(biāo)準(zhǔn)的寫(xiě)法 代碼示例
use object subscripting UseObjectSubscripting 不推薦使用下標(biāo)在數(shù)組或者字典中取值 代碼示例

定義具體檢測(cè)規(guī)則

上面所列出來(lái)的規(guī)則是可以根據(jù)我們的項(xiàng)目需要進(jìn)行自定義的骄噪,比如設(shè)置每行代碼最多200個(gè)字符尚困。

-rc=LONG_LINE=200

設(shè)置變量名稱(chēng)最長(zhǎng)40個(gè)字符

-rc=LONG_VARIABLE_NAME=40

忽略某些檢測(cè)規(guī)則

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

完整的檢測(cè)語(yǔ)句如下:

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 

生成報(bào)告

可以選擇輸出html格式的報(bào)告,直接使用瀏覽器就可以查看結(jié)果链蕊。


結(jié)果查看起來(lái)還是非常方便的事甜,會(huì)定位到具體的類(lèi)以及對(duì)應(yīng)的行,還會(huì)將具體的錯(cuò)誤類(lèi)別展示出來(lái)滔韵。有一個(gè)點(diǎn)要注意逻谦,在生成編譯文件的時(shí)候要加上一句GCC_PRECOMPILE_PREFIX_HEADER=YES,預(yù)先編譯prefix文件陪蜻,不然最終展示出來(lái)的報(bào)告會(huì)出現(xiàn)很多編譯問(wèn)題邦马,完整編譯語(yǔ)句如下:

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

腳本文件

每次都使用命令行進(jìn)行代碼的掃描,其實(shí)是很費(fèi)勁的一件事情宴卖,可以直接使用腳本文件進(jìn)行檢測(cè)滋将。

#!/bin/bash

COLOR_ERR="\033[1;31m"    #出錯(cuò)提示
COLOR_SUCC="\033[0;32m"  #成功提示
COLOR_QS="\033[1;37m"  #問(wèn)題顏色
COLOR_AW="\033[0;37m"  #答案提示
COLOR_END="\033[1;34m"     #顏色結(jié)束符



# 尋找項(xiàng)目的 ProjectName
function searchProjectName () {
    # maxdepth 查找文件夾的深度
    find . -maxdepth 1 -name "*.xcodeproj"
}

function oclintForProject () {
    # 預(yù)先檢測(cè)所需的安裝包是否存在
    if which xcodebuild 2>/dev/null; then
    echo 'xcodebuild exist'
    else
    echo 'xcodebuild 未安裝,請(qǐng)安裝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 未安裝症昏,請(qǐng)安裝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}
    # 字符串替換函數(shù)随闽。//表示全局替換 /表示匹配到的第一個(gè)結(jié)果替換。
    path=${path//.\//}  # ./BridgeLabiPhone.xcodeproj -> BridgeLabiPhone.xcodeproj
    path=${path//.xcodeproj/} # BridgeLabiPhone.xcodeproj -> BridgeLabiPhone
    
    myworkspace=$path".xcworkspace" # workspace名字
    myscheme=$path  # scheme名字
    
    # 清除上次編譯數(shù)據(jù)
    DIR=~/Library/Developer/Xcode/DerivedData/
    echo -e $COLOR_SUCC'??????????清除上次編譯數(shù)據(jù)??????????'$COLOR_SUCC
    rm -r -- "$DIR"*

     # # 生成編譯數(shù)據(jù)
    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編譯數(shù)據(jù)生成完畢??????????'$COLOR_SUCC
    else
    echo -e $COLOR_ERR'???xcpretty編譯數(shù)據(jù)生成失敗???'$COLOR_ERR
    return -1
    fi

    if [ -f ./compile_commands.json ]; then
    echo -e $COLOR_SUCC'??????????xcpretty編譯數(shù)據(jù)生成完畢??????????'$COLOR_SUCC
    else
    echo -e $COLOR_ERR'???xcpretty編譯數(shù)據(jù)生成失敗???'$COLOR_ERR
    return -1
    fi

    echo -e $COLOR_SUCC'??????????OCLint代碼分析開(kāi)始??????????'$COLOR_SUCC
    # 生成報(bào)表
    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分析數(shù)據(jù)生成完畢??????????'$COLOR_SUCC
    else
    echo -e $COLOR_ERR'???oclint分析數(shù)據(jù)生成失敗???'$COLOR_ERR
    return -1
    fi
  
}

oclintForProject $1


OCLint的不足之處

OCLint可以檢測(cè)出來(lái)許許多多代碼不規(guī)范的地方肝谭,這些不規(guī)范會(huì)影響代碼的可讀性問(wèn)題掘宪,不易于維護(hù)蛾扇,時(shí)間長(zhǎng)了會(huì)造成很多技術(shù)債,但是更深層次的問(wèn)題比如資源泄漏添诉,內(nèi)存泄漏這類(lèi)問(wèn)題OCLint是無(wú)法檢測(cè)出來(lái)的屁桑,需要借助其他工具,比如FacebookInfer栏赴,這個(gè)放到下一篇再去分享蘑斧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市须眷,隨后出現(xiàn)的幾起案子竖瘾,更是在濱河造成了極大的恐慌,老刑警劉巖花颗,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捕传,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡扩劝,警方通過(guò)查閱死者的電腦和手機(jī)庸论,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)棒呛,“玉大人聂示,你說(shuō)我怎么就攤上這事〈孛耄” “怎么了鱼喉?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)趋观。 經(jīng)常有香客問(wèn)我扛禽,道長(zhǎng),這世上最難降的妖魔是什么皱坛? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任编曼,我火速辦了婚禮,結(jié)果婚禮上剩辟,老公的妹妹穿的比我還像新娘掐场。我一直安慰自己,他們只是感情好抹沪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布刻肄。 她就那樣靜靜地躺著,像睡著了一般融欧。 火紅的嫁衣襯著肌膚如雪敏弃。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天噪馏,我揣著相機(jī)與錄音麦到,去河邊找鬼绿饵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瓶颠,可吹牛的內(nèi)容都是我干的拟赊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼粹淋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吸祟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起桃移,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤屋匕,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后借杰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體过吻,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年蔗衡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纤虽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绞惦,死狀恐怖逼纸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情翩隧,我是刑警寧澤樊展,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布呻纹,位于F島的核電站堆生,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏雷酪。R本人自食惡果不足惜淑仆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哥力。 院中可真熱鬧蔗怠,春花似錦、人聲如沸吩跋。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)锌钮。三九已至桥温,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梁丘,已是汗流浹背侵浸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工旺韭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掏觉。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓区端,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親澳腹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子织盼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容