在此感謝前交友事業部小夥伴:HaiYi、LV、Yong,曾經的協助!
本文主要闡述使用SonarQube構建iOS:Objective-C、Swift靜態程式碼分析,包括分享遇到的坑,文章有限,一些細節不能到位的,請各位腦補下,謝謝。
SonarQube簡介
舊版Sonar展示維度如下(當時應該是11年左右開始使用的):
舊版sonar展示維度
新版SonarQube已經改變了關注維度,推出質量模型:
- Bugs:是出現了明顯錯誤或是高度近似期望之外行為的程式碼。
- 漏洞:是指程式碼中可能出現被黑客利用的潛在風險點。
- 壞味道:程式碼異味會困擾程式碼的維護者並降低他們的開發效率。主要的衡量標準是修復它們所需的時間。
建議根據團隊需要更新到新版本:至少5.6+以上。
新版SonarQube質量模型
SonarQube架構
SonarQube平臺的組成:
- 資料庫:存放SoanrQube的配置資料,程式碼質量的快照資料
- Web服務:用於檢視SonarQube配置資料,程式碼質量的快照資料
- 分析器:對專案程式碼進行分析,生成質量結果資料並存於資料庫中
- 外掛:各種語言支援的外掛
不要忽略了CI:
雖然SonarQube具備分析器,可以對多種程式語言進行構建分析,但是依然建議使用CI工具,例如Jenkins來管理日常構建,讓SonarQube僅僅展示最終資料即可。
iOS靜態程式碼分析
目前iOS核心開發語言:Objective-C,也有不少專案採用了Swift語言,逐步過渡,因此專案的組成有兩種模式:
- 單一語言使用:Objective-C、Swift
- 混合語言使用:Objective-C+Swift
下面通過實戰分析兩種模式的構建。
iOS靜態程式碼分析的計劃
Objective-C原以為就跟Java構建一樣,如此簡單,
美好的計劃
實際遇到的坑是很大的,而且很受傷,
踩過坑的路才踏實
捅一萬刀也不過分
iOS靜態程式碼分析:Objective-C實戰
工欲善其事必先利其器,工具如下:
- 環境工具:XCode 8.2+、Xcpretty 0.2.8、OCLint 0.12、xctool、gcovr
- 構建靜態分析外掛
- SonarCFamily:
- 官方外掛太貴了,找開源吧
- 開源SonarQube Plugin for Objective C(傳送門)
- 外掛安裝參考網上教程,下載jar拷貝到SonarQube專案目錄下:extensions/plugins
安裝成功的示例
- 構建指令碼
- run-sonar.sh
- 在Jenkins的Execute shell配置指令碼如下,也可以按照專案要求重名更好格式
cd $WORKSPACE
xcodebuild -workspace xxx.xcworkspace -scheme xxx clean build | tee xcodebuild.log | xcpretty --report json-compilation-database
mv build/reports/compilation_db.json compile_commands.json
oclint-json-compilation-database -exclude Pods -- -report-type pmd -o oclint.xml -max-priority-1 99999 -max-priority-2 99999 -max-priority-3 99999 -rc LONG_LINE=140 -rc LONG_METHOD=80 -rc NCSS_METHOD=50 -rc SHORT_VARIABLE_NAME=1 -rc CYCLOMATIC_COMPLEXITY=13 -rc MINIMUM_CASES_IN_SWITCH=2 -rc NPATH_COMPLEXITY=1500
rm -rf sonar-reports
mkdir sonar-reports
cat oclint.xml | sed "s#Switch Statements Should Have Default Rule#switch statements should have default#g" \
| sed "s#missing hash method#must override hash with isEqual#g" \
| sed "s#prefer early exits and continue#use early exits and continue#g" \
| sed "s#use boxed expression#replace with boxed expression#g" \
| sed "s#use container literal#replace with container literal#g" \
| sed "s#use number literal#replace with number literal#g" \
| sed "s#use object subscripting#replace with object subscripting#g" \
| sed "s#missing default in switch statements#switch statements should have default#g" \
| sed "s#unnecessary default statement in covered switch statement#switch statements don't need default when fully covered#g" \
| sed "s#covered switch statements dont need default#switch statements don't need default when fully covered#g" > sonar-reports/oclint.xml
rm -f sonar-project.properties
cat > sonar-project.properties <<- EOF
sonar.projectKey=xxx-iOS
sonar.projectName=xxx-iOS
sonar.projectVersion=x.x.x
sonar.language=objectivec
sonar.sources=sources
sonar.sourceEncoding=UTF-8
sonar.objectivec.oclint.reportPath=sonar-reports/oclint.xml
EOF
/bin/sh sonar-scanner -X複製程式碼
- 構建結果
- 獨門絕技介紹(感謝交友事業部:haiyi大神傾親奉獻)
- 構建錯誤errors generated
3 errors generated.
20 errors generated.
20 errors generated.
20 errors generated.
8 errors generated.
19 errors generated.
3 errors generated.
63 errors generated.複製程式碼
檢查OCLint,升級到0.12版本,與XCode8.2+配合
- 構建錯誤does not exist
The rule 'OCLint:use number literal' does not exist.
The rule 'OCLint:use object subscripting' does not exist.
The rule 'OCLint:ill-placed default label in switch statement' does not exist.
The rule 'OCLint:Switch Statements Misplaced Default Label' does not exist.複製程式碼
主要原因是sonar-objective-c-plugin-0.5.0-SNAPSHOT.jar中未包含此規則,可以通過修改原始碼新增規則解決(網上有一堆教程),比較繁瑣的是,不同專案遇到不同錯誤,需要新增多次,則多次打包jar,再匯入SonarQube,開銷大,haiyi大大給的祕籍是:用sed替換構建的oclint.xml檔案
sed "s#missing hash method#must override hash with isEqual#g"複製程式碼
將缺失規則:missing hash method,替換為:must override hash with isEqual,每次遇到有缺失的新規則,指令碼替換即可,至於怎麼準確匹配,去看看質量配置的具體含義再替換。
- Objective-C實戰總結
- 安裝構建工具所需版本號
- xcodebuild構建專案生成compile_commands.json
- oclint-json-compilation-database構建compile_commands.json生成oclint.xml
- sed替換oclint.xml缺失規則
- sonar-project.properties配置oclint.xml檔案路徑
- /bin/sh sonar-scanner -X 增加-X輸出debug日誌跟蹤
iOS靜態程式碼分析:Swift實戰
工欲善其事必先利其器,工具如下:
- 環境工具
brew install Swiftlint
gem install slather
sudo pip install lizard複製程式碼
- 構建靜態分析外掛
- SonarSwifty:
- 官方外掛太貴了,找開源吧
- 開源sonar-swift(傳送門)
- 外掛安裝參考網上教程(backelite-sonar-swift-plugin-0.3.4.jar SonarQube5.4/5/6/6/3測試通過),下載jar拷貝到SonarQube專案目錄下:extensions/plugins
安裝成功的示例
- 構建指令碼
- run-sonar.sh
- 在Jenkins的Execute shell配置指令碼如下,也可以按照專案要求重名更好格式
cd $WORKSPACE
rm -rf kuai-swiftlint.txt
swiftlint lint --path Duobao > xxx-swiftlint.txt
rm -rf sonar-project.properties
cat > sonar-project.properties <<- EOF
sonar.projectKey=xxx-iOS-swift
sonar.projectName=xxx-iOS-swift
sonar.projectVersion=x.x.x
sonar.language=swift
sonar.projectDescription=xxx with Swift
sonar.sources=sources
sonar.swift.workspace=xxx.xcworkspace
sonar.swift.appScheme=xxx
sonar.sourceEncoding=UTF-8
sonar.swift.swiftlint.report=xxx-swiftlint.txt
EOF
/bin/sh sonar-scanner -X複製程式碼
- 構建結果
- 注意事項
- The structure of the plugin is based on the sonar-objective-c plugin.
- In SonarQube under Quality Profiles the used Linter can be specified by selecting either the SwiftLint Profile or the Tailor Profile as Default profile for Swift Projects:
- 如果不設定,關聯規則有問題
- 目前暫無遇到缺失規則問題
- Swift實戰總結
- 安裝構建工具所需版本號
- swiftlint生成xxx-swiftlint.txt
- sonar-project.properties配置xxx-swiftlint.txt檔案路徑
- /bin/sh sonar-scanner -X 增加-X輸出debu
iOS靜態程式碼分析:Objective-C+Swift實戰
這裡不詳細介紹實戰過程,直接說總結
- Objective-C+Swift:分開構建,指令碼如下,當做兩個專案配置如上文所示
- Objective-C+Swift:一起構建,本質上他們兩個的外掛是不同的,但是可以利用sonar模組的概念來構建
ObjectiveC_Swift目錄結構
--ObjectiveC:完整專案檔案
--Swift:完整專案檔案複製程式碼
- 指令碼如下
sonar.projectKey=objectivec_swift
sonar.projectName=objectivec_swift
sonar.projectVersion=1.9.0
sonar.sourceEncoding=UTF-8
#分模組
sonar.modules=objective,swift
#構建objectivec
objective.sonar.projectName=objectivec
objective.sonar.language=objectivec
objective.sonar.projectBaseDir=objectivec
objective.sonar.sources=sources
objective.sonar.oclint.reportPath=sonar-reports/oclint.xml
#構建swift
swift.sonar.projectName=swift
swift.sonar.language=swift
swift.sonar.sources=sources
swift.sonar.projectBaseDir=swift
swift.sonar.swift.workspace=swift/xxx.xcworkspace
swift.sonar.swift.appScheme=Duobao
swift.sonar.sourceEncoding=UTF-8
swift.sonar.swift.swiftlint.report=swift/xxx-swiftlint.txt複製程式碼
- 構建結果
沒有看到掃描規則問題展示,估計是配置檔案或者構建檔案路徑有問題,暫且告一段落吧,有折騰出來的小夥伴喊一下,謝謝喲,^_^
微信公眾號:樂少黑板報