Skip to content

Commit

Permalink
Generate Threshold{Class,Type} properties for all classes
Browse files Browse the repository at this point in the history
If a class derives from `Java.Lang.Object` it should have the two properties
mentioned above generated, so that it is possible to find methods in the correct
instance of Java class instance that is wrapped by our managed class.

Generator used to decide whether or not to generate these properties based on
the presence of class members (fields, constructors, methods and properties) or
whether the class is an annotation in the API description file.

However there exist a number of classes (for instance `Inet4Address`) which don't
have any of the members present and yet they should have the Threshold*
properties generated for the reasons described above.

The `HasClassHandle` property which was used to determine whether the class should
get these properties (among a handful of other members) doesn't serve its
purpose correctly leading to corner cases when the `Threshold*` properties are
missing and causing runtime bugs (e.g. calling `GetAddress()` on an instance of
`Inet4Address` returns `null` even though the underlying Java class has the
information - the call never reaches `Inet4Address` instance and thus returns
nothing).

Replacing `HasClassHandle` with a simple check for whether the class in question
derives from `Java.Lang.Object` is the correct fix that ensures the missing
properties are generated.

Fixe https://bugzilla.xamarin.com/show_bug.cgi?id=56537
  • Loading branch information
grendello committed Jun 13, 2017
1 parent 824a00e commit 37b709b
Show file tree
Hide file tree
Showing 78 changed files with 418 additions and 111 deletions.
13 changes: 4 additions & 9 deletions tools/generator/ClassGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,6 @@ public override string NativeType {
get { return "IntPtr"; }
}

public bool HasClassHandle {
get { return ctors.Count > 0 || Fields.Count > 0 || Methods.Count > 0 || Properties.Count > 0 || IsAnnotation; }
}

public IList<Ctor> Ctors {
get { return ctors; }
}
Expand Down Expand Up @@ -449,17 +445,16 @@ public override void Generate (StreamWriter sw, string indent, CodeGenerationOpt
sw.WriteLine ();
}

if (HasClassHandle) {
bool requireNew = false;
bool requireNew = InheritsObject;
if (!requireNew) {
for (var bg = BaseGen; bg != null && bg is XmlClassGen; bg = bg.BaseGen) {
if (bg.HasClassHandle) {
if (bg.InheritsObject) {
requireNew = true;
break;
}
}

opt.CodeGenerator.WriteClassHandle (this, sw, indent, opt, requireNew);
}
opt.CodeGenerator.WriteClassHandle (this, sw, indent, opt, requireNew);

GenConstructors (sw, indent + "\t", opt);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
public partial class Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (Object));
internal static IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace Xamarin.Test {
[global::Java.Interop.JavaTypeParameters (new string [] {"T extends xamarin.test.Adapter"})]
public abstract partial class AdapterView : global::Java.Lang.Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/AdapterView", typeof (AdapterView));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/AdapterView", typeof (AdapterView));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace Xamarin.Test {
[global::Android.Runtime.Register ("xamarin/test/GenericReturnObject", DoNotGenerateAcw=true)]
public partial class GenericReturnObject : global::Java.Lang.Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/GenericReturnObject", typeof (GenericReturnObject));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/GenericReturnObject", typeof (GenericReturnObject));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
public partial class Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (Object));
internal static IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public abstract partial class SomeObject : global::Java.Lang.Object {
}
}
}
internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
7 changes: 7 additions & 0 deletions tools/generator/Tests/expected.ji/Arrays/Java.Lang.Object.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
public partial class Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (Object));
internal static IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ public IList<long> Mylongs {
}
}
}
internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace Xamarin.Test {
[global::Android.Runtime.Register ("xamarin/test/CSharpKeywords", DoNotGenerateAcw=true)]
public partial class CSharpKeywords : global::Java.Lang.Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/CSharpKeywords", typeof (CSharpKeywords));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/CSharpKeywords", typeof (CSharpKeywords));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
public partial class Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (Object));
internal static IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace Xamarin.Test {
[global::Android.Runtime.Register ("xamarin/test/SomeObject", DoNotGenerateAcw=true)]
public partial class SomeObject : global::Java.Lang.Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace Com.Google.Android.Exoplayer.Drm {
[global::Android.Runtime.Register ("com/google/android/exoplayer/drm/FrameworkMediaDrm", DoNotGenerateAcw=true)]
public sealed partial class FrameworkMediaDrm : global::Java.Lang.Object, global::Com.Google.Android.Exoplayer.Drm.IExoMediaDrm {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("com/google/android/exoplayer/drm/FrameworkMediaDrm", typeof (FrameworkMediaDrm));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("com/google/android/exoplayer/drm/FrameworkMediaDrm", typeof (FrameworkMediaDrm));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
public partial class Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (Object));
internal static IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
public partial class Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (Object));
internal static IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,25 @@ static IntPtr n_Build_I (IntPtr jnienv, IntPtr native__this, int p0)
}


internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/NotificationCompatBase$Action", typeof (Action));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

public override global::Java.Interop.JniPeerMembers JniPeerMembers {
get { return _members; }
}

protected override IntPtr ThresholdClass {
get { return _members.JniPeerType.PeerReference.Handle; }
}

protected override global::System.Type ThresholdType {
get { return _members.ManagedPeerType; }
}

protected Action (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {}

}
Expand All @@ -129,8 +148,8 @@ public ActionInvoker (IntPtr handle, JniHandleOwnership transfer) : base (handle
[global::Android.Runtime.Register ("xamarin/test/NotificationCompatBase$InstanceInner", DoNotGenerateAcw=true)]
public abstract partial class InstanceInner : global::Java.Lang.Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/NotificationCompatBase$InstanceInner", typeof (InstanceInner));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/NotificationCompatBase$InstanceInner", typeof (InstanceInner));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down Expand Up @@ -190,6 +209,25 @@ public InstanceInnerInvoker (IntPtr handle, JniHandleOwnership transfer) : base
}


internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/NotificationCompatBase", typeof (NotificationCompatBase));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

public override global::Java.Interop.JniPeerMembers JniPeerMembers {
get { return _members; }
}

protected override IntPtr ThresholdClass {
get { return _members.JniPeerType.PeerReference.Handle; }
}

protected override global::System.Type ThresholdType {
get { return _members.ManagedPeerType; }
}

protected NotificationCompatBase (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
public partial class Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (Object));
internal static IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public int Value {
}
}
}
internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
19 changes: 19 additions & 0 deletions tools/generator/Tests/expected.ji/NormalMethods/Java.Lang.Class.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,25 @@ namespace Java.Lang {
[global::Java.Interop.JavaTypeParameters (new string [] {"T"})]
public partial class Class : global::Java.Lang.Object {

internal new static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Class", typeof (Class));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

public override global::Java.Interop.JniPeerMembers JniPeerMembers {
get { return _members; }
}

protected override IntPtr ThresholdClass {
get { return _members.JniPeerType.PeerReference.Handle; }
}

protected override global::System.Type ThresholdType {
get { return _members.ManagedPeerType; }
}

protected Class (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Integer", DoNotGenerateAcw=true)]
public partial class Integer : global::Java.Lang.Object {

internal new static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Integer", typeof (Integer));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

public override global::Java.Interop.JniPeerMembers JniPeerMembers {
get { return _members; }
}

protected override IntPtr ThresholdClass {
get { return _members.JniPeerType.PeerReference.Handle; }
}

protected override global::System.Type ThresholdType {
get { return _members.ManagedPeerType; }
}

protected Integer (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
public partial class Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Object", typeof (Object));
internal static IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@ namespace Java.Lang {
[global::Android.Runtime.Register ("java/lang/Throwable", DoNotGenerateAcw=true)]
public partial class Throwable {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("java/lang/Throwable", typeof (Throwable));
internal static IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public partial class A : global::Java.Lang.Object {
[global::Java.Interop.JavaTypeParameters (new string [] {"T extends xamarin.test.A.B"})]
public partial class B : global::Java.Lang.Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/A$B", typeof (B));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/A$B", typeof (B));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down Expand Up @@ -67,8 +67,8 @@ static IntPtr n_SetCustomDimension_I (IntPtr jnienv, IntPtr native__this, int in

}

internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/A", typeof (A));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/A", typeof (A));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace Xamarin.Test {
[global::Java.Interop.JavaTypeParameters (new string [] {"T extends xamarin.test.C"})]
public partial class C : global::Java.Lang.Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/C", typeof (C));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/C", typeof (C));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace Xamarin.Test {
[global::Android.Runtime.Register ("xamarin/test/SomeObject", DoNotGenerateAcw=true)]
public partial class SomeObject : global::Java.Lang.Object {

internal static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static IntPtr class_ref {
internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/SomeObject", typeof (SomeObject));
internal static new IntPtr class_ref {
get {
return _members.JniPeerType.PeerReference.Handle;
}
Expand Down
Loading

0 comments on commit 37b709b

Please sign in to comment.