From e9391cba826ea2b05618965f5db2f35caa9b2cf7 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 12 Dec 2017 11:35:41 -0600 Subject: [PATCH] [generator] better support for "package-private" classes Fixes https://github.com/xamarin/java.interop/issues/168 Java allows public classes to inherit from "package-private" classes, in which case the `public` & `protected` members of the "package-private" class are visible within the public class: // Java /* package */ abstract class SpannableStringInternal { public void getChars(int start, int end, char[] dest, int off); // ... } public class SpannableString extends SpannableStringInternal { // ... } The problem is that `generator` didn't properly support this construct, and *skips* binding of "package-private" types, resulting in generated C# code such as: // C# public partial class SpannableString : SpannableStringInternal { // CS0246: The type or namespace name `SpannableStringInternal` could not be found } This could be worked aroudn via Metadata by making the "package-private" class `public`, but this means that if (when?) the "package-private" class is *removed*, we have an ABI break. Support this construct by updating `generator` to "copy" the members from the "package-private" class into the declaring class: // C# public partial class SpannableString : Java.Lang.Object { public void GetChars(int start, int end, char[] dest, int off); // ... } This allows the generated code to compile without metadata fixup. Specifics in implementing this: - Add a `FixupAccessModifiers` method to `GenBase`, later this may need to be further extended for methods - Call `FixupAccessModifiers` in the "validation" step - Added a setter for `BaseType` so it can be modified - In `FixupAccessModifiers`, lookup the base class of the current type and check if it is non-public - Skip the package-private types, and replace them with that class's base type - Look for each method on the base type, and copy it to the public type if it does not exist - Added tests for this scenario --- tools/generator/ClassGen.cs | 24 ++++- tools/generator/CodeGenerator.cs | 2 + tools/generator/GenBase.cs | 6 ++ tools/generator/Tests/AccessModifiers.cs | 20 +++++ .../AccessModifiers/Mono.Android.projitems | 18 ++++ .../Xamarin.Test.BasePublicClass.cs | 61 +++++++++++++ .../Xamarin.Test.ExtendPublicClass.cs | 79 ++++++++++++++++ .../Xamarin.Test.PublicClass.cs | 79 ++++++++++++++++ .../Xamarin.Test.PublicFinalClass.cs | 67 ++++++++++++++ tools/generator/Tests/expected.targets | 30 +++++++ .../AccessModifiers/AccessModifiers.xml | 82 +++++++++++++++++ .../Xamarin.Test.BasePublicClass.cs | 62 +++++++++++++ .../Xamarin.Test.ExtendPublicClass.cs | 90 +++++++++++++++++++ .../Xamarin.Test.PublicClass.cs | 90 +++++++++++++++++++ .../Xamarin.Test.PublicFinalClass.cs | 68 ++++++++++++++ tools/generator/Tests/generator-Tests.csproj | 1 + 16 files changed, 778 insertions(+), 1 deletion(-) create mode 100644 tools/generator/Tests/AccessModifiers.cs create mode 100644 tools/generator/Tests/expected.ji/AccessModifiers/Mono.Android.projitems create mode 100644 tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.BasePublicClass.cs create mode 100644 tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.ExtendPublicClass.cs create mode 100644 tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.PublicClass.cs create mode 100644 tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.PublicFinalClass.cs create mode 100644 tools/generator/Tests/expected/AccessModifiers/AccessModifiers.xml create mode 100644 tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.BasePublicClass.cs create mode 100644 tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.ExtendPublicClass.cs create mode 100644 tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.PublicClass.cs create mode 100644 tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.PublicFinalClass.cs diff --git a/tools/generator/ClassGen.cs b/tools/generator/ClassGen.cs index 897dd0919..d0590bf21 100644 --- a/tools/generator/ClassGen.cs +++ b/tools/generator/ClassGen.cs @@ -59,6 +59,7 @@ public ManagedClassGen (TypeDefinition t) public override string BaseType { get { return nominal_base_type != null ? nominal_base_type.FullNameCorrected () : null; } + set { throw new NotSupportedException (); } } public override bool IsAbstract { @@ -121,6 +122,7 @@ public override bool IsFinal { public override string BaseType { get { return base_type; } + set { base_type = value; } } } @@ -164,7 +166,7 @@ public IList Ctors { get { return ctors; } } - public abstract string BaseType { get; } + public abstract string BaseType { get; set; } public bool ContainsCtor (string jni_sig) { @@ -236,6 +238,26 @@ protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterD return true; } + + public override void FixupAccessModifiers () + { + while (!IsAnnotation && !string.IsNullOrEmpty (BaseType)) { + var baseClass = SymbolTable.Lookup (BaseType) as ClassGen; + if (baseClass != null && RawVisibility == "public" && baseClass.RawVisibility != "public") { + //Skip the BaseType and copy over any "missing" methods + foreach (var baseMethod in baseClass.Methods) { + var method = Methods.FirstOrDefault (m => m.Name == baseMethod.Name && m.Parameters.JavaSignature == baseMethod.Parameters.JavaSignature); + if (method == null) + Methods.Add (baseMethod); + } + BaseType = baseClass.BaseType; + } else { + break; + } + } + + base.FixupAccessModifiers (); + } public override void FixupExplicitImplementation () { diff --git a/tools/generator/CodeGenerator.cs b/tools/generator/CodeGenerator.cs index 2f0805e0d..f9f20a83a 100644 --- a/tools/generator/CodeGenerator.cs +++ b/tools/generator/CodeGenerator.cs @@ -400,6 +400,8 @@ static void Validate (List gens, CodeGenerationOptions opt) removed.Clear (); foreach (GenBase gen in gens) gen.ResetValidation (); + foreach (GenBase gen in gens) + gen.FixupAccessModifiers (); foreach (GenBase gen in gens) if ((opt.IgnoreNonPublicType && (gen.RawVisibility != "public" && gen.RawVisibility != "internal")) diff --git a/tools/generator/GenBase.cs b/tools/generator/GenBase.cs index bb026e421..5e000de2c 100644 --- a/tools/generator/GenBase.cs +++ b/tools/generator/GenBase.cs @@ -727,6 +727,12 @@ public void StripNonBindables () n.StripNonBindables (); } + public virtual void FixupAccessModifiers () + { + foreach (var nt in NestedTypes) + nt.FixupAccessModifiers (); + } + public void FillProperties () { if (property_filled) diff --git a/tools/generator/Tests/AccessModifiers.cs b/tools/generator/Tests/AccessModifiers.cs new file mode 100644 index 000000000..c749fb72c --- /dev/null +++ b/tools/generator/Tests/AccessModifiers.cs @@ -0,0 +1,20 @@ +using System; +using NUnit.Framework; + +namespace generatortests +{ + [TestFixture] + public class AccessModifiers : BaseGeneratorTest + { + [Test] + public void GeneratedOK () + { + RunAllTargets ( + outputRelativePath: "AccessModifiers", + apiDescriptionFile: "expected/AccessModifiers/AccessModifiers.xml", + expectedRelativePath: "AccessModifiers", + additionalSupportPaths: null); + } + } +} + diff --git a/tools/generator/Tests/expected.ji/AccessModifiers/Mono.Android.projitems b/tools/generator/Tests/expected.ji/AccessModifiers/Mono.Android.projitems new file mode 100644 index 000000000..c46c82438 --- /dev/null +++ b/tools/generator/Tests/expected.ji/AccessModifiers/Mono.Android.projitems @@ -0,0 +1,18 @@ + + + + $(DefineConstants);ANDROID_1;ANDROID_2;ANDROID_3;ANDROID_4 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.BasePublicClass.cs b/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.BasePublicClass.cs new file mode 100644 index 000000000..19c05c698 --- /dev/null +++ b/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.BasePublicClass.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using Android.Runtime; +using Java.Interop; + +namespace Xamarin.Test { + + // Metadata.xml XPath class reference: path="/api/package[@name='xamarin.test']/class[@name='BasePublicClass']" + [global::Android.Runtime.Register ("xamarin/test/BasePublicClass", DoNotGenerateAcw=true)] + public partial class BasePublicClass : global::Java.Lang.Object { + + internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/BasePublicClass", typeof (BasePublicClass)); + 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 BasePublicClass (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {} + + static Delegate cb_baseMethod; +#pragma warning disable 0169 + static Delegate GetBaseMethodHandler () + { + if (cb_baseMethod == null) + cb_baseMethod = JNINativeWrapper.CreateDelegate ((Action) n_BaseMethod); + return cb_baseMethod; + } + + static void n_BaseMethod (IntPtr jnienv, IntPtr native__this) + { + global::Xamarin.Test.BasePublicClass __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.BaseMethod (); + } +#pragma warning restore 0169 + + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='BasePublicClass']/method[@name='baseMethod' and count(parameter)=0]" + [Register ("baseMethod", "()V", "GetBaseMethodHandler")] + public virtual unsafe void BaseMethod () + { + const string __id = "baseMethod.()V"; + try { + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, null); + } finally { + } + } + + } +} diff --git a/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.ExtendPublicClass.cs b/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.ExtendPublicClass.cs new file mode 100644 index 000000000..e0ab57012 --- /dev/null +++ b/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.ExtendPublicClass.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using Android.Runtime; +using Java.Interop; + +namespace Xamarin.Test { + + // Metadata.xml XPath class reference: path="/api/package[@name='xamarin.test']/class[@name='ExtendPublicClass']" + [global::Android.Runtime.Register ("xamarin/test/ExtendPublicClass", DoNotGenerateAcw=true)] + public partial class ExtendPublicClass : global::Java.Lang.Object { + + internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/ExtendPublicClass", typeof (ExtendPublicClass)); + 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 ExtendPublicClass (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {} + + // Metadata.xml XPath constructor reference: path="/api/package[@name='xamarin.test']/class[@name='ExtendPublicClass']/constructor[@name='ExtendPublicClass' and count(parameter)=0]" + [Register (".ctor", "()V", "")] + public unsafe ExtendPublicClass () + : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer) + { + const string __id = "()V"; + + if (((global::Java.Lang.Object) this).Handle != IntPtr.Zero) + return; + + try { + var __r = _members.InstanceMethods.StartCreateInstance (__id, ((object) this).GetType (), null); + SetHandle (__r.Handle, JniHandleOwnership.TransferLocalRef); + _members.InstanceMethods.FinishCreateInstance (__id, this, null); + } finally { + } + } + + static Delegate cb_foo; +#pragma warning disable 0169 + static Delegate GetFooHandler () + { + if (cb_foo == null) + cb_foo = JNINativeWrapper.CreateDelegate ((Action) n_Foo); + return cb_foo; + } + + static void n_Foo (IntPtr jnienv, IntPtr native__this) + { + global::Xamarin.Test.ExtendPublicClass __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.Foo (); + } +#pragma warning restore 0169 + + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='ExtendPublicClass']/method[@name='foo' and count(parameter)=0]" + [Register ("foo", "()V", "GetFooHandler")] + public virtual unsafe void Foo () + { + const string __id = "foo.()V"; + try { + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, null); + } finally { + } + } + + } +} diff --git a/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.PublicClass.cs b/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.PublicClass.cs new file mode 100644 index 000000000..750477053 --- /dev/null +++ b/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.PublicClass.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using Android.Runtime; +using Java.Interop; + +namespace Xamarin.Test { + + // Metadata.xml XPath class reference: path="/api/package[@name='xamarin.test']/class[@name='PublicClass']" + [global::Android.Runtime.Register ("xamarin/test/PublicClass", DoNotGenerateAcw=true)] + public partial class PublicClass : global::Java.Lang.Object { + + internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/PublicClass", typeof (PublicClass)); + 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 PublicClass (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {} + + // Metadata.xml XPath constructor reference: path="/api/package[@name='xamarin.test']/class[@name='PublicClass']/constructor[@name='PublicClass' and count(parameter)=0]" + [Register (".ctor", "()V", "")] + public unsafe PublicClass () + : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer) + { + const string __id = "()V"; + + if (((global::Java.Lang.Object) this).Handle != IntPtr.Zero) + return; + + try { + var __r = _members.InstanceMethods.StartCreateInstance (__id, ((object) this).GetType (), null); + SetHandle (__r.Handle, JniHandleOwnership.TransferLocalRef); + _members.InstanceMethods.FinishCreateInstance (__id, this, null); + } finally { + } + } + + static Delegate cb_foo; +#pragma warning disable 0169 + static Delegate GetFooHandler () + { + if (cb_foo == null) + cb_foo = JNINativeWrapper.CreateDelegate ((Action) n_Foo); + return cb_foo; + } + + static void n_Foo (IntPtr jnienv, IntPtr native__this) + { + global::Xamarin.Test.PublicClass __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.Foo (); + } +#pragma warning restore 0169 + + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='PublicClass']/method[@name='foo' and count(parameter)=0]" + [Register ("foo", "()V", "GetFooHandler")] + public virtual unsafe void Foo () + { + const string __id = "foo.()V"; + try { + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, null); + } finally { + } + } + + } +} diff --git a/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.PublicFinalClass.cs b/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.PublicFinalClass.cs new file mode 100644 index 000000000..663886e82 --- /dev/null +++ b/tools/generator/Tests/expected.ji/AccessModifiers/Xamarin.Test.PublicFinalClass.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using Android.Runtime; +using Java.Interop; + +namespace Xamarin.Test { + + // Metadata.xml XPath class reference: path="/api/package[@name='xamarin.test']/class[@name='PublicFinalClass']" + [global::Android.Runtime.Register ("xamarin/test/PublicFinalClass", DoNotGenerateAcw=true)] + public sealed partial class PublicFinalClass : global::Xamarin.Test.BasePublicClass { + + internal new static readonly JniPeerMembers _members = new JniPeerMembers ("xamarin/test/PublicFinalClass", typeof (PublicFinalClass)); + 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; } + } + + internal PublicFinalClass (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {} + + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='PublicFinalClass']/method[@name='publicMethod' and count(parameter)=0]" + [Register ("publicMethod", "()V", "")] + public unsafe void PublicMethod () + { + const string __id = "publicMethod.()V"; + try { + _members.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null); + } finally { + } + } + + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='PackageClassB']/method[@name='packageMethodB' and count(parameter)=0]" + [Register ("packageMethodB", "()V", "")] + public unsafe void PackageMethodB () + { + const string __id = "packageMethodB.()V"; + try { + _members.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null); + } finally { + } + } + + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='PackageClassA']/method[@name='packageMethodA' and count(parameter)=0]" + [Register ("packageMethodA", "()V", "")] + public unsafe void PackageMethodA () + { + const string __id = "packageMethodA.()V"; + try { + _members.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null); + } finally { + } + } + + } +} diff --git a/tools/generator/Tests/expected.targets b/tools/generator/Tests/expected.targets index aa1146666..6aafd8b31 100644 --- a/tools/generator/Tests/expected.targets +++ b/tools/generator/Tests/expected.targets @@ -1,5 +1,20 @@ + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -124,6 +139,21 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/tools/generator/Tests/expected/AccessModifiers/AccessModifiers.xml b/tools/generator/Tests/expected/AccessModifiers/AccessModifiers.xml new file mode 100644 index 000000000..9adec7944 --- /dev/null +++ b/tools/generator/Tests/expected/AccessModifiers/AccessModifiers.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.BasePublicClass.cs b/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.BasePublicClass.cs new file mode 100644 index 000000000..f9e404d25 --- /dev/null +++ b/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.BasePublicClass.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using Android.Runtime; + +namespace Xamarin.Test { + + // Metadata.xml XPath class reference: path="/api/package[@name='xamarin.test']/class[@name='BasePublicClass']" + [global::Android.Runtime.Register ("xamarin/test/BasePublicClass", DoNotGenerateAcw=true)] + public partial class BasePublicClass : global::Java.Lang.Object { + + internal static new IntPtr java_class_handle; + internal static new IntPtr class_ref { + get { + return JNIEnv.FindClass ("xamarin/test/BasePublicClass", ref java_class_handle); + } + } + + protected override IntPtr ThresholdClass { + get { return class_ref; } + } + + protected override global::System.Type ThresholdType { + get { return typeof (BasePublicClass); } + } + + protected BasePublicClass (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {} + + static Delegate cb_baseMethod; +#pragma warning disable 0169 + static Delegate GetBaseMethodHandler () + { + if (cb_baseMethod == null) + cb_baseMethod = JNINativeWrapper.CreateDelegate ((Action) n_BaseMethod); + return cb_baseMethod; + } + + static void n_BaseMethod (IntPtr jnienv, IntPtr native__this) + { + global::Xamarin.Test.BasePublicClass __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.BaseMethod (); + } +#pragma warning restore 0169 + + static IntPtr id_baseMethod; + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='BasePublicClass']/method[@name='baseMethod' and count(parameter)=0]" + [Register ("baseMethod", "()V", "GetBaseMethodHandler")] + public virtual unsafe void BaseMethod () + { + if (id_baseMethod == IntPtr.Zero) + id_baseMethod = JNIEnv.GetMethodID (class_ref, "baseMethod", "()V"); + try { + + if (((object) this).GetType () == ThresholdType) + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_baseMethod); + else + JNIEnv.CallNonvirtualVoidMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "baseMethod", "()V")); + } finally { + } + } + + } +} diff --git a/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.ExtendPublicClass.cs b/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.ExtendPublicClass.cs new file mode 100644 index 000000000..7b915c99c --- /dev/null +++ b/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.ExtendPublicClass.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using Android.Runtime; + +namespace Xamarin.Test { + + // Metadata.xml XPath class reference: path="/api/package[@name='xamarin.test']/class[@name='ExtendPublicClass']" + [global::Android.Runtime.Register ("xamarin/test/ExtendPublicClass", DoNotGenerateAcw=true)] + public partial class ExtendPublicClass : global::Java.Lang.Object { + + internal static new IntPtr java_class_handle; + internal static new IntPtr class_ref { + get { + return JNIEnv.FindClass ("xamarin/test/ExtendPublicClass", ref java_class_handle); + } + } + + protected override IntPtr ThresholdClass { + get { return class_ref; } + } + + protected override global::System.Type ThresholdType { + get { return typeof (ExtendPublicClass); } + } + + protected ExtendPublicClass (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {} + + static IntPtr id_ctor; + // Metadata.xml XPath constructor reference: path="/api/package[@name='xamarin.test']/class[@name='ExtendPublicClass']/constructor[@name='ExtendPublicClass' and count(parameter)=0]" + [Register (".ctor", "()V", "")] + public unsafe ExtendPublicClass () + : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer) + { + if (((global::Java.Lang.Object) this).Handle != IntPtr.Zero) + return; + + try { + if (((object) this).GetType () != typeof (ExtendPublicClass)) { + SetHandle ( + global::Android.Runtime.JNIEnv.StartCreateInstance (((object) this).GetType (), "()V"), + JniHandleOwnership.TransferLocalRef); + global::Android.Runtime.JNIEnv.FinishCreateInstance (((global::Java.Lang.Object) this).Handle, "()V"); + return; + } + + if (id_ctor == IntPtr.Zero) + id_ctor = JNIEnv.GetMethodID (class_ref, "", "()V"); + SetHandle ( + global::Android.Runtime.JNIEnv.StartCreateInstance (class_ref, id_ctor), + JniHandleOwnership.TransferLocalRef); + JNIEnv.FinishCreateInstance (((global::Java.Lang.Object) this).Handle, class_ref, id_ctor); + } finally { + } + } + + static Delegate cb_foo; +#pragma warning disable 0169 + static Delegate GetFooHandler () + { + if (cb_foo == null) + cb_foo = JNINativeWrapper.CreateDelegate ((Action) n_Foo); + return cb_foo; + } + + static void n_Foo (IntPtr jnienv, IntPtr native__this) + { + global::Xamarin.Test.ExtendPublicClass __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.Foo (); + } +#pragma warning restore 0169 + + static IntPtr id_foo; + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='ExtendPublicClass']/method[@name='foo' and count(parameter)=0]" + [Register ("foo", "()V", "GetFooHandler")] + public virtual unsafe void Foo () + { + if (id_foo == IntPtr.Zero) + id_foo = JNIEnv.GetMethodID (class_ref, "foo", "()V"); + try { + + if (((object) this).GetType () == ThresholdType) + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_foo); + else + JNIEnv.CallNonvirtualVoidMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "foo", "()V")); + } finally { + } + } + + } +} diff --git a/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.PublicClass.cs b/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.PublicClass.cs new file mode 100644 index 000000000..2b3a7378f --- /dev/null +++ b/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.PublicClass.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using Android.Runtime; + +namespace Xamarin.Test { + + // Metadata.xml XPath class reference: path="/api/package[@name='xamarin.test']/class[@name='PublicClass']" + [global::Android.Runtime.Register ("xamarin/test/PublicClass", DoNotGenerateAcw=true)] + public partial class PublicClass : global::Java.Lang.Object { + + internal static new IntPtr java_class_handle; + internal static new IntPtr class_ref { + get { + return JNIEnv.FindClass ("xamarin/test/PublicClass", ref java_class_handle); + } + } + + protected override IntPtr ThresholdClass { + get { return class_ref; } + } + + protected override global::System.Type ThresholdType { + get { return typeof (PublicClass); } + } + + protected PublicClass (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {} + + static IntPtr id_ctor; + // Metadata.xml XPath constructor reference: path="/api/package[@name='xamarin.test']/class[@name='PublicClass']/constructor[@name='PublicClass' and count(parameter)=0]" + [Register (".ctor", "()V", "")] + public unsafe PublicClass () + : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer) + { + if (((global::Java.Lang.Object) this).Handle != IntPtr.Zero) + return; + + try { + if (((object) this).GetType () != typeof (PublicClass)) { + SetHandle ( + global::Android.Runtime.JNIEnv.StartCreateInstance (((object) this).GetType (), "()V"), + JniHandleOwnership.TransferLocalRef); + global::Android.Runtime.JNIEnv.FinishCreateInstance (((global::Java.Lang.Object) this).Handle, "()V"); + return; + } + + if (id_ctor == IntPtr.Zero) + id_ctor = JNIEnv.GetMethodID (class_ref, "", "()V"); + SetHandle ( + global::Android.Runtime.JNIEnv.StartCreateInstance (class_ref, id_ctor), + JniHandleOwnership.TransferLocalRef); + JNIEnv.FinishCreateInstance (((global::Java.Lang.Object) this).Handle, class_ref, id_ctor); + } finally { + } + } + + static Delegate cb_foo; +#pragma warning disable 0169 + static Delegate GetFooHandler () + { + if (cb_foo == null) + cb_foo = JNINativeWrapper.CreateDelegate ((Action) n_Foo); + return cb_foo; + } + + static void n_Foo (IntPtr jnienv, IntPtr native__this) + { + global::Xamarin.Test.PublicClass __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.Foo (); + } +#pragma warning restore 0169 + + static IntPtr id_foo; + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='PublicClass']/method[@name='foo' and count(parameter)=0]" + [Register ("foo", "()V", "GetFooHandler")] + public virtual unsafe void Foo () + { + if (id_foo == IntPtr.Zero) + id_foo = JNIEnv.GetMethodID (class_ref, "foo", "()V"); + try { + + if (((object) this).GetType () == ThresholdType) + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_foo); + else + JNIEnv.CallNonvirtualVoidMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "foo", "()V")); + } finally { + } + } + + } +} diff --git a/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.PublicFinalClass.cs b/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.PublicFinalClass.cs new file mode 100644 index 000000000..76d083924 --- /dev/null +++ b/tools/generator/Tests/expected/AccessModifiers/Xamarin.Test.PublicFinalClass.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using Android.Runtime; + +namespace Xamarin.Test { + + // Metadata.xml XPath class reference: path="/api/package[@name='xamarin.test']/class[@name='PublicFinalClass']" + [global::Android.Runtime.Register ("xamarin/test/PublicFinalClass", DoNotGenerateAcw=true)] + public sealed partial class PublicFinalClass : global::Xamarin.Test.BasePublicClass { + + internal static new IntPtr java_class_handle; + internal static new IntPtr class_ref { + get { + return JNIEnv.FindClass ("xamarin/test/PublicFinalClass", ref java_class_handle); + } + } + + protected override IntPtr ThresholdClass { + get { return class_ref; } + } + + protected override global::System.Type ThresholdType { + get { return typeof (PublicFinalClass); } + } + + internal PublicFinalClass (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {} + + static IntPtr id_publicMethod; + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='PublicFinalClass']/method[@name='publicMethod' and count(parameter)=0]" + [Register ("publicMethod", "()V", "")] + public unsafe void PublicMethod () + { + if (id_publicMethod == IntPtr.Zero) + id_publicMethod = JNIEnv.GetMethodID (class_ref, "publicMethod", "()V"); + try { + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_publicMethod); + } finally { + } + } + + static IntPtr id_packageMethodB; + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='PackageClassB']/method[@name='packageMethodB' and count(parameter)=0]" + [Register ("packageMethodB", "()V", "")] + public unsafe void PackageMethodB () + { + if (id_packageMethodB == IntPtr.Zero) + id_packageMethodB = JNIEnv.GetMethodID (class_ref, "packageMethodB", "()V"); + try { + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_packageMethodB); + } finally { + } + } + + static IntPtr id_packageMethodA; + // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/class[@name='PackageClassA']/method[@name='packageMethodA' and count(parameter)=0]" + [Register ("packageMethodA", "()V", "")] + public unsafe void PackageMethodA () + { + if (id_packageMethodA == IntPtr.Zero) + id_packageMethodA = JNIEnv.GetMethodID (class_ref, "packageMethodA", "()V"); + try { + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_packageMethodA); + } finally { + } + } + + } +} diff --git a/tools/generator/Tests/generator-Tests.csproj b/tools/generator/Tests/generator-Tests.csproj index acf601492..4ede84fee 100644 --- a/tools/generator/Tests/generator-Tests.csproj +++ b/tools/generator/Tests/generator-Tests.csproj @@ -65,6 +65,7 @@ +