Ship real bindings for Xamarin.AndroidX.Compose.UI / Foundation / Foundation.Layout#1420
Open
jonathanpeppers wants to merge 6 commits into
Open
Ship real bindings for Xamarin.AndroidX.Compose.UI / Foundation / Foundation.Layout#1420jonathanpeppers wants to merge 6 commits into
jonathanpeppers wants to merge 6 commits into
Conversation
`Xamarin.AndroidX.Compose.Runtime.Android` (artifactId `androidx.compose.runtime:runtime-android`) previously shipped as an empty managed facade because `Transforms/Metadata.xml` contained a package-wide `<remove-node path="/api/package" />` strip. This change replaces that strip with targeted `<remove-node>` entries for the Kotlin idioms the JNI binding generator cannot project into C#, so the package now ships ~980 lines of real public API. Mirrors the proven recipe in jonathanpeppers/compose-net@d1c6a5e: - src/ComposeNet.Bindings.Runtime/Transforms/Metadata.xml - src/ComposeNet.Bindings.Runtime/ComposeNet.Bindings.Runtime.csproj Targeted strips (14 from compose-net + 4 added during this work): Compose-net entries: - SnapshotState{List,Map,Set} + *Kt (KMP collection-jvm interface erasure mismatches `java.util.*`) - MutableSnapshot + Snapshot.getReadObserver (Kotlin typealias) - AbstractApplier (generic IApplier erasure) - BroadcastFrameClock, PausableMonotonicFrameClock (missing CoroutineContext.Element.key override) - Mutable{Int,Long,Float,Double}State + non-mutable peers (primitive `value` hides MutableState<T>.value setter) - MonotonicFrameClock.Key, SnapshotContextElement.Key (companion object collides with inherited `key` property) - ComposerKt.isAfterFirstChild (overload collapse) Added here: - androidx.compose.runtime.composer.{gapbuffer,linkbuffer}{,.changelist} (internal Kotlin packages whose namespace collides with the `Composer` class — C# cannot have a namespace and type with the same FQN) Other changes: - `source/_PackageLevelCustomizations.cshtml`: inject `<AndroidIgnoredJavaDependency Include="androidx.collection:collection-jvm:1.5.0" />` into the generated `Xamarin.AndroidX.Compose.Runtime.Android` csproj. - `source/AndroidXProject.cshtml`: drop the "C# bindings are not provided" note from the Compose.Runtime / Compose.Runtime.Android package description (no longer accurate). - `source/androidx.compose.runtime/runtime-android/PublicAPI/PublicAPI.Unshipped.txt`: regenerated baseline (auto-produced by `_GeneratePublicApiFiles` in `Directory.Build.targets`). `Xamarin.AndroidX.Compose.Runtime` (artifactId `runtime`) is the KMP umbrella with no bytecode of its own; it transitively gains the real managed surface via its `ProjectReference` to `runtime-android`, so the consumer-facing nuget also ships real bindings now. Verified locally: both `androidx.compose.runtime.runtime-android` and `androidx.compose.runtime.runtime` build clean for `net9.0-android` and `net10.0-android`. Closes #1415 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Now that Xamarin.AndroidX.Compose.Runtime ships real bindings (#1415), androidx.compose.runtime.Composer is resolvable from downstream consumers like Material3. The binding generator now emits MaterialTheme.getMotionScheme, which previously was silently skipped because its `Composer` parameter type was unresolvable. The emitted method references AndroidX.Compose.Material3.IMotionScheme, but MotionScheme is a Kotlin-internal interface (`visibility=""` in api.xml) that the generator never produces, causing CS0234. Strip the method via metadata; it was never on main either, so public API surface is unchanged. Also regenerates PublicAPI baselines for other Compose.Runtime consumers whose getter methods are now resolvable: lifecycle-runtime-compose-android, runtime-retain-android, navigationevent-compose-android. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
27cf0ab to
0cbd637
Compare
Three Compose.Runtime consumer packages gained many new public methods in 5efe3f7 once IComposer became resolvable. Bump nugetVersion so a restore at the old version vs the new produces different binaries: - Xamarin.AndroidX.Compose.Material3Android 1.4.0.2 -> 1.4.0.3 - Xamarin.AndroidX.Lifecycle.Runtime.Compose.Android 2.10.0.2 -> 2.10.0.3 - Xamarin.AndroidX.NavigationEvent.Compose.Android 1.1.1 -> 1.1.1.1 Xamarin.AndroidX.Compose.Runtime.Retain.Android was already bumped to 1.11.1.1 in the earlier bulk Compose.Runtime.* bump; that single bump already covers its surface change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
0cbd637 to
96f2e67
Compare
Now that Xamarin.AndroidX.Compose.Runtime ships real bindings (#1415), 13 new AndroidX.Compose.Runtime.* namespaces are emitted. Append them to the published list to satisfy the verify-namespace-file CI check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
96f2e67 to
5a4314e
Compare
Base automatically changed from
jonathanpeppers/compose-runtime-real-bindings
to
main
May 22, 2026 19:52
…ndation.Layout (#1416) Follow-up to #1418. The three peer recipes `Xamarin.AndroidX.Compose.UI`, `Xamarin.AndroidX.Compose.Foundation`, and `Xamarin.AndroidX.Compose.Foundation.Layout` all carried the same package-wide `<remove-node path="/api/package" />` strip and shipped as empty managed facades. This replaces the strips with targeted `<remove-node>` entries (mirroring jonathanpeppers/compose-net@d1c6a5e) so each `*-android` recipe now ships real public bindings. ui-android (~1.26 MB net10.0-android36.0): - managedName overrides so all 27 androidx.compose.ui* packages project as AndroidX.Compose.UI.* (uppercase) instead of the default AndroidX.Compose.Ui.*. This is a permanent ABI decision now that these NuGets ship real types, matching the casing the repo already uses for the rest of the project (.UI suffixed assemblies). - AndroidUiFrameClock / MotionDurationScale.Key / InfiniteAnimationPolicy.Key: same problem as MonotonicFrameClock.Key in runtime (CoroutineContext.Element.key collision). - Modifier.Companion / Modifier.Node: CS0542 (member-same-as-enclosing) and namespace/type FQN collision. - FrameRateKt.preferredFrameRate / ScaleFactorKt.times-: Kotlin inline-class hash-mangled overloads that collapse to the same C# signature. - ModifierLocalReadScope / ModifierLocalModifierNode: typealias projection. - SubcomposeSlotReusePolicy / SubcomposeSlotReusePolicy.SlotIdsSet: MutableSet erasure mismatches java.util.Collection on the Invoker. - RequestDisallowInterceptTouchEvent: Function1-as-Java-class projection doesn't surface the interface method. - ModifierNodeElement: abstract any/all(Function1) can't be satisfied by the auto-generated Invoker. foundation-android (~975 KB net10.0-android36.0): - CornerSizeKt.CornerSize- / LazyLayoutCacheWindowKt.LazyLayoutCacheWindow-: inline-class hash-mangled overload collision. - LazyLayoutPinnedItemList: MutableList re-declares java.util.List operations (CS0535/CS0738 on Add/AddAll/Get/Set/Size/SubList/etc.). - KeyMapping / KeyMappingKt / KeyMapping_androidKt: returns java.lang.Enum<KeyCommand> which doesn't project. - StyleState / MutableStyleState / StyleStateKey / StyleStateKt (new in 1.11.x): abstract bool getters not implemented by the auto-generated subclass (CS0534). - SelectionGestures_androidKt (new in 1.11.x): references AndroidX.Compose.Foundation.Text.Selection.ISelectionAdjustment which the generator does not emit as an interface. foundation-layout-android (~267 KB net10.0-android36.0): - PaddingValues.Absolute: Kotlin object whose JVM signatures don't include the calculate*Padding() impls — auto-generated C# class is broken. Other changes: - source/AndroidXProject.cshtml: extend the "C# bindings are not provided" description exception to cover the six new packages (Compose.UI, Compose.UI.Android, Compose.Foundation, Compose.Foundation.Android, Compose.Foundation.Layout, Compose.Foundation.Layout.Android). - config.json: bump nugetVersion 1.11.1 -> 1.11.1.1 for the six packages whose surface area is changing. - source/androidx.compose.{ui,foundation}/*/PublicAPI/PublicAPI.Unshipped.txt: regenerated baselines (auto-produced by _GeneratePublicApiFiles in Directory.Build.targets). Verified locally on Windows: all three *-android csproj projects build clean for net9.0-android and net10.0-android. Closes #1416 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
6ac3be6 to
13f3fc3
Compare
There was a problem hiding this comment.
Pull request overview
This PR converts the Xamarin.AndroidX.Compose.UI*, Xamarin.AndroidX.Compose.Foundation*, and Xamarin.AndroidX.Compose.Foundation.Layout* packages from “empty managed facades” into real, shipped bindings by removing the previous package-wide metadata stripping and replacing it with targeted removals for Kotlin/JNI binding edge-cases. It also updates packaging/versioning metadata and regenerates PublicAPI baselines to reflect the newly exposed surface area.
Changes:
- Replace package-wide
<remove-node path="/api/package" />transforms with targeted<remove-node>exclusions for known generator-incompatible Kotlin patterns. - Apply Compose UI namespace casing decisions (
Ui→UI) viamanagedNameoverrides. - Bump NuGet-only revisions and regenerate API/namespace baselines for the newly shipped bindings.
Reviewed changes
Copilot reviewed 16 out of 18 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| source/AndroidXProject.cshtml | Extends the “no C# bindings provided” description exception list to include the newly-real Compose UI/Foundation packages. |
| source/androidx.compose.ui/ui-android/Transforms/Metadata.xml | Removes package-wide stripping; adds managedName overrides for AndroidX.Compose.UI.* and targeted removals for binding-breakers. |
| source/androidx.compose.foundation/foundation-android/Transforms/Metadata.xml | Removes package-wide stripping; adds targeted removals for inline-class overload collisions and known problematic types. |
| source/androidx.compose.foundation/foundation-layout-android/Transforms/Metadata.xml | Removes package-wide stripping; drops PaddingValues.Absolute which produces broken managed output. |
| source/androidx.compose.foundation/foundation-android/PublicAPI/PublicAPI.Unshipped.txt | Regenerated PublicAPI baseline reflecting newly exposed Foundation API surface. |
| source/androidx.compose.foundation/foundation-layout-android/PublicAPI/PublicAPI.Unshipped.txt | Regenerated PublicAPI baseline reflecting newly exposed Foundation.Layout API surface. |
| published-namespaces.txt | Adds newly published AndroidX.Compose.* namespaces now that bindings are emitted. |
| config.json | NuGet-only revision bump (1.11.1 → 1.11.1.1) for the affected Compose packages. |
Comments suppressed due to low confidence (1)
source/AndroidXProject.cshtml:41
- The package description exception logic is a long chain of
Model.NuGetPackageId != ...checks, which is hard to read and easy to miss future Compose packages that gain bindings. Consider refactoring this into a small set/array of package IDs (or a helper likeIsComposeBindingsProvided) and usingContains/Anyto make updates simpler.
- XAOBS001: While this member is 'public', Google considers it internal API and reserves the right to modify or delete it in the future. Use at your own risk.
- NU1605: Detected package downgrade
-->
…se-ui-foundation-real-bindings # Conflicts: # published-namespaces.txt # source/AndroidXProject.cshtml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Follow-up to #1418. Ship real C# bindings for the three peer Compose recipes that previously shipped as empty managed facades:
Xamarin.AndroidX.Compose.UI/Xamarin.AndroidX.Compose.UI.Android(~1.26 MB)Xamarin.AndroidX.Compose.Foundation/Xamarin.AndroidX.Compose.Foundation.Android(~975 KB)Xamarin.AndroidX.Compose.Foundation.Layout/Xamarin.AndroidX.Compose.Foundation.Layout.Android(~267 KB)Each
*-androidrecipe previously contained a package-wide<remove-node path="/api/package" />strip that erased every type. This PR replaces those strips with targeted<remove-node>entries that only drop the specific Kotlin idioms (inline classes, KMP collection erasure, typealiases, companion-objectKeycollisions, abstract Invokers, etc.) the JNI binding generator cannot project into C#.Reference
Mirrors the proven recipe in
jonathanpeppers/compose-net@d1c6a5e— same approach we used forXamarin.AndroidX.Compose.Runtimein #1418:ComposeNet.Bindings.UI/Transforms/Metadata.xmlComposeNet.Bindings.Foundation/Transforms/Metadata.xmlComposeNet.Bindings.Foundation.Layout/Transforms/Metadata.xmlChanges
source/androidx.compose.ui/ui-android/Transforms/Metadata.xmlmanagedNameoverrides (Ui→UI) plus 11 targeted<remove-node>entries.source/androidx.compose.foundation/foundation-android/Transforms/Metadata.xml<remove-node>entries for inline-class overloads,LazyLayoutPinnedItemList,KeyMapping, and (new in 1.11.x)StyleState/SelectionGestures_androidKt.source/androidx.compose.foundation/foundation-layout-android/Transforms/Metadata.xmlPaddingValues.Absolute.source/AndroidXProject.cshtmlconfig.jsonnugetVersion1.11.1→1.11.1.1for the 6 affected packages (NuGet-only revision bump).source/androidx.compose.{ui,foundation}/*/PublicAPI/PublicAPI.Unshipped.txt_GeneratePublicApiFilesinDirectory.Build.targets).UI casing
The UI
Metadata.xmlappliesmanagedName="…UI…"on everyandroidx.compose.ui*package (27 entries). The default would produceAndroidX.Compose.Ui.*; once these NuGets ship real types, this is a permanent ABI decision, so we go with the conventional uppercase.UIto match every other*UI*namespace/assembly in this repo.Targeted
<remove-node>entriesui-android (11):
AndroidUiFrameClock,MotionDurationScale.Key+interface MotionDurationScale/field Key,InfiniteAnimationPolicy.Key+interface InfiniteAnimationPolicy/field Key— same pattern asMonotonicFrameClock.Keyin runtime: nested companionKeycollides with inheritedCoroutineContext.Element.key(CS0119 / CS0572).Modifier.Companion— Kotlin companion vs nested generator-emittedCompanioncollision.Modifier.Node— CS0542 (member-same-as-enclosing).FrameRateKt.preferredFrameRate,ScaleFactorKt.times-*— Kotlin inline-class hash-mangled overloads collapse to identical C# signatures.ModifierLocalReadScope,ModifierLocalModifierNode— Kotlin typealias that doesn't project as an interface.SubcomposeSlotReusePolicy,SubcomposeSlotReusePolicy.SlotIdsSet— KotlinMutableSetprojected intojava.util.Collectionbreaks the Invoker.RequestDisallowInterceptTouchEvent—Function1-as-Java-class projection where the interface method isn't surfaced.ModifierNodeElement— abstractany/all(Function1)can't be satisfied by the auto-generated Invoker.foundation-android (compose-net 3 + 2 new for 1.11.x):
CornerSizeKt.CornerSize-*,LazyLayoutCacheWindowKt.LazyLayoutCacheWindow-*— inline-class hash-mangled overload collision.LazyLayoutPinnedItemList— KotlinMutableListre-declaresjava.util.Listoperations (CS0535/CS0738 onAdd/AddAll/Get/Set/Size/SubList/etc.).KeyMapping,KeyMappingKt,KeyMapping_androidKt— returnsjava.lang.Enum<KeyCommand>which doesn't project.StyleState,MutableStyleState,StyleStateKey,StyleStateKt— abstractboolgetters (IsChecked/IsPressed/IsSelected/IsHovered/IsEnabled/IsFocused) not implemented by the auto-generatedMutableStyleStatesubclass (CS0534).SelectionGestures_androidKt— referencesAndroidX.Compose.Foundation.Text.Selection.ISelectionAdjustmentwhich the generator does not emit as an interface (only its*Ktcompanion ships).foundation-layout-android (1):
PaddingValues.Absolute— Kotlin object whose JVM signatures don't include thecalculate*Padding()impls, so the auto-generated C# class is broken.Verification
Locally on Windows, all three
*-androidcsproj projects build clean for bothnet9.0-android35.0andnet10.0-android36.0:The PublicAPI baseline diffs are large and intentional — they are the surface area that was previously hidden behind the package-wide
<remove-node>strips.Closes #1416