<
自定义 lint 规则及其三种使用方式
>
上一篇

Build.gradle.kts 脚本 全局属性,及与 groovy 脚本 build.gradle 的对比
下一篇

将 library 发布到 maven 仓库,可发布模块产物 jar aar

Lint

一. 直接使用 lint 模块

1. 创建 lint 模块

选择 Java or Kotlin 类型

2. 依赖

我自己项目中测试使用 3.x.x 版本 依赖下载不下来,我用了最新的 2.x.x 版本

    // https://mvnrepository.com/artifact/com.android.tools.lint/lint-api
    implementation "com.android.tools.lint:lint-api:27.2.2"
    implementation "com.android.tools.lint:lint-checks:27.2.2"

3. 自定义 规则 检查器

class ToastDetector : Detector(), Detector.UastScanner {

    override fun getApplicableMethodNames(): List<String> {
        // 指定方法名
        return listOf("makeText")
    }

    override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
        // 找到指定方法的类
        if (method.containingClass?.qualifiedName == "android.widget.Toast") {
            context.report(
                ISSUE,
                node,
                context.getLocation(node),
                "使用 `toast()` `toastShort()` `toastLong()`"
            )
        }
    }

    companion object {
        val ISSUE: Issue = Issue.create(
            id = "ToastUsage", // `lint.xml` 配置用的是这个 id
            briefDescription = "使用工具类的 Toast",
            explanation = "使用 `toast()`",
            category = Category.CORRECTNESS,
            severity = Severity.WARNING,
            implementation = Implementation(
                ToastDetector::class.java,
                Scope.JAVA_FILE_SCOPE
            )
        )
    }
}

4. 注册

创建一个类,实现 IssueRegistry 的 issues

class MyIssueRegistry : IssueRegistry() {

    override val issues: List<Issue> = listOf(
        ToastDetector.ISSUE,
        LogDetector.ISSUE,
    ) // 将所有自定义 Lint 的 ISSUE 列出

}

然后在模块的 build.gradle.kts 注册上面的类

// kotlin dsl
tasks.jar {
    manifest {
	    // `Lint-Registry` 是 lint 的注册类
	    // 注册 IssueRegistry 的实现类
        attributes("Lint-Registry" to "com.example.test.module_lint.MyIssueRegistry")
    }
}

// groovy
jar {
    manifest {
	    // `Lint-Registry` 是 lint 的注册类
	    // 注册 IssueRegistry 的实现类
        attributes('Lint-Registry': 'com.example.test.module_lint.MyIssueRegistry')
    }
}

可以放到 项目根目录 或 模块根目录,位置就是检查的有效范围

这个 task 的目的是在 Java 的 MANIFEST.MF 添加相关信息,而不是 AndroidManifest.xml

5. 使用

在 build.gradle 中添加 Lint 检查的依赖

dependencies {
    lintChecks project(':module_lint')
}

在根目录创建 lint.xml

<lint>
    <!-- severity="ignore" 禁用 -->
    <issue id="ToastUsage" severity="error" />
    <issue id="LogUsage"  severity="warning"/>
</lint>

这个文件可以方便统一配置多个检查器

二. 打包 aar 文件使用

1. 生成 aar

在 lint 定义的模块 build.gradle 增加以下内容

// 定义 lintJarOutput,在 module_lint_aar 中被调用
val lintJarOutput by configurations.creating

dependencies {
    // ...
    // 将 jar 文件添加到 lintJarOutput
    lintJarOutput(files(tasks.jar.get().archiveFile))
}

新建一个 Android Library 模块(只用作打包 aar,多余的东西都可以删了)

plugins {
    alias(libs.plugins.android.library)
}

android {
    namespace = "com.example.test.module_lint_aar"
    compileSdk = 35
    defaultConfig {
        minSdk = 21
    }
}

dependencies {
    // 调用 module_lint 的 lintJarOutput,获得 jar 包
    lintPublish(project(path = ":module_lint", configuration = "lintJarOutput"))
}

然后 build 一下就可以产出 aar 文件了

这里 aar 文件需要使用 implement 引用才能正常工作

再贴一下基于 groovy 语言的传统 build.gradle 文件

Java Library

// 定义 lintJarOutput,在 module_lint_aar 中被调用
configurations {
    lintJarOutput
}
dependencies {
    // 将 jar 文件添加到 lintJarOutput
    lintJarOutput files(jar)
}

Android Library

dependencies {
    // 调用 module_lint 的 lintJarOutput,获得 jar 包
    lintPublish project(path: ":module_lint", configuration: "lintJarOutput")
}

2. 使用 aar 的 lint

    implementation(files("libs/module_lint_aar-debug.aar")) // 使用 aar,这里要用 implementation,测试过 lintChecks 是不行的
//    lintChecks(project(":module_lint")) // 这个是直接使用模块源码

三. 发布到 maven 使用

1. 定义发布任务

plugins {
    id("com.android.library")
    id("org.jetbrains.kotlin.android")
    `maven-publish`
}

android {
    // ...
    buildTypes {
        release {
            // ...
        }
    }
}

// android module 的 publishing 需要放到 afterEvaluate 里面
afterEvaluate {
    publishing {
        publications {
            // android
            create<MavenPublication>("maven") {
                from(components["release"])
                // 设置 Maven 坐标
                groupId = "your.group"
                artifactId = "lint"
                version = "1.0.0"
            }
        }
        repositories {
            mavenLocal() // 发布到本地 Maven 仓库
        }
    }
}

2. 执行 发布

在模块目录执行命令,就可以发布到本地 maven 了

../gradlew publishToMavenLocal
Top
Foot