Skip to content

Conversation

@jpobst
Copy link
Contributor

@jpobst jpobst commented Mar 5, 2020

Context: dotnet/java-interop#509

Beginning with C#8, interfaces may now contain nested types. This allows us to better match the android.jar we are binding. However, we cannot nest any types prior to API-30, as that would result in a breaking API change.

This PR:

  • Enables the generator flag: --lang-features=nested-interface-types, which will nest all types on interfaces using C#8.
  • Adds metadata that looks for all @merge.SourceFile prior to API-30 and adds the unnest=true attribute to those types. This attribute tells generator to treat them as legacy "unnested" types for backwards compatibility.

API diff between master API-30 and this PR: https://gist.github.com/jpobst/a23ecebbed0837a1abfe7c6cbd7ecf1e

@jpobst jpobst marked this pull request as ready for review March 6, 2020 15:44
@jpobst jpobst requested a review from jonpryor as a code owner March 6, 2020 15:44
@jonpryor jonpryor merged commit a85b546 into master Mar 6, 2020
@jonpryor jonpryor deleted the ma-nested-types branch March 6, 2020 16:21
jonpryor pushed a commit that referenced this pull request Mar 6, 2020
Context: dotnet/java-interop#509
Context: https://gist.github.com/jpobst/a23ecebbed0837a1abfe7c6cbd7ecf1e

Use `generator --lang-features=nested-interface-types` so that we
start binding Java types nested within interfaces in a similar
fashion in C#.  For example:

	// Java
	package android.view;
	public /* partial */ interface WindowInsetsAnimationCallback {
	    public /* partial */ class AnimationBounds {
	    }
	}

Will be bound as:

	// C#
	namespace Android.Views {
	    public partial interface IWindowInsetsAnimationCallback {
	        public partial class AnimationBounds {
		}
	    }
	}

This new binding approach will only be done for types added in API-R.
We can't do this for any previous bindings, as this would break API.
This is done via `metadata` that looks for all `@merge.SourceFile`
values prior to API-30 and adds the `//@unnest=true` attribute to those
types.  This attribute tells `generator` to treat them as legacy
"unnested" types for backwards compatibility.

The v10.0.99/API-R API diff between 54beb90 and this change:

	--- 54beb90.cs	2020-03-06 11:19:47.000000000 -0500
	+++ nested.cs	2020-03-06 11:19:19.000000000 -0500
	@@ -134296,13 +134296,43 @@
	     {
	         int DispatchMode { [Android.Runtime.RegisterAttribute("getDispatchMode", "()I", "GetGetDispatchModeHandler:Android.Views.IWindowInsetsAnimationCallbackInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")] get; }
	         [Android.Runtime.RegisterAttribute("onFinish", "(Landroid/view/WindowInsetsAnimationCallback$InsetsAnimation;)V", "GetOnFinish_Landroid_view_WindowInsetsAnimationCallback_InsetsAnimation_Handler:Android.Views.IWindowInsetsAnimationCallback, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
	-        void OnFinish(Android.Views.WindowInsetsAnimationCallbackInsetsAnimation animation) { }
	+        void OnFinish(Android.Views.IWindowInsetsAnimationCallback.InsetsAnimation animation) { }
	         [Android.Runtime.RegisterAttribute("onPrepare", "(Landroid/view/WindowInsetsAnimationCallback$InsetsAnimation;)V", "GetOnPrepare_Landroid_view_WindowInsetsAnimationCallback_InsetsAnimation_Handler:Android.Views.IWindowInsetsAnimationCallback, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
	-        void OnPrepare(Android.Views.WindowInsetsAnimationCallbackInsetsAnimation animation) { }
	+        void OnPrepare(Android.Views.IWindowInsetsAnimationCallback.InsetsAnimation animation) { }
	         [Android.Runtime.RegisterAttribute("onProgress", "(Landroid/view/WindowInsets;)Landroid/view/WindowInsets;", "GetOnProgress_Landroid_view_WindowInsets_Handler:Android.Views.IWindowInsetsAnimationCallbackInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
	         Android.Views.WindowInsets OnProgress(Android.Views.WindowInsets insets);
	         [Android.Runtime.RegisterAttribute("onStart", "(Landroid/view/WindowInsetsAnimationCallback$InsetsAnimation;Landroid/view/WindowInsetsAnimationCallback$AnimationBounds;)Landroid/view/WindowInsetsAnimationCallback$AnimationBounds;", "GetOnStart_Landroid_view_WindowInsetsAnimationCallback_InsetsAnimation_Landroid_view_WindowInsetsAnimationCallback_AnimationBounds_Handler:Android.Views.IWindowInsetsAnimationCallback, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
	-        Android.Views.WindowInsetsAnimationCallbackAnimationBounds OnStart(Android.Views.WindowInsetsAnimationCallbackInsetsAnimation animation, Android.Views.WindowInsetsAnimationCallbackAnimationBounds bounds) { throw null; }
	+        Android.Views.IWindowInsetsAnimationCallback.AnimationBounds OnStart(Android.Views.IWindowInsetsAnimationCallback.InsetsAnimation animation, Android.Views.IWindowInsetsAnimationCallback.AnimationBounds bounds) { throw null; }
	+        [Android.Runtime.RegisterAttribute("android/view/WindowInsetsAnimationCallback$AnimationBounds", DoNotGenerateAcw=true)]
	+        public sealed partial class AnimationBounds : Java.Lang.Object
	+        {
	+            [Android.Runtime.RegisterAttribute(".ctor", "(Landroid/graphics/Insets;Landroid/graphics/Insets;)V", "")]
	+            public AnimationBounds(Android.Graphics.Insets lowerBound, Android.Graphics.Insets upperBound) { }
	+            public override Java.Interop.JniPeerMembers JniPeerMembers { get { throw null; } }
	+            public Android.Graphics.Insets LowerBound { [Android.Runtime.RegisterAttribute("getLowerBound", "()Landroid/graphics/Insets;", "")] get { throw null; } }
	+            protected override System.IntPtr ThresholdClass { get { throw null; } }
	+            protected override System.Type ThresholdType { get { throw null; } }
	+            public Android.Graphics.Insets UpperBound { [Android.Runtime.RegisterAttribute("getUpperBound", "()Landroid/graphics/Insets;", "")] get { throw null; } }
	+            [Android.Runtime.RegisterAttribute("inset", "(Landroid/graphics/Insets;)Landroid/view/WindowInsetsAnimationCallback$AnimationBounds;", "")]
	+            public Android.Views.IWindowInsetsAnimationCallback.AnimationBounds Inset(Android.Graphics.Insets insets) { throw null; }
	+        }
	+        [Android.Runtime.RegisterAttribute("android/view/WindowInsetsAnimationCallback$InsetsAnimation", DoNotGenerateAcw=true)]
	+        public sealed partial class InsetsAnimation : Java.Lang.Object
	+        {
	+            [Android.Runtime.RegisterAttribute(".ctor", "(ILandroid/view/animation/Interpolator;J)V", "")]
	+            public InsetsAnimation(int typeMask, Android.Views.Animations.IInterpolator interpolator, long durationMs) { }
	+            public float Alpha { [Android.Runtime.RegisterAttribute("getAlpha", "()F", "")] get { throw null; } }
	+            public long DurationMillis { [Android.Runtime.RegisterAttribute("getDurationMillis", "()J", "")] get { throw null; } }
	+            public float Fraction { [Android.Runtime.RegisterAttribute("getFraction", "()F", "")] get { throw null; } [Android.Runtime.RegisterAttribute("setFraction", "(F)V", "")] set { } }
	+            public float InterpolatedFraction { [Android.Runtime.RegisterAttribute("getInterpolatedFraction", "()F", "")] get { throw null; } }
	+            public Android.Views.Animations.IInterpolator Interpolator { [Android.Runtime.RegisterAttribute("getInterpolator", "()Landroid/view/animation/Interpolator;", "")] get { throw null; } }
	+            public override Java.Interop.JniPeerMembers JniPeerMembers { get { throw null; } }
	+            protected override System.IntPtr ThresholdClass { get { throw null; } }
	+            protected override System.Type ThresholdType { get { throw null; } }
	+            public int TypeMask { [Android.Runtime.RegisterAttribute("getTypeMask", "()I", "")] get { throw null; } }
	+            [Android.Runtime.RegisterAttribute("setDuration", "(J)V", "")]
	+            public void SetDuration(long durationMs) { }
	+        }
	     }
	     [Android.Runtime.RegisterAttribute("android/view/WindowInsetsAnimationController", "", "Android.Views.IWindowInsetsAnimationControllerInvoker")]
	     public partial interface IWindowInsetsAnimationController : Android.Runtime.IJavaObject, Java.Interop.IJavaPeerable, System.IDisposable
	@@ -137605,13 +137635,13 @@
	         [Android.Runtime.RegisterAttribute("dispatchWindowFocusChanged", "(Z)V", "GetDispatchWindowFocusChanged_ZHandler")]
	         public virtual void DispatchWindowFocusChanged(bool hasFocus) { }
	         [Android.Runtime.RegisterAttribute("dispatchWindowInsetsAnimationFinish", "(Landroid/view/WindowInsetsAnimationCallback$InsetsAnimation;)V", "GetDispatchWindowInsetsAnimationFinish_Landroid_view_WindowInsetsAnimationCallback_InsetsAnimation_Handler")]
	-        public virtual void DispatchWindowInsetsAnimationFinish(Android.Views.WindowInsetsAnimationCallbackInsetsAnimation animation) { }
	+        public virtual void DispatchWindowInsetsAnimationFinish(Android.Views.IWindowInsetsAnimationCallback.InsetsAnimation animation) { }
	         [Android.Runtime.RegisterAttribute("dispatchWindowInsetsAnimationPrepare", "(Landroid/view/WindowInsetsAnimationCallback$InsetsAnimation;)V", "GetDispatchWindowInsetsAnimationPrepare_Landroid_view_WindowInsetsAnimationCallback_InsetsAnimation_Handler")]
	-        public virtual void DispatchWindowInsetsAnimationPrepare(Android.Views.WindowInsetsAnimationCallbackInsetsAnimation animation) { }
	+        public virtual void DispatchWindowInsetsAnimationPrepare(Android.Views.IWindowInsetsAnimationCallback.InsetsAnimation animation) { }
	         [Android.Runtime.RegisterAttribute("dispatchWindowInsetsAnimationProgress", "(Landroid/view/WindowInsets;)Landroid/view/WindowInsets;", "GetDispatchWindowInsetsAnimationProgress_Landroid_view_WindowInsets_Handler")]
	         public virtual Android.Views.WindowInsets DispatchWindowInsetsAnimationProgress(Android.Views.WindowInsets insets) { throw null; }
	         [Android.Runtime.RegisterAttribute("dispatchWindowInsetsAnimationStart", "(Landroid/view/WindowInsetsAnimationCallback$InsetsAnimation;Landroid/view/WindowInsetsAnimationCallback$AnimationBounds;)Landroid/view/WindowInsetsAnimationCallback$AnimationBounds;", "GetDispatchWindowInsetsAnimationStart_Landroid_view_WindowInsetsAnimationCallback_InsetsAnimation_Landroid_view_WindowInsetsAnimationCallback_AnimationBounds_Handler")]
	-        public virtual Android.Views.WindowInsetsAnimationCallbackAnimationBounds DispatchWindowInsetsAnimationStart(Android.Views.WindowInsetsAnimationCallbackInsetsAnimation animation, Android.Views.WindowInsetsAnimationCallbackAnimationBounds bounds) { throw null; }
	+        public virtual Android.Views.IWindowInsetsAnimationCallback.AnimationBounds DispatchWindowInsetsAnimationStart(Android.Views.IWindowInsetsAnimationCallback.InsetsAnimation animation, Android.Views.IWindowInsetsAnimationCallback.AnimationBounds bounds) { throw null; }
	         [Android.Runtime.RegisterAttribute("dispatchWindowSystemUiVisiblityChanged", "(I)V", "GetDispatchWindowSystemUiVisiblityChanged_IHandler", ApiSince=16)]
	         public virtual void DispatchWindowSystemUiVisiblityChanged([Android.Runtime.GeneratedEnumAttribute] Android.Views.SystemUiFlags visible) { }
	         [Android.Runtime.RegisterAttribute("dispatchWindowVisibilityChanged", "(I)V", "GetDispatchWindowVisibilityChanged_IHandler")]
	@@ -139966,42 +139996,12 @@
	         [Android.Runtime.RegisterAttribute("DISPATCH_MODE_STOP")]
	         public const int DispatchModeStop = 0;
	     }
	-    [Android.Runtime.RegisterAttribute("android/view/WindowInsetsAnimationCallback$AnimationBounds", DoNotGenerateAcw=true)]
	-    public sealed partial class WindowInsetsAnimationCallbackAnimationBounds : Java.Lang.Object
	-    {
	-        [Android.Runtime.RegisterAttribute(".ctor", "(Landroid/graphics/Insets;Landroid/graphics/Insets;)V", "")]
	-        public WindowInsetsAnimationCallbackAnimationBounds(Android.Graphics.Insets lowerBound, Android.Graphics.Insets upperBound) { }
	-        public override Java.Interop.JniPeerMembers JniPeerMembers { get { throw null; } }
	-        public Android.Graphics.Insets LowerBound { [Android.Runtime.RegisterAttribute("getLowerBound", "()Landroid/graphics/Insets;", "")] get { throw null; } }
	-        protected override System.IntPtr ThresholdClass { get { throw null; } }
	-        protected override System.Type ThresholdType { get { throw null; } }
	-        public Android.Graphics.Insets UpperBound { [Android.Runtime.RegisterAttribute("getUpperBound", "()Landroid/graphics/Insets;", "")] get { throw null; } }
	-        [Android.Runtime.RegisterAttribute("inset", "(Landroid/graphics/Insets;)Landroid/view/WindowInsetsAnimationCallback$AnimationBounds;", "")]
	-        public Android.Views.WindowInsetsAnimationCallbackAnimationBounds Inset(Android.Graphics.Insets insets) { throw null; }
	-    }
	     [Android.Runtime.RegisterAttribute("android/view/WindowInsetsAnimationCallback", DoNotGenerateAcw=true)]
	     [System.ObsoleteAttribute("Use the 'WindowInsetsAnimationCallback' type. This type will be removed in a future release.", true)]
	     public abstract partial class WindowInsetsAnimationCallbackConsts : Android.Views.WindowInsetsAnimationCallback
	     {
	         internal WindowInsetsAnimationCallbackConsts() { }
	     }
	-    [Android.Runtime.RegisterAttribute("android/view/WindowInsetsAnimationCallback$InsetsAnimation", DoNotGenerateAcw=true)]
	-    public sealed partial class WindowInsetsAnimationCallbackInsetsAnimation : Java.Lang.Object
	-    {
	-        [Android.Runtime.RegisterAttribute(".ctor", "(ILandroid/view/animation/Interpolator;J)V", "")]
	-        public WindowInsetsAnimationCallbackInsetsAnimation(int typeMask, Android.Views.Animations.IInterpolator interpolator, long durationMs) { }
	-        public float Alpha { [Android.Runtime.RegisterAttribute("getAlpha", "()F", "")] get { throw null; } }
	-        public long DurationMillis { [Android.Runtime.RegisterAttribute("getDurationMillis", "()J", "")] get { throw null; } }
	-        public float Fraction { [Android.Runtime.RegisterAttribute("getFraction", "()F", "")] get { throw null; } [Android.Runtime.RegisterAttribute("setFraction", "(F)V", "")] set { } }
	-        public float InterpolatedFraction { [Android.Runtime.RegisterAttribute("getInterpolatedFraction", "()F", "")] get { throw null; } }
	-        public Android.Views.Animations.IInterpolator Interpolator { [Android.Runtime.RegisterAttribute("getInterpolator", "()Landroid/view/animation/Interpolator;", "")] get { throw null; } }
	-        public override Java.Interop.JniPeerMembers JniPeerMembers { get { throw null; } }
	-        protected override System.IntPtr ThresholdClass { get { throw null; } }
	-        protected override System.Type ThresholdType { get { throw null; } }
	-        public int TypeMask { [Android.Runtime.RegisterAttribute("getTypeMask", "()I", "")] get { throw null; } }
	-        [Android.Runtime.RegisterAttribute("setDuration", "(J)V", "")]
	-        public void SetDuration(long durationMs) { }
	-    }
	     [Android.Runtime.RegisterAttribute("android/view/WindowInsetsController", DoNotGenerateAcw=true)]
	     public abstract partial class WindowInsetsController : Java.Lang.Object
	     {
@github-actions github-actions bot locked and limited conversation to collaborators Jan 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants