这可能是最好的AndroidLint开源库

Android Lint

这是一个通用Android Lint库,你可以用它来检查代码规范、bug、资源命名等✌️。

本库最大特点是通用,相较于其他Lint库(规则直接在代码写死),最大的不同是,规则全靠配置生成,更加灵活,在多团队协作下,只需拷贝配置文件,修改提示信息即可完成迁移。

支持增量扫描功能,速度更快。

支持lint发现错误后自动执行脚本功能,更加友好。

对于增量扫描原理可以看Lint增量扫描实践,具体在项目中使用可以参考Android Lint代码检查实践

如果有感兴趣的大佬,欢迎一起开发、交流。

地址

github.com/RocketZLY/A…

项目结构

.
├── app // demo工程用来展示lint检查效果
├── checks // lint规则代码
├── custom_lint_config.json // 规则配置文件
├── lintlibrary // 空项目,依赖了checks用来生成aar包
├── lintpatch // 实现lint增量扫描、修复lint26.5.3bug的补丁代码
├── lintplugin // lint插件,用来增量扫描、执行脚本、简化配置、日志输出等

依赖

需要Android Gradle Plugin在3.5.0以上,目前我项目使用的是3.5.3实测ok。

根目录gradle

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath "com.rocketzly:lintPlugin:$lastVersion"
  }
}
复制代码

module gradle

apply plugin: "com.rocketzly.lintPlugin"
复制代码

使用

添加依赖后,并在项目根目录下添加custom_lint_config.json规则配置文件(关于配置可以看后面的规则配置)

编码实时提示

添加依赖和配置文件后Rebuild一下(如果还不行则执行次./gradlew :${moduleName}:lintFull)即可编码实时提示。

有一点需要注意,AS对于Lint实时提示支持的不算特别好,少数情况下会出现编码时提示不了的情况,但是命令行执行生成报告结果都是正常的,所以以报告结果为准。

命令行执行

目前支持两个命令:

  • ./gradlew lintFull 全量扫描(只扫自定义issue)
  • ./gradlew lintIncrement -Pbaseline="xxx" -Prevision="xxx" 增量扫描(只扫自定义issue)

参数描述:

  • baseline:执行lintIncrement必须参数,用来设置基线代码分支或者commit节点
  • revision:执行lintIncrement必须参数,用来设置最新分支或者commit节点
  • scriptPath:可选参数,在lint发现错误的时候自动执行脚本路径,目前只支持执行python3和shell脚本

脚本入参:

  • reportPath:html报告地址
  • userName:操作人名字
  • moduleName:模块名字
  • errorCount:错误数

具体参数获取方法可以参照项目根目录中lintScriptDemo脚本

顺带提一句增量扫描是通过git diff $baseline $revision --name-only --diff-filter=ACMRTUXB 去找到变更文件的,所以只要是git命令支持的都可以作为baseline和revision的入参。

那么添加依赖和配置文件后,Terminal执行./gradlew :app:lintFull或者./gradlew :app:lintIncrement -Pbaseline="xxx" -Prevision="xxx就可以看到检查结果。

以本库为例,执行./gradlew :app:lintIncrement -Pbaseline="dev" -Prevision="HEAD" -PscriptPath="lintNotification.py"结果如下:

[图片上传失败...(image-8aa624-1602771897095)]

查看生成的Html文件可以查看详细lint报告

[图片上传失败...(image-13de15-1602771897095)]

最新版本代码日志和报告可能稍有不同但不影响结果

Lint配置

module gradle

lintConfig {
    baseline = true//生成baseline文件,默认为false不会生成
}
复制代码
  • baseline:是否生成baseline文件,默认为false不生成,如果需要生成则设置为true(可选项)

默认值(目前还不支持配置,如有需要可以提issue)

  • 只扫描自定义Issue
  • 不会将warning视为error
  • 只有发现error的时候才会停止task执行
  • html报告地址:${modulePath}/build/reports/lint-results.html
  • xml报告地址:${modulePath}/build/reports/lint-results.xml
  • baseline地址:${modulePath}/lint-baseline.xml

规则配置

自定义Issue规则是从根目录custom_lint_config.json文件读取。

目前支持五大类规则(后期会继续增加、完善规则,欢迎有兴趣大佬一起开发)

  • 避免使用Api(又可细分为三类)
    • 避免使用的方法
    • 避免创建的类
    • 避免继承或实现的类
  • 需要处理异常的方法
  • 有依赖关系Api(即trigger_method方法调用后,必须调用dependency_method方法)
  • 资源命名规范
  • Serializerable对象的引用类型成员变量也必须要实现Serializerable接口

具体配置规则和说明如下(注:由于markdown表格没法表示层级关系,故用+代表json层级关系)

字段 类型 默认值 是否必须 备注
avoid_usage_api Object 非必须 避免使用api
+method Object[] 非必须 避免使用的方法
++name String name和name_regex有一个即可 方法名,匹配方法全路径,以Toast#show()为例,则应填入android.widget.Toast.show
++name_regex String name和name_regex有一个即可 方法名正则匹配,以Log#i()为例,则应填入android.util.Log.(v d i w e)
++message String 必须 提示信息
++exclude String[] 非必须 需要排除检查的类,匹配全路径类名,例如com.rocketzly.androidlint.Test
++exclude_regex String 非必须 需要排除检查的类正则匹配
++severity String "error" 非必须 lint错误严重程度默认error,可输入fatal、error、warning、informational、ignore
+construction Object[] 非必须 避免创建类
++name String name和name_regex有一个即可 构造函数名,匹配方法全路径,以Thread构造函数为例java.lang.Thread
++name_regex String name和name_regex有一个即可 方法名正则匹配
++message String 必须 提示信息
++exclude String[] 非必须 需要排除检查的类,匹配全路径类名,例如com.rocketzly.androidlint.Test
++exclude_regex String 非必须 需要排除检查的类正则匹配
++severity String "error" 非必须 lint错误严重程度默认error,可输入fatal、error、warning、informational、ignore
+inherit Object[] 非必须 避免继承或实现的类
++name String name和name_regex有一个即可 类名,匹配全路径类名,例如com.rocketzly.androidlint.Test
++name_regex String name和name_regex有一个即可 类名正则匹配,例如.(AppCompat Main)?Activity$
++message String 必须 提示信息
++exclude String[] 非必须 需要排除检查的类,匹配全路径类名,例如com.rocketzly.androidlint.Test
++exclude_regex String 非必须 需要排除检查的类正则匹配
++severity String "error" 非必须 lint错误严重程度默认error,可输入fatal、error、warning、informational、ignore
handle_exception_method Object[] 非必须 需要处理异常的方法
+name String name和name_regex有一个即可 方法名,匹配方法全路径,以Toast#show()为例,则应填入android.widget.Toast.show
+name_regex String name和name_regex有一个即可 方法名正则匹配,以Log#i()为例,则应填入android.util.Log.(v d i w e)
+exception String 必须 需要处理的异常全路径类名,如java.lang.IllegalArgumentException
+message String 必须 提示信息
+exclude String[] 非必须 需要排除检查的类,匹配全路径类名,例如com.rocketzly.androidlint.Test
+exclude_regex String 非必须 需要排除检查的类正则匹配
+severity String "error" 非必须 lint错误严重程度默认error,可输入fatal、error、warning、informational、ignore
dependency_api Object[] 非必须 有依赖关系api
+trigger_method String 必须 触发方法,匹配方法全路径,以Toast#show()为例,则应填入android.widget.Toast.show
+dependency_method String 必须 依赖方法,匹配方法全路径,即当调用trigger_method后需要调用dependency_method方法
+message String 必须 提示信息
+severity String "error" 非必须 lint错误严重程度默认error,可输入fatal、error、warning、informational、ignore
resource_name Object 非必须 资源命名规范
+drawable Object 非必须 drawable命名规范
++name_regex String 必须 资源名正则规范
++message String 必须 提示信息
++severity String "error" 非必须 lint错误严重程度默认error,可输入fatal、error、warning、informational、ignore
+layout Object 非必须 layout命名规范
++name_regex String 必须 资源名正则规范
++message String 必须 提示信息
++severity String "error" 非必须 lint错误严重程度默认error,可输入fatal、error、warning、informational、ignore
serializable_config Object 非必须 Serializable配置
+name_regex String 必须 检查哪些包下的类,例如只检查自己包下的类^com.rocketzly.androidlint
+message String 必须 提示信息
+severity String "error" 非必须 lint错误严重程度默认error,可输入fatal、error、warning、informational、ignore

匹配规则是先排除后匹配,优先级上exclude > exclude_regex > name > name_regex。

message会影响到AS实时提示展示的信息和report中展示信息。

severity则是对应AS实时提示的错误等级和report中错误等级。

具体demo可以看项目根目录下custom_lint_config.json

作者:朱利源
链接:https://juejin.im/post/6882200690606178311

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