3

在此感谢前交友事业部小伙伴:HaiYi、LV、Yong,曾经的协助!

本文主要阐述使用SonarQube构建iOS:Objective-C、Swift静态代码分析,包括分享遇到的坑,文章有限,一些细节不能到位的,请各位脑补下,谢谢。
SonarQube简介
旧版Sonar展示维度如下(当时应该是11年左右开始使用的):
v2-ec68c6f48a4bed2172607258637dc911_hd.jpg

旧版sonar展示维度

新版SonarQube已经改变了关注维度,推出质量模型:

Bugs:是出现了明显错误或是高度近似期望之外行为的代码。

漏洞:是指代码中可能出现被黑客利用的潜在风险点。

坏味道:代码异味会困扰代码的维护者并降低他们的开发效率。主要的衡量标准是修复它们所需的时间。

建议根据团队需要更新到新版本:至少5.6+以上。
v2-a53c6122fb700401b6c91b06357797eb_hd.jpg
新版SonarQube质量模型

SonarQube架构
SonarQube平台的组成:

数据库:存放SoanrQube的配置数据,代码质量的快照数据

Web服务:用于查看SonarQube配置数据,代码质量的快照数据

分析器:对项目代码进行分析,生成质量结果数据并存于数据库中

插件:各种语言支持的插件

v2-5412f3772a6e1bcbb6533e76a00f51eb_hd.jpg

不要忽略了CI:
虽然SonarQube具备分析器,可以对多种编程语言进行构建分析,但是依然建议使用CI工具,例如Jenkins来管理日常构建,让SonarQube仅仅展示最终数据即可。

v2-4be3049b1947f6b9e722a4bc4493b7ae_hd.jpg

iOS静态代码分析
目前iOS核心开发语言:Objective-C,也有不少项目采用了Swift语言,逐步过渡,因此项目的组成有两种模式:

单一语言使用:Objective-C、Swift

混合语言使用:Objective-C+Swift

下面通过实战分析两种模式的构建。

iOS静态代码分析的计划
Objective-C原以为就跟Java构建一样,如此简单,

v2-9671b98f55fd275df3584739fd3b7b15_hd.jpg

美好的计划

实际遇到的坑是很大的,而且很受伤,

v2-59f73652ebbead9dad8e0ccb71864188_hd.jpg

踩过坑的路才踏实
v2-6f6f9f5c43ffa45bfa1d29fcb0cd0c8e_hd.jpg

捅一万刀也不过分

iOS静态代码分析:Objective-C实战
工欲善其事必先利其器,工具如下:

环境工具:XCode 8.2+、Xcpretty 0.2.8、OCLint 0.12、xctool、gcovr

构建静态分析插件

SonarCFamily:

v2-4ae15f995ff68626b38e6a7ea750f008_hd.jpg

官方插件太贵了,找开源吧

开源SonarQube Plugin for Objective C(传送门)

插件安装参考网上教程,下载jar拷贝到SonarQube项目目录下:extensions/plugins

v2-0fdc5e8e7af4349b5259886375a99a45_hd.png

安装成功的示例

构建脚本

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

构建结果
v2-365265d120ba44211e148b93ae26eeac_hd.jpg

独门绝技介绍(感谢交友事业部: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:
v2-2dfbd4be2a6c2e1f62fdac1bac00f8b9_hd.jpg

官方插件太贵了,找开源吧

开源sonar-swift(传送门)

插件安装参考网上教程(backelite-sonar-swift-plugin-0.3.4.jar SonarQube5.4/5/6/6/3测试通过),下载jar拷贝到SonarQube项目目录下:extensions/plugins

v2-3632e351b30df730d6dc547305070794_hd.png

安装成功的示例

构建脚本

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

构建结果

v2-cc1fd32ffe519463b956c61dc8040c9b_hd.jpg

注意事项

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:

v2-2ae00afbf0fabecf0195d7c0dc050669_hd.jpg

如果不设置,关联规则有问题

目前暂无遇到缺失规则问题


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

构建结果

v2-145517c851a928f32555619a13c21725_hd.jpg

没有看到扫描规则问题展示,估计是配置文件或者构建文件路径有问题,暂且告一段落吧,有折腾出来的小伙伴喊一下,谢谢哟,^_^

微信公众号:乐少黑板报


乐少
4 声望0 粉丝