Lint增量扫描实践

本文介绍了一种实现Lint增量扫描的方法,通过分析LintTask执行流程,找到变更文件并插入到Lint请求中,从而大幅减少扫描时间。实践结果显示,原本3.5分钟的扫描时间缩短到了30秒左右。文章详细讲解了如何找到变更文件、构建增量扫描思路、调试Lint Task、插入代码以及设置任务入口,并提请注意Ci缓存和Gradle版本适配问题。
摘要由CSDN通过智能技术生成

Lint增量扫描实践

1. 背景

在上一篇Android Lint代码检查实践中说到了Lint全量扫描项目的耗时在3.5m,执行时机是在mr的时候,所以在大多数时候,不会因为Lint检查阻塞开发流程。

但是,特殊情况下,比如你只提交了几行代码需要mr的时候,review只需要10秒完事了,而Lint检查却需要3.5m,这个时候你就需要浪费宝贵的3分多钟进行等待,这种事情是我不希望看到的,本着对极致的追求,我决定支持增量扫描的功能,来压缩Lint扫描的时间。

老规矩先看下成果,不然被我骗着做完后发现没卵用怎么办,滑稽脸。

效果是不是很显著,从3分30秒压缩到了30秒左右,23333成功勾起了各位看官的欲望,接下来看看怎么实现的吧。

先来波广告上篇文章中所有功能和本篇的增量扫描都在AndroidLint实现了,欢迎star。

2. 怎么做

2.1 如何找到变更文件

先从简单的入手,对于找到变更文件我们可以通过git diff命令,git diff支持两个分支或者不同commit节点等方式对比修改。我这里的命令是git diff $baseline $revision --name-only --diff-filter=ACMRTUXB--name-only是只展示文件名,--diff-filter=ACMRTUXB是用来过滤掉删除的文件只要增改的文件,其他的不过多赘述官方文档有详细说明。

2.2 增量扫描思路的形成

变更文件找到了,接下来是做Lint增量扫描,首先想到的肯定是去看LintOptions有没有提供这个功能,很遗憾没有,那也就意味着需要自定义了,但我们并不知道怎么起手,所以就只能先看看AGP提供的LintTask怎么做的。最好情况是他有提供这个功能只是没有开放api给我们,那反射反射程序员的快乐一下就O了,最差的就是得照着他源码自己手撸一套有增量扫描功能的LintTask,这里我直接给出结果,AGP提供的LintTask有这个功能只是没开放api。

接下来我们将debug一遍LintTask执行流程,看看如何开启增量扫描功能,(ps:源码全贴的话特别多不容易抓住重点,所以非重点的就直接展示调用流程了,重点的地方在贴源码)

2.3 Debug Lint Task

LintTask默认有三个实现类

不管哪个都是调到LintBaseTask#runLint()进行lint扫描,具体调用流程如下:

LintBaseTask#runLint()

ReflectiveLintRunner#runLint()

LintGradleExecution#analyze()

LintGradleExecution#runLint()//这里其实跳了一步,三个Task实现类稍有不同但都会调到这

LintGradleClient#run()

LintCliClient#run()

LintDriver#analyze()

LintDriver#checkProject()

LintDriver#runFileDetectors()

我们着重看LintDriver#runFileDetectors()对源码检测的部分

private fun runFileDetectors(project: Project, main: Project?) {
   
  ...
  if (scope.contains(Scope.JAVA_FILE) || scope.contains(Scope.ALL_JAVA_FILES)) {
   
            val checks = union(
                scopeDetectors[Scope.JAVA_FILE],
                scopeDetectors[Scope.ALL_JAVA_FILES]
            )
            if (checks != null && !checks.isEmpty()) {
   
                val files = project.subset
                if (files != null) {
   //如果project.subset不为空
                    checkIndividualJavaFiles(project, main, checks, files)//则进行自定义文件的扫描
                } 
            }
        }
  ...
}

可以看到他在project.subset不为null的时候进行自定义文件的扫描,那么我们要做的就是将变更的文件插入到Project中,于是来看Project.subset取的什么

    /**
     * Adds the given file to the list of files which should be checked in this project. If no files
     * are added, the whole project will be checked.
     *
     * @param file the file to be checked
     */
    public void addFile(@NonNull File file) {
   
        if (files == null) {
   
            files = new ArrayList<>();
        }
        files.add(file);
    }

    /**
     * The list of files to be checked in this project. If null, the whole project should be
     * checked.
     *
     * @return the subset of files to be checked, or null for the whole project
     */
    @Nullable
    public List<File> getSubset() {
   
        return files;
    }

注释我特意没删,上面明确说明了如果getSubset()返回值不为null将只对files中的文件扫描,再次印证了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值