背景
1、大多代码规范都浮于表面,全靠开发自觉和Code Review来保障导致很多遗留的老大难问题。
2、基础模块很多规范只能通过注释或者文档来约束。
相关文档
设计目标
开发自定义Lint规则,通过Android Studio提供的Inspections实时检测代码,对不规范的代码进行实时提示。
- 能够实时进行代码规范提示
- 实现仅对单个模块生效
- 可以控制提示等级
- 不增加包体积
- 不占用过多的系统内存
概览
Lint相关API
1、Issue:表示一个Lint规则。
2、Detector:用于检测并报告代码中的Issue,每个Issue都要指定Detector。
3、Scope:声明Detector要扫描的代码范围,例如JAVA_FILE_SCOPE、CLASS_FILE_SCOPE、RESOURCE_FILE_SCOPE、GRADLE_SCOPE等,一个Issue可包含一到多个Scope。
4、Scanner:用于扫描并发现代码中的Issue,每个Detector可以实现一到多个Scanner。
5、IssueRegistry:Lint规则加载的入口,提供要检查的Issue列表。
自定义规则举例:实现了Serializable接口的类,引用类型成员变量也必须要实现Serializable接口
class SerializableClassDetector : BaseDetector(), Detector.UastScanner {
companion object {
private const val REPORT_MESSAGE = "该对象必须要实现Serializable接口,因为外部类实现了Serializable接口"
val ISSUE = Issue.create(
"SerializableClassCheck",
REPORT_MESSAGE,
REPORT_MESSAGE,
Category.CORRECTNESS,
10,
Severity.ERROR,
Implementation(SerializableClassDetector::class.java, Scope.JAVA_FILE_SCOPE)
)
}
override fun applicableSuperClasses(): List<String>? {
return listOf(CLASS_SERIALIZABLE)
}
override fun visitClass(context: JavaContext, declaration: UClass) {
for (field in declaration.fields) {
//字段是引用类型,并且可以拿到该class
val psiClass = (field.type as? PsiClassType)?.resolve() ?: continue
if (!LintMatcher.matchClass(lintConfig.serializableConfig, psiClass)) return
if (!context.evaluator.implementsInterface(psiClass, CLASS_SERIALIZABLE, true)) {
context.report(
ISSUE,
context.getLocation(field.typeReference!!),
lintConfig.serializableConfig
)
}
}
}
}
// Lint规则注册入口
class CustomIssueRegistry : IssueRegistry() {
override val issues: List<Issue>
get() = listOf(SerializableClassDetector.ISSUE)
}
Uast相关的继承关系:
设置提示等级
1、可以直接在Preferences-Inspections中设置问题的严重程度
Error 红色波浪线
Warning 淡黄色背景色
WeakWarning 黄色波浪线
Server Problem
2、通过lintOption进行提示等级设置
效果
目前实现的自定义lint检查实时提醒效果如下
在Android Studio 3.x版本中,打开Android工程源码后,IDE会加载工程中的自定义Lint规则,在设置菜单的Inspections列表里可以查看,和原生Lint效果相同(Android Studio会在打开源文件时触发对该文件的代码检查)。
使用方法一
自定义lint检查代码都在lint模块(Java Module)中;lintlibrary是一个空的Android Module,负责将livelint打出的jar包打入一个aar包中。
app模块通过compileOnly依赖livelibrary模块,相关的自定义检测就会只对该模块生效了,并且不会打入release包中。
使用方法二
编译完成后,将"/lint/build/libs"的"lint.jar"文件复制到(mac下)".android/lint"目录下(没有lint目录,新建一个)即可。
如果没有出现实时的静态检测提示,rebuild项目,仍然失败重新Android Studio
如果多次尝试仍然没有实时提示,只能使用./gradlew lint
命令进行手动检查。
app/build/reports/lint-results.html生成的该文件中可以查看检查的详细结果。