Skip to content

Commit 6bd19a0

Browse files
committed
[generator] do not generate identical methods to previously generated ones.
There are classes that implement more than one interfaces that share an identical methods (which share the same name and the same JNI signature). For example, java.nio.AsynchronousFileChannel implements Closeable and AsynchronousChannel, both of which contain `close()` method. Only one `Close()` should be generated for that class.
1 parent 689c752 commit 6bd19a0

22 files changed

+902
-3
lines changed

tools/generator/ClassGen.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,7 @@ public override ClassGen BaseGen {
313313
void GenerateAbstractMembers (StreamWriter sw, string indent, CodeGenerationOptions opt)
314314
{
315315
foreach (InterfaceGen gen in GetAllDerivedInterfaces ())
316-
// FIXME: this is an ugly workaround for bug in generator that generates extraneous member.
317-
if (FullName != "Android.Views.Animations.BaseInterpolator" || gen.FullName != "Android.Views.Animations.IInterpolator")
318-
gen.GenerateAbstractMembers (this, sw, indent, opt);
316+
gen.GenerateAbstractMembers (this, sw, indent, opt);
319317
}
320318

321319
void GenMethods (StreamWriter sw, string indent, CodeGenerationOptions opt)
@@ -339,6 +337,7 @@ void GenMethods (StreamWriter sw, string indent, CodeGenerationOptions opt)
339337
m.GenerateAbstractDeclaration (sw, indent, opt, null, this);
340338
else
341339
m.Generate (sw, indent, opt, this, true);
340+
opt.ContextGeneratedMethods.Add (m);
342341
m.IsVirtual = virt;
343342
}
344343

@@ -371,6 +370,8 @@ void GenProperties (StreamWriter sw, string indent, CodeGenerationOptions opt)
371370
public override void Generate (StreamWriter sw, string indent, CodeGenerationOptions opt, GenerationInfo gen_info)
372371
{
373372
opt.ContextTypes.Push (this);
373+
opt.ContextGeneratedMethods = new List<Method> ();
374+
374375
gen_info.TypeRegistrations.Add (new KeyValuePair<string, string>(RawJniName, AssemblyQualifiedName));
375376
bool is_enum = base_symbol != null && base_symbol.FullName == "Java.Lang.Enum";
376377
if (is_enum)
@@ -497,6 +498,9 @@ public override void Generate (StreamWriter sw, string indent, CodeGenerationOpt
497498
sw.WriteLine ();
498499
GenerateInvoker (sw, indent, opt);
499500
}
501+
502+
opt.ContextGeneratedMethods.Clear ();
503+
500504
opt.ContextTypes.Pop ();
501505
}
502506

tools/generator/CodeGenerator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ public class CodeGenerationOptions
560560
public Stack<GenBase> ContextTypes {
561561
get { return context_types; }
562562
}
563+
public List<Method> ContextGeneratedMethods { get; set; } = new List<Method> ();
563564
public GenBase ContextType {
564565
get { return context_types.Any () ? context_types.Peek () : null; }
565566
}

tools/generator/InterfaceGen.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,8 @@ public void GenerateAbstractMembers (ClassGen gen, StreamWriter sw, string inden
620620
foreach (Method m in Methods.Where (m => !m.IsInterfaceDefaultMethod && !m.IsStatic)) {
621621
bool mapped = false;
622622
string sig = m.GetSignature ();
623+
if (opt.ContextGeneratedMethods.Any (_ => _.Name == m.Name && _.JniSignature == m.JniSignature))
624+
continue;
623625
for (var cls = gen; cls != null; cls = cls.BaseGen)
624626
if (cls.ContainsMethod (m, false) || cls != gen && gen.ExplicitlyImplementedInterfaceMethods.Contains (sig)) {
625627
mapped = true;
@@ -631,6 +633,7 @@ public void GenerateAbstractMembers (ClassGen gen, StreamWriter sw, string inden
631633
m.GenerateExplicitInterfaceImplementation (sw, indent, opt, this);
632634
else
633635
m.GenerateAbstractDeclaration (sw, indent, opt, this, gen);
636+
opt.ContextGeneratedMethods.Add (m);
634637
}
635638
foreach (Property prop in Properties) {
636639
if (gen.ContainsProperty (prop.Name, false))
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using NUnit.Framework;
3+
4+
namespace generatortests
5+
{
6+
[TestFixture]
7+
public class InterfaceMethodsConflict : BaseGeneratorTest
8+
{
9+
[Test]
10+
public void GeneratedOK ()
11+
{
12+
RunAllTargets (
13+
outputRelativePath: "InterfaceMethodsConflict",
14+
apiDescriptionFile: "expected/InterfaceMethodsConflict/InterfaceMethodsConflict.xml",
15+
expectedRelativePath: "InterfaceMethodsConflict");
16+
}
17+
}
18+
}
19+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<api>
3+
<package name="xamarin.test">
4+
<class abstract="false" deprecated="not deprecated" final="false" name="Object" static="false" visibility="public">
5+
</class>
6+
</package>
7+
<package name="xamarin.test">
8+
<interface abstract="true" deprecated="not deprecated" final="false" name="I1" static="false" visibility="public">
9+
<method abstract="true" deprecated="not deprecated" final="false" name="close" native="false" return="void" static="false" synchronized="false" visibility="public">
10+
</method>
11+
</interface>
12+
<interface abstract="true" deprecated="not deprecated" final="false" name="I2" static="false" visibility="public">
13+
<method abstract="true" deprecated="not deprecated" final="false" name="close" native="false" return="void" static="false" synchronized="false" visibility="public">
14+
</method>
15+
</interface>
16+
<class abstract="true" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object"
17+
final="false" name="SomeObject" static="false" visibility="public">
18+
<implements name="xamarin.test.I1" name-generic-aware="xamarin.test.I1" />
19+
<implements name="xamarin.test.I2" name-generic-aware="xamarin.test.I2" />
20+
</class>
21+
</package>
22+
</api>
23+
24+
25+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Android.Runtime;
4+
5+
namespace Java.Interop {
6+
7+
partial class __TypeRegistrations {
8+
9+
public static void RegisterPackages ()
10+
{
11+
#if MONODROID_TIMING
12+
var start = DateTime.Now;
13+
Android.Util.Log.Info ("MonoDroid-Timing", "RegisterPackages start: " + (start - new DateTime (1970, 1, 1)).TotalMilliseconds);
14+
#endif // def MONODROID_TIMING
15+
Java.Interop.TypeManager.RegisterPackages (
16+
new string[]{
17+
},
18+
new Converter<string, Type>[]{
19+
});
20+
#if MONODROID_TIMING
21+
var end = DateTime.Now;
22+
Android.Util.Log.Info ("MonoDroid-Timing", "RegisterPackages time: " + (end - new DateTime (1970, 1, 1)).TotalMilliseconds + " [elapsed: " + (end - start).TotalMilliseconds + " ms]");
23+
#endif // def MONODROID_TIMING
24+
}
25+
26+
static Type Lookup (string[] mappings, string javaType)
27+
{
28+
string managedType = Java.Interop.TypeManager.LookupTypeMapping (mappings, javaType);
29+
if (managedType == null)
30+
return null;
31+
return Type.GetType (managedType);
32+
}
33+
}
34+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Android.Runtime;
4+
using Java.Interop;
5+
6+
namespace Java.Lang {
7+
8+
// Metadata.xml XPath class reference: path="/api/package[@name='java.lang']/class[@name='Object']"
9+
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
10+
public partial class Object {
11+
12+
}
13+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Android.Runtime;
4+
using Java.Interop;
5+
6+
namespace Xamarin.Test {
7+
8+
// Metadata.xml XPath interface reference: path="/api/package[@name='xamarin.test']/interface[@name='I1']"
9+
[Register ("xamarin/test/I1", "", "Xamarin.Test.II1Invoker")]
10+
public partial interface II1 : IJavaObject {
11+
12+
// Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='I1']/method[@name='close' and count(parameter)=0]"
13+
[Register ("close", "()V", "GetCloseHandler:Xamarin.Test.II1Invoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
14+
void Close ();
15+
16+
}
17+
18+
[global::Android.Runtime.Register ("xamarin/test/I1", DoNotGenerateAcw=true)]
19+
internal class II1Invoker : global::Java.Lang.Object, II1 {
20+
21+
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/I1", typeof (II1Invoker));
22+
23+
static IntPtr java_class_ref {
24+
get { return _members.JniPeerType.PeerReference.Handle; }
25+
}
26+
27+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
28+
get { return _members; }
29+
}
30+
31+
protected override IntPtr ThresholdClass {
32+
get { return class_ref; }
33+
}
34+
35+
protected override global::System.Type ThresholdType {
36+
get { return _members.ManagedPeerType; }
37+
}
38+
39+
IntPtr class_ref;
40+
41+
public static II1 GetObject (IntPtr handle, JniHandleOwnership transfer)
42+
{
43+
return global::Java.Lang.Object.GetObject<II1> (handle, transfer);
44+
}
45+
46+
static IntPtr Validate (IntPtr handle)
47+
{
48+
if (!JNIEnv.IsInstanceOf (handle, java_class_ref))
49+
throw new InvalidCastException (string.Format ("Unable to convert instance of type '{0}' to type '{1}'.",
50+
JNIEnv.GetClassNameFromInstance (handle), "xamarin.test.I1"));
51+
return handle;
52+
}
53+
54+
protected override void Dispose (bool disposing)
55+
{
56+
if (this.class_ref != IntPtr.Zero)
57+
JNIEnv.DeleteGlobalRef (this.class_ref);
58+
this.class_ref = IntPtr.Zero;
59+
base.Dispose (disposing);
60+
}
61+
62+
public II1Invoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer)
63+
{
64+
IntPtr local_ref = JNIEnv.GetObjectClass (((global::Java.Lang.Object) this).Handle);
65+
this.class_ref = JNIEnv.NewGlobalRef (local_ref);
66+
JNIEnv.DeleteLocalRef (local_ref);
67+
}
68+
69+
static Delegate cb_close;
70+
#pragma warning disable 0169
71+
static Delegate GetCloseHandler ()
72+
{
73+
if (cb_close == null)
74+
cb_close = JNINativeWrapper.CreateDelegate ((Action<IntPtr, IntPtr>) n_Close);
75+
return cb_close;
76+
}
77+
78+
static void n_Close (IntPtr jnienv, IntPtr native__this)
79+
{
80+
global::Xamarin.Test.II1 __this = global::Java.Lang.Object.GetObject<global::Xamarin.Test.II1> (jnienv, native__this, JniHandleOwnership.DoNotTransfer);
81+
__this.Close ();
82+
}
83+
#pragma warning restore 0169
84+
85+
IntPtr id_close;
86+
public unsafe void Close ()
87+
{
88+
if (id_close == IntPtr.Zero)
89+
id_close = JNIEnv.GetMethodID (class_ref, "close", "()V");
90+
JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_close);
91+
}
92+
93+
}
94+
95+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Android.Runtime;
4+
using Java.Interop;
5+
6+
namespace Xamarin.Test {
7+
8+
// Metadata.xml XPath interface reference: path="/api/package[@name='xamarin.test']/interface[@name='I2']"
9+
[Register ("xamarin/test/I2", "", "Xamarin.Test.II2Invoker")]
10+
public partial interface II2 : IJavaObject {
11+
12+
// Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='I2']/method[@name='close' and count(parameter)=0]"
13+
[Register ("close", "()V", "GetCloseHandler:Xamarin.Test.II2Invoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
14+
void Close ();
15+
16+
}
17+
18+
[global::Android.Runtime.Register ("xamarin/test/I2", DoNotGenerateAcw=true)]
19+
internal class II2Invoker : global::Java.Lang.Object, II2 {
20+
21+
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/I2", typeof (II2Invoker));
22+
23+
static IntPtr java_class_ref {
24+
get { return _members.JniPeerType.PeerReference.Handle; }
25+
}
26+
27+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
28+
get { return _members; }
29+
}
30+
31+
protected override IntPtr ThresholdClass {
32+
get { return class_ref; }
33+
}
34+
35+
protected override global::System.Type ThresholdType {
36+
get { return _members.ManagedPeerType; }
37+
}
38+
39+
IntPtr class_ref;
40+
41+
public static II2 GetObject (IntPtr handle, JniHandleOwnership transfer)
42+
{
43+
return global::Java.Lang.Object.GetObject<II2> (handle, transfer);
44+
}
45+
46+
static IntPtr Validate (IntPtr handle)
47+
{
48+
if (!JNIEnv.IsInstanceOf (handle, java_class_ref))
49+
throw new InvalidCastException (string.Format ("Unable to convert instance of type '{0}' to type '{1}'.",
50+
JNIEnv.GetClassNameFromInstance (handle), "xamarin.test.I2"));
51+
return handle;
52+
}
53+
54+
protected override void Dispose (bool disposing)
55+
{
56+
if (this.class_ref != IntPtr.Zero)
57+
JNIEnv.DeleteGlobalRef (this.class_ref);
58+
this.class_ref = IntPtr.Zero;
59+
base.Dispose (disposing);
60+
}
61+
62+
public II2Invoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer)
63+
{
64+
IntPtr local_ref = JNIEnv.GetObjectClass (((global::Java.Lang.Object) this).Handle);
65+
this.class_ref = JNIEnv.NewGlobalRef (local_ref);
66+
JNIEnv.DeleteLocalRef (local_ref);
67+
}
68+
69+
static Delegate cb_close;
70+
#pragma warning disable 0169
71+
static Delegate GetCloseHandler ()
72+
{
73+
if (cb_close == null)
74+
cb_close = JNINativeWrapper.CreateDelegate ((Action<IntPtr, IntPtr>) n_Close);
75+
return cb_close;
76+
}
77+
78+
static void n_Close (IntPtr jnienv, IntPtr native__this)
79+
{
80+
global::Xamarin.Test.II2 __this = global::Java.Lang.Object.GetObject<global::Xamarin.Test.II2> (jnienv, native__this, JniHandleOwnership.DoNotTransfer);
81+
__this.Close ();
82+
}
83+
#pragma warning restore 0169
84+
85+
IntPtr id_close;
86+
public unsafe void Close ()
87+
{
88+
if (id_close == IntPtr.Zero)
89+
id_close = JNIEnv.GetMethodID (class_ref, "close", "()V");
90+
JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_close);
91+
}
92+
93+
}
94+
95+
}

0 commit comments

Comments
 (0)