Skip to content

Commit 0361b4c

Browse files
committed
[generator] Get *full* list of implemented Interfaces
Consider `java.util.Deque`: /* partial */ interface Collection<E> { boolean add(E e); void clear(); } /* partial */ interface Queue<E> implements Collection<E> { boolean add(E e); } /* partial */ interface Deque<E> implements Queue<E> { boolean add(E e); } When implementing `IDequeInvoker`, we need to implement `ICollection.Clear()`, which is only declared in `Collection`: partial class IDequeInvoker { static readonly JniPeerMembers _members_java_util_Deque = new JniPeerMembers ("java/util/Deque", typeof (IDequeInvoker)); static readonly JniPeerMembers _members_java_util_Queue = new JniPeerMembers ("java/util/Queue", typeof (IDequeInvoker)); public unsafe void Clear () { const string __id = "clear.()V"; try { _members_java_util_Collection.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null); } finally { } } } The problem? `_members_java_util_Collection` didn't exist, because we only emitted `_members_*` fields for interfaces returned by `GenBase.GetAllImplementedInterfaces()`, which only returns "toplevel" implemented interfaces, but not the full graph of interfaces. In this case, we got `_members_java_util_Queue`, but not `_members_java_util_Collection`, which meant that `IDequeInvoker.Clear()` was attempting to access a field which did not exist. Update `InterfaceInvokerClass` so that the complete set of implemented interfaces is retrieved and emitted.
1 parent 430cf97 commit 0361b4c

File tree

14 files changed

+677
-2
lines changed

14 files changed

+677
-2
lines changed

tests/generator-Tests/Integration-Tests/Interfaces.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ namespace generatortests
66
[TestFixture]
77
public class Interfaces : BaseGeneratorTest
88
{
9+
public Interfaces ()
10+
{
11+
AllowWarnings = true;
12+
}
13+
914
protected override bool TryJavaInterop1 => true;
1015

1116
[Test]
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
#nullable restore
11+
using System;
12+
using System.Collections.Generic;
13+
using Java.Interop;
14+
15+
// Metadata.xml XPath class reference: path="/api/package[@name='']/class[@name='ClassWithoutNamespace']"
16+
[global::Java.Interop.JniTypeSignature ("ClassWithoutNamespace", GenerateJavaPeer=false)]
17+
public abstract partial class ClassWithoutNamespace : global::Java.Lang.Object, IInterfaceWithoutNamespace {
18+
static readonly JniPeerMembers _members = new JniPeerMembers ("ClassWithoutNamespace", typeof (ClassWithoutNamespace));
19+
20+
[global::System.Diagnostics.DebuggerBrowsable (global::System.Diagnostics.DebuggerBrowsableState.Never)]
21+
[global::System.ComponentModel.EditorBrowsable (global::System.ComponentModel.EditorBrowsableState.Never)]
22+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
23+
get { return _members; }
24+
}
25+
26+
protected ClassWithoutNamespace (ref JniObjectReference reference, JniObjectReferenceOptions options) : base (ref reference, options)
27+
{
28+
}
29+
30+
// Metadata.xml XPath constructor reference: path="/api/package[@name='']/class[@name='ClassWithoutNamespace']/constructor[@name='ClassWithoutNamespace' and count(parameter)=0]"
31+
public unsafe ClassWithoutNamespace () : base (ref *InvalidJniObjectReference, JniObjectReferenceOptions.None)
32+
{
33+
const string __id = "()V";
34+
35+
if (PeerReference.IsValid)
36+
return;
37+
38+
try {
39+
var __r = _members.InstanceMethods.StartCreateInstance (__id, ((object) this).GetType (), null);
40+
Construct (ref __r, JniObjectReferenceOptions.CopyAndDispose);
41+
_members.InstanceMethods.FinishCreateInstance (__id, this, null);
42+
} finally {
43+
}
44+
}
45+
46+
// Metadata.xml XPath method reference: path="/api/package[@name='']/interface[@name='InterfaceWithoutNamespace']/method[@name='Foo' and count(parameter)=0]"
47+
public abstract void Foo ();
48+
49+
}
50+
51+
[global::Java.Interop.JniTypeSignature ("ClassWithoutNamespace", GenerateJavaPeer=false)]
52+
internal partial class ClassWithoutNamespaceInvoker : ClassWithoutNamespace {
53+
public ClassWithoutNamespaceInvoker (ref JniObjectReference reference, JniObjectReferenceOptions options) : base (ref reference, options)
54+
{
55+
}
56+
57+
static readonly JniPeerMembers _members = new JniPeerMembers ("ClassWithoutNamespace", typeof (ClassWithoutNamespaceInvoker));
58+
59+
[global::System.Diagnostics.DebuggerBrowsable (global::System.Diagnostics.DebuggerBrowsableState.Never)]
60+
[global::System.ComponentModel.EditorBrowsable (global::System.ComponentModel.EditorBrowsableState.Never)]
61+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
62+
get { return _members; }
63+
}
64+
65+
// Metadata.xml XPath method reference: path="/api/package[@name='']/interface[@name='InterfaceWithoutNamespace']/method[@name='Foo' and count(parameter)=0]"
66+
[global::Java.Interop.JniMethodSignature ("Foo", "()V")]
67+
public override unsafe void Foo ()
68+
{
69+
const string __id = "Foo.()V";
70+
try {
71+
_members.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
72+
} finally {
73+
}
74+
}
75+
76+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Java.Interop;
4+
5+
// Metadata.xml XPath interface reference: path="/api/package[@name='']/interface[@name='InterfaceWithoutNamespace']"
6+
[global::Java.Interop.JniTypeSignature ("InterfaceWithoutNamespace", GenerateJavaPeer=false)]
7+
public partial interface IInterfaceWithoutNamespace : IJavaPeerable {
8+
// Metadata.xml XPath method reference: path="/api/package[@name='']/interface[@name='InterfaceWithoutNamespace']/method[@name='Foo' and count(parameter)=0]"
9+
[global::Java.Interop.JniMethodSignature ("Foo", "()V")]
10+
void Foo ();
11+
12+
}
13+
14+
[global::Java.Interop.JniTypeSignature ("InterfaceWithoutNamespace", GenerateJavaPeer=false)]
15+
internal partial class IInterfaceWithoutNamespaceInvoker : global::Java.Lang.Object, IInterfaceWithoutNamespace {
16+
[global::System.Diagnostics.DebuggerBrowsable (global::System.Diagnostics.DebuggerBrowsableState.Never)]
17+
[global::System.ComponentModel.EditorBrowsable (global::System.ComponentModel.EditorBrowsableState.Never)]
18+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
19+
get { return _members__InterfaceWithoutNamespace; }
20+
}
21+
22+
static readonly JniPeerMembers _members__InterfaceWithoutNamespace = new JniPeerMembers ("InterfaceWithoutNamespace", typeof (IInterfaceWithoutNamespaceInvoker));
23+
24+
public IInterfaceWithoutNamespaceInvoker (ref JniObjectReference reference, JniObjectReferenceOptions options) : base (ref reference, options)
25+
{
26+
}
27+
28+
public unsafe void Foo ()
29+
{
30+
const string __id = "Foo.()V";
31+
try {
32+
_members__InterfaceWithoutNamespace.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
33+
} finally {
34+
}
35+
}
36+
37+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Java.Interop;
4+
5+
namespace Java.Util {
6+
7+
// Metadata.xml XPath interface reference: path="/api/package[@name='java.util']/interface[@name='Collection']"
8+
[global::Java.Interop.JniTypeSignature ("java/util/Collection", GenerateJavaPeer=false)]
9+
[global::Java.Interop.JavaTypeParameters (new string [] {"E"})]
10+
public partial interface ICollection : IJavaPeerable {
11+
// Metadata.xml XPath method reference: path="/api/package[@name='java.util']/interface[@name='Collection']/method[@name='add' and count(parameter)=1 and parameter[1][@type='E']]"
12+
[global::Java.Interop.JniMethodSignature ("add", "(Ljava/lang/Object;)Z")]
13+
bool Add (global::Java.Lang.Object e);
14+
15+
// Metadata.xml XPath method reference: path="/api/package[@name='java.util']/interface[@name='Collection']/method[@name='clear' and count(parameter)=0]"
16+
[global::Java.Interop.JniMethodSignature ("clear", "()V")]
17+
void Clear ();
18+
19+
}
20+
21+
[global::Java.Interop.JniTypeSignature ("java/util/Collection", GenerateJavaPeer=false)]
22+
internal partial class ICollectionInvoker : global::Java.Lang.Object, ICollection {
23+
[global::System.Diagnostics.DebuggerBrowsable (global::System.Diagnostics.DebuggerBrowsableState.Never)]
24+
[global::System.ComponentModel.EditorBrowsable (global::System.ComponentModel.EditorBrowsableState.Never)]
25+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
26+
get { return _members_java_util_Collection; }
27+
}
28+
29+
static readonly JniPeerMembers _members_java_util_Collection = new JniPeerMembers ("java/util/Collection", typeof (ICollectionInvoker));
30+
31+
public ICollectionInvoker (ref JniObjectReference reference, JniObjectReferenceOptions options) : base (ref reference, options)
32+
{
33+
}
34+
35+
public unsafe bool Add (global::Java.Lang.Object e)
36+
{
37+
const string __id = "add.(Ljava/lang/Object;)Z";
38+
var native_e = (e?.PeerReference ?? default);
39+
try {
40+
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
41+
__args [0] = new JniArgumentValue (native_e);
42+
var __rm = _members_java_util_Collection.InstanceMethods.InvokeAbstractBooleanMethod (__id, this, __args);
43+
return __rm;
44+
} finally {
45+
global::System.GC.KeepAlive (e);
46+
}
47+
}
48+
49+
public unsafe void Clear ()
50+
{
51+
const string __id = "clear.()V";
52+
try {
53+
_members_java_util_Collection.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
54+
} finally {
55+
}
56+
}
57+
58+
}
59+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Java.Interop;
4+
5+
namespace Java.Util {
6+
7+
// Metadata.xml XPath interface reference: path="/api/package[@name='java.util']/interface[@name='Deque']"
8+
[global::Java.Interop.JniTypeSignature ("java/util/Deque", GenerateJavaPeer=false)]
9+
[global::Java.Interop.JavaTypeParameters (new string [] {"E"})]
10+
public partial interface IDeque : global::Java.Util.IQueue {
11+
// Metadata.xml XPath method reference: path="/api/package[@name='java.util']/interface[@name='Deque']/method[@name='add' and count(parameter)=1 and parameter[1][@type='E']]"
12+
[global::Java.Interop.JniMethodSignature ("add", "(Ljava/lang/Object;)Z")]
13+
bool Add (global::Java.Lang.Object e);
14+
15+
}
16+
17+
[global::Java.Interop.JniTypeSignature ("java/util/Deque", GenerateJavaPeer=false)]
18+
internal partial class IDequeInvoker : global::Java.Lang.Object, IDeque {
19+
[global::System.Diagnostics.DebuggerBrowsable (global::System.Diagnostics.DebuggerBrowsableState.Never)]
20+
[global::System.ComponentModel.EditorBrowsable (global::System.ComponentModel.EditorBrowsableState.Never)]
21+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
22+
get { return _members_java_util_Deque; }
23+
}
24+
25+
static readonly JniPeerMembers _members_java_util_Deque = new JniPeerMembers ("java/util/Deque", typeof (IDequeInvoker));
26+
27+
static readonly JniPeerMembers _members_java_util_Queue = new JniPeerMembers ("java/util/Queue", typeof (IDequeInvoker));
28+
29+
static readonly JniPeerMembers _members_java_util_Collection = new JniPeerMembers ("java/util/Collection", typeof (IDequeInvoker));
30+
31+
public IDequeInvoker (ref JniObjectReference reference, JniObjectReferenceOptions options) : base (ref reference, options)
32+
{
33+
}
34+
35+
public unsafe bool Add (global::Java.Lang.Object e)
36+
{
37+
const string __id = "add.(Ljava/lang/Object;)Z";
38+
var native_e = (e?.PeerReference ?? default);
39+
try {
40+
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
41+
__args [0] = new JniArgumentValue (native_e);
42+
var __rm = _members_java_util_Deque.InstanceMethods.InvokeAbstractBooleanMethod (__id, this, __args);
43+
return __rm;
44+
} finally {
45+
global::System.GC.KeepAlive (e);
46+
}
47+
}
48+
49+
public unsafe void Clear ()
50+
{
51+
const string __id = "clear.()V";
52+
try {
53+
_members_java_util_Collection.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
54+
} finally {
55+
}
56+
}
57+
58+
}
59+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Java.Interop;
4+
5+
namespace Java.Util {
6+
7+
// Metadata.xml XPath interface reference: path="/api/package[@name='java.util']/interface[@name='Queue']"
8+
[global::Java.Interop.JniTypeSignature ("java/util/Queue", GenerateJavaPeer=false)]
9+
[global::Java.Interop.JavaTypeParameters (new string [] {"E"})]
10+
public partial interface IQueue : global::Java.Util.ICollection {
11+
// Metadata.xml XPath method reference: path="/api/package[@name='java.util']/interface[@name='Queue']/method[@name='add' and count(parameter)=1 and parameter[1][@type='E']]"
12+
[global::Java.Interop.JniMethodSignature ("add", "(Ljava/lang/Object;)Z")]
13+
bool Add (global::Java.Lang.Object e);
14+
15+
}
16+
17+
[global::Java.Interop.JniTypeSignature ("java/util/Queue", GenerateJavaPeer=false)]
18+
internal partial class IQueueInvoker : global::Java.Lang.Object, IQueue {
19+
[global::System.Diagnostics.DebuggerBrowsable (global::System.Diagnostics.DebuggerBrowsableState.Never)]
20+
[global::System.ComponentModel.EditorBrowsable (global::System.ComponentModel.EditorBrowsableState.Never)]
21+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
22+
get { return _members_java_util_Queue; }
23+
}
24+
25+
static readonly JniPeerMembers _members_java_util_Queue = new JniPeerMembers ("java/util/Queue", typeof (IQueueInvoker));
26+
27+
static readonly JniPeerMembers _members_java_util_Collection = new JniPeerMembers ("java/util/Collection", typeof (IQueueInvoker));
28+
29+
public IQueueInvoker (ref JniObjectReference reference, JniObjectReferenceOptions options) : base (ref reference, options)
30+
{
31+
}
32+
33+
public unsafe bool Add (global::Java.Lang.Object e)
34+
{
35+
const string __id = "add.(Ljava/lang/Object;)Z";
36+
var native_e = (e?.PeerReference ?? default);
37+
try {
38+
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
39+
__args [0] = new JniArgumentValue (native_e);
40+
var __rm = _members_java_util_Queue.InstanceMethods.InvokeAbstractBooleanMethod (__id, this, __args);
41+
return __rm;
42+
} finally {
43+
global::System.GC.KeepAlive (e);
44+
}
45+
}
46+
47+
public unsafe void Clear ()
48+
{
49+
const string __id = "clear.()V";
50+
try {
51+
_members_java_util_Collection.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
52+
} finally {
53+
}
54+
}
55+
56+
}
57+
}

tests/generator-Tests/expected.ji/TestInterface/Mono.Android.projitems

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
<Compile Include="$(MSBuildThisFileDirectory)IInterfaceWithoutNamespace.cs" />
1010
<Compile Include="$(MSBuildThisFileDirectory)Java.Lang.Object.cs" />
1111
<Compile Include="$(MSBuildThisFileDirectory)Java.Lang.String.cs" />
12+
<Compile Include="$(MSBuildThisFileDirectory)Java.Util.ICollection.cs" />
13+
<Compile Include="$(MSBuildThisFileDirectory)Java.Util.IDeque.cs" />
14+
<Compile Include="$(MSBuildThisFileDirectory)Java.Util.IQueue.cs" />
1215
<Compile Include="$(MSBuildThisFileDirectory)Test.ME.GenericImplementation.cs" />
1316
<Compile Include="$(MSBuildThisFileDirectory)Test.ME.GenericObjectPropertyImplementation.cs" />
1417
<Compile Include="$(MSBuildThisFileDirectory)Test.ME.GenericStringImplementation.cs" />

tests/generator-Tests/expected.ji/TestInterface/TestInterface.xml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,41 @@
77
final="true" name="String" static="false" visibility="public">
88
</class>
99
</package>
10+
<package name="java.util">
11+
<interface abstract="true" deprecated="not deprecated" final="false" name="Collection" static="false" visibility="public" jni-signature="Ljava/util/Collection;">
12+
<typeParameters>
13+
<typeParameter name="E" classBound="java.lang.Object" jni-classBound="Ljava/lang/Object;"></typeParameter>
14+
</typeParameters>
15+
<method abstract="true" deprecated="not deprecated" final="false" name="add" jni-signature="(Ljava/lang/Object;)Z" bridge="false" native="false" return="boolean" jni-return="Z" static="false" synchronized="false" synthetic="false" visibility="public">
16+
<parameter name="e" type="E" jni-type="TE;">
17+
</parameter>
18+
</method>
19+
<method abstract="true" deprecated="not deprecated" final="false" name="clear" jni-signature="()V" bridge="false" native="false" return="void" jni-return="V" static="false" synchronized="false" synthetic="false" visibility="public">
20+
</method>
21+
</interface>
22+
<interface abstract="true" deprecated="not deprecated" final="false" name="Queue" static="false" visibility="public" jni-signature="Ljava/util/Queue;">
23+
<implements name="java.util.Collection" name-generic-aware="java.util.Collection&lt;E&gt;" jni-type="Ljava/util/Collection&lt;TE;&gt;;">
24+
</implements>
25+
<typeParameters>
26+
<typeParameter name="E" classBound="java.lang.Object" jni-classBound="Ljava/lang/Object;"></typeParameter>
27+
</typeParameters>
28+
<method abstract="true" deprecated="not deprecated" final="false" name="add" jni-signature="(Ljava/lang/Object;)Z" bridge="false" native="false" return="boolean" jni-return="Z" static="false" synchronized="false" synthetic="false" visibility="public">
29+
<parameter name="e" type="E" jni-type="TE;">
30+
</parameter>
31+
</method>
32+
</interface>
33+
<interface abstract="true" deprecated="not deprecated" final="false" name="Deque" static="false" visibility="public" jni-signature="Ljava/util/Deque;">
34+
<implements name="java.util.Queue" name-generic-aware="java.util.Queue&lt;E&gt;" jni-type="Ljava/util/Queue&lt;TE;&gt;;">
35+
</implements>
36+
<typeParameters>
37+
<typeParameter name="E" classBound="java.lang.Object" jni-classBound="Ljava/lang/Object;"></typeParameter>
38+
</typeParameters>
39+
<method abstract="true" deprecated="not deprecated" final="false" name="add" jni-signature="(Ljava/lang/Object;)Z" bridge="false" native="false" return="boolean" jni-return="Z" static="false" synchronized="false" synthetic="false" visibility="public">
40+
<parameter name="e" type="E" jni-type="TE;">
41+
</parameter>
42+
</method>
43+
</interface>
44+
</package>
1045
<package name="test.me">
1146
<!--
1247
public interface TestInterface {

0 commit comments

Comments
 (0)