From 54cd216122819f951f4331fa9de235392a014f7e Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Fri, 9 Aug 2019 10:35:34 -0500 Subject: [PATCH 01/10] [generator] Support default interface methods. --- ...niPeerMembers.JniInstanceMethods_Invoke.tt | 2 +- tools/generator/CodeGenerationOptions.cs | 1 + tools/generator/CodeGenerator.cs | 3 +- tools/generator/CodeGeneratorOptions.cs | 8 +- .../CodeGenerator.cs | 106 ++++++++++++++---- .../JavaInteropCodeGenerator.cs | 15 ++- .../XamarinAndroidCodeGenerator.cs | 2 +- .../GenBase.cs | 36 ++++-- .../InterfaceGen.cs | 2 + .../Method.cs | 2 +- ...WriteInterfaceRedeclaredDefaultMethod.txt} | 9 +- .../WriteInterfaceDefaultMethod.txt | 34 ++++++ .../WriteInterfaceDefaultProperty.txt | 63 +++++++++++ ...riteInterfaceDefaultPropertyGetterOnly.txt | 36 ++++++ .../JavaInterop1/WriteInterfaceMethod.txt | 11 -- .../WriteInterfaceDefaultMethod.txt | 34 ++++++ .../WriteInterfaceDefaultProperty.txt | 63 +++++++++++ ...riteInterfaceDefaultPropertyGetterOnly.txt | 36 ++++++ .../WriteInterfaceDefaultMethod.txt | 40 +++++++ .../WriteInterfaceDefaultProperty.txt | 74 ++++++++++++ ...riteInterfaceDefaultPropertyGetterOnly.txt | 41 +++++++ .../Tests/Unit-Tests/CodeGeneratorTests.cs | 2 +- .../DefaultInterfaceMethodsTests.cs | 85 ++++++++++---- .../Unit-Tests/InterfaceConstantsTests.cs | 73 ++++++++++++ .../Tests/Unit-Tests/SupportTypes.cs | 9 ++ tools/generator/Tests/generator-Tests.csproj | 31 +++++ 26 files changed, 731 insertions(+), 87 deletions(-) rename tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/{XamarinAndroid/WriteInterfaceMethod.txt => Common/WriteInterfaceRedeclaredDefaultMethod.txt} (55%) create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt delete mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceMethod.txt create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt create mode 100644 tools/generator/Tests/Unit-Tests/InterfaceConstantsTests.cs diff --git a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.tt b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.tt index 5e5ae6994..0cfd669b5 100644 --- a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.tt +++ b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.tt @@ -44,7 +44,7 @@ namespace Java.Interop { JniPeerMembers.AssertSelf (self); var declaringType = DeclaringType; - if (Members.ShouldUseVirtualDispatch (self, declaringType)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { var m = GetMethodInfo (encodedMember); <#= returnType.ReturnType != "void" ? "return " : "" #>JniEnvironment.InstanceMethods.Call<#= returnType.JniCallType #>Method (self.PeerReference, m, parameters); <#= returnType.ReturnType == "void" ? "return;" : "" #> diff --git a/tools/generator/CodeGenerationOptions.cs b/tools/generator/CodeGenerationOptions.cs index 55718a92f..c3797b4fd 100644 --- a/tools/generator/CodeGenerationOptions.cs +++ b/tools/generator/CodeGenerationOptions.cs @@ -48,6 +48,7 @@ internal CodeGenerator CreateCodeGenerator (TextWriter writer) public bool UseShortFileNames { get; set; } public int ProductVersion { get; set; } public bool SupportInterfaceConstants { get; set; } + public bool SupportDefaultInterfaceMethods { get; set; } public bool UseShallowReferencedTypes { get; set; } bool? buildingCoreAssembly; diff --git a/tools/generator/CodeGenerator.cs b/tools/generator/CodeGenerator.cs index 19966634e..575762467 100644 --- a/tools/generator/CodeGenerator.cs +++ b/tools/generator/CodeGenerator.cs @@ -66,6 +66,7 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve UseShortFileNames = options.UseShortFileNames, ProductVersion = options.ProductVersion, SupportInterfaceConstants = options.SupportInterfaceConstants, + SupportDefaultInterfaceMethods = options.SupportDefaultInterfaceMethods }; // Load reference libraries @@ -143,7 +144,7 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve // disable interface default methods here, especially before validation. gens = gens.Where (g => !g.IsObfuscated && g.Visibility != "private").ToList (); foreach (var gen in gens) { - gen.StripNonBindables (); + gen.StripNonBindables (opt); if (gen.IsGeneratable) AddTypeToTable (opt, gen); } diff --git a/tools/generator/CodeGeneratorOptions.cs b/tools/generator/CodeGeneratorOptions.cs index f9c1e5ff7..b17e2dbd3 100644 --- a/tools/generator/CodeGeneratorOptions.cs +++ b/tools/generator/CodeGeneratorOptions.cs @@ -40,6 +40,7 @@ public CodeGeneratorOptions () public bool OnlyRunApiXmlAdjuster { get; set; } public string ApiXmlAdjusterOutput { get; set; } public bool SupportInterfaceConstants { get; set; } + public bool SupportDefaultInterfaceMethods { get; set; } public static CodeGeneratorOptions Parse (string[] args) { @@ -87,8 +88,11 @@ public static CodeGeneratorOptions Parse (string[] args) "SDK Platform {VERSION}/API level.", v => opts.ApiLevel = v }, { "lang-features=", - "For internal use. (Flags: interface-constants)", - v => opts.SupportInterfaceConstants = v?.Contains ("interface-constants") == true }, + "For internal use. (Flags: interface-constants,default-interface-methods)", + v => { + opts.SupportInterfaceConstants = v?.Contains ("interface-constants") == true; + opts.SupportDefaultInterfaceMethods = v?.Contains ("default-interface-methods") == true; + }}, { "preserve-enums", "For internal use.", v => opts.PreserveEnums = v != null }, diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs index 78a109c50..9c45e1c5a 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs @@ -35,7 +35,7 @@ protected CodeGenerator (TextWriter writer, CodeGenerationOptions options) internal abstract void WriteConstructorBody (Ctor ctor, string indent, StringCollection call_cleanup); internal abstract void WriteMethodIdField (Method method, string indent); - internal abstract void WriteMethodBody (Method method, string indent); + internal abstract void WriteMethodBody (Method method, string indent, GenBase type); internal abstract void WriteFieldIdField (Field field, string indent); internal abstract void WriteFieldGetBody (Field field, string indent, GenBase type); @@ -139,7 +139,7 @@ public void WriteClass (ClassGen @class, string indent, GenerationInfo gen_info) WriteClassConstructors (@class, indent + "\t"); - WriteClassProperties (@class, indent + "\t"); + WriteImplementedProperties (@class.Properties, indent + "\t", @class.IsFinal, @class); WriteClassMethods (@class, indent + "\t"); if (@class.IsAbstract) @@ -245,7 +245,7 @@ public void WriteClassInvokerMembers (ClassGen @class, string indent, HashSet !@class.ContainsProperty (p.Name, false, false)), indent, members); - WriteClassMethodInvokers (@class, iface.Methods.Where (m => !m.IsInterfaceDefaultMethod && !@class.ContainsMethod (m, false, false) && !@class.IsCovariantMethod (m) && !@class.ExplicitlyImplementedInterfaceMethods.Contains (m.GetSignature ())), indent, members, iface); + WriteClassMethodInvokers (@class, iface.Methods.Where (m => (opt.SupportDefaultInterfaceMethods || !m.IsInterfaceDefaultMethod) && !@class.ContainsMethod (m, false, false) && !@class.IsCovariantMethod (m) && !@class.ExplicitlyImplementedInterfaceMethods.Contains (m.GetSignature ())), indent, members, iface); } if (@class.BaseGen != null && @class.BaseGen.FullName != "Java.Lang.Object") @@ -275,6 +275,8 @@ public void WriteClassMethodInvokers (ClassGen @class, IEnumerable metho public void WriteClassMethods (ClassGen @class, string indent) { + var methodsToDeclare = @class.Methods.AsEnumerable (); + // This does not exclude overrides (unlike virtual methods) because we're not sure // if calling the base interface default method via JNI expectedly dispatches to // the derived method. @@ -282,15 +284,17 @@ public void WriteClassMethods (ClassGen @class, string indent) .SelectMany (i => i.Methods) .Where (m => m.IsInterfaceDefaultMethod) .Where (m => !@class.ContainsMethod (m, false, false)); - var overrides = defaultMethods.Where (m => m.IsInterfaceDefaultMethodOverride); + var overrides = defaultMethods.Where (m => m.OverriddenInterfaceMethod != null); var overridens = defaultMethods.Where (m => overrides.Where (_ => _.Name == m.Name && _.JniSignature == m.JniSignature) .Any (mm => mm.DeclaringType.GetAllDerivedInterfaces ().Contains (m.DeclaringType))); - foreach (Method m in @class.Methods.Concat (defaultMethods.Except (overridens)).Where (m => m.DeclaringType.IsGeneratable)) { + methodsToDeclare = opt.SupportDefaultInterfaceMethods ? methodsToDeclare : methodsToDeclare.Concat (defaultMethods.Except (overridens)).Where (m => m.DeclaringType.IsGeneratable); + + foreach (var m in methodsToDeclare) { bool virt = m.IsVirtual; m.IsVirtual = !@class.IsFinal && virt; - if (m.IsAbstract && !m.IsInterfaceDefaultMethodOverride && !m.IsInterfaceDefaultMethod) + if (m.IsAbstract && m.OverriddenInterfaceMethod == null && (opt.SupportDefaultInterfaceMethods || !m.IsInterfaceDefaultMethod)) WriteMethodAbstractDeclaration (m, indent, null, @class); else WriteMethod (m, indent, @class, true); @@ -324,6 +328,25 @@ public void WriteClassProperties (ClassGen @class, string indent) } } + protected void WriteImplementedProperties (IEnumerable targetProperties, string indent, bool isFinal, GenBase gen) + { + foreach (var prop in targetProperties) { + bool get_virt = prop.Getter.IsVirtual; + bool set_virt = prop.Setter == null ? false : prop.Setter.IsVirtual; + prop.Getter.IsVirtual = !isFinal && get_virt; + if (prop.Setter != null) + prop.Setter.IsVirtual = !isFinal && set_virt; + if (prop.Getter.IsAbstract) + WritePropertyAbstractDeclaration (prop, indent, gen); + else + WriteProperty (prop, gen, indent); + prop.Getter.IsVirtual = get_virt; + if (prop.Setter != null) + prop.Setter.IsVirtual = set_virt; + } + } + + public void WriteClassPropertyInvokers (ClassGen @class, IEnumerable properties, string indent, HashSet members) { foreach (Property prop in properties) { @@ -476,7 +499,7 @@ public void WriteInterface (InterfaceGen @interface, string indent, GenerationIn // For each interface, generate either an abstract method or an explicit implementation method. public void WriteInterfaceAbstractMembers (InterfaceGen @interface, ClassGen gen, string indent) { - foreach (Method m in @interface.Methods.Where (m => !m.IsInterfaceDefaultMethod && !m.IsStatic)) { + foreach (var m in @interface.Methods.Where (m => (!opt.SupportDefaultInterfaceMethods || !m.IsInterfaceDefaultMethod) && !m.IsStatic)) { bool mapped = false; string sig = m.GetSignature (); if (Context.ContextGeneratedMethods.Any (_ => _.Name == m.Name && _.JniSignature == m.JniSignature)) @@ -494,7 +517,7 @@ public void WriteInterfaceAbstractMembers (InterfaceGen @interface, ClassGen gen WriteMethodAbstractDeclaration (m, indent, @interface, gen); Context.ContextGeneratedMethods.Add (m); } - foreach (Property prop in @interface.Properties.Where (p => !p.Getter.IsStatic)) { + foreach (var prop in @interface.Properties.Where (p => (!opt.SupportDefaultInterfaceMethods || !p.Getter.IsInterfaceDefaultMethod) && !p.Getter.IsStatic)) { if (gen.ContainsProperty (prop.Name, false)) continue; WritePropertyAbstractDeclaration (prop, indent, gen); @@ -525,6 +548,10 @@ public void WriteInterfaceDeclaration (InterfaceGen @interface, string indent) writer.WriteLine ("{0}{1}", indent, @interface.TypeParameters.ToGeneratedAttributeString ()); writer.WriteLine ("{0}{1} partial interface {2}{3} {{", indent, @interface.Visibility, @interface.Name, @interface.IsConstSugar ? string.Empty : @interface.Interfaces.Count == 0 || sb.Length == 0 ? " : " + GetAllInterfaceImplements () : " : " + sb.ToString ()); + + if (opt.SupportDefaultInterfaceMethods && @interface.HasDefaultMethods) + WriteClassHandle (@interface, indent + "\t", @interface.Name); + WriteInterfaceFields (@interface, indent + "\t"); writer.WriteLine (); WriteInterfaceProperties (@interface, indent + "\t"); @@ -789,14 +816,14 @@ public void WriteInterfaceInvoker (InterfaceGen @interface, string indent) writer.WriteLine (); HashSet members = new HashSet (); - WriteInterfacePropertyInvokers (@interface, @interface.Properties.Where (p => !p.Getter.IsStatic), indent + "\t", members); - WriteInterfaceMethodInvokers (@interface, @interface.Methods.Where (m => !m.IsStatic), indent + "\t", members); + WriteInterfacePropertyInvokers (@interface, @interface.Properties.Where (p => !p.Getter.IsStatic && !p.Getter.IsInterfaceDefaultMethod), indent + "\t", members); + WriteInterfaceMethodInvokers (@interface, @interface.Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod), indent + "\t", members); if (@interface.FullName == "Java.Lang.ICharSequence") WriteCharSequenceEnumerator (indent + "\t"); foreach (InterfaceGen iface in @interface.GetAllDerivedInterfaces ()) { - WriteInterfacePropertyInvokers (@interface, iface.Properties.Where (p => !p.Getter.IsStatic), indent + "\t", members); - WriteInterfaceMethodInvokers (@interface, iface.Methods.Where (m => !m.IsStatic && !@interface.IsCovariantMethod (m) && !(iface.FullName.StartsWith ("Java.Lang.ICharSequence") && m.Name.EndsWith ("Formatted"))), indent + "\t", members); + WriteInterfacePropertyInvokers (@interface, iface.Properties.Where (p => !p.Getter.IsStatic && !p.Getter.IsInterfaceDefaultMethod), indent + "\t", members); + WriteInterfaceMethodInvokers (@interface, iface.Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod && !@interface.IsCovariantMethod (m) && !(iface.FullName.StartsWith ("Java.Lang.ICharSequence") && m.Name.EndsWith ("Formatted"))), indent + "\t", members); if (iface.FullName == "Java.Lang.ICharSequence") WriteCharSequenceEnumerator (indent + "\t"); } @@ -968,17 +995,23 @@ public void WriteInterfaceMethodInvokers (InterfaceGen @interface, IEnumerable !m.IsStatic)) { + foreach (var m in @interface.Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod)) { if (m.Name == @interface.Name || @interface.ContainsProperty (m.Name, true)) m.Name = "Invoke" + m.Name; + WriteMethodDeclaration (m, indent, @interface, @interface.AssemblyQualifiedName + "Invoker"); } + + foreach (var m in @interface.Methods.Where (m => m.IsInterfaceDefaultMethod)) + WriteMethod (m, indent, @interface, true); } public void WriteInterfaceProperties (InterfaceGen @interface, string indent) { - foreach (Property prop in @interface.Properties.Where (p => !p.Getter.IsStatic)) + foreach (var prop in @interface.Properties.Where (p => !p.Getter.IsStatic && !p.Getter.IsInterfaceDefaultMethod)) WritePropertyDeclaration (prop, indent, @interface, @interface.AssemblyQualifiedName + "Invoker"); + + WriteImplementedProperties (@interface.Properties.Where (p => p.Getter.IsInterfaceDefaultMethod), indent, false, @interface); } public void WriteInterfacePropertyInvokers (InterfaceGen @interface, IEnumerable properties, string indent, HashSet members) @@ -1063,7 +1096,7 @@ public void WriteMethodExplicitInterfaceInvoker (Method method, string indent, G writer.WriteLine ("{0}unsafe {1} {2}.{3} ({4})", indent, opt.GetOutputName (method.RetVal.FullName), opt.GetOutputName (iface.FullName), method.Name, method.GetSignature (opt)); writer.WriteLine ("{0}{{", indent); - WriteMethodBody (method, indent + "\t"); + WriteMethodBody (method, indent + "\t", iface); writer.WriteLine ("{0}}}", indent); writer.WriteLine (); } @@ -1255,14 +1288,23 @@ public void WriteMethodExtensionOverload (Method method, string indent, string s string ret = opt.GetOutputName (method.RetVal.FullName.Replace ("Java.Lang.ICharSequence", "string")); writer.WriteLine (); - writer.WriteLine ("{0}public static {1} {2} (this {3} self, {4})", - indent, ret, method.Name, selfType, - method.GetSignature (opt).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string")); + + var parameters = method.GetSignature (opt).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string"); + writer.WriteLine ("{0}public static {1} {2} (this {3} self{4}{5})", indent, ret, method.Name, selfType, parameters.Length > 0 ? ", " : "", parameters); + writer.WriteLine ("{0}{{", indent); WriteMethodStringOverloadBody (method, indent + "\t", true); writer.WriteLine ("{0}}}", indent); } + static string GetDeclaringTypeOfExplicitInterfaceMethod (Method method) + { + return method.OverriddenInterfaceMethod != null ? + GetDeclaringTypeOfExplicitInterfaceMethod (method.OverriddenInterfaceMethod) : + method.DeclaringType.FullName; + } + + public void WriteMethodAsyncWrapper (Method method, string indent) { if (!method.Asyncify) @@ -1315,7 +1357,10 @@ public void WriteMethod (Method method, string indent, GenBase type, bool genera bool gen_string_overload = !method.IsOverride && method.Parameters.HasCharSequence && !type.ContainsMethod (name_and_jnisig); string static_arg = method.IsStatic ? " static" : String.Empty; - string virt_ov = method.IsOverride ? " override" : method.IsVirtual ? " virtual" : String.Empty; + + var is_explicit = opt.SupportDefaultInterfaceMethods && type is InterfaceGen && method.OverriddenInterfaceMethod != null; + var virt_ov = is_explicit ? string.Empty : method.IsOverride ? (opt.SupportDefaultInterfaceMethods && method.OverriddenInterfaceMethod != null ? " virtual" : " override") : method.IsVirtual ? " virtual" : string.Empty; + if ((string.IsNullOrEmpty (virt_ov) || virt_ov == " virtual") && type.RequiresNew (method.AdjustedName)) { virt_ov = " new" + virt_ov; } @@ -1331,9 +1376,22 @@ public void WriteMethod (Method method, string indent, GenBase type, bool genera writer.WriteLine ("{0}[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, method.JavaName, method.JniSignature, method.IsVirtual ? method.ConnectorName : String.Empty, method.AdditionalAttributeString ()); WriteMethodCustomAttributes (method, indent); - writer.WriteLine ("{0}{1}{2}{3}{4} unsafe {5} {6} ({7})", indent, method.Visibility, static_arg, virt_ov, seal, ret, method.AdjustedName, method.GetSignature (opt)); + + var visibility = type is InterfaceGen && !method.IsStatic ? string.Empty : method.Visibility; + + writer.WriteLine ("{0}{1}{2}{3}{4} unsafe {5} {6}{7} ({8})", + indent, + visibility, + static_arg, + virt_ov, + seal, + ret, + is_explicit ? GetDeclaringTypeOfExplicitInterfaceMethod (method.OverriddenInterfaceMethod) + '.' : string.Empty, + method.AdjustedName, + method.GetSignature (opt)); + writer.WriteLine ("{0}{{", indent); - WriteMethodBody (method, indent + "\t"); + WriteMethodBody (method, indent + "\t", type); writer.WriteLine ("{0}}}", indent); writer.WriteLine (); @@ -1418,7 +1476,7 @@ public void WriteProperty (Property property, GenBase gen, string indent, bool w WriteMethodIdField (property.Getter, indent); if (property.Setter != null) WriteMethodIdField (property.Setter, indent); - string visibility = property.Getter.IsAbstract && property.Getter.RetVal.IsGeneric ? "protected" : (property.Setter ?? property.Getter).Visibility; + string visibility = gen is InterfaceGen ? string.Empty : property.Getter.IsAbstract && property.Getter.RetVal.IsGeneric ? "protected" : (property.Setter ?? property.Getter).Visibility; // Unlike [Register], mcs does not allow applying [Obsolete] on property accessors, so we can apply them only under limited condition... if (property.Getter.Deprecated != null && (property.Setter == null || property.Setter.Deprecated != null)) writer.WriteLine ("{0}[Obsolete (@\"{1}\")]", indent, property.Getter.Deprecated.Replace ("\"", "\"\"").Trim () + (property.Setter != null && property.Setter.Deprecated != property.Getter.Deprecated ? " " + property.Setter.Deprecated.Replace ("\"", "\"\"").Trim () : null)); @@ -1428,7 +1486,7 @@ public void WriteProperty (Property property, GenBase gen, string indent, bool w writer.WriteLine ("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.MetadataXPathReference, property.Getter.JavaName, property.Getter.Parameters.GetMethodXPathPredicate ()); writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, property.Getter.JavaName, property.Getter.JniSignature, property.Getter.ConnectorName, property.Getter.AdditionalAttributeString ()); writer.WriteLine ("{0}\tget {{", indent); - WriteMethodBody (property.Getter, indent + "\t\t"); + WriteMethodBody (property.Getter, indent + "\t\t", gen); writer.WriteLine ("{0}\t}}", indent); if (property.Setter != null) { if (gen.IsGeneratable) @@ -1438,7 +1496,7 @@ public void WriteProperty (Property property, GenBase gen, string indent, bool w writer.WriteLine ("{0}\tset {{", indent); string pname = property.Setter.Parameters [0].Name; property.Setter.Parameters [0].Name = "value"; - WriteMethodBody (property.Setter, indent + "\t\t"); + WriteMethodBody (property.Setter, indent + "\t\t", gen); property.Setter.Parameters [0].Name = pname; writer.WriteLine ("{0}\t}}", indent); } else if (property.GenerateDispatchingSetter) { diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs index 15613e4f2..ef36a32f7 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs @@ -134,7 +134,7 @@ internal override void WriteMethodIdField (Method method, string indent) // No method id_ field required; it's now an `id` constant in the binding. } - internal override void WriteMethodBody (Method method, string indent) + internal override void WriteMethodBody (Method method, string indent, GenBase type) { writer.WriteLine ("{0}const string __id = \"{1}.{2}\";", indent, method.JavaName, method.JniSignature); foreach (string prep in method.Parameters.GetCallPrep (opt)) @@ -151,21 +151,26 @@ internal override void WriteMethodBody (Method method, string indent) writer.Write ("var __rm = "); } + var castToPeerable = type is InterfaceGen ? "(IJavaPeerable) " : string.Empty; + if (method.IsStatic) { writer.WriteLine ("_members.StaticMethods.Invoke{0}Method (__id{1});", invokeType, method.Parameters.GetCallArgs (opt, invoker: false)); - } else if (method.IsFinal) { - writer.WriteLine ("_members.InstanceMethods.InvokeNonvirtual{0}Method (__id, this{1});", + } else if (method.IsFinal || method.IsInterfaceDefaultMethod) { + writer.WriteLine ("_members.InstanceMethods.InvokeNonvirtual{0}Method (__id, {1}this{2});", invokeType, + castToPeerable, method.Parameters.GetCallArgs (opt, invoker: false)); } else if (method.IsVirtual && !method.IsAbstract) { - writer.WriteLine ("_members.InstanceMethods.InvokeVirtual{0}Method (__id, this{1});", + writer.WriteLine ("_members.InstanceMethods.InvokeVirtual{0}Method (__id, {1}this{2});", invokeType, + castToPeerable, method.Parameters.GetCallArgs (opt, invoker: false)); } else { - writer.WriteLine ("_members.InstanceMethods.InvokeAbstract{0}Method (__id, this{1});", + writer.WriteLine ("_members.InstanceMethods.InvokeAbstract{0}Method (__id, {1}this{2});", invokeType, + castToPeerable, method.Parameters.GetCallArgs (opt, invoker: false)); } diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/XamarinAndroidCodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/XamarinAndroidCodeGenerator.cs index a24fe21c6..1de68e0c4 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/XamarinAndroidCodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/XamarinAndroidCodeGenerator.cs @@ -123,7 +123,7 @@ void GenerateJNICall (Method method, string indent, string call, bool declare_re writer.WriteLine ("{0}return {1};", indent, method.RetVal.FromNative (opt, call, true)); } - internal override void WriteMethodBody (Method method, string indent) + internal override void WriteMethodBody (Method method, string indent, GenBase type) { writer.WriteLine ("{0}if ({1} == IntPtr.Zero)", indent, method.EscapedIdName); writer.WriteLine ("{0}\t{1} = JNIEnv.Get{2}MethodID (class_ref, \"{3}\", \"{4}\");", indent, method.EscapedIdName, method.IsStatic ? "Static" : String.Empty, method.JavaName, method.JniSignature); diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index 1628785ba..44bb1c980 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -290,7 +290,7 @@ public virtual void FixupExplicitImplementation () public void FixupMethodOverrides (CodeGenerationOptions opt) { - foreach (var m in Methods.Where (m => !m.IsInterfaceDefaultMethod)) { + foreach (var m in Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod)) { for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { var bm = bt.Methods.FirstOrDefault (mm => mm.Name == m.Name && mm.Visibility == m.Visibility && ParameterList.Equals (mm.Parameters, m.Parameters)); if (bm != null && bm.RetVal.FullName == m.RetVal.FullName) { // if return type is different, it could be still "new", not "override". @@ -301,11 +301,22 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) } // Interface default methods can be overriden. We want to process them differently. - foreach (var m in Methods.Where (m => m.IsInterfaceDefaultMethod)) { - foreach (var bt in GetAllDerivedInterfaces ()) { - var bm = bt.Methods.FirstOrDefault (mm => mm.Name == m.Name && ParameterList.Equals (mm.Parameters, m.Parameters)); + var checkDimOverrideTargets = opt.SupportDefaultInterfaceMethods ? Methods : Methods.Where (m => m.IsInterfaceDefaultMethod); + + // We need to check all the implemented interfaces of all the base types. + var allIfaces = new List (); + + for (var gen = this; gen != null; gen = gen.BaseGen) + gen.GetAllDerivedInterfaces (allIfaces); + + foreach (var m in checkDimOverrideTargets.Where (m => !m.IsStatic)) { + foreach (var bt in allIfaces.Distinct ()) { + // We mark a method as an override if (1) it is a DIM, or (2) if the base method is DIM + // (i.e. we don't mark as override if a class method "implements" normal iface method.) + var bm = bt.Methods.FirstOrDefault (mm => (m.IsInterfaceDefaultMethod || !mm.IsAbstract) && mm.Name == m.Name && ParameterList.Equals (mm.Parameters, m.Parameters)); + if (bm != null) { - m.IsInterfaceDefaultMethodOverride = true; + m.OverriddenInterfaceMethod = bm; break; } } @@ -411,7 +422,7 @@ void visit (ISymbol isym) } public IEnumerable GetAllMethods () => - Methods.Concat (Properties.Select (p => p.Getter)).Concat (Properties.Select (p => p.Setter).Where (m => m != null)); + Methods.Concat (Properties.Select (p => p.Getter)).Concat (Properties.Select (p => p.Setter)).Where (m => m != null); GenBase GetBaseGen (CodeGenerationOptions opt) { @@ -734,15 +745,16 @@ bool ReturnTypeMatches (Method m, Method mm) public bool ShouldGenerateAnnotationAttribute => IsAnnotation; - public void StripNonBindables () + public void StripNonBindables (CodeGenerationOptions opt) { - // As of now, if we generate bindings for interface default methods, that means users will - // have to "implement" those methods because they are declared and you have to implement - // any declared methods in C#. That is going to be problematic a lot. - Methods = Methods.Where (m => !m.IsInterfaceDefaultMethod).ToList (); + // Strip out default interface methods if not desired + if (!opt.SupportDefaultInterfaceMethods) + Methods = Methods.Where (m => !m.IsInterfaceDefaultMethod).ToList (); + NestedTypes = NestedTypes.Where (n => !n.IsObfuscated && n.Visibility != "private").ToList (); + foreach (var n in NestedTypes) - n.StripNonBindables (); + n.StripNonBindables (opt); } static readonly HashSet ThrowableRequiresNew = new HashSet ( diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs index e0bbba10b..ce36922f6 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs @@ -117,6 +117,8 @@ public IEnumerable GetGeneratableFields (CodeGenerationOptions options) return Fields.Where (f => !f.NeedsProperty && !(f.DeprecatedComment?.Contains ("constant will be removed") == true)); } + public bool HasDefaultMethods => GetAllMethods ().Any (m => m.IsInterfaceDefaultMethod); + public bool IsConstSugar { get { if (Methods.Count > 0 || Properties.Count > 0) diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs index 3017e4124..d3c0882ea 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs @@ -20,7 +20,7 @@ public Method (GenBase declaringType) : base (declaringType) public bool IsAbstract { get; set; } public bool IsFinal { get; set; } public bool IsInterfaceDefaultMethod { get; set; } - public bool IsInterfaceDefaultMethodOverride { get; set; } + public Method OverriddenInterfaceMethod { get; set; } public bool IsReturnEnumified { get; set; } public bool IsStatic { get; set; } public bool IsVirtual { get; set; } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/Common/WriteInterfaceRedeclaredDefaultMethod.txt similarity index 55% rename from tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceMethod.txt rename to tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/Common/WriteInterfaceRedeclaredDefaultMethod.txt index e82dbe04a..ce320dde0 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceMethod.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/Common/WriteInterfaceRedeclaredDefaultMethod.txt @@ -1,10 +1,9 @@ -// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" -[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] -public partial interface IMyInterface : IJavaObject { +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface2']" +[Register ("java/code/IMyInterface2", "", "java.code.IMyInterface2Invoker")] +public partial interface IMyInterface2 : java.code.IMyInterface { // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" - [global::Java.Interop.JavaInterfaceDefaultMethod] - [Register ("DoSomething", "()V", "GetDoSomethingHandler:java.code.IMyInterfaceInvoker, ")] + [Register ("DoSomething", "()V", "GetDoSomethingHandler:java.code.IMyInterface2Invoker, ")] void DoSomething (); } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt new file mode 100644 index 000000000..ca8045b7b --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt @@ -0,0 +1,34 @@ +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" +[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] +public partial interface IMyInterface : IJavaObject, IJavaPeerable { + static new readonly JniPeerMembers _members = new JniPeerMembers ("java/code/IMyInterface", typeof (IMyInterface)); + + static Delegate cb_DoSomething; +#pragma warning disable 0169 + static Delegate GetDoSomethingHandler () + { + if (cb_DoSomething == null) + cb_DoSomething = JNINativeWrapper.CreateDelegate ((Action) n_DoSomething); + return cb_DoSomething; + } + + static void n_DoSomething (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.DoSomething (); + } +#pragma warning restore 0169 + + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" + [Register ("DoSomething", "()V", "GetDoSomethingHandler")] + virtual unsafe void DoSomething () + { + const string __id = "DoSomething.()V"; + try { + _members.InstanceMethods.InvokeNonvirtualVoidMethod (__id, (IJavaPeerable) this, null); + } finally { + } + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt new file mode 100644 index 000000000..1fdc9f8ff --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt @@ -0,0 +1,63 @@ +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" +[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] +public partial interface IMyInterface : IJavaObject, IJavaPeerable { + static new readonly JniPeerMembers _members = new JniPeerMembers ("java/code/IMyInterface", typeof (IMyInterface)); + + static Delegate cb_get_Value; +#pragma warning disable 0169 + static Delegate Getget_ValueHandler () + { + if (cb_get_Value == null) + cb_get_Value = JNINativeWrapper.CreateDelegate ((Func) n_get_Value); + return cb_get_Value; + } + + static int n_get_Value (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + return __this.Value; + } +#pragma warning restore 0169 + + static Delegate cb_set_Value_I; +#pragma warning disable 0169 + static Delegate Getset_Value_IHandler () + { + if (cb_set_Value_I == null) + cb_set_Value_I = JNINativeWrapper.CreateDelegate ((Action) n_set_Value_I); + return cb_set_Value_I; + } + + static void n_set_Value_I (IntPtr jnienv, IntPtr native__this, int value) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.Value = value; + } +#pragma warning restore 0169 + + virtual unsafe int Value { + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" + [Register ("get_Value", "()I", "Getget_ValueHandler")] + get { + const string __id = "get_Value.()I"; + try { + var __rm = _members.InstanceMethods.InvokeNonvirtualInt32Method (__id, (IJavaPeerable) this, null); + return __rm; + } finally { + } + } + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='set_Value' and count(parameter)=1 and parameter[1][@type='int']]" + [Register ("set_Value", "(I)V", "Getset_Value_IHandler")] + set { + const string __id = "set_Value.(I)V"; + try { + JniArgumentValue* __args = stackalloc JniArgumentValue [1]; + __args [0] = new JniArgumentValue (value); + _members.InstanceMethods.InvokeNonvirtualVoidMethod (__id, (IJavaPeerable) this, __args); + } finally { + } + } + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt new file mode 100644 index 000000000..5eaf59a90 --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -0,0 +1,36 @@ +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" +[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] +public partial interface IMyInterface : IJavaObject, IJavaPeerable { + static new readonly JniPeerMembers _members = new JniPeerMembers ("java/code/IMyInterface", typeof (IMyInterface)); + + static Delegate cb_get_Value; +#pragma warning disable 0169 + static Delegate Getget_ValueHandler () + { + if (cb_get_Value == null) + cb_get_Value = JNINativeWrapper.CreateDelegate ((Func) n_get_Value); + return cb_get_Value; + } + + static int n_get_Value (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + return __this.Value; + } +#pragma warning restore 0169 + + virtual unsafe int Value { + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" + [Register ("get_Value", "()I", "Getget_ValueHandler")] + get { + const string __id = "get_Value.()I"; + try { + var __rm = _members.InstanceMethods.InvokeNonvirtualInt32Method (__id, (IJavaPeerable) this, null); + return __rm; + } finally { + } + } + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceMethod.txt deleted file mode 100644 index b616be47a..000000000 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceMethod.txt +++ /dev/null @@ -1,11 +0,0 @@ -// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" -[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] -public partial interface IMyInterface : IJavaObject, IJavaPeerable { - - // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" - [global::Java.Interop.JavaInterfaceDefaultMethod] - [Register ("DoSomething", "()V", "GetDoSomethingHandler:java.code.IMyInterfaceInvoker, ")] - void DoSomething (); - -} - diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt new file mode 100644 index 000000000..81084c7b6 --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt @@ -0,0 +1,34 @@ +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" +[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] +public partial interface IMyInterface : IJavaObject, IJavaPeerable { + static new readonly JniPeerMembers _members = new XAPeerMembers ("java/code/IMyInterface", typeof (IMyInterface)); + + static Delegate cb_DoSomething; +#pragma warning disable 0169 + static Delegate GetDoSomethingHandler () + { + if (cb_DoSomething == null) + cb_DoSomething = JNINativeWrapper.CreateDelegate ((Action) n_DoSomething); + return cb_DoSomething; + } + + static void n_DoSomething (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.DoSomething (); + } +#pragma warning restore 0169 + + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" + [Register ("DoSomething", "()V", "GetDoSomethingHandler")] + virtual unsafe void DoSomething () + { + const string __id = "DoSomething.()V"; + try { + _members.InstanceMethods.InvokeNonvirtualVoidMethod (__id, (IJavaPeerable) this, null); + } finally { + } + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt new file mode 100644 index 000000000..258fa7b04 --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt @@ -0,0 +1,63 @@ +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" +[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] +public partial interface IMyInterface : IJavaObject, IJavaPeerable { + static new readonly JniPeerMembers _members = new XAPeerMembers ("java/code/IMyInterface", typeof (IMyInterface)); + + static Delegate cb_get_Value; +#pragma warning disable 0169 + static Delegate Getget_ValueHandler () + { + if (cb_get_Value == null) + cb_get_Value = JNINativeWrapper.CreateDelegate ((Func) n_get_Value); + return cb_get_Value; + } + + static int n_get_Value (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + return __this.Value; + } +#pragma warning restore 0169 + + static Delegate cb_set_Value_I; +#pragma warning disable 0169 + static Delegate Getset_Value_IHandler () + { + if (cb_set_Value_I == null) + cb_set_Value_I = JNINativeWrapper.CreateDelegate ((Action) n_set_Value_I); + return cb_set_Value_I; + } + + static void n_set_Value_I (IntPtr jnienv, IntPtr native__this, int value) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.Value = value; + } +#pragma warning restore 0169 + + virtual unsafe int Value { + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" + [Register ("get_Value", "()I", "Getget_ValueHandler")] + get { + const string __id = "get_Value.()I"; + try { + var __rm = _members.InstanceMethods.InvokeNonvirtualInt32Method (__id, (IJavaPeerable) this, null); + return __rm; + } finally { + } + } + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='set_Value' and count(parameter)=1 and parameter[1][@type='int']]" + [Register ("set_Value", "(I)V", "Getset_Value_IHandler")] + set { + const string __id = "set_Value.(I)V"; + try { + JniArgumentValue* __args = stackalloc JniArgumentValue [1]; + __args [0] = new JniArgumentValue (value); + _members.InstanceMethods.InvokeNonvirtualVoidMethod (__id, (IJavaPeerable) this, __args); + } finally { + } + } + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt new file mode 100644 index 000000000..317e073c5 --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -0,0 +1,36 @@ +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" +[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] +public partial interface IMyInterface : IJavaObject, IJavaPeerable { + static new readonly JniPeerMembers _members = new XAPeerMembers ("java/code/IMyInterface", typeof (IMyInterface)); + + static Delegate cb_get_Value; +#pragma warning disable 0169 + static Delegate Getget_ValueHandler () + { + if (cb_get_Value == null) + cb_get_Value = JNINativeWrapper.CreateDelegate ((Func) n_get_Value); + return cb_get_Value; + } + + static int n_get_Value (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + return __this.Value; + } +#pragma warning restore 0169 + + virtual unsafe int Value { + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" + [Register ("get_Value", "()I", "Getget_ValueHandler")] + get { + const string __id = "get_Value.()I"; + try { + var __rm = _members.InstanceMethods.InvokeNonvirtualInt32Method (__id, (IJavaPeerable) this, null); + return __rm; + } finally { + } + } + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt new file mode 100644 index 000000000..b282c8612 --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt @@ -0,0 +1,40 @@ +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" +[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] +public partial interface IMyInterface : IJavaObject { + new static IntPtr class_ref = JNIEnv.FindClass ("java/code/IMyInterface"); + + static Delegate cb_DoSomething; +#pragma warning disable 0169 + static Delegate GetDoSomethingHandler () + { + if (cb_DoSomething == null) + cb_DoSomething = JNINativeWrapper.CreateDelegate ((Action) n_DoSomething); + return cb_DoSomething; + } + + static void n_DoSomething (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.DoSomething (); + } +#pragma warning restore 0169 + + static IntPtr id_DoSomething; + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" + [Register ("DoSomething", "()V", "GetDoSomethingHandler")] + virtual unsafe void DoSomething () + { + if (id_DoSomething == IntPtr.Zero) + id_DoSomething = JNIEnv.GetMethodID (class_ref, "DoSomething", "()V"); + try { + + if (((object) this).GetType () == ThresholdType) + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_DoSomething); + else + JNIEnv.CallNonvirtualVoidMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "DoSomething", "()V")); + } finally { + } + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt new file mode 100644 index 000000000..64b5a05a4 --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt @@ -0,0 +1,74 @@ +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" +[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] +public partial interface IMyInterface : IJavaObject { + new static IntPtr class_ref = JNIEnv.FindClass ("java/code/IMyInterface"); + + static Delegate cb_get_Value; +#pragma warning disable 0169 + static Delegate Getget_ValueHandler () + { + if (cb_get_Value == null) + cb_get_Value = JNINativeWrapper.CreateDelegate ((Func) n_get_Value); + return cb_get_Value; + } + + static int n_get_Value (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + return __this.Value; + } +#pragma warning restore 0169 + + static Delegate cb_set_Value_I; +#pragma warning disable 0169 + static Delegate Getset_Value_IHandler () + { + if (cb_set_Value_I == null) + cb_set_Value_I = JNINativeWrapper.CreateDelegate ((Action) n_set_Value_I); + return cb_set_Value_I; + } + + static void n_set_Value_I (IntPtr jnienv, IntPtr native__this, int value) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.Value = value; + } +#pragma warning restore 0169 + + static IntPtr id_get_Value; + static IntPtr id_set_Value_I; + virtual unsafe int Value { + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" + [Register ("get_Value", "()I", "Getget_ValueHandler")] + get { + if (id_get_Value == IntPtr.Zero) + id_get_Value = JNIEnv.GetMethodID (class_ref, "get_Value", "()I"); + try { + + if (((object) this).GetType () == ThresholdType) + return JNIEnv.CallIntMethod (((global::Java.Lang.Object) this).Handle, id_get_Value); + else + return JNIEnv.CallNonvirtualIntMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "get_Value", "()I")); + } finally { + } + } + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='set_Value' and count(parameter)=1 and parameter[1][@type='int']]" + [Register ("set_Value", "(I)V", "Getset_Value_IHandler")] + set { + if (id_set_Value_I == IntPtr.Zero) + id_set_Value_I = JNIEnv.GetMethodID (class_ref, "set_Value", "(I)V"); + try { + JValue* __args = stackalloc JValue [1]; + __args [0] = new JValue (value); + + if (((object) this).GetType () == ThresholdType) + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_set_Value_I, __args); + else + JNIEnv.CallNonvirtualVoidMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "set_Value", "(I)V"), __args); + } finally { + } + } + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt new file mode 100644 index 000000000..d07d58d61 --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -0,0 +1,41 @@ +// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" +[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] +public partial interface IMyInterface : IJavaObject { + new static IntPtr class_ref = JNIEnv.FindClass ("java/code/IMyInterface"); + + static Delegate cb_get_Value; +#pragma warning disable 0169 + static Delegate Getget_ValueHandler () + { + if (cb_get_Value == null) + cb_get_Value = JNINativeWrapper.CreateDelegate ((Func) n_get_Value); + return cb_get_Value; + } + + static int n_get_Value (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + return __this.Value; + } +#pragma warning restore 0169 + + static IntPtr id_get_Value; + virtual unsafe int Value { + // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" + [Register ("get_Value", "()I", "Getget_ValueHandler")] + get { + if (id_get_Value == IntPtr.Zero) + id_get_Value = JNIEnv.GetMethodID (class_ref, "get_Value", "()I"); + try { + + if (((object) this).GetType () == ThresholdType) + return JNIEnv.CallIntMethod (((global::Java.Lang.Object) this).Handle, id_get_Value); + else + return JNIEnv.CallNonvirtualIntMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "get_Value", "()I")); + } finally { + } + } + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorTests.cs b/tools/generator/Tests/Unit-Tests/CodeGeneratorTests.cs index c051f11d1..03c957321 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorTests.cs +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorTests.cs @@ -663,7 +663,7 @@ public void WriteMethodBody () var method = new TestMethod (@class, "bar"); Assert.IsTrue (method.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "method.Validate failed!"); - generator.WriteMethodBody (method, string.Empty); + generator.WriteMethodBody (method, string.Empty, @class); Assert.AreEqual (GetTargetedExpected (nameof (WriteMethodBody)), writer.ToString ().NormalizeLineEndings ()); } diff --git a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs index eb38f2cdd..29491c767 100644 --- a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs +++ b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs @@ -1,19 +1,26 @@ using System; using MonoDroid.Generation; using NUnit.Framework; +using Xamarin.Android.Binder; namespace generatortests { [TestFixture] class JavaInteropDefaultInterfaceMethodsTests : DefaultInterfaceMethodsTests { - protected override Xamarin.Android.Binder.CodeGenerationTarget Target => Xamarin.Android.Binder.CodeGenerationTarget.JavaInterop1; + protected override CodeGenerationTarget Target => CodeGenerationTarget.JavaInterop1; + } + + [TestFixture] + class XAJavaInteropDefaultInterfaceMethodsTests : DefaultInterfaceMethodsTests + { + protected override CodeGenerationTarget Target => CodeGenerationTarget.XAJavaInterop1; } [TestFixture] class XamarinAndroidDefaultInterfaceMethodsTests : DefaultInterfaceMethodsTests { - protected override Xamarin.Android.Binder.CodeGenerationTarget Target => Xamarin.Android.Binder.CodeGenerationTarget.XamarinAndroid; + protected override CodeGenerationTarget Target => CodeGenerationTarget.XamarinAndroid; } abstract class DefaultInterfaceMethodsTests : CodeGeneratorTestBase @@ -22,52 +29,84 @@ protected override CodeGenerationOptions CreateOptions () { var options = base.CreateOptions (); - options.SupportInterfaceConstants = true; + options.SupportDefaultInterfaceMethods = true; return options; } [Test] - public void WriteInterfaceFields () + public void WriteInterfaceDefaultMethod () { - // This is an interface that has both fields and method declarations + // Create an interface with a default method var iface = SupportTypeBuilder.CreateEmptyInterface("java.code.IMyInterface"); - iface.Fields.Add (new TestField ("int", "MyConstantField").SetConstant ().SetValue ("7")); - iface.Methods.Add (new TestMethod (iface, "DoSomething").SetAbstract ()); + iface.Methods.Add (new TestMethod (iface, "DoSomething").SetDefaultInterfaceMethod ()); + + iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()); + + generator.WriteInterfaceDeclaration (iface, string.Empty); + + Assert.AreEqual (GetTargetedExpected (nameof (WriteInterfaceDefaultMethod)), writer.ToString ().NormalizeLineEndings ()); + } + + [Test] + public void WriteInterfaceRedeclaredDefaultMethod () + { + // Create an interface with a default method + var iface = SupportTypeBuilder.CreateEmptyInterface ("java.code.IMyInterface"); + iface.Methods.Add (new TestMethod (iface, "DoSomething").SetDefaultInterfaceMethod ()); + options.SymbolTable.AddType (iface); + + // Create a second interface that inerhits the first, declaring the method as not default + var iface2 = SupportTypeBuilder.CreateEmptyInterface ("java.code.IMyInterface2"); + iface2.AddImplementedInterface ("java.code.IMyInterface"); + iface2.Methods.Add (new TestMethod (iface, "DoSomething")); + + iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()); + iface2.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()); + + generator.WriteInterfaceDeclaration (iface2, string.Empty); + + // IMyInterface2 should generate the method as abstract, not a default method + Assert.AreEqual (GetExpected (nameof (WriteInterfaceRedeclaredDefaultMethod)), writer.ToString ().NormalizeLineEndings ()); + } + + [Test] + public void WriteInterfaceDefaultProperty () + { + // Create an interface with a default method + var iface = SupportTypeBuilder.CreateEmptyInterface ("java.code.IMyInterface"); + var prop = SupportTypeBuilder.CreateProperty (iface, "Value", "int", options); + + prop.Getter.IsInterfaceDefaultMethod = true; + prop.Setter.IsInterfaceDefaultMethod = true; + + iface.Properties.Add (prop); iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()); - generator.Context.ContextTypes.Push (iface); generator.WriteInterfaceDeclaration (iface, string.Empty); - generator.Context.ContextTypes.Pop (); - Assert.AreEqual (GetTargetedExpected (nameof (WriteInterfaceFields)), writer.ToString ().NormalizeLineEndings ()); + Assert.AreEqual (GetTargetedExpected (nameof (WriteInterfaceDefaultProperty)), writer.ToString ().NormalizeLineEndings ()); } [Test] - public void WriteConstSugarInterfaceFields () + public void WriteInterfaceDefaultPropertyGetterOnly () { - // This is an interface that only has fields (IsConstSugar) - // We treat a little differenly because they don't need to interop with Java + // Create an interface with a default method var iface = SupportTypeBuilder.CreateEmptyInterface ("java.code.IMyInterface"); + var prop = SupportTypeBuilder.CreateProperty (iface, "Value", "int", options); - // These interface fields are supported and should be in the output - iface.Fields.Add (new TestField ("int", "MyConstantField").SetConstant ().SetValue ("7")); - iface.Fields.Add (new TestField ("java.lang.String", "MyConstantStringField").SetConstant ().SetValue ("\"hello\"")); - iface.Fields.Add (new TestField ("int", "MyDeprecatedField").SetConstant ().SetValue ("7").SetDeprecated ()); + prop.Getter.IsInterfaceDefaultMethod = true; + prop.Setter = null; - // These interface fields are not supported and should be ignored - iface.Fields.Add (new TestField ("int", "MyDeprecatedEnumField").SetConstant ().SetValue ("MyEnumValue").SetDeprecated ("This constant will be removed in the future version.")); - iface.Fields.Add (new TestField ("int", "MyStaticField").SetStatic ().SetValue ("7")); + iface.Properties.Add (prop); iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()); - generator.Context.ContextTypes.Push (iface); generator.WriteInterfaceDeclaration (iface, string.Empty); - generator.Context.ContextTypes.Pop (); - Assert.AreEqual (GetTargetedExpected (nameof (WriteConstSugarInterfaceFields)), writer.ToString ().NormalizeLineEndings ()); + Assert.AreEqual (GetTargetedExpected (nameof (WriteInterfaceDefaultPropertyGetterOnly)), writer.ToString ().NormalizeLineEndings ()); } } } diff --git a/tools/generator/Tests/Unit-Tests/InterfaceConstantsTests.cs b/tools/generator/Tests/Unit-Tests/InterfaceConstantsTests.cs new file mode 100644 index 000000000..1bcfdc24d --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/InterfaceConstantsTests.cs @@ -0,0 +1,73 @@ +using System; +using MonoDroid.Generation; +using NUnit.Framework; + +namespace generatortests +{ + [TestFixture] + class JavaInteropInterfaceConstantsTests : InterfaceConstantsTests + { + protected override Xamarin.Android.Binder.CodeGenerationTarget Target => Xamarin.Android.Binder.CodeGenerationTarget.JavaInterop1; + } + + [TestFixture] + class XamarinAndroidInterfaceConstantsTests : InterfaceConstantsTests + { + protected override Xamarin.Android.Binder.CodeGenerationTarget Target => Xamarin.Android.Binder.CodeGenerationTarget.XamarinAndroid; + } + + abstract class InterfaceConstantsTests : CodeGeneratorTestBase + { + protected override CodeGenerationOptions CreateOptions () + { + var options = base.CreateOptions (); + + options.SupportInterfaceConstants = true; + + return options; + } + + [Test] + public void WriteInterfaceFields () + { + // This is an interface that has both fields and method declarations + var iface = SupportTypeBuilder.CreateEmptyInterface("java.code.IMyInterface"); + + iface.Fields.Add (new TestField ("int", "MyConstantField").SetConstant ().SetValue ("7")); + iface.Methods.Add (new TestMethod (iface, "DoSomething").SetAbstract ()); + + iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()); + + generator.Context.ContextTypes.Push (iface); + generator.WriteInterfaceDeclaration (iface, string.Empty); + generator.Context.ContextTypes.Pop (); + + Assert.AreEqual (GetTargetedExpected (nameof (WriteInterfaceFields)), writer.ToString ().NormalizeLineEndings ()); + } + + [Test] + public void WriteConstSugarInterfaceFields () + { + // This is an interface that only has fields (IsConstSugar) + // We treat a little differenly because they don't need to interop with Java + var iface = SupportTypeBuilder.CreateEmptyInterface ("java.code.IMyInterface"); + + // These interface fields are supported and should be in the output + iface.Fields.Add (new TestField ("int", "MyConstantField").SetConstant ().SetValue ("7")); + iface.Fields.Add (new TestField ("java.lang.String", "MyConstantStringField").SetConstant ().SetValue ("\"hello\"")); + iface.Fields.Add (new TestField ("int", "MyDeprecatedField").SetConstant ().SetValue ("7").SetDeprecated ()); + + // These interface fields are not supported and should be ignored + iface.Fields.Add (new TestField ("int", "MyDeprecatedEnumField").SetConstant ().SetValue ("MyEnumValue").SetDeprecated ("This constant will be removed in the future version.")); + iface.Fields.Add (new TestField ("int", "MyStaticField").SetStatic ().SetValue ("7")); + + iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()); + + generator.Context.ContextTypes.Push (iface); + generator.WriteInterfaceDeclaration (iface, string.Empty); + generator.Context.ContextTypes.Pop (); + + Assert.AreEqual (GetTargetedExpected (nameof (WriteConstSugarInterfaceFields)), writer.ToString ().NormalizeLineEndings ()); + } + } +} diff --git a/tools/generator/Tests/Unit-Tests/SupportTypes.cs b/tools/generator/Tests/Unit-Tests/SupportTypes.cs index 3dd968019..9ce051837 100644 --- a/tools/generator/Tests/Unit-Tests/SupportTypes.cs +++ b/tools/generator/Tests/Unit-Tests/SupportTypes.cs @@ -155,6 +155,15 @@ public TestMethod SetReturnEnumified () IsReturnEnumified = true; return this; } + + public TestMethod SetDefaultInterfaceMethod () + { + IsAbstract = false; + IsStatic = false; + IsInterfaceDefaultMethod = true; + + return this; + } } class TestCtor : Ctor diff --git a/tools/generator/Tests/generator-Tests.csproj b/tools/generator/Tests/generator-Tests.csproj index b95a0f447..71f266298 100644 --- a/tools/generator/Tests/generator-Tests.csproj +++ b/tools/generator/Tests/generator-Tests.csproj @@ -74,6 +74,7 @@ + @@ -176,6 +177,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -242,6 +246,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -353,6 +366,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -533,6 +555,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest From ea8e9d6f130b4d1fc5ef42e7bbb6ba7ebe0ddbb0 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Tue, 13 Aug 2019 10:15:47 -0500 Subject: [PATCH 02/10] [generator] Invalid DIM methods should not invalidate the interface. --- .../GenBase.cs | 7 ++- .../Tests/Unit-Tests/InterfaceTests.cs | 57 +++++++++++++++++++ tools/generator/Tests/generator-Tests.csproj | 1 + 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 tools/generator/Tests/Unit-Tests/InterfaceTests.cs diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index 44bb1c980..ffa0e1751 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -670,9 +670,12 @@ protected virtual bool OnValidate (CodeGenerationOptions opt, GenericParameterDe } Fields = valid_fields; - int method_cnt = Methods.Count; + // If we can't validate a default interface method it's ok to ignore it and still bind the interface + var method_cnt = Methods.Where (m => !m.IsInterfaceDefaultMethod).Count (); + Methods = Methods.Where (m => ValidateMethod (opt, m, context)).ToList (); - MethodValidationFailed = method_cnt != Methods.Count; + MethodValidationFailed = method_cnt != Methods.Where (m => !m.IsInterfaceDefaultMethod).Count (); + foreach (Method m in Methods) { if (m.IsVirtual) HasVirtualMethods = true; diff --git a/tools/generator/Tests/Unit-Tests/InterfaceTests.cs b/tools/generator/Tests/Unit-Tests/InterfaceTests.cs new file mode 100644 index 000000000..d619910fd --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/InterfaceTests.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using MonoDroid.Generation; +using NUnit.Framework; + +namespace generatortests +{ + public class InterfaceTests + { + [Test] + public void ValidateInterfaceMethods () + { + var options = new CodeGenerationOptions { SupportDefaultInterfaceMethods = true }; + var iface = SupportTypeBuilder.CreateEmptyInterface ("My.Test.Interface"); + + iface.Methods.Add (SupportTypeBuilder.CreateMethod (iface, "DoAbstractThing", options)); + iface.Methods.Add (SupportTypeBuilder.CreateMethod (iface, "DoDefaultThing", options).SetDefaultInterfaceMethod ()); + + // The interface should be valid + Assert.True (iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ())); + + Assert.AreEqual (2, iface.Methods.Count); + } + + [Test] + public void ValidateInvalidDefaultInterfaceMethods () + { + var options = new CodeGenerationOptions { SupportDefaultInterfaceMethods = true }; + var iface = SupportTypeBuilder.CreateEmptyInterface ("My.Test.Interface"); + + iface.Methods.Add (SupportTypeBuilder.CreateMethod (iface, "DoAbstractThing", options)); + iface.Methods.Add (SupportTypeBuilder.CreateMethod (iface, "DoDefaultThing", options, "potato").SetDefaultInterfaceMethod ()); + + // The interface should still be valid despite the default method being invalid + Assert.True (iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ())); + + // The invalid default method should be removed, leaving just the valid abstract method + Assert.AreEqual (1, iface.Methods.Count); + } + + [Test] + public void ValidateInvalidAbstractInterfaceMethods () + { + var options = new CodeGenerationOptions { SupportDefaultInterfaceMethods = true }; + var iface = SupportTypeBuilder.CreateEmptyInterface ("My.Test.Interface"); + + iface.Methods.Add (SupportTypeBuilder.CreateMethod (iface, "DoAbstractThing", options, "potato")); + iface.Methods.Add (SupportTypeBuilder.CreateMethod (iface, "DoDefaultThing", options).SetDefaultInterfaceMethod ()); + + // The interface should be invalid because an abstract method is invalid + Assert.False (iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ())); + + // The invalid abstract method should be removed, leaving just the valid default method + Assert.AreEqual (1, iface.Methods.Count); + } + } +} diff --git a/tools/generator/Tests/generator-Tests.csproj b/tools/generator/Tests/generator-Tests.csproj index 71f266298..6a24b292f 100644 --- a/tools/generator/Tests/generator-Tests.csproj +++ b/tools/generator/Tests/generator-Tests.csproj @@ -75,6 +75,7 @@ + From 9fad1dc248b02e05be6c9012b846ae2700c966bc Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Tue, 13 Aug 2019 14:37:51 -0500 Subject: [PATCH 03/10] [generator] Prevent DIM from creating "virtual sealed" methods. --- tools/generator/CodeGenerator.cs | 2 +- .../CodeGenerator.cs | 8 +++++- .../DefaultInterfaceMethodsTests.cs | 28 ++++++++++++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/tools/generator/CodeGenerator.cs b/tools/generator/CodeGenerator.cs index 575762467..65b795f60 100644 --- a/tools/generator/CodeGenerator.cs +++ b/tools/generator/CodeGenerator.cs @@ -66,7 +66,7 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve UseShortFileNames = options.UseShortFileNames, ProductVersion = options.ProductVersion, SupportInterfaceConstants = options.SupportInterfaceConstants, - SupportDefaultInterfaceMethods = options.SupportDefaultInterfaceMethods + SupportDefaultInterfaceMethods = options.SupportDefaultInterfaceMethods, }; // Load reference libraries diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs index 9c45e1c5a..28455650b 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs @@ -1360,11 +1360,17 @@ public void WriteMethod (Method method, string indent, GenBase type, bool genera var is_explicit = opt.SupportDefaultInterfaceMethods && type is InterfaceGen && method.OverriddenInterfaceMethod != null; var virt_ov = is_explicit ? string.Empty : method.IsOverride ? (opt.SupportDefaultInterfaceMethods && method.OverriddenInterfaceMethod != null ? " virtual" : " override") : method.IsVirtual ? " virtual" : string.Empty; + string seal = method.IsOverride && method.IsFinal ? " sealed" : null; + + // When using DIM, don't generate "virtual sealed" methods, remove both modifiers instead + if (opt.SupportDefaultInterfaceMethods && method.OverriddenInterfaceMethod != null && virt_ov == " virtual" && seal == " sealed") { + virt_ov = string.Empty; + seal = string.Empty; + } if ((string.IsNullOrEmpty (virt_ov) || virt_ov == " virtual") && type.RequiresNew (method.AdjustedName)) { virt_ov = " new" + virt_ov; } - string seal = method.IsOverride && method.IsFinal ? " sealed" : null; string ret = opt.GetOutputName (method.RetVal.FullName); WriteMethodIdField (method, indent); if (method.DeclaringType.IsGeneratable) diff --git a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs index 29491c767..3c09ffcaa 100644 --- a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs +++ b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs @@ -57,7 +57,7 @@ public void WriteInterfaceRedeclaredDefaultMethod () iface.Methods.Add (new TestMethod (iface, "DoSomething").SetDefaultInterfaceMethod ()); options.SymbolTable.AddType (iface); - // Create a second interface that inerhits the first, declaring the method as not default + // Create a second interface that inherits the first, declaring the method as not default var iface2 = SupportTypeBuilder.CreateEmptyInterface ("java.code.IMyInterface2"); iface2.AddImplementedInterface ("java.code.IMyInterface"); iface2.Methods.Add (new TestMethod (iface, "DoSomething")); @@ -108,5 +108,31 @@ public void WriteInterfaceDefaultPropertyGetterOnly () Assert.AreEqual (GetTargetedExpected (nameof (WriteInterfaceDefaultPropertyGetterOnly)), writer.ToString ().NormalizeLineEndings ()); } + + [Test] + public void WriteSealedOverriddenDefaultMethod () + { + // Create an interface with a default method + var iface = SupportTypeBuilder.CreateEmptyInterface ("java.code.IMyInterface"); + iface.Methods.Add (new TestMethod (iface, "DoSomething").SetDefaultInterfaceMethod ()); + options.SymbolTable.AddType (iface); + + // Create a type that inherits the interface, overriding the method as final + var klass = new TestClass ("java.code.IMyInterface", "java.code.MyClass"); + klass.AddImplementedInterface ("java.code.IMyInterface"); + klass.Methods.Add (new TestMethod (iface, "DoSomething").SetFinal ()); + + iface.Validate (options, new GenericParameterDefinitionList (), generator.Context); + klass.Validate (options, new GenericParameterDefinitionList (), generator.Context); + + klass.FixupMethodOverrides (options); + + generator.Context.ContextTypes.Push (klass); + generator.WriteClass (klass, string.Empty, new GenerationInfo (string.Empty, string.Empty, "MyAssembly")); + generator.Context.ContextTypes.Pop (); + + // The method should not be marked as 'virtual sealed' + Assert.False (writer.ToString ().Contains ("virtual sealed")); + } } } From aa28dc2a6c11a4911f0045e7d9664d3d07ec2f28 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Wed, 14 Aug 2019 14:44:48 -0500 Subject: [PATCH 04/10] [generator] DIM connectors are located on the interface, not the implementing type. --- .../CodeGenerator.cs | 10 +++++----- .../Java.Interop.Tools.Generator.ObjectModel/Method.cs | 3 +++ .../Common/WriteInterfaceRedeclaredDefaultMethod.txt | 2 +- .../JavaInterop1/WriteInterfaceDefaultMethod.txt | 2 +- .../JavaInterop1/WriteInterfaceDefaultProperty.txt | 4 ++-- .../WriteInterfaceDefaultPropertyGetterOnly.txt | 2 +- .../XAJavaInterop1/WriteInterfaceDefaultMethod.txt | 2 +- .../XAJavaInterop1/WriteInterfaceDefaultProperty.txt | 4 ++-- .../WriteInterfaceDefaultPropertyGetterOnly.txt | 2 +- .../XamarinAndroid/WriteInterfaceDefaultMethod.txt | 2 +- .../XamarinAndroid/WriteInterfaceDefaultProperty.txt | 4 ++-- .../WriteInterfaceDefaultPropertyGetterOnly.txt | 2 +- .../Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs | 1 + 13 files changed, 22 insertions(+), 18 deletions(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs index 28455650b..d973ad6ed 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs @@ -1380,7 +1380,7 @@ public void WriteMethod (Method method, string indent, GenBase type, bool genera if (method.IsReturnEnumified) writer.WriteLine ("{0}[return:global::Android.Runtime.GeneratedEnum]", indent); writer.WriteLine ("{0}[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", - indent, method.JavaName, method.JniSignature, method.IsVirtual ? method.ConnectorName : String.Empty, method.AdditionalAttributeString ()); + indent, method.JavaName, method.JniSignature, method.IsVirtual ? method.GetConnectorNameFull (opt) : String.Empty, method.AdditionalAttributeString ()); WriteMethodCustomAttributes (method, indent); var visibility = type is InterfaceGen && !method.IsStatic ? string.Empty : method.Visibility; @@ -1490,7 +1490,7 @@ public void WriteProperty (Property property, GenBase gen, string indent, bool w writer.WriteLine ("{0}{1}{2} unsafe {3} {4} {{", indent, visibility, virtual_override, opt.GetOutputName (property.Getter.ReturnType), decl_name); if (gen.IsGeneratable) writer.WriteLine ("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.MetadataXPathReference, property.Getter.JavaName, property.Getter.Parameters.GetMethodXPathPredicate ()); - writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, property.Getter.JavaName, property.Getter.JniSignature, property.Getter.ConnectorName, property.Getter.AdditionalAttributeString ()); + writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, property.Getter.JavaName, property.Getter.JniSignature, property.Getter.GetConnectorNameFull (opt), property.Getter.AdditionalAttributeString ()); writer.WriteLine ("{0}\tget {{", indent); WriteMethodBody (property.Getter, indent + "\t\t", gen); writer.WriteLine ("{0}\t}}", indent); @@ -1498,7 +1498,7 @@ public void WriteProperty (Property property, GenBase gen, string indent, bool w if (gen.IsGeneratable) writer.WriteLine ("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.MetadataXPathReference, property.Setter.JavaName, property.Setter.Parameters.GetMethodXPathPredicate ()); WriteMethodCustomAttributes (property.Setter, indent); - writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, property.Setter.JavaName, property.Setter.JniSignature, property.Setter.ConnectorName, property.Setter.AdditionalAttributeString ()); + writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, property.Setter.JavaName, property.Setter.JniSignature, property.Setter.GetConnectorNameFull (opt), property.Setter.AdditionalAttributeString ()); writer.WriteLine ("{0}\tset {{", indent); string pname = property.Setter.Parameters [0].Name; property.Setter.Parameters [0].Name = "value"; @@ -1548,12 +1548,12 @@ public void WritePropertyAbstractDeclaration (Property property, string indent, if (property.Getter.IsReturnEnumified) writer.WriteLine ("{0}[return:global::Android.Runtime.GeneratedEnum]", indent); WriteMethodCustomAttributes (property.Getter, indent); - writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})] get;", indent, property.Getter.JavaName, property.Getter.JniSignature, property.Getter.ConnectorName, property.Getter.AdditionalAttributeString ()); + writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})] get;", indent, property.Getter.JavaName, property.Getter.JniSignature, property.Getter.GetConnectorNameFull (opt), property.Getter.AdditionalAttributeString ()); if (property.Setter != null) { if (gen.IsGeneratable) writer.WriteLine ("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.MetadataXPathReference, property.Setter.JavaName, property.Setter.Parameters.GetMethodXPathPredicate ()); WriteMethodCustomAttributes (property.Setter, indent); - writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})] set;", indent, property.Setter.JavaName, property.Setter.JniSignature, property.Setter.ConnectorName, property.Setter.AdditionalAttributeString ()); + writer.WriteLine ("{0}\t[Register (\"{1}\", \"{2}\", \"{3}\"{4})] set;", indent, property.Setter.JavaName, property.Setter.JniSignature, property.Setter.GetConnectorNameFull (opt), property.Setter.AdditionalAttributeString ()); } writer.WriteLine ("{0}}}", indent); writer.WriteLine (); diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs index d3c0882ea..9c37eae99 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs @@ -122,6 +122,9 @@ internal string GetAdapterName (CodeGenerationOptions opt, string adapter) return adapter + AssemblyName; } + // Connectors for DIM are defined on the interface, not the implementing type + public string GetConnectorNameFull (CodeGenerationOptions opt) => ConnectorName + (opt.SupportDefaultInterfaceMethods && IsInterfaceDefaultMethod ? $":{DeclaringType.FullName}, " + (AssemblyName ?? opt.AssemblyName) : string.Empty); + internal string GetDelegateType () { var parms = Parameters.DelegateTypeParams; diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/Common/WriteInterfaceRedeclaredDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/Common/WriteInterfaceRedeclaredDefaultMethod.txt index ce320dde0..5b678cfd5 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/Common/WriteInterfaceRedeclaredDefaultMethod.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/Common/WriteInterfaceRedeclaredDefaultMethod.txt @@ -3,7 +3,7 @@ public partial interface IMyInterface2 : java.code.IMyInterface { // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" - [Register ("DoSomething", "()V", "GetDoSomethingHandler:java.code.IMyInterface2Invoker, ")] + [Register ("DoSomething", "()V", "GetDoSomethingHandler:java.code.IMyInterface2Invoker, MyAssembly")] void DoSomething (); } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt index ca8045b7b..76d7bb75e 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt @@ -20,7 +20,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { #pragma warning restore 0169 // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" - [Register ("DoSomething", "()V", "GetDoSomethingHandler")] + [Register ("DoSomething", "()V", "GetDoSomethingHandler:java.code.IMyInterface, MyAssembly")] virtual unsafe void DoSomething () { const string __id = "DoSomething.()V"; diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt index 1fdc9f8ff..d0cfd31a0 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt @@ -37,7 +37,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { virtual unsafe int Value { // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" - [Register ("get_Value", "()I", "Getget_ValueHandler")] + [Register ("get_Value", "()I", "Getget_ValueHandler:java.code.IMyInterface, MyAssembly")] get { const string __id = "get_Value.()I"; try { @@ -47,7 +47,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { } } // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='set_Value' and count(parameter)=1 and parameter[1][@type='int']]" - [Register ("set_Value", "(I)V", "Getset_Value_IHandler")] + [Register ("set_Value", "(I)V", "Getset_Value_IHandler:java.code.IMyInterface, MyAssembly")] set { const string __id = "set_Value.(I)V"; try { diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt index 5eaf59a90..659ae5c29 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -21,7 +21,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { virtual unsafe int Value { // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" - [Register ("get_Value", "()I", "Getget_ValueHandler")] + [Register ("get_Value", "()I", "Getget_ValueHandler:java.code.IMyInterface, MyAssembly")] get { const string __id = "get_Value.()I"; try { diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt index 81084c7b6..6590a6415 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt @@ -20,7 +20,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { #pragma warning restore 0169 // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" - [Register ("DoSomething", "()V", "GetDoSomethingHandler")] + [Register ("DoSomething", "()V", "GetDoSomethingHandler:java.code.IMyInterface, MyAssembly")] virtual unsafe void DoSomething () { const string __id = "DoSomething.()V"; diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt index 258fa7b04..6aa83b629 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt @@ -37,7 +37,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { virtual unsafe int Value { // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" - [Register ("get_Value", "()I", "Getget_ValueHandler")] + [Register ("get_Value", "()I", "Getget_ValueHandler:java.code.IMyInterface, MyAssembly")] get { const string __id = "get_Value.()I"; try { @@ -47,7 +47,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { } } // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='set_Value' and count(parameter)=1 and parameter[1][@type='int']]" - [Register ("set_Value", "(I)V", "Getset_Value_IHandler")] + [Register ("set_Value", "(I)V", "Getset_Value_IHandler:java.code.IMyInterface, MyAssembly")] set { const string __id = "set_Value.(I)V"; try { diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt index 317e073c5..fe8f44e3a 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -21,7 +21,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { virtual unsafe int Value { // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" - [Register ("get_Value", "()I", "Getget_ValueHandler")] + [Register ("get_Value", "()I", "Getget_ValueHandler:java.code.IMyInterface, MyAssembly")] get { const string __id = "get_Value.()I"; try { diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt index b282c8612..7449f1cc4 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt @@ -21,7 +21,7 @@ public partial interface IMyInterface : IJavaObject { static IntPtr id_DoSomething; // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" - [Register ("DoSomething", "()V", "GetDoSomethingHandler")] + [Register ("DoSomething", "()V", "GetDoSomethingHandler:java.code.IMyInterface, MyAssembly")] virtual unsafe void DoSomething () { if (id_DoSomething == IntPtr.Zero) diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt index 64b5a05a4..3d117c626 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt @@ -39,7 +39,7 @@ public partial interface IMyInterface : IJavaObject { static IntPtr id_set_Value_I; virtual unsafe int Value { // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" - [Register ("get_Value", "()I", "Getget_ValueHandler")] + [Register ("get_Value", "()I", "Getget_ValueHandler:java.code.IMyInterface, MyAssembly")] get { if (id_get_Value == IntPtr.Zero) id_get_Value = JNIEnv.GetMethodID (class_ref, "get_Value", "()I"); @@ -53,7 +53,7 @@ public partial interface IMyInterface : IJavaObject { } } // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='set_Value' and count(parameter)=1 and parameter[1][@type='int']]" - [Register ("set_Value", "(I)V", "Getset_Value_IHandler")] + [Register ("set_Value", "(I)V", "Getset_Value_IHandler:java.code.IMyInterface, MyAssembly")] set { if (id_set_Value_I == IntPtr.Zero) id_set_Value_I = JNIEnv.GetMethodID (class_ref, "set_Value", "(I)V"); diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt index d07d58d61..4fe69e7ae 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -22,7 +22,7 @@ public partial interface IMyInterface : IJavaObject { static IntPtr id_get_Value; virtual unsafe int Value { // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" - [Register ("get_Value", "()I", "Getget_ValueHandler")] + [Register ("get_Value", "()I", "Getget_ValueHandler:java.code.IMyInterface, MyAssembly")] get { if (id_get_Value == IntPtr.Zero) id_get_Value = JNIEnv.GetMethodID (class_ref, "get_Value", "()I"); diff --git a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs index 3c09ffcaa..2399ca156 100644 --- a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs +++ b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs @@ -29,6 +29,7 @@ protected override CodeGenerationOptions CreateOptions () { var options = base.CreateOptions (); + options.AssemblyName = "MyAssembly"; options.SupportDefaultInterfaceMethods = true; return options; From a72ce30af704303547e7be15438d57e49b885d59 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 22 Aug 2019 09:47:16 -0500 Subject: [PATCH 05/10] [generator] Prohibit DIM use with codegen-target=XamarinAndroid . --- tools/generator/CodeGeneratorOptions.cs | 5 ++ .../WriteInterfaceDefaultMethod.txt | 40 ---------- .../WriteInterfaceDefaultProperty.txt | 74 ------------------- ...riteInterfaceDefaultPropertyGetterOnly.txt | 41 ---------- .../DefaultInterfaceMethodsTests.cs | 6 -- tools/generator/Tests/generator-Tests.csproj | 9 --- tools/generator/Utilities/Report.cs | 1 + 7 files changed, 6 insertions(+), 170 deletions(-) delete mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt delete mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt delete mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt diff --git a/tools/generator/CodeGeneratorOptions.cs b/tools/generator/CodeGeneratorOptions.cs index b17e2dbd3..ae78d0557 100644 --- a/tools/generator/CodeGeneratorOptions.cs +++ b/tools/generator/CodeGeneratorOptions.cs @@ -161,6 +161,11 @@ public static CodeGeneratorOptions Parse (string[] args) opts.ApiDescriptionFile = apis [0]; + if (opts.SupportDefaultInterfaceMethods && opts.CodeGenerationTarget == CodeGenerationTarget.XamarinAndroid) { + Console.Error.WriteLine (Report.Format (true, Report.ErrorInvalidArgument, "lang-features=default-interface-methods is not compatible with codegen-target=xamarinandroid.")); + return null; + } + return opts; } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt deleted file mode 100644 index 7449f1cc4..000000000 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultMethod.txt +++ /dev/null @@ -1,40 +0,0 @@ -// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" -[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] -public partial interface IMyInterface : IJavaObject { - new static IntPtr class_ref = JNIEnv.FindClass ("java/code/IMyInterface"); - - static Delegate cb_DoSomething; -#pragma warning disable 0169 - static Delegate GetDoSomethingHandler () - { - if (cb_DoSomething == null) - cb_DoSomething = JNINativeWrapper.CreateDelegate ((Action) n_DoSomething); - return cb_DoSomething; - } - - static void n_DoSomething (IntPtr jnienv, IntPtr native__this) - { - java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); - __this.DoSomething (); - } -#pragma warning restore 0169 - - static IntPtr id_DoSomething; - // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='DoSomething' and count(parameter)=0]" - [Register ("DoSomething", "()V", "GetDoSomethingHandler:java.code.IMyInterface, MyAssembly")] - virtual unsafe void DoSomething () - { - if (id_DoSomething == IntPtr.Zero) - id_DoSomething = JNIEnv.GetMethodID (class_ref, "DoSomething", "()V"); - try { - - if (((object) this).GetType () == ThresholdType) - JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_DoSomething); - else - JNIEnv.CallNonvirtualVoidMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "DoSomething", "()V")); - } finally { - } - } - -} - diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt deleted file mode 100644 index 3d117c626..000000000 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultProperty.txt +++ /dev/null @@ -1,74 +0,0 @@ -// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" -[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] -public partial interface IMyInterface : IJavaObject { - new static IntPtr class_ref = JNIEnv.FindClass ("java/code/IMyInterface"); - - static Delegate cb_get_Value; -#pragma warning disable 0169 - static Delegate Getget_ValueHandler () - { - if (cb_get_Value == null) - cb_get_Value = JNINativeWrapper.CreateDelegate ((Func) n_get_Value); - return cb_get_Value; - } - - static int n_get_Value (IntPtr jnienv, IntPtr native__this) - { - java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); - return __this.Value; - } -#pragma warning restore 0169 - - static Delegate cb_set_Value_I; -#pragma warning disable 0169 - static Delegate Getset_Value_IHandler () - { - if (cb_set_Value_I == null) - cb_set_Value_I = JNINativeWrapper.CreateDelegate ((Action) n_set_Value_I); - return cb_set_Value_I; - } - - static void n_set_Value_I (IntPtr jnienv, IntPtr native__this, int value) - { - java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); - __this.Value = value; - } -#pragma warning restore 0169 - - static IntPtr id_get_Value; - static IntPtr id_set_Value_I; - virtual unsafe int Value { - // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" - [Register ("get_Value", "()I", "Getget_ValueHandler:java.code.IMyInterface, MyAssembly")] - get { - if (id_get_Value == IntPtr.Zero) - id_get_Value = JNIEnv.GetMethodID (class_ref, "get_Value", "()I"); - try { - - if (((object) this).GetType () == ThresholdType) - return JNIEnv.CallIntMethod (((global::Java.Lang.Object) this).Handle, id_get_Value); - else - return JNIEnv.CallNonvirtualIntMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "get_Value", "()I")); - } finally { - } - } - // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='set_Value' and count(parameter)=1 and parameter[1][@type='int']]" - [Register ("set_Value", "(I)V", "Getset_Value_IHandler:java.code.IMyInterface, MyAssembly")] - set { - if (id_set_Value_I == IntPtr.Zero) - id_set_Value_I = JNIEnv.GetMethodID (class_ref, "set_Value", "(I)V"); - try { - JValue* __args = stackalloc JValue [1]; - __args [0] = new JValue (value); - - if (((object) this).GetType () == ThresholdType) - JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_set_Value_I, __args); - else - JNIEnv.CallNonvirtualVoidMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "set_Value", "(I)V"), __args); - } finally { - } - } - } - -} - diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt deleted file mode 100644 index 4fe69e7ae..000000000 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XamarinAndroid/WriteInterfaceDefaultPropertyGetterOnly.txt +++ /dev/null @@ -1,41 +0,0 @@ -// Metadata.xml XPath interface reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']" -[Register ("java/code/IMyInterface", "", "java.code.IMyInterfaceInvoker")] -public partial interface IMyInterface : IJavaObject { - new static IntPtr class_ref = JNIEnv.FindClass ("java/code/IMyInterface"); - - static Delegate cb_get_Value; -#pragma warning disable 0169 - static Delegate Getget_ValueHandler () - { - if (cb_get_Value == null) - cb_get_Value = JNINativeWrapper.CreateDelegate ((Func) n_get_Value); - return cb_get_Value; - } - - static int n_get_Value (IntPtr jnienv, IntPtr native__this) - { - java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); - return __this.Value; - } -#pragma warning restore 0169 - - static IntPtr id_get_Value; - virtual unsafe int Value { - // Metadata.xml XPath method reference: path="/api/package[@name='java.code']/interface[@name='IMyInterface']/method[@name='get_Value' and count(parameter)=0]" - [Register ("get_Value", "()I", "Getget_ValueHandler:java.code.IMyInterface, MyAssembly")] - get { - if (id_get_Value == IntPtr.Zero) - id_get_Value = JNIEnv.GetMethodID (class_ref, "get_Value", "()I"); - try { - - if (((object) this).GetType () == ThresholdType) - return JNIEnv.CallIntMethod (((global::Java.Lang.Object) this).Handle, id_get_Value); - else - return JNIEnv.CallNonvirtualIntMethod (((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID (ThresholdClass, "get_Value", "()I")); - } finally { - } - } - } - -} - diff --git a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs index 2399ca156..9ea887508 100644 --- a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs +++ b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs @@ -17,12 +17,6 @@ class XAJavaInteropDefaultInterfaceMethodsTests : DefaultInterfaceMethodsTests protected override CodeGenerationTarget Target => CodeGenerationTarget.XAJavaInterop1; } - [TestFixture] - class XamarinAndroidDefaultInterfaceMethodsTests : DefaultInterfaceMethodsTests - { - protected override CodeGenerationTarget Target => CodeGenerationTarget.XamarinAndroid; - } - abstract class DefaultInterfaceMethodsTests : CodeGeneratorTestBase { protected override CodeGenerationOptions CreateOptions () diff --git a/tools/generator/Tests/generator-Tests.csproj b/tools/generator/Tests/generator-Tests.csproj index 6a24b292f..a82c510ab 100644 --- a/tools/generator/Tests/generator-Tests.csproj +++ b/tools/generator/Tests/generator-Tests.csproj @@ -556,15 +556,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - PreserveNewest diff --git a/tools/generator/Utilities/Report.cs b/tools/generator/Utilities/Report.cs index 0db1bbd17..4561f043c 100644 --- a/tools/generator/Utilities/Report.cs +++ b/tools/generator/Utilities/Report.cs @@ -13,6 +13,7 @@ public class Report public const int ErrorParser = 0x4200; public const int ErrorApiFixup = 0x4300; public const int ErrorCodeGenerator = 0x4400; + public const int ErrorInvalidArgument = 0x4500; public const int WarningClassGen = 0x8100; public const int WarningCodeGenerator = 0x8200; public const int WarningCtor = 0x8300; From 12cc41b2daa9298095bbfbb36cfcbe415f7169d1 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 22 Aug 2019 10:21:16 -0500 Subject: [PATCH 06/10] [generator] Add a unit test for interface invoker with DIM. --- .../WriteDefaultInterfaceMethodInvoker.txt | 77 +++++++++++++++++++ .../WriteDefaultInterfaceMethodInvoker.txt | 77 +++++++++++++++++++ .../DefaultInterfaceMethodsTests.cs | 19 +++++ tools/generator/Tests/generator-Tests.csproj | 6 ++ 4 files changed, 179 insertions(+) create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteDefaultInterfaceMethodInvoker.txt create mode 100644 tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteDefaultInterfaceMethodInvoker.txt diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteDefaultInterfaceMethodInvoker.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteDefaultInterfaceMethodInvoker.txt new file mode 100644 index 000000000..98f44e7f2 --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteDefaultInterfaceMethodInvoker.txt @@ -0,0 +1,77 @@ +[global::Android.Runtime.Register ("java/code/IMyInterface", DoNotGenerateAcw=true)] +internal partial class IMyInterfaceInvoker : global::Java.Lang.Object, IMyInterface { + + internal static new readonly JniPeerMembers _members = new JniPeerMembers ("java/code/IMyInterface", typeof (IMyInterfaceInvoker)); + + static IntPtr java_class_ref { + get { return _members.JniPeerType.PeerReference.Handle; } + } + + public override global::Java.Interop.JniPeerMembers JniPeerMembers { + get { return _members; } + } + + protected override IntPtr ThresholdClass { + get { return class_ref; } + } + + protected override global::System.Type ThresholdType { + get { return _members.ManagedPeerType; } + } + + IntPtr class_ref; + + public static IMyInterface GetObject (IntPtr handle, JniHandleOwnership transfer) + { + return global::Java.Lang.Object.GetObject (handle, transfer); + } + + static IntPtr Validate (IntPtr handle) + { + if (!JNIEnv.IsInstanceOf (handle, java_class_ref)) + throw new InvalidCastException (string.Format ("Unable to convert instance of type '{0}' to type '{1}'.", + JNIEnv.GetClassNameFromInstance (handle), "java.code.IMyInterface")); + return handle; + } + + protected override void Dispose (bool disposing) + { + if (this.class_ref != IntPtr.Zero) + JNIEnv.DeleteGlobalRef (this.class_ref); + this.class_ref = IntPtr.Zero; + base.Dispose (disposing); + } + + public IMyInterfaceInvoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer) + { + IntPtr local_ref = JNIEnv.GetObjectClass (((global::Java.Lang.Object) this).Handle); + this.class_ref = JNIEnv.NewGlobalRef (local_ref); + JNIEnv.DeleteLocalRef (local_ref); + } + + static Delegate cb_DoDeclaration; +#pragma warning disable 0169 + static Delegate GetDoDeclarationHandler () + { + if (cb_DoDeclaration == null) + cb_DoDeclaration = JNINativeWrapper.CreateDelegate ((Action) n_DoDeclaration); + return cb_DoDeclaration; + } + + static void n_DoDeclaration (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.DoDeclaration (); + } +#pragma warning restore 0169 + + IntPtr id_DoDeclaration; + public unsafe void DoDeclaration () + { + if (id_DoDeclaration == IntPtr.Zero) + id_DoDeclaration = JNIEnv.GetMethodID (class_ref, "DoDeclaration", "()V"); + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_DoDeclaration); + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteDefaultInterfaceMethodInvoker.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteDefaultInterfaceMethodInvoker.txt new file mode 100644 index 000000000..550d22615 --- /dev/null +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteDefaultInterfaceMethodInvoker.txt @@ -0,0 +1,77 @@ +[global::Android.Runtime.Register ("java/code/IMyInterface", DoNotGenerateAcw=true)] +internal partial class IMyInterfaceInvoker : global::Java.Lang.Object, IMyInterface { + + internal static new readonly JniPeerMembers _members = new XAPeerMembers ("java/code/IMyInterface", typeof (IMyInterfaceInvoker)); + + static IntPtr java_class_ref { + get { return _members.JniPeerType.PeerReference.Handle; } + } + + public override global::Java.Interop.JniPeerMembers JniPeerMembers { + get { return _members; } + } + + protected override IntPtr ThresholdClass { + get { return class_ref; } + } + + protected override global::System.Type ThresholdType { + get { return _members.ManagedPeerType; } + } + + IntPtr class_ref; + + public static IMyInterface GetObject (IntPtr handle, JniHandleOwnership transfer) + { + return global::Java.Lang.Object.GetObject (handle, transfer); + } + + static IntPtr Validate (IntPtr handle) + { + if (!JNIEnv.IsInstanceOf (handle, java_class_ref)) + throw new InvalidCastException (string.Format ("Unable to convert instance of type '{0}' to type '{1}'.", + JNIEnv.GetClassNameFromInstance (handle), "java.code.IMyInterface")); + return handle; + } + + protected override void Dispose (bool disposing) + { + if (this.class_ref != IntPtr.Zero) + JNIEnv.DeleteGlobalRef (this.class_ref); + this.class_ref = IntPtr.Zero; + base.Dispose (disposing); + } + + public IMyInterfaceInvoker (IntPtr handle, JniHandleOwnership transfer) : base (Validate (handle), transfer) + { + IntPtr local_ref = JNIEnv.GetObjectClass (((global::Java.Lang.Object) this).Handle); + this.class_ref = JNIEnv.NewGlobalRef (local_ref); + JNIEnv.DeleteLocalRef (local_ref); + } + + static Delegate cb_DoDeclaration; +#pragma warning disable 0169 + static Delegate GetDoDeclarationHandler () + { + if (cb_DoDeclaration == null) + cb_DoDeclaration = JNINativeWrapper.CreateDelegate ((Action) n_DoDeclaration); + return cb_DoDeclaration; + } + + static void n_DoDeclaration (IntPtr jnienv, IntPtr native__this) + { + java.code.IMyInterface __this = global::Java.Lang.Object.GetObject (jnienv, native__this, JniHandleOwnership.DoNotTransfer); + __this.DoDeclaration (); + } +#pragma warning restore 0169 + + IntPtr id_DoDeclaration; + public unsafe void DoDeclaration () + { + if (id_DoDeclaration == IntPtr.Zero) + id_DoDeclaration = JNIEnv.GetMethodID (class_ref, "DoDeclaration", "()V"); + JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_DoDeclaration); + } + +} + diff --git a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs index 9ea887508..a4189194b 100644 --- a/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs +++ b/tools/generator/Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs @@ -104,6 +104,25 @@ public void WriteInterfaceDefaultPropertyGetterOnly () Assert.AreEqual (GetTargetedExpected (nameof (WriteInterfaceDefaultPropertyGetterOnly)), writer.ToString ().NormalizeLineEndings ()); } + + [Test] + public void WriteDefaultInterfaceMethodInvoker () + { + // Create an interface with a default method + var iface = SupportTypeBuilder.CreateEmptyInterface ("java.code.IMyInterface"); + + iface.Methods.Add (new TestMethod (iface, "DoDeclaration")); + iface.Methods.Add (new TestMethod (iface, "DoDefault").SetDefaultInterfaceMethod ()); + + iface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()); + + generator.Context.ContextTypes.Push (iface); + generator.WriteInterfaceInvoker (iface, string.Empty); + generator.Context.ContextTypes.Pop (); + + Assert.AreEqual (GetTargetedExpected (nameof (WriteDefaultInterfaceMethodInvoker)), writer.ToString ().NormalizeLineEndings ()); + } + [Test] public void WriteSealedOverriddenDefaultMethod () { diff --git a/tools/generator/Tests/generator-Tests.csproj b/tools/generator/Tests/generator-Tests.csproj index a82c510ab..a46c7f2c4 100644 --- a/tools/generator/Tests/generator-Tests.csproj +++ b/tools/generator/Tests/generator-Tests.csproj @@ -220,6 +220,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -337,6 +340,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 26d3bb221855f50f2efc013ea1e31f85a12901ab Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 22 Aug 2019 11:11:29 -0500 Subject: [PATCH 07/10] [generator] Call DIM methods as Virtual rather than Nonvirtual. --- .../JavaInteropCodeGenerator.cs | 4 ++-- .../JavaInterop1/WriteInterfaceDefaultMethod.txt | 2 +- .../JavaInterop1/WriteInterfaceDefaultProperty.txt | 4 ++-- .../JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt | 2 +- .../XAJavaInterop1/WriteInterfaceDefaultMethod.txt | 2 +- .../XAJavaInterop1/WriteInterfaceDefaultProperty.txt | 4 ++-- .../WriteInterfaceDefaultPropertyGetterOnly.txt | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs index ef36a32f7..425bdd8b2 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs @@ -157,12 +157,12 @@ internal override void WriteMethodBody (Method method, string indent, GenBase ty writer.WriteLine ("_members.StaticMethods.Invoke{0}Method (__id{1});", invokeType, method.Parameters.GetCallArgs (opt, invoker: false)); - } else if (method.IsFinal || method.IsInterfaceDefaultMethod) { + } else if (method.IsFinal) { writer.WriteLine ("_members.InstanceMethods.InvokeNonvirtual{0}Method (__id, {1}this{2});", invokeType, castToPeerable, method.Parameters.GetCallArgs (opt, invoker: false)); - } else if (method.IsVirtual && !method.IsAbstract) { + } else if ((method.IsVirtual && !method.IsAbstract) || method.IsInterfaceDefaultMethod) { writer.WriteLine ("_members.InstanceMethods.InvokeVirtual{0}Method (__id, {1}this{2});", invokeType, castToPeerable, diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt index 76d7bb75e..cbbe17d47 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt @@ -25,7 +25,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { { const string __id = "DoSomething.()V"; try { - _members.InstanceMethods.InvokeNonvirtualVoidMethod (__id, (IJavaPeerable) this, null); + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, (IJavaPeerable) this, null); } finally { } } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt index d0cfd31a0..aa4c094c5 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt @@ -41,7 +41,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { get { const string __id = "get_Value.()I"; try { - var __rm = _members.InstanceMethods.InvokeNonvirtualInt32Method (__id, (IJavaPeerable) this, null); + var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, (IJavaPeerable) this, null); return __rm; } finally { } @@ -53,7 +53,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { try { JniArgumentValue* __args = stackalloc JniArgumentValue [1]; __args [0] = new JniArgumentValue (value); - _members.InstanceMethods.InvokeNonvirtualVoidMethod (__id, (IJavaPeerable) this, __args); + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, (IJavaPeerable) this, __args); } finally { } } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt index 659ae5c29..24d30d5d7 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -25,7 +25,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { get { const string __id = "get_Value.()I"; try { - var __rm = _members.InstanceMethods.InvokeNonvirtualInt32Method (__id, (IJavaPeerable) this, null); + var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, (IJavaPeerable) this, null); return __rm; } finally { } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt index 6590a6415..f37164561 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt @@ -25,7 +25,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { { const string __id = "DoSomething.()V"; try { - _members.InstanceMethods.InvokeNonvirtualVoidMethod (__id, (IJavaPeerable) this, null); + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, (IJavaPeerable) this, null); } finally { } } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt index 6aa83b629..962fa189d 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt @@ -41,7 +41,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { get { const string __id = "get_Value.()I"; try { - var __rm = _members.InstanceMethods.InvokeNonvirtualInt32Method (__id, (IJavaPeerable) this, null); + var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, (IJavaPeerable) this, null); return __rm; } finally { } @@ -53,7 +53,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { try { JniArgumentValue* __args = stackalloc JniArgumentValue [1]; __args [0] = new JniArgumentValue (value); - _members.InstanceMethods.InvokeNonvirtualVoidMethod (__id, (IJavaPeerable) this, __args); + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, (IJavaPeerable) this, __args); } finally { } } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt index fe8f44e3a..23e3be7e2 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -25,7 +25,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { get { const string __id = "get_Value.()I"; try { - var __rm = _members.InstanceMethods.InvokeNonvirtualInt32Method (__id, (IJavaPeerable) this, null); + var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, (IJavaPeerable) this, null); return __rm; } finally { } From c97112286125209e2c5fecee920a619e9f81b4c1 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Fri, 23 Aug 2019 10:58:38 -0500 Subject: [PATCH 08/10] [generator] Remove old refactored property generation code. --- .../CodeGenerator.cs | 21 +------------------ .../Tests/Unit-Tests/CodeGeneratorTests.cs | 2 +- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs index d973ad6ed..614490f7c 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs @@ -310,25 +310,7 @@ public void WriteClassMethods (ClassGen @class, string indent) } } - public void WriteClassProperties (ClassGen @class, string indent) - { - foreach (Property prop in @class.Properties) { - bool get_virt = prop.Getter.IsVirtual; - bool set_virt = prop.Setter == null ? false : prop.Setter.IsVirtual; - prop.Getter.IsVirtual = !@class.IsFinal && get_virt; - if (prop.Setter != null) - prop.Setter.IsVirtual = !@class.IsFinal && set_virt; - if (prop.Getter.IsAbstract) - WritePropertyAbstractDeclaration (prop, indent, @class); - else - WriteProperty (prop, @class, indent); - prop.Getter.IsVirtual = get_virt; - if (prop.Setter != null) - prop.Setter.IsVirtual = set_virt; - } - } - - protected void WriteImplementedProperties (IEnumerable targetProperties, string indent, bool isFinal, GenBase gen) + public void WriteImplementedProperties (IEnumerable targetProperties, string indent, bool isFinal, GenBase gen) { foreach (var prop in targetProperties) { bool get_virt = prop.Getter.IsVirtual; @@ -346,7 +328,6 @@ protected void WriteImplementedProperties (IEnumerable targetPropertie } } - public void WriteClassPropertyInvokers (ClassGen @class, IEnumerable properties, string indent, HashSet members) { foreach (Property prop in properties) { diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorTests.cs b/tools/generator/Tests/Unit-Tests/CodeGeneratorTests.cs index 03c957321..2f405b876 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorTests.cs +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorTests.cs @@ -163,7 +163,7 @@ public void WriteClassProperties () var @class = SupportTypeBuilder.CreateClass ("java.code.MyClass", options); generator.Context.ContextTypes.Push (@class); - generator.WriteClassProperties (@class, string.Empty); + generator.WriteImplementedProperties (@class.Properties, string.Empty, @class.IsFinal, @class); generator.Context.ContextTypes.Pop (); Assert.AreEqual (GetTargetedExpected (nameof (WriteClassProperties)), writer.ToString ().NormalizeLineEndings ()); From bd8d01985a02a581e00cd87f2b683bfbf5bdfbda Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Fri, 23 Aug 2019 11:11:38 -0500 Subject: [PATCH 09/10] [generator] Remove unneeded DIM check. --- .../CodeGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs index 614490f7c..e36a6a9b0 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs @@ -480,7 +480,7 @@ public void WriteInterface (InterfaceGen @interface, string indent, GenerationIn // For each interface, generate either an abstract method or an explicit implementation method. public void WriteInterfaceAbstractMembers (InterfaceGen @interface, ClassGen gen, string indent) { - foreach (var m in @interface.Methods.Where (m => (!opt.SupportDefaultInterfaceMethods || !m.IsInterfaceDefaultMethod) && !m.IsStatic)) { + foreach (var m in @interface.Methods.Where (m => !m.IsInterfaceDefaultMethod && !m.IsStatic)) { bool mapped = false; string sig = m.GetSignature (); if (Context.ContextGeneratedMethods.Any (_ => _.Name == m.Name && _.JniSignature == m.JniSignature)) @@ -498,7 +498,7 @@ public void WriteInterfaceAbstractMembers (InterfaceGen @interface, ClassGen gen WriteMethodAbstractDeclaration (m, indent, @interface, gen); Context.ContextGeneratedMethods.Add (m); } - foreach (var prop in @interface.Properties.Where (p => (!opt.SupportDefaultInterfaceMethods || !p.Getter.IsInterfaceDefaultMethod) && !p.Getter.IsStatic)) { + foreach (var prop in @interface.Properties.Where (p => !p.Getter.IsInterfaceDefaultMethod && !p.Getter.IsStatic)) { if (gen.ContainsProperty (prop.Name, false)) continue; WritePropertyAbstractDeclaration (prop, indent, gen); From 16def2907fdc73541083bd4560fff4563b37d532 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Fri, 23 Aug 2019 13:56:40 -0500 Subject: [PATCH 10/10] [generator] Remove unncessary IJavaPeerable cast. --- .../JavaInteropCodeGenerator.cs | 11 +++-------- .../JavaInterop1/WriteInterfaceDefaultMethod.txt | 2 +- .../JavaInterop1/WriteInterfaceDefaultProperty.txt | 4 ++-- .../WriteInterfaceDefaultPropertyGetterOnly.txt | 2 +- .../XAJavaInterop1/WriteInterfaceDefaultMethod.txt | 2 +- .../XAJavaInterop1/WriteInterfaceDefaultProperty.txt | 4 ++-- .../WriteInterfaceDefaultPropertyGetterOnly.txt | 2 +- 7 files changed, 11 insertions(+), 16 deletions(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs index 425bdd8b2..3c89671a1 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/JavaInteropCodeGenerator.cs @@ -151,26 +151,21 @@ internal override void WriteMethodBody (Method method, string indent, GenBase ty writer.Write ("var __rm = "); } - var castToPeerable = type is InterfaceGen ? "(IJavaPeerable) " : string.Empty; - if (method.IsStatic) { writer.WriteLine ("_members.StaticMethods.Invoke{0}Method (__id{1});", invokeType, method.Parameters.GetCallArgs (opt, invoker: false)); } else if (method.IsFinal) { - writer.WriteLine ("_members.InstanceMethods.InvokeNonvirtual{0}Method (__id, {1}this{2});", + writer.WriteLine ("_members.InstanceMethods.InvokeNonvirtual{0}Method (__id, this{1});", invokeType, - castToPeerable, method.Parameters.GetCallArgs (opt, invoker: false)); } else if ((method.IsVirtual && !method.IsAbstract) || method.IsInterfaceDefaultMethod) { - writer.WriteLine ("_members.InstanceMethods.InvokeVirtual{0}Method (__id, {1}this{2});", + writer.WriteLine ("_members.InstanceMethods.InvokeVirtual{0}Method (__id, this{1});", invokeType, - castToPeerable, method.Parameters.GetCallArgs (opt, invoker: false)); } else { - writer.WriteLine ("_members.InstanceMethods.InvokeAbstract{0}Method (__id, {1}this{2});", + writer.WriteLine ("_members.InstanceMethods.InvokeAbstract{0}Method (__id, this{1});", invokeType, - castToPeerable, method.Parameters.GetCallArgs (opt, invoker: false)); } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt index cbbe17d47..6eece822a 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultMethod.txt @@ -25,7 +25,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { { const string __id = "DoSomething.()V"; try { - _members.InstanceMethods.InvokeVirtualVoidMethod (__id, (IJavaPeerable) this, null); + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, null); } finally { } } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt index aa4c094c5..0a9514cbf 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultProperty.txt @@ -41,7 +41,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { get { const string __id = "get_Value.()I"; try { - var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, (IJavaPeerable) this, null); + var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, this, null); return __rm; } finally { } @@ -53,7 +53,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { try { JniArgumentValue* __args = stackalloc JniArgumentValue [1]; __args [0] = new JniArgumentValue (value); - _members.InstanceMethods.InvokeVirtualVoidMethod (__id, (IJavaPeerable) this, __args); + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args); } finally { } } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt index 24d30d5d7..6eb8aa760 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -25,7 +25,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { get { const string __id = "get_Value.()I"; try { - var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, (IJavaPeerable) this, null); + var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, this, null); return __rm; } finally { } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt index f37164561..ff77d6c71 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultMethod.txt @@ -25,7 +25,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { { const string __id = "DoSomething.()V"; try { - _members.InstanceMethods.InvokeVirtualVoidMethod (__id, (IJavaPeerable) this, null); + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, null); } finally { } } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt index 962fa189d..a0c56ba92 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultProperty.txt @@ -41,7 +41,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { get { const string __id = "get_Value.()I"; try { - var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, (IJavaPeerable) this, null); + var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, this, null); return __rm; } finally { } @@ -53,7 +53,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { try { JniArgumentValue* __args = stackalloc JniArgumentValue [1]; __args [0] = new JniArgumentValue (value); - _members.InstanceMethods.InvokeVirtualVoidMethod (__id, (IJavaPeerable) this, __args); + _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args); } finally { } } diff --git a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt index 23e3be7e2..a0f879bd5 100644 --- a/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt +++ b/tools/generator/Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1/WriteInterfaceDefaultPropertyGetterOnly.txt @@ -25,7 +25,7 @@ public partial interface IMyInterface : IJavaObject, IJavaPeerable { get { const string __id = "get_Value.()I"; try { - var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, (IJavaPeerable) this, null); + var __rm = _members.InstanceMethods.InvokeVirtualInt32Method (__id, this, null); return __rm; } finally { }