Skip to content

Commit 6abb5af

Browse files
committed
[generator] Fix names of classes nested in an interface.
1 parent b33d183 commit 6abb5af

File tree

3 files changed

+153
-8
lines changed

3 files changed

+153
-8
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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 class reference: path="/api/package[@name='com.xamarin.android']/class[@name='Parent.Child']"
11+
[global::Android.Runtime.Register ("com/xamarin/android/Parent$Child", DoNotGenerateAcw=true)]
12+
public partial class Child : Java.Lang.Object {
13+
14+
static readonly JniPeerMembers _members = new JniPeerMembers ("com/xamarin/android/Parent$Child", typeof (Child));
15+
internal static new IntPtr class_ref {
16+
get {
17+
return _members.JniPeerType.PeerReference.Handle;
18+
}
19+
}
20+
21+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
22+
get { return _members; }
23+
}
24+
25+
protected override IntPtr ThresholdClass {
26+
get { return _members.JniPeerType.PeerReference.Handle; }
27+
}
28+
29+
protected override global::System.Type ThresholdType {
30+
get { return _members.ManagedPeerType; }
31+
}
32+
33+
protected Child (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {}
34+
35+
}
36+
37+
}
38+
39+
[global::Android.Runtime.Register ("com/xamarin/android/Parent", DoNotGenerateAcw=true)]
40+
internal partial class IParentInvoker : global::Java.Lang.Object, IParent {
41+
42+
static readonly JniPeerMembers _members = new JniPeerMembers ("com/xamarin/android/Parent", typeof (IParentInvoker));
43+
44+
static IntPtr java_class_ref {
45+
get { return _members.JniPeerType.PeerReference.Handle; }
46+
}
47+
48+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
49+
get { return _members; }
50+
}
51+
52+
protected override IntPtr ThresholdClass {
53+
get { return class_ref; }
54+
}
55+
56+
protected override global::System.Type ThresholdType {
57+
get { return _members.ManagedPeerType; }
58+
}
59+
60+
new IntPtr class_ref;
61+
62+
public static IParent GetObject (IntPtr handle, JniHandleOwnership transfer)
63+
{
64+
return global::Java.Lang.Object.GetObject<IParent> (handle, transfer);
65+
}
66+
67+
static IntPtr Validate (IntPtr handle)
68+
{
69+
if (!JNIEnv.IsInstanceOf (handle, java_class_ref))
70+
throw new InvalidCastException (string.Format ("Unable to convert instance of type '{0}' to type '{1}'.",
71+
JNIEnv.GetClassNameFromInstance (handle), "com.xamarin.android.Parent"));
72+
return handle;
73+
}
74+
75+
protected override void Dispose (bool disposing)
76+
{
77+
if (this.class_ref != IntPtr.Zero)
78+
JNIEnv.DeleteGlobalRef (this.class_ref);
79+
this.class_ref = IntPtr.Zero;
80+
base.Dispose (disposing);
81+
}
82+
83+
public IParentInvoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer)
84+
{
85+
IntPtr local_ref = JNIEnv.GetObjectClass (((global::Java.Lang.Object) this).Handle);
86+
this.class_ref = JNIEnv.NewGlobalRef (local_ref);
87+
JNIEnv.DeleteLocalRef (local_ref);
88+
}
89+
90+
static Delegate cb_getBar;
91+
#pragma warning disable 0169
92+
static Delegate GetGetBarHandler ()
93+
{
94+
if (cb_getBar == null)
95+
cb_getBar = JNINativeWrapper.CreateDelegate ((Func<IntPtr, IntPtr, int>) n_GetBar);
96+
return cb_getBar;
97+
}
98+
99+
static int n_GetBar (IntPtr jnienv, IntPtr native__this)
100+
{
101+
Com.Xamarin.Android.IParent __this = global::Java.Lang.Object.GetObject<Com.Xamarin.Android.IParent> (jnienv, native__this, JniHandleOwnership.DoNotTransfer);
102+
return __this.Bar;
103+
}
104+
#pragma warning restore 0169
105+
106+
IntPtr id_getBar;
107+
public unsafe int Bar {
108+
get {
109+
if (id_getBar == IntPtr.Zero)
110+
id_getBar = JNIEnv.GetMethodID (class_ref, "getBar", "()I");
111+
return JNIEnv.CallIntMethod (((global::Java.Lang.Object) this).Handle, id_getBar);
112+
}
113+
}
114+
115+
}
116+

tests/generator-Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,18 @@ public void WriteStaticInterfaceProperty ()
241241
</package>
242242
</api>";
243243

244+
readonly string nested_class_api = @"<api>
245+
<package name='java.lang' jni-name='java/lang'>
246+
<class abstract='false' deprecated='not deprecated' final='false' name='Object' static='false' visibility='public' jni-signature='Ljava/lang/EmptyOverrideClass;' />
247+
</package>
248+
<package name='com.xamarin.android' jni-name='com/xamarin/android'>
249+
<interface abstract='true' deprecated='not deprecated' final='false' name='Parent' static='false' visibility='public' jni-signature='Lcom/xamarin/android/Parent;'>
250+
<method abstract='true' deprecated='not deprecated' final='false' name='getBar' jni-signature='()I' bridge='false' native='false' return='int' jni-return='I' static='false' synchronized='false' synthetic='false' visibility='public'></method>
251+
</interface>
252+
<class abstract='false' deprecated='not deprecated' extends='java.lang.Object' extends-generic-aware='java.lang.Object' jni-extends='Ljava/lang/Object;' final='false' name='Parent.Child' static='false' visibility='public' jni-signature='Lcom/xamarin/android/Parent$Child;' />
253+
</package>
254+
</api>";
255+
244256
[Test]
245257
public void WriteUnnestedInterfaceTypes ()
246258
{
@@ -273,5 +285,23 @@ public void WriteNestedInterfaceTypes ()
273285

274286
Assert.AreEqual (GetTargetedExpected (nameof (WriteNestedInterfaceTypes)), writer.ToString ().NormalizeLineEndings ());
275287
}
288+
289+
[Test]
290+
public void WriteNestedInterfaceClass ()
291+
{
292+
// Traditionally this would have created namespace.IParent and namespace.IParentChild
293+
// With nested types this creates namespace.IParent and namespace.IParent.IChild
294+
options.SupportNestedInterfaceTypes = true;
295+
296+
var gens = ParseApiDefinition (nested_class_api);
297+
298+
var parent_iface = gens.OfType<InterfaceGen> ().Single ();
299+
300+
parent_iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ());
301+
302+
generator.WriteInterface (parent_iface, string.Empty, new GenerationInfo (string.Empty, string.Empty, "MyAssembly"));
303+
304+
Assert.AreEqual (GetTargetedExpected (nameof (WriteNestedInterfaceClass)), writer.ToString ().NormalizeLineEndings ());
305+
}
276306
}
277307
}

tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@ public override void AddNestedType (GenBase gen)
2020
var nest_name = gen.JavaName.Substring (JavaName.Length + 1);
2121

2222
if (nest_name.IndexOf (".") < 0) {
23-
if (gen is InterfaceGen) {
24-
25-
// We don't need to mangle the name if we support nested interface types
26-
// ex: my.namespace.IParent.IChild
27-
if (!gen.Unnest) {
28-
gen.FullName = FullName + "." + gen.Name;
29-
return;
30-
}
23+
// We don't need to mangle the name if we support nested interface types
24+
// ex: my.namespace.IParent.IChild
25+
if (!gen.Unnest) {
26+
gen.FullName = FullName + "." + gen.Name;
27+
return;
28+
}
3129

30+
if (gen is InterfaceGen) {
3231
// ex: my.namespace.IParentChild
3332
gen.FullName = FullName + gen.Name.Substring (1);
3433
gen.Name = Name + gen.Name.Substring (1);

0 commit comments

Comments
 (0)