告别繁琐配置:Catchpig Detekt Plugin 让 Kotlin/Android 代码检查开箱即用

告别繁琐配置:Catchpig Detekt Plugin 让 Kotlin/Android 代码检查开箱即用

前言

在 Kotlin/Android 项目中,保证代码质量是每个团队都在努力的事情。detekt 作为 Kotlin 生态最流行的静态代码分析工具,相信大家都不陌生。但实际项目中,配置 detekt 往往是一件繁琐的事情:

  • 需要在每个模块的 build.gradle.kts 中手动配置
  • 规则集需要单独管理
  • 与 CI/CD 的集成需要额外步骤
  • 多模块项目配置更是指数级复杂

今天要介绍的 Catchpig Detekt Plugin,正是为了解决这些痛点而生。它是一个 Gradle 插件,只需几行配置,就能在打包时自动完成代码质量检查。

项目简介

Catchpig Detekt Plugin 是一款基于 detekt 构建的 Gradle 插件,专注于为 Android/Java 项目提供零配置的静态代码分析能力。

GitHub 地址 :github.com/catchpig/de...

核心特性

  • 零配置开箱即用 - 内置默认规则集,无需额外配置
  • 自动触发检查 - 打包时自动执行,无需手动运行
  • 多模块自动支持 - 自动递归应用到所有子项目
  • 灵活的构建类型控制 - 支持 debug/release/dev/all 等构建类型
  • 外部配置支持 - 可自定义 detekt.yml 配置文件路径

快速开始

1. 添加插件依赖

在 settings.gradle.kts 中添加 JitPack 仓库:

kotlin 复制代码
pluginManagement {
    repositories {
        maven { url = uri("https://jitpack.io") }
    }
}

2. 应用插件

在根项目的 build.gradle.kts 中应用插件:

kotlin 复制代码
plugins {
    id("com.github.catchpig.detekt-plugin") version "1.0.0"
}

3. 配置扩展属性(可选)

kotlin 复制代码
catchpigDetekt {
    // 触发检查的构建类型: "debug" (默认) / "release" / "dev" / "all"
    buildType = "debug"

    // 是否启用所有规则,默认 false
    allRules = false

    // 自定义 detekt.yml 配置文件路径
    configPath = null
}

4. 完成!自动检查

现在,在你执行打包命令时,detekt 会自动运行:

bash 复制代码
# Android Application 模块 - assembleDebug 时自动检查
./gradlew assembleDebug

# Android Library 模块 - compileDebugKotlin 时自动检查
./gradlew :mylibrary:compileDebugKotlin

# Java Library 模块 - compileJava 时自动检查
./gradlew :myjavalib:compileJava

支持的项目类型

项目类型 触发任务 检查时机
com.android.application assemble{BuildType} APK 打包时
com.android.library compile{BuildType}Kotlin Kotlin 编译时
java-library compileJava Java 编译时

配置详解

扩展属性说明

属性 类型 默认值 说明
buildType String "debug" 触发检查的构建类型
allRules Boolean false 是否启用所有规则
configPath String? null 自定义配置文件路径

buildType 可选值

值 行为
"debug" 仅在 debug 构建类型时触发(默认)
"release" 仅在 release 构建类型时触发
"dev" 仅在 dev 构建类型时触发
"all" 在所有构建类型时都触发

配置文件优先级

  1. configPath 扩展属性指定的外部配置
  2. 插件内置的默认规则集

自定义规则配置

如果需要使用自定义规则,只需指定配置文件路径:

kotlin 复制代码
catchpigDetekt {
    configPath = "config/detekt.yml"
}

注意:configPath 配置的路径是相对于根项目的路径。

内置规则集

插件内置的规则集覆盖了以下维度:

规则集 说明
comments 文档和注释相关规则
complexity 代码复杂度规则
coroutines 协程使用规范
empty-blocks 空代码块检查
exceptions 异常处理规范
naming 命名规范
performance 性能相关规则
potential-bugs 潜在 Bug 检测
style 代码风格规则

多模块项目支持

插件会自动递归应用到所有子项目。假设你的项目结构如下:

lua 复制代码
root/
├── app/
├── library/
├── common/
└── build.gradle.kts  <-- 插件配置在这里

只需在根项目的 build.gradle.kts 中配置一次,插件会自动将 detekt 能力传递到所有子模块。

实现原理简析

插件的核心实现基于 Gradle 的响应式编程模型,下面从几个关键维度来解析:

1. 双扩展机制

插件定义了两层扩展:

  • CatchpigDetektExtension :面向用户的 DSL 扩展,用户通过 catchpigDetekt { } 代码块配置
  • DetektExtension:detekt 官方扩展,用于配置 detekt 本身
kotlin 复制代码
// 创建用户配置扩展
val configExtension = target.extensions.create("catchpigDetekt", CatchpigDetektExtension::class.java)

// 获取官方 detekt 扩展并配置
val detektExtension = target.extensions.getByType(DetektExtension::class.java)
detektExtension.buildUponDefaultConfig = true  // 在默认配置基础上扩展
detektExtension.allRules = configExtension.allRules

2. 延迟配置策略

使用 plugins.withId() 实现延迟配置,这是插件实现的关键:

kotlin 复制代码
target.plugins.withId("com.android.application") {
    val taskPattern = if (buildType == "all") {
        { _: String -> true }  // 匹配所有 assemble 任务
    } else {
        { taskName: String -> taskName == "assemble$buildTypeCapitalized" }
    }
    target.tasks.matching { taskPattern(it.name) }.configureEach {
        dependsOn("detekt")  // assemble 任务依赖 detekt
    }
}

这样做的好处是:不用关心插件和应用插件的顺序,而是等到对应插件就绪后再响应式地追加配置。

3. 任务依赖绑定

通过 dependsOn("detekt") 将构建任务与检查任务绑定,确保打包前先完成代码检查:

项目类型 触发的构建任务 绑定的检查任务
Android Application assembleDebug detekt
Android Library compileDebugKotlin detekt
Java Library compileJava detekt

4. 配置文件加载策略

插件采用两级优先级的配置文件加载策略:

kotlin 复制代码
val externalConfig = configExtension.configPath?.let { target.rootProject.file(it) }
when {
    externalConfig != null && externalConfig.exists() -> {
        // 优先使用用户指定的外部配置
        detektExtension.config.setFrom(externalConfig)
    }
    else -> {
        // 降级到插件内置配置
        // 将 JAR 内资源复制到临时文件,因为 detekt 不支持 JAR URI
        val tempConfigFile = target.layout.buildDirectory.file("detekt-temp-config.yml").get().asFile
        if (!tempConfigFile.exists()) {
            tempConfigFile.writeText(javaClass.classClassLoader.getResourceAsStream("detekt.yml")!!.readText())
        }
        detektExtension.config.setFrom(tempConfigFile)
    }
}

5. 递归应用机制

仅在根项目执行时,将插件递归应用到所有子项目:

kotlin 复制代码
if (target == target.rootProject) {
    // 递归应用到所有子项目
    target.subprojects {
        plugins.apply(DetektPlugin::class.java)
    }

    // 创建 detektAll 任务,汇总所有子项目的检查结果
    target.tasks.create("detektAll") { ... }

    // 创建 checkWithDetekt 任务,完整的 CI 检查流程
    target.afterEvaluate {
        target.tasks.create("checkWithDetekt") { ... }
    }
}

6. 任务执行流程图

scss 复制代码
执行 ./gradlew assembleDebug
           │
           ▼
    ┌──────────────────┐
    │  assembleDebug   │
    │    (Android App) │
    └────────┬─────────┘
             │ dependsOn("detekt")
             ▼
    ┌──────────────────┐
    │     detekt       │
    │  (代码静态检查)   │
    └────────┬─────────┘
             │ no issues found
             ▼
    ┌──────────────────┐
    │  继续 APK 打包    │
    └──────────────────┘

通过这种设计,插件实现了:零配置 -> 自动触发 -> 多模块统一的体验。

环境要求

  • JDK 17+
  • Gradle 8.0+
  • Kotlin 项目或 Android 项目

结语

Catchpig Detekt Plugin 通过极简的配置,让 detekt 这把"利剑"变得触手可及。无需在每个模块中重复配置,无需记住复杂的命令,打包即检查,真正实现了代码质量检查的无感知化。

如果你正在为团队寻找一个低门槛的 Kotlin/Android 代码质量解决方案,不妨试试这个插件。

项目地址 :github.com/catchpig/de...

欢迎 Star & Fork & PR!


相关推荐
alexhilton9 小时前
生命周期感知的多模块启动模式
android·kotlin·android jetpack
hai_android15 小时前
LruCache 图片浏览器内存缓存
android·java·kotlin
mmsx20 小时前
Android 自定义 View 三关:触摸分发、绘制与坐标错位
android·kotlin
JMchen20 小时前
自定义View在复杂业务场景中的实战
android·kotlin·canvas
hai_android21 小时前
RecyclerView 缓存机制详解
android·kotlin·android jetpack
花开路口1 天前
深入理解 Java/Kotlin 协变与逆变
java·kotlin
mmsx1 天前
Android 一个设备多个 App 抢:跨进程共享服务的架构设计
android·kotlin·app
这个DBA有点耶1 天前
从异步复制到MGR:MySQL复制机制的三层演进与选型框架
数据库·mysql·代码规范
kisshyshy1 天前
《从屎山到秩序:Vibe Coding 95 驾驭术全公开》
人工智能·代码规范·vibecoding
hai_android1 天前
深入理解 Java 的四种引用:强引用、软引用、弱引用、虚引用
android·kotlin·android jetpack