マルチモジュールなプロジェクトでdetektをComposite Buildsにまとめて各モジュールに適用する
/ 6 min read
Updated:Table of Contents
はじめに
Kotlin向けの静的解析ツールにdetektというツールがあります。今回はフォーマッターとしてdetektをマルチモジュールなプロジェクトに適用したいと思い使ってみました。
普通に各モジュールに適用するだけでもいいのですが設定を各モジュールに書くと大変なので、GradleのComposite Buiildsを使ってdetektの設定をプラグインとして切り出し、各モジュールは切り出した自作プラグインを適用するだけにします。
Composite Buiildsは、droidkaigiやnowinandroidでも使われていてAndroidエンジニアとしても勉強せねば…というモチベーションで使ってみました。
GitHub - DroidKaigi/conference-app-2024: The Official Conference App for DroidKaigi 2024
実際に作ったコードはGitHub上に公開しています。
実装
今回使っているライブラリのバージョンは以下の通りです。
[versions]detekt = "1.23.7"detektComposeRule = "0.4.16"
[libraries]detektGradlePlugin = { group = "io.gitlab.arturbosch.detekt", name = "detekt-gradle-plugin", version.ref = "detekt" }detektFormatting = { group = "io.gitlab.arturbosch.detekt", name = "detekt-formatting", version.ref = "detekt" }detektComposeRule = { group = "io.nlopez.compose.rules", name = "detekt", version.ref = "detektComposeRule" }
[plugins]detektGradlePlugin = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
[bundles]plugins = [ "detektGradlePlugin"]bundlesのpluginsは書かなくてもいいのですが、このように書いたほうが複数のプラグインを使う時に楽なのでまとめています(droidkaigiがこの書き方で参考にしました)。
dependencies { // 一行で済む implementation(libs.bundles.plugins)}Composite Buiildsはモジュールではなくサブプロジェクトとして作るようなので、メインのプロジェクトで使っているVersion Catalogをサブプロジェクトからも見えるように設定を書きます。今回はbuild-logicという名前で作成しました。droidkaigiやnowinandroidや解説サイトでもこの名前が多かったので参考にしました。
どうしてサブプロジェクトとして作るのかはあまり理解できてないので、そこら辺の理解も深めたい…
dependencyResolutionManagement { repositories { google() mavenCentral() } versionCatalogs { create("libs") { from(files("../gradle/libs.versions.toml")) } }}Version Catalogで定義したライブラリやプラグイン名をlibs で取れるようにしたいので、設定を追加します。
internal val Project.libs: VersionCatalog get() = extensions.getByType<VersionCatalogsExtension>().named("libs")detektの設定を書きます。普通だったらbuild.gradle.ktなどに書いていく設定をここに書きます。
class DetektPlugin : Plugin<Project> {
override fun apply(target: Project) { with(target) { // build.gradleでapply("hogefuga")している pluginManager.apply("io.gitlab.arturbosch.detekt") // detektを適用するディレクトリなどを設定 val fileTree = project.files("./").asFileTree.matching { include("**/*.kt") include("**/*.kts") exclude("**/build/**") exclude("**/resources/**") } val extension = extensions.getByType<DetektExtension>() // build.gradleのdetektブロックでする設定 extension.apply { buildUponDefaultConfig = true autoCorrect = true config.setFrom(project.files("${project.rootProject.rootDir}/config/detekt.yml")) debug = true source.setFrom(fileTree) }
dependencies { // detektPluginsを使って適用するライブラリ // フォーマッタとJetpack Composeのライブラリを追加 "detektPlugins"(libs.findLibrary("detektFormatting").get()) "detektPlugins"(libs.findLibrary("detektComposeRule").get()) } } }}DetektPluginで自作したプラグインをGradleのプラグインとして登録します。
gradlePlugin { plugins { register("detekt") { id = "love.aespa.nemomemo.detekt" implementationClass = "DetektPlugin" } }}これでlove.aespa.nemomemo.detektという名前でプラグインを使えるようになったので各モジュールに設定します。
plugins { id("love.aespa.nemomemo.detekt")}detektの準備が整ったので、設定ファイルを生成しコードを整形します。
detektの設定ファイルを生成 ./gradlew detektConfig detektを使ってコードを整形 ./gradlew detekt --auto-correct終わりに
マルチモジュールなプロジェクトでComposite Buidsを使ってdetektの設定をプラグインとしてまとめ、各モジュールに適用する方法を説明しました。
Composite Buildsを使うことで設定をまとめることでき、コードの見通しが非常によくなりました。しかし、Composite Builds自体の設定が難しいのでこれをチームに導入するには、チームの認識を揃えてからにしないと使われなくなりそう…と感じました。
自分も人に説明できるくらいには理解して使いこなせるようになりたいです!
参考文献
- Hello from detekt | detekt
- Composite Builds
- DroidKaigi/conference-app-2024: The Official Conference App for DroidKaigi 2024
- android/nowinandroid: A fully functional Android app built entirely with Kotlin and Jetpack Compose
- https://bps-e.com/dev/android-tool-001/
- Androidプロジェクトでbuild-logicの整理をしたときのメモ #gradle - Qiita