Skip to content

Commit 28b1fc9

Browse files
authored
[generator] Support using DIM to nest interface types. (#589)
Context: #509 Consider the following Java code: package example; public interface Parent { public interface Child { } } Before C#8, interfaces could not contain types. To bind `example.Parent.Child`, we had to "un-nest" the interface, *prefixing* the interface name with the name of the enclosing type: namespace Example { public interface IParent { } public interface IParentChild { } } With C#8, interfaces can now contain types. We can now emit: namespace Example { public interface IParent { public interface IChild { } } } Enable this new style of binding when `generator --lang-features=nested-interface-types` is used. This is *disabled* by default. However, even when `nested-interface-types` is enabled, not all interfaces should follow this new strategy. In the case of `Mono.Android.dll`, nested interface types should *only* be used for types added in API-R/API-30. Add support for a new `unnest` Metadata attribute which can be placed on nested types to explicitly emit the C#7-compatible bindings: <attr path="/api/package[@name='example']/interface[@name='Parent.Child']" name="unnest">true</attr> In a future integration with xamarin-android, [`src/Mono.Android/metadata`][0] can be updated so that all APIs prior to API-30 are unnested, and all APIs starting with API-30 are nested: <!-- Handle everything that has always existed --> <attr api-since="30" path="/api/package/interface[not(@merge.SourceFile)]" name="unnest">true</attr> <attr api-since="30" path="/api/package/class[not(@merge.SourceFile)]" name="unnest">true</attr> <!-- Need these 2 for each platform prior to 30 --> <attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-29.xml.in')]" name="unnest">true</attr> <attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-29.xml.in')]" name="unnest">true</attr> This will ensure we preserve API compatibility. [0]: https://github.com/xamarin/xamarin-android/blob/b366ac1e6d411dc052dc8711d881d71b7e967685/src/Mono.Android/metadata
1 parent cdf840f commit 28b1fc9

File tree

18 files changed

+833
-34
lines changed

18 files changed

+833
-34
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Metadata.xml XPath interface reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent']"
2+
[Register ("com/xamarin/android/Parent", "", "Com.Xamarin.Android.IParentInvoker")]
3+
public partial interface IParent : IJavaObject, IJavaPeerable {
4+
5+
int Bar {
6+
// Metadata.xml XPath method reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent']/method[@name='getBar' and count(parameter)=0]"
7+
[Register ("getBar", "()I", "GetGetBarHandler:Com.Xamarin.Android.IParentInvoker, MyAssembly")] get;
8+
}
9+
10+
// Metadata.xml XPath interface reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent.Child']"
11+
[Register ("com/xamarin/android/Parent$Child", "", "Com.Xamarin.Android.IParent/IChildInvoker")]
12+
public partial interface IChild : IJavaObject, IJavaPeerable {
13+
14+
int Bar {
15+
// Metadata.xml XPath method reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent.Child']/method[@name='getBar' and count(parameter)=0]"
16+
[Register ("getBar", "()I", "GetGetBarHandler:Com.Xamarin.Android.IParent/IChildInvoker, MyAssembly")] get;
17+
}
18+
19+
}
20+
21+
[global::Android.Runtime.Register ("com/xamarin/android/Parent$Child", DoNotGenerateAcw=true)]
22+
internal partial class IChildInvoker : global::Java.Lang.Object, IChild {
23+
24+
static readonly JniPeerMembers _members = new JniPeerMembers ("com/xamarin/android/Parent$Child", typeof (IChildInvoker));
25+
26+
static IntPtr java_class_ref {
27+
get { return _members.JniPeerType.PeerReference.Handle; }
28+
}
29+
30+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
31+
get { return _members; }
32+
}
33+
34+
protected override IntPtr ThresholdClass {
35+
get { return class_ref; }
36+
}
37+
38+
protected override global::System.Type ThresholdType {
39+
get { return _members.ManagedPeerType; }
40+
}
41+
42+
new IntPtr class_ref;
43+
44+
public static IChild GetObject (IntPtr handle, JniHandleOwnership transfer)
45+
{
46+
return global::Java.Lang.Object.GetObject<IChild> (handle, transfer);
47+
}
48+
49+
static IntPtr Validate (IntPtr handle)
50+
{
51+
if (!JNIEnv.IsInstanceOf (handle, java_class_ref))
52+
throw new InvalidCastException (string.Format ("Unable to convert instance of type '{0}' to type '{1}'.",
53+
JNIEnv.GetClassNameFromInstance (handle), "com.xamarin.android.Parent.Child"));
54+
return handle;
55+
}
56+
57+
protected override void Dispose (bool disposing)
58+
{
59+
if (this.class_ref != IntPtr.Zero)
60+
JNIEnv.DeleteGlobalRef (this.class_ref);
61+
this.class_ref = IntPtr.Zero;
62+
base.Dispose (disposing);
63+
}
64+
65+
public IChildInvoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer)
66+
{
67+
IntPtr local_ref = JNIEnv.GetObjectClass (((global::Java.Lang.Object) this).Handle);
68+
this.class_ref = JNIEnv.NewGlobalRef (local_ref);
69+
JNIEnv.DeleteLocalRef (local_ref);
70+
}
71+
72+
static Delegate cb_getBar;
73+
#pragma warning disable 0169
74+
static Delegate GetGetBarHandler ()
75+
{
76+
if (cb_getBar == null)
77+
cb_getBar = JNINativeWrapper.CreateDelegate ((Func<IntPtr, IntPtr, int>) n_GetBar);
78+
return cb_getBar;
79+
}
80+
81+
static int n_GetBar (IntPtr jnienv, IntPtr native__this)
82+
{
83+
Com.Xamarin.Android.IParent.IChild __this = global::Java.Lang.Object.GetObject<Com.Xamarin.Android.IParent.IChild> (jnienv, native__this, JniHandleOwnership.DoNotTransfer);
84+
return __this.Bar;
85+
}
86+
#pragma warning restore 0169
87+
88+
IntPtr id_getBar;
89+
public unsafe int Bar {
90+
get {
91+
if (id_getBar == IntPtr.Zero)
92+
id_getBar = JNIEnv.GetMethodID (class_ref, "getBar", "()I");
93+
return JNIEnv.CallIntMethod (((global::Java.Lang.Object) this).Handle, id_getBar);
94+
}
95+
}
96+
97+
}
98+
99+
100+
}
101+
102+
[global::Android.Runtime.Register ("com/xamarin/android/Parent", DoNotGenerateAcw=true)]
103+
internal partial class IParentInvoker : global::Java.Lang.Object, IParent {
104+
105+
static readonly JniPeerMembers _members = new JniPeerMembers ("com/xamarin/android/Parent", typeof (IParentInvoker));
106+
107+
static IntPtr java_class_ref {
108+
get { return _members.JniPeerType.PeerReference.Handle; }
109+
}
110+
111+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
112+
get { return _members; }
113+
}
114+
115+
protected override IntPtr ThresholdClass {
116+
get { return class_ref; }
117+
}
118+
119+
protected override global::System.Type ThresholdType {
120+
get { return _members.ManagedPeerType; }
121+
}
122+
123+
new IntPtr class_ref;
124+
125+
public static IParent GetObject (IntPtr handle, JniHandleOwnership transfer)
126+
{
127+
return global::Java.Lang.Object.GetObject<IParent> (handle, transfer);
128+
}
129+
130+
static IntPtr Validate (IntPtr handle)
131+
{
132+
if (!JNIEnv.IsInstanceOf (handle, java_class_ref))
133+
throw new InvalidCastException (string.Format ("Unable to convert instance of type '{0}' to type '{1}'.",
134+
JNIEnv.GetClassNameFromInstance (handle), "com.xamarin.android.Parent"));
135+
return handle;
136+
}
137+
138+
protected override void Dispose (bool disposing)
139+
{
140+
if (this.class_ref != IntPtr.Zero)
141+
JNIEnv.DeleteGlobalRef (this.class_ref);
142+
this.class_ref = IntPtr.Zero;
143+
base.Dispose (disposing);
144+
}
145+
146+
public IParentInvoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer)
147+
{
148+
IntPtr local_ref = JNIEnv.GetObjectClass (((global::Java.Lang.Object) this).Handle);
149+
this.class_ref = JNIEnv.NewGlobalRef (local_ref);
150+
JNIEnv.DeleteLocalRef (local_ref);
151+
}
152+
153+
static Delegate cb_getBar;
154+
#pragma warning disable 0169
155+
static Delegate GetGetBarHandler ()
156+
{
157+
if (cb_getBar == null)
158+
cb_getBar = JNINativeWrapper.CreateDelegate ((Func<IntPtr, IntPtr, int>) n_GetBar);
159+
return cb_getBar;
160+
}
161+
162+
static int n_GetBar (IntPtr jnienv, IntPtr native__this)
163+
{
164+
Com.Xamarin.Android.IParent __this = global::Java.Lang.Object.GetObject<Com.Xamarin.Android.IParent> (jnienv, native__this, JniHandleOwnership.DoNotTransfer);
165+
return __this.Bar;
166+
}
167+
#pragma warning restore 0169
168+
169+
IntPtr id_getBar;
170+
public unsafe int Bar {
171+
get {
172+
if (id_getBar == IntPtr.Zero)
173+
id_getBar = JNIEnv.GetMethodID (class_ref, "getBar", "()I");
174+
return JNIEnv.CallIntMethod (((global::Java.Lang.Object) this).Handle, id_getBar);
175+
}
176+
}
177+
178+
}
179+
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Metadata.xml XPath interface reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent.Child']"
2+
[Register ("com/xamarin/android/Parent$Child", "", "Com.Xamarin.Android.IParentChildInvoker")]
3+
public partial interface IParentChild : IJavaObject, IJavaPeerable {
4+
5+
int Bar {
6+
// Metadata.xml XPath method reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent.Child']/method[@name='getBar' and count(parameter)=0]"
7+
[Register ("getBar", "()I", "GetGetBarHandler:Com.Xamarin.Android.IParentChildInvoker, MyAssembly")] get;
8+
}
9+
10+
}
11+
12+
[global::Android.Runtime.Register ("com/xamarin/android/Parent$Child", DoNotGenerateAcw=true)]
13+
internal partial class IParentChildInvoker : global::Java.Lang.Object, IParentChild {
14+
15+
static readonly JniPeerMembers _members = new JniPeerMembers ("com/xamarin/android/Parent$Child", typeof (IParentChildInvoker));
16+
17+
static IntPtr java_class_ref {
18+
get { return _members.JniPeerType.PeerReference.Handle; }
19+
}
20+
21+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
22+
get { return _members; }
23+
}
24+
25+
protected override IntPtr ThresholdClass {
26+
get { return class_ref; }
27+
}
28+
29+
protected override global::System.Type ThresholdType {
30+
get { return _members.ManagedPeerType; }
31+
}
32+
33+
new IntPtr class_ref;
34+
35+
public static IParentChild GetObject (IntPtr handle, JniHandleOwnership transfer)
36+
{
37+
return global::Java.Lang.Object.GetObject<IParentChild> (handle, transfer);
38+
}
39+
40+
static IntPtr Validate (IntPtr handle)
41+
{
42+
if (!JNIEnv.IsInstanceOf (handle, java_class_ref))
43+
throw new InvalidCastException (string.Format ("Unable to convert instance of type '{0}' to type '{1}'.",
44+
JNIEnv.GetClassNameFromInstance (handle), "com.xamarin.android.Parent.Child"));
45+
return handle;
46+
}
47+
48+
protected override void Dispose (bool disposing)
49+
{
50+
if (this.class_ref != IntPtr.Zero)
51+
JNIEnv.DeleteGlobalRef (this.class_ref);
52+
this.class_ref = IntPtr.Zero;
53+
base.Dispose (disposing);
54+
}
55+
56+
public IParentChildInvoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer)
57+
{
58+
IntPtr local_ref = JNIEnv.GetObjectClass (((global::Java.Lang.Object) this).Handle);
59+
this.class_ref = JNIEnv.NewGlobalRef (local_ref);
60+
JNIEnv.DeleteLocalRef (local_ref);
61+
}
62+
63+
static Delegate cb_getBar;
64+
#pragma warning disable 0169
65+
static Delegate GetGetBarHandler ()
66+
{
67+
if (cb_getBar == null)
68+
cb_getBar = JNINativeWrapper.CreateDelegate ((Func<IntPtr, IntPtr, int>) n_GetBar);
69+
return cb_getBar;
70+
}
71+
72+
static int n_GetBar (IntPtr jnienv, IntPtr native__this)
73+
{
74+
Com.Xamarin.Android.IParentChild __this = global::Java.Lang.Object.GetObject<Com.Xamarin.Android.IParentChild> (jnienv, native__this, JniHandleOwnership.DoNotTransfer);
75+
return __this.Bar;
76+
}
77+
#pragma warning restore 0169
78+
79+
IntPtr id_getBar;
80+
public unsafe int Bar {
81+
get {
82+
if (id_getBar == IntPtr.Zero)
83+
id_getBar = JNIEnv.GetMethodID (class_ref, "getBar", "()I");
84+
return JNIEnv.CallIntMethod (((global::Java.Lang.Object) this).Handle, id_getBar);
85+
}
86+
}
87+
88+
}
89+
90+
91+
// Metadata.xml XPath interface reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent']"
92+
[Register ("com/xamarin/android/Parent", "", "Com.Xamarin.Android.IParentInvoker")]
93+
public partial interface IParent : IJavaObject, IJavaPeerable {
94+
95+
int Bar {
96+
// Metadata.xml XPath method reference: path="/api/package[@name='com.xamarin.android']/interface[@name='Parent']/method[@name='getBar' and count(parameter)=0]"
97+
[Register ("getBar", "()I", "GetGetBarHandler:Com.Xamarin.Android.IParentInvoker, MyAssembly")] get;
98+
}
99+
100+
}
101+
102+
[global::Android.Runtime.Register ("com/xamarin/android/Parent", DoNotGenerateAcw=true)]
103+
internal partial class IParentInvoker : global::Java.Lang.Object, IParent {
104+
105+
static readonly JniPeerMembers _members = new JniPeerMembers ("com/xamarin/android/Parent", typeof (IParentInvoker));
106+
107+
static IntPtr java_class_ref {
108+
get { return _members.JniPeerType.PeerReference.Handle; }
109+
}
110+
111+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
112+
get { return _members; }
113+
}
114+
115+
protected override IntPtr ThresholdClass {
116+
get { return class_ref; }
117+
}
118+
119+
protected override global::System.Type ThresholdType {
120+
get { return _members.ManagedPeerType; }
121+
}
122+
123+
new IntPtr class_ref;
124+
125+
public static IParent GetObject (IntPtr handle, JniHandleOwnership transfer)
126+
{
127+
return global::Java.Lang.Object.GetObject<IParent> (handle, transfer);
128+
}
129+
130+
static IntPtr Validate (IntPtr handle)
131+
{
132+
if (!JNIEnv.IsInstanceOf (handle, java_class_ref))
133+
throw new InvalidCastException (string.Format ("Unable to convert instance of type '{0}' to type '{1}'.",
134+
JNIEnv.GetClassNameFromInstance (handle), "com.xamarin.android.Parent"));
135+
return handle;
136+
}
137+
138+
protected override void Dispose (bool disposing)
139+
{
140+
if (this.class_ref != IntPtr.Zero)
141+
JNIEnv.DeleteGlobalRef (this.class_ref);
142+
this.class_ref = IntPtr.Zero;
143+
base.Dispose (disposing);
144+
}
145+
146+
public IParentInvoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer)
147+
{
148+
IntPtr local_ref = JNIEnv.GetObjectClass (((global::Java.Lang.Object) this).Handle);
149+
this.class_ref = JNIEnv.NewGlobalRef (local_ref);
150+
JNIEnv.DeleteLocalRef (local_ref);
151+
}
152+
153+
static Delegate cb_getBar;
154+
#pragma warning disable 0169
155+
static Delegate GetGetBarHandler ()
156+
{
157+
if (cb_getBar == null)
158+
cb_getBar = JNINativeWrapper.CreateDelegate ((Func<IntPtr, IntPtr, int>) n_GetBar);
159+
return cb_getBar;
160+
}
161+
162+
static int n_GetBar (IntPtr jnienv, IntPtr native__this)
163+
{
164+
Com.Xamarin.Android.IParent __this = global::Java.Lang.Object.GetObject<Com.Xamarin.Android.IParent> (jnienv, native__this, JniHandleOwnership.DoNotTransfer);
165+
return __this.Bar;
166+
}
167+
#pragma warning restore 0169
168+
169+
IntPtr id_getBar;
170+
public unsafe int Bar {
171+
get {
172+
if (id_getBar == IntPtr.Zero)
173+
id_getBar = JNIEnv.GetMethodID (class_ref, "getBar", "()I");
174+
return JNIEnv.CallIntMethod (((global::Java.Lang.Object) this).Handle, id_getBar);
175+
}
176+
}
177+
178+
}
179+

0 commit comments

Comments
 (0)