Skip to content

Commit c29109e

Browse files
jpobstjonpryor
authored andcommitted
[Mono.Android] Interfaces contain nested types in API-30+ (#4363)
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 {
1 parent a25ae7d commit c29109e

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

src/Mono.Android/Mono.Android.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
<_Api>$(IntermediateOutputPath)mcw\api.xml</_Api>
9999
<_Dirs>--enumdir=$(IntermediateOutputPath)mcw</_Dirs>
100100
<_FullIntermediateOutputPath>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)'))</_FullIntermediateOutputPath>
101-
<_LangFeatures Condition="$(AndroidApiLevel) &gt;= 30">--lang-features=default-interface-methods</_LangFeatures>
101+
<_LangFeatures Condition="$(AndroidApiLevel) &gt;= 30">--lang-features=default-interface-methods,nested-interface-types</_LangFeatures>
102102
</PropertyGroup>
103103
<Exec
104104
Command="$(ManagedRuntime) $(ManagedRuntimeArgs) $(Generator) $(_GenFlags) $(_ApiLevel) $(_Out) $(_Codegen) $(_Fixup) $(_Enums1) $(_Enums2) $(_Versions) $(_Annotations) $(_Assembly) $(_TypeMap) $(_LangFeatures) $(_Dirs) $(_Api)"

src/Mono.Android/metadata

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,4 +1560,44 @@
15601560
<remove-node api-since="30" path="/api/package[@name='android.animation']/interface[@name='Animator.AnimatorListener']/method[@name='onAnimationStart' and count(parameter)=2]" />
15611561
<remove-node api-since="30" path="/api/package[@name='android.animation']/interface[@name='Animator.AnimatorListener']/method[@name='onAnimationEnd' and count(parameter)=2]" />
15621562

1563+
<!-- Starting with API added in API-30, we are going to allow interfaces to contain nested types.
1564+
To preserve backwards compatibility, we need to "un-nest" anything added before API-30 -->
1565+
1566+
<!-- Handle everything that has always existed (no @merge.SourceFile) -->
1567+
<attr api-since="30" path="/api/package/interface[not(@merge.SourceFile)]" name="unnest">true</attr>
1568+
<attr api-since="30" path="/api/package/class[not(@merge.SourceFile)]" name="unnest">true</attr>
1569+
1570+
<!-- Need these for each platform prior to 30 -->
1571+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-10.xml.in')]" name="unnest">true</attr>
1572+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-10.xml.in')]" name="unnest">true</attr>
1573+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-15.xml.in')]" name="unnest">true</attr>
1574+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-15.xml.in')]" name="unnest">true</attr>
1575+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-16.xml.in')]" name="unnest">true</attr>
1576+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-16.xml.in')]" name="unnest">true</attr>
1577+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-17.xml.in')]" name="unnest">true</attr>
1578+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-17.xml.in')]" name="unnest">true</attr>
1579+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-18.xml.in')]" name="unnest">true</attr>
1580+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-18.xml.in')]" name="unnest">true</attr>
1581+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-19.xml.in')]" name="unnest">true</attr>
1582+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-19.xml.in')]" name="unnest">true</attr>
1583+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-20.xml.in')]" name="unnest">true</attr>
1584+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-20.xml.in')]" name="unnest">true</attr>
1585+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-21.xml.in')]" name="unnest">true</attr>
1586+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-21.xml.in')]" name="unnest">true</attr>
1587+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-22.xml.in')]" name="unnest">true</attr>
1588+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-22.xml.in')]" name="unnest">true</attr>
1589+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-23.xml.in')]" name="unnest">true</attr>
1590+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-23.xml.in')]" name="unnest">true</attr>
1591+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-24.xml.in')]" name="unnest">true</attr>
1592+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-24.xml.in')]" name="unnest">true</attr>
1593+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-25.xml.in')]" name="unnest">true</attr>
1594+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-25.xml.in')]" name="unnest">true</attr>
1595+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-26.xml.in')]" name="unnest">true</attr>
1596+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-26.xml.in')]" name="unnest">true</attr>
1597+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-27.xml.in')]" name="unnest">true</attr>
1598+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-27.xml.in')]" name="unnest">true</attr>
1599+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-28.xml.in')]" name="unnest">true</attr>
1600+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-28.xml.in')]" name="unnest">true</attr>
1601+
<attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-29.xml.in')]" name="unnest">true</attr>
1602+
<attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-29.xml.in')]" name="unnest">true</attr>
15631603
</metadata>

0 commit comments

Comments
 (0)