Skip to content

build: update Metalava to 0.5.0 - #3935

Merged
AlvaroBrey merged 2 commits into
mainfrom
build/bump-metalava
Aug 11, 2026
Merged

build: update Metalava to 0.5.0#3935
AlvaroBrey merged 2 commits into
mainfrom
build/bump-metalava

Conversation

@AlvaroBrey

@AlvaroBrey AlvaroBrey commented Aug 11, 2026

Copy link
Copy Markdown
Member

Part of the AGP 9 upgrade pre-work, split out standalone because it doesn't need the Kotlin bump to justify it and shouldn't be entangled with it.

  • Metalava's Kotlin-metadata reading is out of date: it will silently drop the throws clause it synthesizes from @Throws once the repo's Kotlin compiler moves past 2.0.x (a follow-up PR bumps Kotlin), so this needs to land ahead of that.
  • api*.txt diff is large but fully audited: every change is either correctly excluding @InternalRevenueCatAPI/@JvmSynthetic members that were leaking into the tracked API surface before, a methodproperty rendering fix that also corrects several value-class-typed members previously shown with their erased type, or new informational @InaccessibleFromKotlin/@KotlinOnly annotations on members that were otherwise unchanged.
    • @InaccessibleFromKotlin: the member is callable from Java but not from Kotlin source. Shows up on the JVM getter Kotlin auto-generates for its own properties, since Kotlin only ever calls those via property syntax, never the raw getter name.
    • @KotlinOnly: the member is callable from Kotlin but not meaningfully from Java. Shows up on @JvmSynthetic methods (already hidden from Java) and @Composable functions
  • No real, currently-supported public API was removed. Verified with a systematic name-level diff across all 6 files, plus javap spot checks against the actual compiled bytecode.
  • Second commit excludes AGP's generated BuildConfig, which 0.5.0 started pulling into the dumps (thanks @cursor). It isn't part of the SDK contract, and it made the dump non-deterministic: ENABLE_EXTRA_REQUEST_LOGGING comes from the git-ignored local.properties, and BILLING_CLIENT_VERSION would force an api*.txt regeneration on any unrelated Billing Client bump. Verified by flipping that flag locally: api-check.sh stays clean now, where before it would have produced a diff.

Checklist

  • If applicable, unit tests
  • If applicable, create follow-up issues for purchases-ios and hybrids
Agent description

Motivation

Part of the AGP 9 upgrade, split into small independently-shippable PRs, and further split out on
its own from the planned Kotlin 2.2.10 bump: Metalava doesn't need Kotlin to move to be worth
upgrading, and keeping it separate makes each PR's diff explainable on its own.

The concrete problem: me.tylerbwong.gradle.metalava 0.4.0-alpha03 can't fully parse the metadata
format a Kotlin 2.2 compiler produces. Confirmed by testing the pairing directly: with Kotlin
still at 2.0.21 (this PR), 0.4.0-alpha03 has no issue and getPackage()'s throws java.util.NoSuchElementException clause round-trips unchanged. Once Kotlin moves to 2.2.x (a
separate, later PR), the old Metalava starts emitting "Module was compiled with an incompatible
version of Kotlin... expected version is 2.0.0" and silently drops that clause from the tracked
signature file, even though the real compiled bytecode is unaffected (confirmed with javap).
Landing this first avoids that combination ever existing on main.

0.5.0's diff turned out to be much bigger than that one fix, so it needed its own audit before
being accepted:

  • Members backing @InternalRevenueCatAPI-annotated properties (e.g.
    Offering.getPaywall()/getPaywallComponents()) are now correctly excluded from the tracked
    surface. The old Metalava was leaking them in despite the hiddenAnnotations config already
    telling it to hide @InternalRevenueCatAPI.
  • @JvmSynthetic members (never callable from Java to begin with) are now also excluded, rather
    than tracked as if they were part of the Java-facing API surface.
  • Several methodproperty rendering changes also fix the underlying type shown for
    value-class-typed members, which the old Metalava rendered using their erased type (e.g.
    AdMediatorName mediatorName was shown as String mediatorName).
  • New @InaccessibleFromKotlin/@KotlinOnly annotations appear on members that are otherwise
    unchanged; these document pre-existing Kotlin/Java accessibility asymmetry (e.g. a Kotlin
    property's JVM-visible getter form can't be called from Kotlin source, only Java; a
    @JvmSynthetic or @Composable member can't meaningfully be called from Java).

Verified none of this drops real, currently-supported API: extracted a name-level diff of every
method/constructor/property/field across all 6 changed files and confirmed every apparent removal
resolves to one of the categories above, with no unexplained disappearance.

Description

  • gradle/libs.versions.toml: metalava 0.4.0-alpha03 → 0.5.0.
  • purchases/api-defauts.txt, purchases/api-entitlement.txt, ui/revenuecatui/api.txt,
    feature/admob/api.txt, feature/galaxy/api.txt, ui/debugview/api.txt: regenerated via
    scripts/api-dump.sh, audited as described above.

Tested: scripts/api-check.sh clean, :purchases/:ui:revenuecatui unit tests green, detektAll
and lint clean, all with Kotlin still at 2.0.21 and Poko at 0.17.2 (unchanged).


Note

Low Risk
Changes are limited to the Metalava plugin version and regenerated API signature files; runtime SDK code is untouched, with no intended removal of supported public API per the PR audit.

Overview
Bumps Metalava from 0.4.0-alpha03 to 0.5.0 in gradle/libs.versions.toml and regenerates the tracked api*.txt signatures (core purchases, AdMob, Galaxy, etc.). This is tooling-only for published API tracking; compiled SDK behavior is unchanged.

The signature files change heavily because 0.5.0 models Kotlin/Java interop more accurately, not because supported public API was intentionally removed:

  • Kotlin-only / Java-only markers: @KotlinOnly on @JvmSynthetic coroutines and AdMob helpers; @InaccessibleFromKotlin on JVM getters for Kotlin properties.
  • Hiding what was never real Java API: @JvmSynthetic and @InternalRevenueCatAPI members (e.g. internal listeners, checkpoint slot) drop out of the tracked surface; Offering paywall-related ctor parameters no longer appear as ordinary public API in the dump.
  • Type fidelity: Ad event payloads in the dump now show AdFormat, AdMediatorName, and AdRevenuePrecision instead of erased String types; @Throws on suspend helpers is preserved in the signatures (important before a future Kotlin 2.2 bump).
  • Misc. dump fixes: sealed exhaustive classes, fuller SubscriptionOptions List API, new deprecated typealiases (AdMob reward verification; purchase callback aliases in core), and serialization @SerialName on some virtual-currency properties.

Purchases.adTracker appears in the core API dump as the Kotlin-facing property for ad tracking (replacing previously tracked synthetic getter noise).

Reviewed by Cursor Bugbot for commit ce4128d. Bugbot is set up for automated code reviews on this repo. Configure here.

0.4.0-alpha03's Kotlin-metadata reading is out of date: it will silently
drop the throws clause it synthesizes from @throws once the repo's Kotlin
compiler moves past 2.0.x (see the follow-up Kotlin bump), so this needs to
land first.

0.5.0's own api*.txt diff is large (~3000 lines across 6 files) but fully
audited: every change is either Metalava now correctly excluding
@InternalRevenueCatAPI/@JvmSynthetic members that were leaking into the
tracked surface before (e.g. Offering.getPaywall()/getPaywallComponents(),
which back internal-only properties), a method->property rendering fix
that also corrects several value-class-typed members previously shown
with their erased type (e.g. AdMediatorName mediatorName was rendered as
String mediatorName), or new informational @InaccessibleFromKotlin/
@KotlinOnly annotations on members that were otherwise unchanged. No real,
currently-supported public API was removed; verified with a name-level
diff across all 6 files plus javap spot checks on the actual compiled
bytecode.
@AlvaroBrey AlvaroBrey self-assigned this Aug 11, 2026
@AlvaroBrey
AlvaroBrey requested a review from a team August 11, 2026 11:44
@AlvaroBrey
AlvaroBrey marked this pull request as ready for review August 11, 2026 11:45
@AlvaroBrey
AlvaroBrey requested a review from a team as a code owner August 11, 2026 11:45
@AlvaroBrey
AlvaroBrey removed the request for review from a team August 11, 2026 11:45

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7f0414d. Configure here.

Comment thread purchases/api-defauts.txt

@tonidero tonidero 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.

I wonder if we should fix the InaccessibleFromKotlin APIs to either remove them or expose them to kotlin... But I guess that would be a breaking change 🥴 So yeah, let's keep as is. Amazing job!

@AlvaroBrey

Copy link
Copy Markdown
Member Author

I wonder if we should fix the InaccessibleFromKotlin APIs to either remove them or expose them to kotlin...

Not really, those are stuff like getProductId() etc, which are just exposed as properties in Kotlin. I.e. Java accessors for Kotlin code, which Kotlin just doesn't see

Metalava 0.5.0 started picking up AGP's generated BuildConfig, which is not
part of the published SDK contract. Two of its fields make the dump
non-deterministic across machines and unrelated changes:
ENABLE_EXTRA_REQUEST_LOGGING is read from local.properties (git-ignored) and
BILLING_CLIENT_VERSION embeds the Billing Client version, so an unrelated
dependency bump would force an api*.txt regeneration.

Excludes the generated buildConfig source dirs from the two modules that
enable buildConfig. Note the plugin subtracts excludedSourceSets as an exact
FileCollection, not by prefix, so the variant-specific dirs have to be listed
individually rather than their parent.
@AlvaroBrey
AlvaroBrey added this pull request to the merge queue Aug 11, 2026
@AlvaroBrey
AlvaroBrey removed this pull request from the merge queue due to a manual request Aug 11, 2026
@AlvaroBrey
AlvaroBrey enabled auto-merge August 11, 2026 14:10
@AlvaroBrey
AlvaroBrey added this pull request to the merge queue Aug 11, 2026
Merged via the queue into main with commit 65c5345 Aug 11, 2026
34 checks passed
@AlvaroBrey
AlvaroBrey deleted the build/bump-metalava branch August 11, 2026 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants