当前位置: 首页 > news >正文

使用 Kotlin 实现 Android 自定义 Lint 检查规则的步骤指南

一、创建 Lint 规则模块

  1. 新建 Android 库模块
    在项目中创建新的 Java/Kotlin Library 模块(非Android模块),例如命名为 custom-lint

  2. 配置 build.gradle.kts

plugins {id("java-library")id("org.jetbrains.kotlin.jvm") version "1.8.20" // 使用最新Kotlin版本
}dependencies {compileOnly("com.android.tools.lint:lint-api:30.4.0") // 根据AGP版本调整compileOnly("com.android.tools.lint:lint-checks:30.4.0")compileOnly(kotlin("stdlib"))
}java {sourceCompatibility = JavaVersion.VERSION_11targetCompatibility = JavaVersion.VERSION_11
}

二、实现自定义规则

1. 创建 Detector 类
import com.android.tools.lint.detector.api.*class ToastDetector : Detector(), Detector.UastScanner {override fun getApplicableMethodNames(): List<String> = listOf("makeText")override fun visitMethodCall(context: JavaContext,node: UCallExpression,method: PsiMethod) {val evaluator = context.evaluatorif (evaluator.isMemberInClass(method, "android.widget.Toast")) {// 检查是否调用了 show()val parent = node.parentif (parent !is UExpressionList || parent.uastParent !is UCallExpression ||(parent.uastParent as? UCallExpression)?.methodName != "show") {context.report(issue = ISSUE,location = context.getLocation(node),message = "必须调用 show() 方法显示 Toast")}}}companion object {val ISSUE = Issue.create(id = "ToastShowMissing",briefDescription = "缺少 Toast.show() 调用",explanation = "检测到 Toast.makeText() 但没有调用 show() 方法",category = Category.CORRECTNESS,priority = 6,severity = Severity.ERROR,implementation = Implementation(ToastDetector::class.java,Scope.JAVA_FILE_SCOPE))}
}
2. 创建 Issue Registry
@Suppress("UnstableApiUsage")
class CustomIssueRegistry : IssueRegistry() {override val issues: List<Issue>get() = listOf(ToastDetector.ISSUE// 添加更多检测规则)override val api: Int = CURRENT_API // 当前使用 14
}

三、配置清单文件

  1. 在模块 src/main/resources/META-INF/ 下创建 services 目录
  2. 新建文件 com.android.tools.lint.client.api.IssueRegistry
  3. 文件内容:
com.example.lint.CustomIssueRegistry

四、集成到项目

  1. 在应用模块的 build.gradle 中添加:
dependencies {lintChecks project(':custom-lint')
}

五、测试规则

  1. 编写测试用例
class LintTest : LintDetectorTest() {override fun getDetector(): Detector = ToastDetector()fun testMissingShow() {val code = """import android.widget.Toast;import android.content.Context;class Example {void test(Context context) {Toast.makeText(context, "test", Toast.LENGTH_SHORT);}}""".trimIndent()lint().files(java(code),// 添加必要依赖的stub文件*kotlin("""package android.widget;public class Toast {public static Toast makeText(Context c, String s, int d) { return null; }public void show() {}}""").indented()).issues(ToastDetector.ISSUE).run().expect("""|src/Example.java:6: Error: 必须调用 show() 方法显示 Toast [ToastShowMissing]|        Toast.makeText(context, "test", Toast.LENGTH_SHORT);|        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|1 errors, 0 warnings""".trimMargin())}
}

六、发布规则(可选)

  1. 打包为 AAR/JAR
./gradlew :custom-lint:assemble
  1. 发布到 Maven 仓库:
// 在 custom-lint 的 build.gradle 中添加
publishing {publications {create<MavenPublication>("lint") {groupId = "com.example"artifactId = "custom-lint"version = "1.0.0"from(components["java"])}}
}

高级技巧

  1. 检测 XML 布局
class XmlDetector : ResourceXmlDetector() {override fun getApplicableAttributes(): Collection<String> = listOf("textSize")override fun visitAttribute(context: XmlContext, attribute: Attr) {if (attribute.value.endsWith("sp")) {context.report(ISSUE, attribute, context.getValueLocation(attribute),"建议使用 dp 代替 sp 作为尺寸单位")}}
}
  1. 快速修复支持
context.report(issue = ISSUE,location = context.getLocation(node),message = "问题描述",quickfixData = LintFix.create().replace().text("旧代码").with("新代码").build()
)

注意事项:

  1. 保持 Lint API 版本与 AGP 版本一致
  2. 使用 ./gradlew lint 进行测试
  3. 通过 lint.debug = true 启用调试日志
  4. 在 Android Studio 的 Preferences | Editor | Inspections 中启用自定义检查

通过以上步骤,您可以创建针对团队特定编码规范的自定义 Lint 规则,有效提升代码质量和一致性。

相关文章:

  • 沉石鱼惊旋
  • [ARM][架构] 02.AArch32 程序状态
  • GPT-4o 风格提示词案例大全(持续更新 ing...)
  • AE THYRO-AX 功率控制器 THYRISTOR-LEISTUNGSSTELLER THYRISTOR POWER CONTROLLER
  • Kotlin学习34-data数据类1
  • uniapp开发小程序,如何根据权限动态配置按钮或页面内容
  • 【Java学习笔记】抽象类
  • Redis 性能优化:核心技术、技巧与最佳实践
  • C++(4)
  • 第7章:Zephyr 的低功耗机制
  • 跟着华为去变革 ——读《常变与长青》有感
  • 读懂 std::true_type 和 std::false_type
  • 2025年- H52-Lc160--114. 二叉树展开为链表(前序遍历 + 用栈 + 原地修改)--Java版
  • 04_redis之ZSet使用实例-积分榜
  • leetcode-295 Find Median from Data Stream
  • Wan2.1 图生视频 多卡推理批量生成视频
  • 视频问答功能播放器(视频问答)视频弹题功能实例
  • ffmpeg转换竖屏(画面是横屏旋转90度的竖屏文件格式)视频到横屏
  • 网易互娱游戏研发实习一面
  • 在 ElementUI 中实现 Table 单元格合并
  • 做宠物网站赚钱吗/公众号软文素材
  • 北京住房和城乡建设局门户网站/搜索优化指的是什么
  • 广东广东网站建设工作/推广营销app
  • css网站布局原码/微信公众号营销
  • 小企业做网站/百度软件优化排名
  • 百度提交网站的入口地址/杭州做搜索引擎网站的公司