Skip to content

Expand detekt coverage to Android flavor and device-test sources #123

Description

@altaywtf

Problem

The current detekt source discovery omits Android flavor and device-test Kotlin roots. A clean configured gate therefore does not establish that all Android source sets were checked.

A preserved candidate explicitly selects app/src and extends only detekt’s bundled test exclusions to the actual Android flavor-test paths. Its last measured inventory covered 139 Kotlin files and reported five structural findings. No baseline, production exclusion, or threshold increase is proposed.

Remaining work

  • Reconcile the coverage candidate onto current main after refactor(mobile): simplify state ownership and navigation wiring #122 lands.
  • Resolve the five findings through useful ownership or logic improvements: MobileAuthController function count (16); MobileReadyVideoPlayer complexity (27); TransferItem.statusLabel complexity (16); SignedInMobileRoot readiness condition (5); readyPlayerSubtreeCanBeRemovedAndRecreated length (87).
  • Preserve exhaustive status handling, single ownership of player/auth state, controller readiness behavior, and the full retained-position lifecycle regression. Do not introduce parameter bags, forwarding helpers, or arbitrary file/class splits merely to satisfy counters.
  • Enable explicit app/src discovery and document it in AGENTS only once the expanded gate passes.

Acceptance

  • The detekt task’s actual input inventory includes every intended shared, mobile, TV, and device-test Kotlin root. Record the current count; 139 is historical evidence, not a permanent target.
  • Temporary negative probes in the six previously omitted roots each fail detekt; remove probes afterward and confirm no exclusions, baseline, or thresholds hide production findings.
  • The full canonical gate, codegen tests, both debug assemblies, and behavior proof for changed owners pass on the final app/SDK pair.
  • Run exact-final independent review and publish the repository-required runtime evidence for behavior-sensitive changes.

Until this follow-up lands, detekt retains its existing configured source coverage. The separate source-cleanup PR #122 does not close this gap.

Preserved three-file coverage candidate (reconcile before applying)
diff --git a/AGENTS.md b/AGENTS.md
index ce5f389..e9df57e 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -53,7 +53,8 @@ SDK root resolution everywhere: `ANDROID_HOME` → `ANDROID_SDK_ROOT` →

verify runs Android Lint (warningsAsErrors, config in app/lint.xml),
-detekt (config in detekt.yml, Compose exemptions only), the local unit
+detekt over all Kotlin sources under app/src/, including flavor and device-test
+source sets (config in detekt.yml, Compose exemptions only), the local unit
tests (app/src/test/, JUnit4 + Robolectric, Compose UI assertions run on
the JVM), and an unsigned minified mobileProductionRelease build that proves
the composite Kotlin SDK against minSdk 26 and R8. :buildSrc:test covers the
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 968e409..511ab51 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -118,6 +118,8 @@ androidComponents {
}

detekt {

  • // Detekt 1.x does not discover flavor sources through AGP's built-in Kotlin support.
  • source.setFrom("src")
    config.setFrom(rootProject.file("detekt.yml"))
    buildUponDefaultConfig = true
    }
    diff --git a/detekt.yml b/detekt.yml
    index 328b81a..2d9db8b 100644
    --- a/detekt.yml
    +++ b/detekt.yml
    @@ -1,10 +1,23 @@

detekt configuration (merged on top of the bundled defaults via

buildUponDefaultConfig). Only deviations from the defaults live here —

mostly Compose idioms the default Kotlin rules reject.

+# Keep bundled test exclusions aligned with Android flavor test source sets.

naming:
FunctionNaming:
ignoreAnnotated: ['Composable']

  • excludes: &testSources
  •  - '**/test/**'
    
  •  - '**/androidTest/**'
    
  •  - '**/commonTest/**'
    
  •  - '**/jvmTest/**'
    
  •  - '**/androidUnitTest/**'
    
  •  - '**/androidInstrumentedTest/**'
    
  •  - '**/jsTest/**'
    
  •  - '**/iosTest/**'
    
  •  - '**/testMobile/**'
    
  •  - '**/testTv/**'
    
  •  - '**/androidTestMobile/**'
    

complexity:
LongMethod:
@@ -12,10 +25,42 @@ complexity:
LongParameterList:
ignoreAnnotated: ['Composable']
TooManyFunctions:

  • excludes: *testSources
    ignoreAnnotatedFunctions: ['Composable', 'Preview']

+exceptions:

  • InstanceOfCheckForException:
  • excludes: *testSources
  • ThrowingExceptionsWithoutMessageOrCause:
  • excludes: *testSources
  • TooGenericExceptionCaught:
  • excludes: *testSources

+performance:

  • ForEachOnRange:
  • excludes: *testSources
  • SpreadOperator:
  • excludes: *testSources

+potential-bugs:

  • UnsafeCallOnNullableType:
  • excludes: *testSources

style:
MagicNumber:

  • excludes:
  •  - '**/test/**'
    
  •  - '**/androidTest/**'
    
  •  - '**/commonTest/**'
    
  •  - '**/jvmTest/**'
    
  •  - '**/androidUnitTest/**'
    
  •  - '**/androidInstrumentedTest/**'
    
  •  - '**/jsTest/**'
    
  •  - '**/iosTest/**'
    
  •  - '**/testMobile/**'
    
  •  - '**/testTv/**'
    
  •  - '**/androidTestMobile/**'
    
  •  - '**/*.kts'
    
    ignoreAnnotated: ['Composable']
    UnusedPrivateMember:
    ignoreAnnotated: ['Preview']

</details>

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions