mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
7.2 KiB
7.2 KiB
Skill: Code Review
Description
Perform comprehensive code reviews for Meshtastic-Android, ensuring changes adhere to KMP architecture, Kotlin Multiplatform conventions, MAD standards, and CMP best practices.
Code Review Checklist
When reviewing code, meticulously verify the following categories. Flag any deviations and propose the canonical project pattern as a fix.
1. KMP Architecture & Source Set Boundaries
- No Platform Bleed: Ensure absolutely no
java.*orandroid.*imports exist incommonMainsource sets. - KMP Native Alternatives: Verify the use of KMP alternatives for standard JVM libraries:
java.util.concurrent.locks.*->kotlinx.coroutines.sync.Mutexjava.util.concurrent.ConcurrentHashMap->atomicfuor Mutex-guardedmutableMapOf()java.io.*->Okio(BufferedSource/BufferedSink)java.util.Locale-> Kotlinuppercase()/lowercase()(purged fromcommonMain)
- Coroutine Safety: Use
safeCatching {}fromcore:commoninstead ofrunCatching {}in coroutine/suspend contexts.runCatchingsilently swallowsCancellationException, breaking structured concurrency. KeeprunCatchingonly in cleanup/teardown code (abort, close, eviction). Usekotlinx.coroutines.CancellationException(notkotlin.coroutines.cancellation.CancellationException). - Shared Helpers: If
androidMainandjvmMaincontain identical pure-Kotlin logic, mandate extracting it to a shared function incommonMain. - File Naming Conflicts: For
expect/actualdeclarations, ensure files sharing the same package namespace have distinct names (e.g., keepexpectinLogExporter.ktand shared helpers inLogFormatter.kt) to avoid duplicate class errors on the JVM target. - Interface & DI Over
expect/actual: Check thatexpect/actualis reserved for small platform primitives. Interfaces + DI should be preferred for larger capabilities.
2. UI & Compose Multiplatform (CMP)
- Compose Multiplatform Resources: Ensure NO hardcoded strings. Must use
core:resources(e.g.,stringResource(Res.string.key)or asynchronousgetStringSuspend(Res.string.key)for ViewModels/Coroutines). NEVER use blockinggetString()in a coroutine. - String Formatting: CMP only supports
%N$sand%N$d. Flag any float formats (%N$.1f) in Compose string resources; they must be pre-formatted usingNumberFormatter.format()fromcore:common. UseMetricFormatterfor metric-specific displays (temperature, voltage, current, percent, humidity, pressure, SNR, RSSI). - Centralized Dialogs & Alerts: Flag inline alert-rendering logic. Mandate the use of
AlertHost(alertManager)orSharedDialogsfromcore:ui/commonMain. - Placeholders: Require
PlaceholderScreen(name)fromcore:ui/commonMainfor unimplemented desktop/JVM features. No inline placeholders in feature modules. - Adaptive Layouts: Verify use of
currentWindowAdaptiveInfo(supportLargeAndXLargeWidth = true)to support desktop/tablet breakpoints (≥ 1200dp).
3. Navigation & State
- Shared Navigation Graphs: Feature navigation graphs must be defined as extension functions on
EntryProviderScope<NavKey>incommonMain(e.g.,fun EntryProviderScope<NavKey>.settingsGraph(...)). Flag any graphs defined in platform-specific source sets. - Navigation Host: Ensure
MeshtasticNavDisplay(fromcore:ui/commonMain) is used as the host instead of invokingNavDisplaydirectly. Host modules should not configureentryDecoratorsthemselves. - ViewModel Scoping: ViewModels obtained via
koinViewModel()must be insideentry<T>blocks to correctly tie to the backstack lifetime.
4. Dependency Injection (Koin Annotations)
- Annotation Usage: Ensure Koin is configured via annotations (
@Single,@Factory,@KoinViewModel). - Root Assembly: Confirm that the root Koin DI graph is only assembled in host shells (
appanddesktop).
5. Networking, DB & I/O
- Ktor Strictly: Check that Ktor is used for all HTTP networking. Flag and reject any usage of OkHttp.
- HTTP Configuration: Verify timeouts and base URLs use
HttpClientDefaultsfromcore:network. Never hardcode timeouts in feature modules.DefaultRequestsets the base URL; feature API services use relative paths. - Image Loading (Coil): Coil must use
coil-network-ktor3in host modules. Feature modules should ONLY depend onlibs.coil(coil-compose) and never configure fetchers. - Room KMP: Ensure
factory = { MeshtasticDatabaseConstructor.initialize() }is used inRoom.databaseBuilder. DAOs and Entities must reside incommonMain. - Room Patterns: Verify use of
@Upsertfor insert-or-update logic. Check forLIMIT 1on single-row queries. Flag N+1 query patterns (loops calling single-row queries) — batch with chunkedWHERE INinstead. - Bluetooth (BLE): All Bluetooth communication must be routed through
core:bleusing Kable abstractions.
6. Dependency Catalog Aliases
- JetBrains vs. AndroidX:
- In
commonMain: Must usejetbrains-*aliases (e.g.,jetbrains-lifecycle-*,jetbrains-navigation3-ui). - In
androidMain: Can useandroidx-*orjetbrains-*as appropriate, but do not mix them up incommonMain.
- In
- Compose Multiplatform: Ensure
compose-multiplatform-*aliases are used instead of plainandroidx.composein all KMP modules.
7. Testing
- Test Placement: New Compose UI tests must go in
commonTestusingrunComposeUiTest {}fromandroidx.compose.ui.test.v2(not the deprecated v1androidx.compose.ui.testpackage) +kotlin.test.Test. Do not addandroidTest(instrumented) tests. - Shared Test Utilities: Test fakes, doubles, and utilities should be placed in
core:testing. - Libraries: Verify usage of
Turbinefor Flow testing,Kotestfor property-based testing, andMokkeryfor mocking. - Robolectric Configuration: Check that Compose UI tests running via Robolectric on JVM are pinned to
@Config(sdk = [34])to prevent Java 21 / SDK 35 compatibility issues.
8. ProGuard / R8 Rules
- New Dependencies: If a new reflection-heavy dependency is added (DI, serialization, JNI, ServiceLoader), verify keep rules exist in both
app/proguard-rules.pro(R8) anddesktop/proguard-rules.pro(ProGuard). The two files must stay aligned. - Release Smoke-Test: For dependency or ProGuard rule changes, verify
assembleReleaseand./gradlew :desktop:runReleasesucceed.
Review Output Guidelines
- Be Specific & Constructive: Provide exact file references and code snippets illustrating the required project pattern.
- Reference the Docs: Cite
AGENTS.mdand project architecture playbooks to justify change requests (e.g., "Per AGENTS.md,java.io.*cannot be used incommonMain; please migrate to Okio"). - Enforce Build Health: Remind authors to run
./gradlew test allTestslocally to verify changes, especially since KMPtesttasks are ambiguous. - Praise Good Patterns: Acknowledge correct usage of complex architecture requirements, like proper Navigation 3 scene transitions or elegant
commonMainhelper extractions.