Skip to content

fix(auth)!: resolve the 12 baselined Compose lint findings - #2502

Closed
demolaf wants to merge 1 commit into
ci/run-android-lint-in-the-buildfrom
claude/hopeful-bassi-7986ee
Closed

fix(auth)!: resolve the 12 baselined Compose lint findings#2502
demolaf wants to merge 1 commit into
ci/run-android-lint-in-the-buildfrom
claude/hopeful-bassi-7986ee

Conversation

@demolaf

@demolaf demolaf commented Sep 9, 2026

Copy link
Copy Markdown
Member

auth/lint-baseline.xml shipped with 12 Compose findings suppressed alongside CPRN-432's
168 localization entries, so the new lint gate could go green before the code behind them
was fixed. This fixes all 12 and removes exactly those entries; the 168 localization ones
are untouched.

MutableCollectionMutableState at MfaEnrollmentScreen.kt:159 was the only one with
runtime consequences, though not the ones the check warns about. Nothing mutated that
collection in place, so there was no missed recomposition today. The hazard was at the two
enrolledFactors.value = user.multiFactor.enrolledFactors sites, where the SDK hands back
its own MutableList: had it ever returned the same instance it had just mutated,
MutableState's structural-equality check would have compared the list against itself and
skipped the update. The state now holds an immutable List<MultiFactorInfo> and both
assignments snapshot with toList(), which closes that off and satisfies the check.
MfaEnrollmentContentState and MfaEnrollmentDefaults already declared List, so nothing
downstream changed.

The 7 LocalContextGetResourceValueCall sites could not all become stringResource().
Six are not in composable scopes at all: five sit in LaunchedEffect bodies in
FirebaseAuthScreen, and AuthTextField's is inside a Modifier.semantics {} lambda.
Those now resolve in composition and close over the result, which also means a
configuration change is observed — something LocalContext.current.getString(...) never
did. Only SignInUI.kt:245 was a direct read in composition. None of the seven were
deliberate AuthUIStringProvider routing: the provider exposes no slot for any of the
five strings involved, so keeping them on the resource path is the smaller change. Worth
raising separately that FirebaseAuthUI.kt:432 and :568 build AuthState.Loading from
context.getString(R.string.fui_loading_signing_out) while DefaultAuthUIStringProvider
already exposes loadingSigningOut for that exact string — the provider is partly
bypassed by the runtime, which is its own piece of work.

ComposableLambdaParameterPosition is the breaking part. customLayout moves to the last
parameter of the public AuthMethodPicker, and content to the last of the internal
EmailAuthStep. All 28 AuthMethodPicker call sites in the repo (3 in main, 25 in
tests) and both EmailAuthStep ones pass named arguments, so nothing here changed — but
an external positional caller of AuthMethodPicker would break. Acceptable pre-GA at
10.0.0. The KDoc @param order follows the signature.

NonObservableLocale at MfaEnrollmentDefaults.kt:399 read java.util.Locale.getDefault()
in a composable. It now reads LocalLocale.current, which resolves the Activity's
configured locale rather than the process global. The two disagree when a host installs a
per-context locale override, and the date was then rendering in a different language from
every stringResource beside it. androidx.compose.ui.text.intl.Locale.current would not
have fixed that — it silences the detector but resolves through AndroidLocaleDelegateAPI24
to the same process-global android.os.LocaleList. The SimpleDateFormat also moved into a
remember keyed on the locale; it was previously reconstructed on every recomposition.
LocalLocale is new in compose-ui 1.11, which the BOM already pins well past.

ComposableNaming is test-only: ReauthScopeProbe.capture() becomes Capture(), with its
27 call sites across three test files.

The lint { } baseline comment in auth/build.gradle.kts no longer claims the file holds
Compose findings, since it now holds only CPRN-432's localization entries.

./scripts/build.sh and ./gradlew lintAll are both clean — lint runs in its own
workflow now rather than inside the script. :auth lint reports no new issues with 168
filtered by baseline, and the baseline diff is 132 deletions with no additions. :auth
unit tests are 78 classes / 990 tests, no failures.


Note: stacked on #2498 — needs a rebase once that lands.


Maintainer note: Fixes internal CPRN-436

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request resolves several Compose correctness and localization issues, allowing the removal of suppressed issues from the lint baseline. Key changes include resolving string resources within composable scopes, moving composable lambda parameters to the end of function signatures, respecting per-context locale overrides, snapshotting mutable SDK lists to trigger recomposition, and capitalizing composable test functions. The feedback suggests using a locale-sensitive date format instead of a hardcoded pattern to ensure proper internationalization.

Comment on lines +370 to +372
val enrollmentDateFormat = remember(locale) {
java.text.SimpleDateFormat("MMM dd, yyyy", locale.platformLocale)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While using LocalLocale.current is a great improvement for localization, the date format string "MMM dd, yyyy" is hardcoded. This format is not suitable for all locales (e.g., many European locales use dd.MM.yyyy).

To properly internationalize the date, you should use a locale-sensitive date format provided by java.text.DateFormat. This will ensure the date is displayed in a format that is familiar to users in different regions.

Suggested change
val enrollmentDateFormat = remember(locale) {
java.text.SimpleDateFormat("MMM dd, yyyy", locale.platformLocale)
}
val enrollmentDateFormat = remember(locale) {
java.text.DateFormat.getDateInstance(java.text.DateFormat.MEDIUM, locale.platformLocale)
}

@demolaf
demolaf force-pushed the ci/run-android-lint-in-the-build branch 2 times, most recently from 64ce7cf to 4f2b154 Compare September 9, 2026 13:35
@demolaf
demolaf force-pushed the claude/hopeful-bassi-7986ee branch from d6efbb2 to 6b4bbe9 Compare September 9, 2026 13:44
@demolaf demolaf closed this Sep 9, 2026
@github-project-automation github-project-automation Bot moved this from Backlog to Done in studio-2394994192-60a69 Sep 9, 2026
@demolaf
demolaf deleted the claude/hopeful-bassi-7986ee branch September 9, 2026 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant