告别繁琐配置: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!


相关推荐
Fate_I_C5 小时前
Kotlin 内部类和嵌套类
java·开发语言·kotlin
steem_ding6 小时前
AI-代码扫描工具
代码规范
Ww.xh7 小时前
Flutter配置Gradle完整教程
flutter·gradle·android studio
千码君20167 小时前
kotlin:jetpack compose 生成动态可控的动画
vue.js·elementui·kotlin
许杰小刀17 小时前
ctfshow-web文件包含(web78-web86)
android·前端·android studio
alexhilton1 天前
Jetpack Compose元球边缘效果
android·kotlin·android jetpack
Kiri霧1 天前
Kotlin递归
android·开发语言·kotlin
普通网友1 天前
Android开发:使用Kotlin+协程+自定义注解+Retrofit的网络框架
android·kotlin·retrofit
常利兵1 天前
Kotlin抽象类与接口:相爱相杀的编程“CP”
android·开发语言·kotlin