skydoves / skydoves/compose-stability-analyzer

[Gradle] Distinguish non-Unit-return false positives from real instability in stability dump

Open
#205 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
1.7k
Forks
42
Avg merge
13h 5m
Merged PRs (30d)
6

Description

Is your feature request related to a problem?

Every @Composable function that returns a non-Unit value is reported as skippable: false and restartable: false in the .stability dump, no matter how stable its parameters are. This is expected Compose compiler behavior — the compiler only generates skip/restart group logic for Unit-returning composables, since skipping means "do nothing and return", which isn't possible when a value must be produced. It is not a real stability regression.

The dump gives no way to distinguish this compiler-inherent case from an actual problem (unstable/unknown params). Minimal repro:

@Composable
private fun borderColor(enabled: Boolean): Color =
    if (enabled) Color.Red else Color.Gray

Generated dump (unstableOnly = true):

@Composable
private fun com.example.borderColor(enabled: kotlin.Boolean): androidx.compose.ui.graphics.Color
  skippable: false
  restartable: false
  params:
    - enabled: STABLE (primitive type)

enabled is STABLE and there are no other params, yet the function is still flagged — purely because it returns Color instead of Unit. In a large codebase this produces a steady stream of dump entries that reviewers have to manually re-verify are non-issues every time, and CI/baseline diffing can't tell them apart from genuine regressions.

Describe the solution you'd like:

Give consumers a way to separate "flagged only because of non-Unit return type, params otherwise stable" from real instability, for example:

  • Per-entry metadata, e.g. nonSkippableReason: NON_UNIT_RETURN_TYPE, when skippable/restartable are false solely because the return type isn't Unit and every param is STABLE.
  • Or a stabilityValidation { } option (alongside the existing unstableOnly) such as ignoreNonUnitReturnFalsePositives = true that excludes these entries from the dump entirely.

Describe alternatives you've considered:

We currently post-process the generated .stability file ourselves in the consuming Gradle module: parsing the skippable: / restartable: / params: lines with regex to strip out entries matching this pattern, and deleting the file once nothing else is left. It works, but it's brittle text-parsing against a format the plugin explicitly says not to hand-edit, and it will silently break if the dump format ever changes.

Environment

  • com.github.skydoves.compose.stability.analyzer plugin: 0.13.0
  • Kotlin / Compose compiler plugin: 2.4.10
  • Gradle: 9.5.0

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing how the plugin generates the .stability dump and how the existing unstableOnly option filters entries. Compare the proposed metadata and filtering approaches against the non-Unit example, then verify that stable-parameter non-Unit composables can be distinguished from genuine instability without brittle consumer-side parsing.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
build-system, tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.