|
|
|
@@ -1,4 +1,5 @@
|
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
import org.gradle.testing.jacoco.tasks.JacocoReport
|
|
|
|
|
import java.util.Properties
|
|
|
|
|
|
|
|
|
|
plugins {
|
|
|
|
@@ -9,6 +10,11 @@ plugins {
|
|
|
|
|
id("org.jetbrains.kotlin.plugin.compose")
|
|
|
|
|
id("com.google.devtools.ksp")
|
|
|
|
|
id("com.google.dagger.hilt.android")
|
|
|
|
|
// JaCoCo (Gradle built-in) — unit-test code-coverage reporting (issue #192). The base `jacoco`
|
|
|
|
|
// plugin auto-instruments the JVM `testDebugUnitTest` task; the jacocoTestReport task below turns
|
|
|
|
|
// its exec data into XML + HTML. AGP-9-safe: it does NOT apply org.jetbrains.kotlin.android (which
|
|
|
|
|
// ClassCastExceptions against AGP 9's built-in-Kotlin DSL — see CLAUDE.md) and touches no variant DSL.
|
|
|
|
|
jacoco
|
|
|
|
|
// Lint/format — resolved from the Gradle Plugin Portal (not the buildscript classpath).
|
|
|
|
|
alias(libs.plugins.ktlint)
|
|
|
|
|
alias(libs.plugins.detekt)
|
|
|
|
@@ -172,6 +178,85 @@ detekt {
|
|
|
|
|
config.setFrom(rootProject.file("config/detekt/detekt.yml"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pin a modern JaCoCo (version catalog) so the coverage agent understands Kotlin 2.4.0 bytecode
|
|
|
|
|
// on JDK 21.
|
|
|
|
|
jacoco {
|
|
|
|
|
toolVersion = libs.versions.jacoco.get()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unit-test coverage report (issue #192). Reads the exec data the base `jacoco` plugin records for
|
|
|
|
|
// the JVM `testDebugUnitTest` task, mapped against the debug variant's compiled Kotlin classes and
|
|
|
|
|
// the hand-written main sources. Produces machine-readable XML + human-readable HTML under
|
|
|
|
|
// build/reports/jacoco/jacocoTestReport/. Instrumented/E2E coverage is out of scope (issue #192).
|
|
|
|
|
tasks.register<JacocoReport>("jacocoTestReport") {
|
|
|
|
|
// Ensure the unit tests (and thus their coverage exec data) have run first.
|
|
|
|
|
dependsOn("testDebugUnitTest")
|
|
|
|
|
group = "verification"
|
|
|
|
|
description = "Generates JaCoCo XML + HTML coverage for the debug JVM unit tests."
|
|
|
|
|
|
|
|
|
|
reports {
|
|
|
|
|
xml.required.set(true)
|
|
|
|
|
html.required.set(true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Strip generated code from the denominator so the % reflects hand-written Kotlin. Verified
|
|
|
|
|
// against an actual compileDebugKotlin output tree: Room's KSP-generated `_Impl` DAOs/database
|
|
|
|
|
// and the Compose compiler's per-file ComposableSingletons holders are the only generated code
|
|
|
|
|
// that actually lands in classDirectories below (Room's KSP output is added as an extra Kotlin
|
|
|
|
|
// source root on the *same* compile task, so it comes out the same door as hand-written code).
|
|
|
|
|
// Hilt/Dagger's generated Java (Hilt_*, Dagger*_HiltComponents*, *_GeneratedInjector, *_Factory,
|
|
|
|
|
// *_MembersInjector, hilt_aggregated_deps) and AGP's BuildConfig/R/Manifest are compiled by a
|
|
|
|
|
// separate javac task (hiltJavaCompileDebug / compileDebugJavaWithJavac) into a directory this
|
|
|
|
|
// report never reads, so those patterns are conventional belt-and-suspenders in case that ever
|
|
|
|
|
// changes. DataBinding isn't enabled in this module (no buildFeatures.dataBinding/viewBinding),
|
|
|
|
|
// so there's nothing generated for it to exclude; if it's turned on later, add "**/BR.class",
|
|
|
|
|
// "**/DataBinderMapperImpl*.class" and "**/*Binding.class".
|
|
|
|
|
//
|
|
|
|
|
// Deliberately NOT excluded: Kotlin's own `$$inlined$` synthetic classes (e.g. for
|
|
|
|
|
// `Flow.map { ... }` in the repositories) — those hold real hand-written transform logic, not
|
|
|
|
|
// generated boilerplate, so stripping them would silently shrink the measured surface.
|
|
|
|
|
val generated = listOf(
|
|
|
|
|
"**/R.class",
|
|
|
|
|
"**/R\$*.class",
|
|
|
|
|
"**/BuildConfig.*",
|
|
|
|
|
"**/Manifest*.*",
|
|
|
|
|
"**/Hilt_*.class",
|
|
|
|
|
"**/Dagger*.class",
|
|
|
|
|
"**/*_Hilt*",
|
|
|
|
|
"**/*_GeneratedInjector.class",
|
|
|
|
|
"**/hilt_aggregated_deps/**",
|
|
|
|
|
"**/dagger/**",
|
|
|
|
|
"**/*_Factory*",
|
|
|
|
|
"**/*_MembersInjector*",
|
|
|
|
|
"**/*_Provide*",
|
|
|
|
|
"**/*_Impl*",
|
|
|
|
|
"**/ComposableSingletons*",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Classes = the debug variant's compiled Kotlin (AGP 9 built-in Kotlin output). All hand-written
|
|
|
|
|
// code here is Kotlin, so the javac output (purely Hilt/Dagger/BuildConfig generated) is omitted.
|
|
|
|
|
val debugKotlinClasses = layout.buildDirectory.dir(
|
|
|
|
|
"intermediates/built_in_kotlinc/debug/compileDebugKotlin/classes",
|
|
|
|
|
)
|
|
|
|
|
classDirectories.setFrom(
|
|
|
|
|
fileTree(debugKotlinClasses) { exclude(generated) },
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Sources = hand-written main Kotlin.
|
|
|
|
|
sourceDirectories.setFrom(files("src/main/kotlin"))
|
|
|
|
|
|
|
|
|
|
// Exec data written by the instrumented testDebugUnitTest task. Accept the base `jacoco` plugin's
|
|
|
|
|
// default location and AGP's enableUnitTestCoverage location so the wiring is robust either way.
|
|
|
|
|
executionData.setFrom(
|
|
|
|
|
fileTree(layout.buildDirectory) {
|
|
|
|
|
include(
|
|
|
|
|
"jacoco/testDebugUnitTest.exec",
|
|
|
|
|
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dependencies {
|
|
|
|
|
implementation(libs.androidx.core.ktx)
|
|
|
|
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
|
|
|
|