Skip to content

Commit 08d62b0

Browse files
atsushienojonpryor
authored andcommitted
[generator] fix generic parameter code generation for interface. (#100)
Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=43513 The background for the fix is, well, complicated. It was generating wrong code: // This method is explicitly implemented as a member of an instantiated Com.Google.Android.Exoplayer.Drm.IExoMediaDrm void global::Com.Google.Android.Exoplayer.Drm.IExoMediaDrm.SetOnEventListener (global::Com.Google.Android.Exoplayer.Drm.IExoMediaDrmOnEventListener p0) { SetOnEventListener (global::Java.Interop.JavaObjectExtensions.JavaCast<global::Com.Google.Android.Exoplayer.Drm.IExoMediaDrmOnEventListener<Java.Lang.Object>>(p0)); } where IExoMediaDrmOnEventListener is a normally generated interface ACW which does not have any generic parameter. The problem is, the Java API has generic argument T. Usually it does not matter in normal classes. But reference to an interface type with generic arguments is treated special: `IRequireGenericMarshal` It was introduced at old monodroid commit 443598f (which is not in this Java.Interop repo) for fixing bug #5979 to handle IList and ICollection for collection marshaling. So... basically ACWs were not expected to behave as IRequireGenericMarshal. And now that behavior bites us at bug #43513. Now, how to fix this new bug? This change introduces another boolean flag to determine if reference to this type should really output generic arguments. If it is False, then do not output any further. This is the best logical explanation I can make right now. What I still wonder are 1) whether it is only about InterfaceGen, and 2) if we could rather simplify things and eliminate this IRequireGenericMarshal thing. But so far I have no answer to those.
1 parent b25dd1b commit 08d62b0

15 files changed

+915
-2
lines changed

tools/generator/CollectionSymbol.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ public string ElementType {
5252
get { return null; }
5353
}
5454

55+
public bool MayHaveManagedGenericArguments {
56+
get { return true; }
57+
}
58+
5559
public string GetObjectHandleProperty (string variable)
5660
{
5761
return $"((global::Java.Lang.Object) {variable}).Handle";

tools/generator/GenericSymbol.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ public string FromNative (CodeGenerationOptions opt, string varname, bool owned)
9191

9292
public string GetGenericType (Dictionary<string, string> mappings)
9393
{
94-
return gen.FullName + (mappings == null ? tps : MapTypeParams (mappings));
94+
var rgm = gen as IRequireGenericMarshal;
95+
return gen.FullName + (rgm != null && !rgm.MayHaveManagedGenericArguments ? null : mappings == null ? tps : MapTypeParams (mappings));
9596
}
9697

9798
public string ToNative (CodeGenerationOptions opt, string varname)

tools/generator/IRequireGenericMarshal.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace MonoDroid.Generation
55
{
66
public interface IRequireGenericMarshal
77
{
8+
bool MayHaveManagedGenericArguments { get; }
89
string GetGenericJavaObjectTypeOverride ();
910
string ToInteroperableJavaObject (string varname);
1011
}

tools/generator/InterfaceGen.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@ public ManagedInterfaceGen (TypeDefinition t)
2424
AddMethod (new ManagedMethod (this, m));
2525
}
2626
}
27+
2728
public override string ArgsType {
2829
get { throw new NotImplementedException (); }
2930
}
31+
32+
public override bool MayHaveManagedGenericArguments {
33+
get { return !this.IsAcw; }
34+
}
3035
}
3136
#endif
3237

@@ -109,6 +114,10 @@ public bool IsListener {
109114
get { return Name.EndsWith ("Listener") && Properties.Count == 0 && Interfaces.Count == 0; }
110115
}
111116

117+
public virtual bool MayHaveManagedGenericArguments {
118+
get { return false; }
119+
}
120+
112121
public override string NativeType {
113122
get { return "IntPtr"; }
114123
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using NUnit.Framework;
3+
4+
namespace generatortests
5+
{
6+
[TestFixture]
7+
public class GenericArguments : BaseGeneratorTest
8+
{
9+
[Test]
10+
public void GeneratedOK ()
11+
{
12+
RunAllTargets (
13+
outputRelativePath: "GenericArguments",
14+
apiDescriptionFile: "expected/GenericArguments/GenericArguments.xml",
15+
expectedRelativePath: "GenericArguments",
16+
additionalSupportPaths: null);
17+
}
18+
}
19+
}
20+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Android.Runtime;
4+
using Java.Interop;
5+
6+
namespace Com.Google.Android.Exoplayer.Drm {
7+
8+
// Metadata.xml XPath class reference: path="/api/package[@name='com.google.android.exoplayer.drm']/class[@name='FrameworkMediaDrm']"
9+
[global::Android.Runtime.Register ("com/google/android/exoplayer/drm/FrameworkMediaDrm", DoNotGenerateAcw=true)]
10+
public sealed partial class FrameworkMediaDrm : global::Java.Lang.Object, global::Com.Google.Android.Exoplayer.Drm.IExoMediaDrm {
11+
12+
internal static readonly JniPeerMembers _members = new JniPeerMembers ("com/google/android/exoplayer/drm/FrameworkMediaDrm", typeof (FrameworkMediaDrm));
13+
internal static IntPtr class_ref {
14+
get {
15+
return _members.JniPeerType.PeerReference.Handle;
16+
}
17+
}
18+
19+
public override global::Java.Interop.JniPeerMembers JniPeerMembers {
20+
get { return _members; }
21+
}
22+
23+
protected override IntPtr ThresholdClass {
24+
get { return _members.JniPeerType.PeerReference.Handle; }
25+
}
26+
27+
protected override global::System.Type ThresholdType {
28+
get { return _members.ManagedPeerType; }
29+
}
30+
31+
internal FrameworkMediaDrm (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {}
32+
33+
// Metadata.xml XPath constructor reference: path="/api/package[@name='com.google.android.exoplayer.drm']/class[@name='FrameworkMediaDrm']/constructor[@name='FrameworkMediaDrm' and count(parameter)=0]"
34+
[Register (".ctor", "()V", "")]
35+
public unsafe FrameworkMediaDrm ()
36+
: base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
37+
{
38+
const string __id = "()V";
39+
40+
if (((global::Java.Lang.Object) this).Handle != IntPtr.Zero)
41+
return;
42+
43+
try {
44+
var __r = _members.InstanceMethods.StartCreateInstance (__id, ((object) this).GetType (), null);
45+
SetHandle (__r.Handle, JniHandleOwnership.TransferLocalRef);
46+
_members.InstanceMethods.FinishCreateInstance (__id, this, null);
47+
} finally {
48+
}
49+
}
50+
51+
// Metadata.xml XPath method reference: path="/api/package[@name='com.google.android.exoplayer.drm']/class[@name='FrameworkMediaDrm']/method[@name='setOnEventListener' and count(parameter)=1 and parameter[1][@type='com.google.android.exoplayer.drm.ExoMediaDrm.OnEventListener&lt;com.google.android.exoplayer.drm.FrameworkMediaCrypto&gt;']]"
52+
[Register ("setOnEventListener", "(Lcom/google/android/exoplayer/drm/ExoMediaDrm$OnEventListener;)V", "")]
53+
public unsafe void SetOnEventListener (global::Com.Google.Android.Exoplayer.Drm.IExoMediaDrmOnEventListener p0)
54+
{
55+
const string __id = "setOnEventListener.(Lcom/google/android/exoplayer/drm/ExoMediaDrm$OnEventListener;)V";
56+
try {
57+
JniArgumentValue* __args = stackalloc JniArgumentValue [1];
58+
__args [0] = new JniArgumentValue ((p0 == null) ? IntPtr.Zero : ((global::Java.Lang.Object) p0).Handle);
59+
_members.InstanceMethods.InvokeAbstractVoidMethod (__id, this, __args);
60+
} finally {
61+
}
62+
}
63+
64+
// This method is explicitly implemented as a member of an instantiated Com.Google.Android.Exoplayer.Drm.IExoMediaDrm
65+
void global::Com.Google.Android.Exoplayer.Drm.IExoMediaDrm.SetOnEventListener (global::Com.Google.Android.Exoplayer.Drm.IExoMediaDrmOnEventListener p0)
66+
{
67+
SetOnEventListener (global::Java.Interop.JavaObjectExtensions.JavaCast<global::Com.Google.Android.Exoplayer.Drm.IExoMediaDrmOnEventListener>(p0));
68+
}
69+
70+
}
71+
}

0 commit comments

Comments
 (0)