增量Lint检测实现原理
在Lint实现原理里已经知道,Lint检测的文件,默认是Project的javaSourceFolders和resourceFolders,但是这样会造成每次Lint检测的时间很长,我们pipeline的效率就很低;所以我们设想要做到一种增量检查:每次只检查改动的文件
一.基本思路
我们先回顾一下获取要检测文件的方式:
val files = project.subset
if (files != null) {
checkIndividualJavaFiles(project, main, checks, files)
} else {
val sourceFolders = project.javaSourceFolders
checkJava(project, main, sourceFolders, testFolders, generatedFolders, checks)
}
可以发现,在取Project的代码目录前,会优先判断其subset这个List有没有值,有的话,就只检测这些文件,所以我们可以得出结论:将我们改动的文件,放到Project的subset字段里即可
在此,我们需要实现一个自定义gradle插件来实现这一套功能
二.实现
1.自定义LintClient
那Project在哪里可以获取到呢?这里要注意,检测时使用的Project,是Lint里的com.android.tools.lint.detector.api.Project,不是gradle的Project:
@Override
protected LintRequest createLintRequest(@NonNull List<File> files) {
LintRequest lintRequest = new LintRequest(this, files);
LintGradleProject.ProjectSearch search = new LintGradleProject.ProjectSearch();
Project project =
search.getProject(this, gradleProject, variant != null ? variant.getName() : null);
lintRequest.setProjects(Collections.singletonList(project));
//...
return lintRequest;
}
往上倒可以发现,Project是在创建LintRequest时创建的,只有拿到LintRequest,才可以获取Project
LintCliClient:
public int run(@NonNull IssueRegistry registry, @NonNull List<File> files) throws IOException {
//...
LintRequest lintRequest = createLintRequest(files);
}
可以发现,createLintRequest()方法是LintCliClient的一个重写方法,而LintCliClient在Lint里的实现是LintGradleClient类,那么我们可以继承LintGradleClient写一个类,重写createLintRequest()方法,就可以拿到LintRequest对象了:
public class IncrementLintClient extends LintGradleClient {
private final org.gradle.api.Project gradleProject;
private IncrementLintExtension extension;
public IncrementLintClient(...) {
super(version, registry, flags, gradleProject, sdkHome, variant, variantInputs, buildToolInfoRevision, isAndroid, baselineVariantName);
this.gradleProject = gradleProject;
this.extension = extension;
}
@Override
protected LintRequest createLintRequest(List<File> files) {
LintRequest lintRequest = super.createLintRequest(files);
if (lintRequest != null) {
Collection<Project> projects = lintRequest.getProjects();
if (projects