diff --git a/tools/generator/CodeGenerationOptions.cs b/tools/generator/CodeGenerationOptions.cs index 83e7d0ade..c0b7c272b 100644 --- a/tools/generator/CodeGenerationOptions.cs +++ b/tools/generator/CodeGenerationOptions.cs @@ -52,7 +52,7 @@ internal CodeGenerator CreateCodeGenerator (TextWriter writer) bool? buildingCoreAssembly; public bool BuildingCoreAssembly { get { - return buildingCoreAssembly ?? (buildingCoreAssembly = (SymbolTable.Lookup ("java.lang.Object") is XmlClassGen)).Value; + return buildingCoreAssembly ?? (buildingCoreAssembly = (SymbolTable.Lookup ("java.lang.Object") is ClassGen gen && gen.FromXml)).Value; } } diff --git a/tools/generator/CodeGenerator.cs b/tools/generator/CodeGenerator.cs index a5c47bd5a..543609c8e 100644 --- a/tools/generator/CodeGenerator.cs +++ b/tools/generator/CodeGenerator.cs @@ -267,7 +267,7 @@ internal static void ProcessReferencedType (TypeDefinition td, CodeGenerationOpt //Console.Error.WriteLine ("WARNING: " + td.FullName + " survived"); } - ISymbol gb = td.IsEnum ? (ISymbol)new EnumSymbol (td.FullNameCorrected ()) : td.IsInterface ? (ISymbol)new ManagedInterfaceGen (td, opt) : new ManagedClassGen (td, opt); + ISymbol gb = td.IsEnum ? (ISymbol)new EnumSymbol (td.FullNameCorrected ()) : td.IsInterface ? (ISymbol)CecilApiImporter.CreateInterface (td, opt) : CecilApiImporter.CreateClass (td, opt); opt.SymbolTable.AddType (gb); foreach (var nt in td.NestedTypes) diff --git a/tools/generator/Extensions/ManagedExtensions.cs b/tools/generator/Extensions/ManagedExtensions.cs index ac7e3e380..1bddc6ddd 100644 --- a/tools/generator/Extensions/ManagedExtensions.cs +++ b/tools/generator/Extensions/ManagedExtensions.cs @@ -42,7 +42,7 @@ public static IEnumerable GetParameters (this MethodDefinition m, Cus // custom enum types and cannot simply use JNI signature here. var rawtype = e?.Current.Type; var type = p.ParameterType.FullName == "System.IO.Stream" && e != null ? e.Current.Type : null; - yield return Parameter.FromManagedParameter (p, type, rawtype); + yield return CecilApiImporter.CreateParameter (p, type, rawtype); } } } diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs index 6f6e3cfc4..bc5a85922 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs @@ -126,7 +126,7 @@ public void WriteClass (ClassGen @class, string indent, GenerationInfo gen_info) bool requireNew = @class.InheritsObject; if (!requireNew) { - for (var bg = @class.BaseGen; bg != null && bg is XmlClassGen; bg = bg.BaseGen) { + for (var bg = @class.BaseGen; bg != null && bg is ClassGen classGen && classGen.FromXml; bg = bg.BaseGen) { if (bg.InheritsObject) { requireNew = true; break; @@ -367,7 +367,7 @@ internal virtual void WriteConstructor (Ctor constructor, string indent, bool us if (constructor.Annotation != null) writer.WriteLine ("{0}{1}", indent, constructor.Annotation); - writer.WriteLine ("{0}{1} unsafe {2} ({3})", indent, constructor.Visibility, constructor.Name, GenBase.GetSignature (constructor, opt)); + writer.WriteLine ("{0}{1} unsafe {2} ({3})", indent, constructor.Visibility, constructor.Name, constructor.GetSignature (opt)); writer.WriteLine ("{0}\t: {1} (IntPtr.Zero, JniHandleOwnership.DoNotTransfer)", indent, useBase ? "base" : "this"); writer.WriteLine ("{0}{{", indent); WriteConstructorBody (constructor, indent + "\t", call_cleanup); @@ -375,7 +375,7 @@ internal virtual void WriteConstructor (Ctor constructor, string indent, bool us writer.WriteLine (); if (gen_string_overload) { writer.WriteLine ("{0}[Register (\"{1}\", \"{2}\", \"{3}\"{4})]", indent, ".ctor", jni_sig, String.Empty, constructor.AdditionalAttributeString ()); - writer.WriteLine ("{0}{1} unsafe {2} ({3})", indent, constructor.Visibility, constructor.Name, GenBase.GetSignature (constructor, opt).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string")); + writer.WriteLine ("{0}{1} unsafe {2} ({3})", indent, constructor.Visibility, constructor.Name, constructor.GetSignature (opt).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string")); writer.WriteLine ("{0}\t: {1} (IntPtr.Zero, JniHandleOwnership.DoNotTransfer)", indent, useBase ? "base" : "this"); writer.WriteLine ("{0}{{", indent); WriteConstructorBody (constructor, indent + "\t", call_cleanup); @@ -582,7 +582,7 @@ public void WriteInterfaceEventArgs (InterfaceGen @interface, Method m, string i writer.WriteLine (); } } else { - writer.WriteLine ("{0}public delegate {1} {2} ({3});", indent, opt.GetOutputName (m.RetVal.FullName), @interface.GetEventDelegateName (m), GenBase.GetSignature (m, opt)); + writer.WriteLine ("{0}public delegate {1} {2} ({3});", indent, opt.GetOutputName (m.RetVal.FullName), @interface.GetEventDelegateName (m), m.GetSignature (opt)); writer.WriteLine (); } } @@ -645,7 +645,7 @@ public void WriteInterfaceEventHandlerImplContent (InterfaceGen @interface, Meth writer.WriteLine ("#pragma warning restore 0649"); } writer.WriteLine (); - writer.WriteLine ("{0}\tpublic {1} {2} ({3})", indent, m.RetVal.FullName, m.Name, GenBase.GetSignature (m, opt)); + writer.WriteLine ("{0}\tpublic {1} {2} ({3})", indent, m.RetVal.FullName, m.Name, m.GetSignature (opt)); writer.WriteLine ("{0}\t{{", indent); if (m.EventName == string.Empty) { // generate nothing @@ -1047,7 +1047,7 @@ public void WriteMethodExplicitInterfaceImplementation (Method method, string in { //writer.WriteLine ("// explicitly implemented method from " + iface.FullName); WriteMethodCustomAttributes (method, indent); - writer.WriteLine ("{0}{1} {2}.{3} ({4})", indent, opt.GetOutputName (method.RetVal.FullName), opt.GetOutputName (iface.FullName), method.Name, GenBase.GetSignature (method, opt)); + writer.WriteLine ("{0}{1} {2}.{3} ({4})", indent, opt.GetOutputName (method.RetVal.FullName), opt.GetOutputName (iface.FullName), method.Name, method.GetSignature (opt)); writer.WriteLine ("{0}{{", indent); writer.WriteLine ("{0}\treturn {1} ({2});", indent, method.Name, method.Parameters.GetCall (opt)); writer.WriteLine ("{0}}}", indent); @@ -1059,7 +1059,7 @@ public void WriteMethodExplicitInterfaceInvoker (Method method, string indent, G //writer.WriteLine ("\t\t// explicitly implemented invoker method from " + iface.FullName); WriteMethodIdField (method, indent); writer.WriteLine ("{0}unsafe {1} {2}.{3} ({4})", - indent, opt.GetOutputName (method.RetVal.FullName), opt.GetOutputName (iface.FullName), method.Name, GenBase.GetSignature (method, opt)); + indent, opt.GetOutputName (method.RetVal.FullName), opt.GetOutputName (iface.FullName), method.Name, method.GetSignature (opt)); writer.WriteLine ("{0}{{", indent); WriteMethodBody (method, indent + "\t"); writer.WriteLine ("{0}}}", indent); @@ -1070,7 +1070,7 @@ public void WriteMethodAbstractDeclaration (Method method, string indent, Interf { if (method.RetVal.IsGeneric && gen != null) { WriteMethodCustomAttributes (method, indent); - writer.WriteLine ("{0}{1} {2}.{3} ({4})", indent, opt.GetOutputName (method.RetVal.FullName), opt.GetOutputName (gen.FullName), method.Name, GenBase.GetSignature (method, opt)); + writer.WriteLine ("{0}{1} {2}.{3} ({4})", indent, opt.GetOutputName (method.RetVal.FullName), opt.GetOutputName (gen.FullName), method.Name, method.GetSignature (opt)); writer.WriteLine ("{0}{{", indent); writer.WriteLine ("{0}\tthrow new NotImplementedException ();", indent); writer.WriteLine ("{0}}}", indent); @@ -1089,7 +1089,7 @@ public void WriteMethodAbstractDeclaration (Method method, string indent, Interf method.Visibility, opt.GetOutputName (method.RetVal.FullName), name, - GenBase.GetSignature (method, opt)); + method.GetSignature (opt)); writer.WriteLine (); if (gen_as_formatted || method.Parameters.HasCharSequence) @@ -1111,13 +1111,13 @@ public void WriteMethodDeclaration (Method method, string indent, GenBase type, writer.WriteLine ("{0}[global::Java.Interop.JavaInterfaceDefaultMethod]", indent); writer.WriteLine ("{0}[Register (\"{1}\", \"{2}\", \"{3}:{4}\"{5})]", indent, method.JavaName, method.JniSignature, method.ConnectorName, method.GetAdapterName (opt, adapter), method.AdditionalAttributeString ()); WriteMethodCustomAttributes (method, indent); - writer.WriteLine ("{0}{1} {2} ({3});", indent, opt.GetOutputName (method.RetVal.FullName), method.AdjustedName, GenBase.GetSignature (method, opt)); + writer.WriteLine ("{0}{1} {2} ({3});", indent, opt.GetOutputName (method.RetVal.FullName), method.AdjustedName, method.GetSignature (opt)); writer.WriteLine (); } public void WriteMethodEventDelegate (Method method, string indent) { - writer.WriteLine ("{0}public delegate {1} {2}EventHandler ({3});", indent, opt.GetOutputName (method.RetVal.FullName), method.Name, GenBase.GetSignature (method, opt)); + writer.WriteLine ("{0}public delegate {1} {2}EventHandler ({3});", indent, opt.GetOutputName (method.RetVal.FullName), method.Name, method.GetSignature (opt)); writer.WriteLine (); } @@ -1126,7 +1126,7 @@ public void WriteMethodExplicitIface (Method method, string indent, GenericSymbo { writer.WriteLine ("{0}// This method is explicitly implemented as a member of an instantiated {1}", indent, gen.FullName); WriteMethodCustomAttributes (method, indent); - writer.WriteLine ("{0}{1} {2}.{3} ({4})", indent, opt.GetOutputName (method.RetVal.FullName), opt.GetOutputName (gen.Gen.FullName), method.Name, GenBase.GetSignature (method, opt)); + writer.WriteLine ("{0}{1} {2}.{3} ({4})", indent, opt.GetOutputName (method.RetVal.FullName), opt.GetOutputName (gen.Gen.FullName), method.Name, method.GetSignature (opt)); writer.WriteLine ("{0}{{", indent); Dictionary mappings = new Dictionary (); for (int i = 0; i < gen.TypeParams.Length; i++) @@ -1163,7 +1163,7 @@ public void WriteMethodInvoker (Method method, string indent, GenBase type) WriteMethodCallback (method, indent, type, null, method.IsReturnCharSequence); WriteMethodIdField (method, indent, invoker: true); writer.WriteLine ("{0}public unsafe {1}{2} {3} ({4})", - indent, method.IsStatic ? "static " : string.Empty, opt.GetOutputName (method.RetVal.FullName), method.AdjustedName, GenBase.GetSignature (method, opt)); + indent, method.IsStatic ? "static " : string.Empty, opt.GetOutputName (method.RetVal.FullName), method.AdjustedName, method.GetSignature (opt)); writer.WriteLine ("{0}{{", indent); WriteMethodInvokerBody (method, indent + "\t"); writer.WriteLine ("{0}}}", indent); @@ -1239,7 +1239,7 @@ void WriteMethodStringOverload (Method method, string indent) string ret = opt.GetOutputName (method.RetVal.FullName.Replace ("Java.Lang.ICharSequence", "string")); if (method.Deprecated != null) writer.WriteLine ("{0}[Obsolete (@\"{1}\")]", indent, method.Deprecated.Replace ("\"", "\"\"").Trim ()); - writer.WriteLine ("{0}{1}{2} {3} {4} ({5})", indent, method.Visibility, static_arg, ret, method.Name, GenBase.GetSignature (method, opt).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string")); + writer.WriteLine ("{0}{1}{2} {3} {4} ({5})", indent, method.Visibility, static_arg, ret, method.Name, method.GetSignature (opt).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string")); writer.WriteLine ("{0}{{", indent); WriteMethodStringOverloadBody (method, indent + "\t", false); writer.WriteLine ("{0}}}", indent); @@ -1255,7 +1255,7 @@ public void WriteMethodExtensionOverload (Method method, string indent, string s writer.WriteLine (); writer.WriteLine ("{0}public static {1} {2} (this {3} self, {4})", indent, ret, method.Name, selfType, - GenBase.GetSignature (method, opt).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string")); + method.GetSignature (opt).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string")); writer.WriteLine ("{0}{{", indent); WriteMethodStringOverloadBody (method, indent + "\t", true); writer.WriteLine ("{0}}}", indent); @@ -1274,7 +1274,7 @@ public void WriteMethodAsyncWrapper (Method method, string indent) else ret = "global::System.Threading.Tasks.Task<" + opt.GetOutputName (method.RetVal.FullName) + ">"; - writer.WriteLine ("{0}{1}{2} {3} {4}Async ({5})", indent, method.Visibility, static_arg, ret, method.AdjustedName, GenBase.GetSignature (method, opt)); + writer.WriteLine ("{0}{1}{2} {3} {4}Async ({5})", indent, method.Visibility, static_arg, ret, method.AdjustedName, method.GetSignature (opt)); writer.WriteLine ("{0}{{", indent); writer.WriteLine ("{0}\treturn global::System.Threading.Tasks.Task.Run (() => {1} ({2}));", indent, method.AdjustedName, method.Parameters.GetCall (opt)); writer.WriteLine ("{0}}}", indent); @@ -1293,7 +1293,7 @@ public void WriteMethodExtensionAsyncWrapper (Method method, string indent, stri else ret = "global::System.Threading.Tasks.Task<" + opt.GetOutputName (method.RetVal.FullName) + ">"; - writer.WriteLine ("{0}public static {1} {2}Async (this {3} self{4}{5})", indent, ret, method.AdjustedName, selfType, method.Parameters.Count > 0 ? ", " : string.Empty, GenBase.GetSignature (method, opt)); + writer.WriteLine ("{0}public static {1} {2}Async (this {3} self{4}{5})", indent, ret, method.AdjustedName, selfType, method.Parameters.Count > 0 ? ", " : string.Empty, method.GetSignature (opt)); writer.WriteLine ("{0}{{", indent); writer.WriteLine ("{0}\treturn global::System.Threading.Tasks.Task.Run (() => self.{1} ({2}));", indent, method.AdjustedName, method.Parameters.GetCall (opt)); writer.WriteLine ("{0}}}", indent); @@ -1329,7 +1329,7 @@ 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, GenBase.GetSignature (method, opt)); + 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)); writer.WriteLine ("{0}{{", indent); WriteMethodBody (method, indent + "\t"); writer.WriteLine ("{0}}}", indent); diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedClassGen.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedClassGen.cs deleted file mode 100644 index cda432a3a..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedClassGen.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Linq; -using Mono.Cecil; - -namespace MonoDroid.Generation -{ -#if HAVE_CECIL - public class ManagedClassGen : ClassGen - { - TypeDefinition t; - TypeReference nominal_base_type; - - public ManagedClassGen (TypeDefinition t, CodeGenerationOptions opt) - : base (new ManagedGenBaseSupport (t, opt)) - { - this.t = t; - foreach (var ifaceImpl in t.Interfaces) { - var iface = ifaceImpl.InterfaceType; - var def = ifaceImpl.InterfaceType.Resolve (); - if (def != null && def.IsNotPublic) - continue; - AddInterface (iface.FullNameCorrected ()); - } - bool implements_charsequence = t.Interfaces.Any (it => it.InterfaceType.FullName == "Java.Lang.CharSequence"); - foreach (var m in t.Methods) { - if (m.IsPrivate || m.IsAssembly || !m.CustomAttributes.Any (ca => ca.AttributeType.FullNameCorrected () == "Android.Runtime.RegisterAttribute")) - continue; - if (implements_charsequence && t.Methods.Any (mm => mm.Name == m.Name + "Formatted")) - continue; - if (m.IsConstructor) - Ctors.Add (new ManagedCtor (this, m)); - else - AddMethod (new ManagedMethod (this, m)); - } - foreach (var f in t.Fields) - if (!f.IsPrivate && !f.CustomAttributes.Any (ca => ca.AttributeType.FullNameCorrected () == "Android.Runtime.RegisterAttribute")) - AddField (new ManagedField (f)); - for (nominal_base_type = t.BaseType; nominal_base_type != null && (nominal_base_type.HasGenericParameters || nominal_base_type.IsGenericInstance); nominal_base_type = nominal_base_type.Resolve ().BaseType) - ; // iterate up to non-generic type, at worst System.Object. - } - - public override string BaseType { - get { return nominal_base_type != null ? nominal_base_type.FullNameCorrected () : null; } - set { throw new NotSupportedException (); } - } - - public override bool IsAbstract { - get { return t.IsAbstract; } - } - - public override bool IsFinal { - get { return t.IsSealed; } - } - } -#endif -} diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedCtor.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedCtor.cs deleted file mode 100644 index 58f55bea5..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedCtor.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Linq; -using Mono.Cecil; - -namespace MonoDroid.Generation -{ -#if HAVE_CECIL - public class ManagedCtor : Ctor { - MethodDefinition m; - string name; - bool is_acw; - - public ManagedCtor (GenBase declaringType, MethodDefinition m) - : base (declaringType) - { - this.m = m; - GenericArguments = m.GenericArguments (); - name = m.Name; - // If 'elem' is a constructor for a non-static nested type, then - // the type of the containing class must be inserted as the first - // argument - if (IsNonStaticNestedType) - Parameters.AddFirst (Parameter.FromManagedType (m.DeclaringType.DeclaringType, DeclaringType.JavaName)); - var regatt = m.CustomAttributes.FirstOrDefault (a => a.AttributeType.FullName == "Android.Runtime.RegisterAttribute"); - is_acw = regatt != null; - foreach (var p in m.GetParameters (regatt)) - Parameters.Add (p); - } - - public override bool IsAcw { - get { return is_acw; } - } - - public override bool IsNonStaticNestedType { - // not a beautiful way to check static type, yes :| - get { return m.DeclaringType.IsNested && !(m.DeclaringType.IsAbstract && m.DeclaringType.IsSealed); } - } - - public override string Name { - get { return name; } - set { name = value; } - } - - public override string CustomAttributes { - get { return null; } - } - - public override string AssemblyName => m.DeclaringType.Module.Assembly.FullName; - - public override string Visibility => m.Visibility (); - - public override string Deprecated => m.Deprecated (); - } -#endif -} diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedField.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedField.cs deleted file mode 100644 index d94543e10..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedField.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Linq; -using Mono.Cecil; - -namespace MonoDroid.Generation -{ -#if HAVE_CECIL - public class ManagedField : Field { - FieldDefinition f; - string java_name; - bool is_acw; - - public ManagedField (FieldDefinition f) - { - this.f = f; - var regatt = f.CustomAttributes.FirstOrDefault (a => a.AttributeType.FullNameCorrected () == "Android.Runtime.RegisterAttribute"); - is_acw = regatt != null; - java_name = regatt != null ? ((string) regatt.ConstructorArguments [0].Value).Replace ('/', '.') : f.Name; - } - - public override bool IsAcw { - get { return is_acw; } - } - - public override bool IsDeprecated { - get { return f.CustomAttributes.Any (a => a.AttributeType.FullNameCorrected () == "System.ObsoleteAttribute"); } - } - - public override string DeprecatedComment { - get { - if (!IsDeprecated) - return null; - var ca = f.CustomAttributes.First (a => a.AttributeType.FullNameCorrected () == "System.ObsoleteAttribute"); - return ca.ConstructorArguments.Any () ? (string) ca.ConstructorArguments [0].Value : string.Empty; - } - } - - public override bool IsEnumified { - get { return f.CustomAttributes.Any (c => c.AttributeType.FullName == "Android.Runtime.GeneratedEnumAttribute"); } - } - - public override bool IsFinal { - get { return f.Constant != null; } - } - - public override bool IsStatic { - get { return f.IsStatic; } - } - - public override string JavaName { - get { return java_name; } - } - - public override string TypeName { - get { return f.FieldType.FullNameCorrected (); } - } - - public override string Name { - get { return f.Name; } - set { throw new NotSupportedException (); } - } - - public override string Value { - get { return f.Constant == null ? null : f.FieldType.FullName == "System.String" ? '"' + f.Constant.ToString () + '"' : f.Constant.ToString (); } - } - - public override string Visibility { - get { return f.IsPublic ? "public" : f.IsFamilyOrAssembly ? "protected internal" : f.IsFamily ? "protected" : f.IsAssembly ? "internal" : "private"; } - } - - protected override Parameter SetterParameter { - get { - var p = Parameter.FromManagedType (f.FieldType.Resolve (), null); - p.Name = "value"; - return p; - } - } - } -#endif -} diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedGenBaseSupport.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedGenBaseSupport.cs deleted file mode 100644 index 579e73901..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedGenBaseSupport.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Linq; -using Mono.Cecil; - -namespace MonoDroid.Generation -{ -#if HAVE_CECIL - public class ManagedGenBaseSupport : GenBaseSupport - { - TypeDefinition t; - string pkg_name, java_name, full_name; - GenericParameterDefinitionList type_parameters; - bool deprecated, is_acw; - string deprecatedComment; - - public ManagedGenBaseSupport (TypeDefinition t, CodeGenerationOptions opt) - { - this.t = t; - var regatt = t.CustomAttributes.FirstOrDefault (a => a.AttributeType.FullNameCorrected () == "Android.Runtime.RegisterAttribute"); - is_acw = regatt != null; - string jn = regatt != null ? ((string) regatt.ConstructorArguments [0].Value).Replace ('/', '.') : t.FullNameCorrected (); - int idx = jn.LastIndexOf ('.'); - pkg_name = idx < 0 ? String.Empty : jn.Substring (0, idx); - java_name = SymbolTable.FilterPrimitiveFullName (t.FullNameCorrected ()); - if (java_name == null) { - java_name = idx < 0 ? jn : jn.Substring (idx + 1); - full_name = t.FullNameCorrected (); - } else { - var sym = opt.SymbolTable.Lookup (java_name); - full_name = sym != null ? sym.FullName : t.FullNameCorrected (); - } - java_name = java_name.Replace ('$', '.'); - type_parameters = GenericParameterDefinitionList.FromMetadata (t.GenericParameters); - - var obsolete = t.CustomAttributes.FirstOrDefault (ca => ca.AttributeType.FullName == "System.ObsoleteAttribute"); - if (obsolete != null) { - deprecated = true; - deprecatedComment = obsolete.HasConstructorArguments - ? obsolete.ConstructorArguments [0].Value.ToString () - : "This class is obsoleted in this android platform"; - } - } - - public override bool IsAcw { - get { return is_acw; } - } - - public override bool IsDeprecated { - get { return deprecated; } - } - - public override bool IsObfuscated { - get { return false; } // obfuscated types have no chance to be already bound in managed types. - } - - public override string DeprecatedComment { - get { return deprecatedComment; } - } - - public override bool IsGeneratable { - get { return false; } - } - - public override string FullName { - get { return full_name; } - set { throw new NotImplementedException (); } - } - - public override bool IsGeneric { - get { return t.HasGenericParameters; } - } - - public override string JavaSimpleName { - get { return java_name; } - } - - /* - public override string Marshaler { - get { return null; } - } - */ - - public override string Name { - get { return t.Name; } - set { throw new NotImplementedException (); } - } - - public override string Namespace { - get { return t.Namespace; } - } - - public override string PackageName { - get { return pkg_name; } - set { throw new NotImplementedException (); } - } - - public override string TypeNamePrefix { - get { return String.Empty; } - } - - public override GenericParameterDefinitionList TypeParameters { - get { return type_parameters; } - } - - public override string Visibility { - get { return t.IsPublic || t.IsNestedPublic ? "public" : "protected internal"; } - } - } -#endif -} diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedInterfaceGen.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedInterfaceGen.cs deleted file mode 100644 index 22f2d9652..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedInterfaceGen.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Linq; -using Mono.Cecil; - -namespace MonoDroid.Generation -{ -#if HAVE_CECIL - public class ManagedInterfaceGen : InterfaceGen { - public ManagedInterfaceGen (TypeDefinition t, CodeGenerationOptions opt) - : base (new ManagedGenBaseSupport (t, opt)) - { - foreach (var ifaceImpl in t.Interfaces) { - AddInterface (ifaceImpl.InterfaceType.FullNameCorrected ()); - } - foreach (var m in t.Methods) { - if (m.IsPrivate || m.IsAssembly || !m.CustomAttributes.Any (ca => ca.AttributeType.FullNameCorrected () == "Android.Runtime.RegisterAttribute")) - continue; - AddMethod (new ManagedMethod (this, m)); - } - } - - public override string ArgsType { - get { throw new NotImplementedException (); } - } - - public override bool MayHaveManagedGenericArguments { - get { return !this.IsAcw; } - } - } -#endif -} diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedMethod.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedMethod.cs deleted file mode 100644 index 1ca462eb0..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Cecil/ManagedMethod.cs +++ /dev/null @@ -1,121 +0,0 @@ -using Java.Interop.Tools.TypeNameMappings; -using Mono.Cecil; -using System; -using System.Linq; - -namespace MonoDroid.Generation -{ -#if HAVE_CECIL - public class ManagedMethod : Method { - MethodDefinition m; - string java_name; - string java_return; - bool is_acw; - bool is_interface_default_method; - - public ManagedMethod (GenBase declaringType, MethodDefinition m) - : base (declaringType) - { - this.m = m; - GenericArguments = m.GenericArguments (); - var regatt = m.CustomAttributes.FirstOrDefault (a => a.AttributeType.FullName == "Android.Runtime.RegisterAttribute"); - is_acw = regatt != null; - is_interface_default_method = m.CustomAttributes - .Any (ca => ca.AttributeType.FullName == "Java.Interop.JavaInterfaceDefaultMethodAttribute"); - java_name = regatt != null ? ((string) regatt.ConstructorArguments [0].Value) : m.Name; - - foreach (var p in m.GetParameters (regatt)) - Parameters.Add (p); - - if (regatt != null) { - var jnisig = (string)(regatt.ConstructorArguments.Count > 1 ? regatt.ConstructorArguments [1].Value : regatt.Properties.First (p => p.Name == "JniSignature").Argument.Value); - var rt = JavaNativeTypeManager.ReturnTypeFromSignature (jnisig); - if (rt != null) - java_return = rt.Type; - } - FillReturnType (); - } - - public override string AssemblyName => m.DeclaringType.Module.Assembly.FullName; - - public override string Deprecated => m.Deprecated (); - - public override string Visibility => m.Visibility (); - - public override bool IsAcw { - get { return is_acw; } - } - - public override bool IsInterfaceDefaultMethod { - get { return is_interface_default_method; } - } - - // Strip "Formatted" from ICharSequence-based method. Use this wherever m.Name was used. - string NameBase { - get { return IsReturnCharSequence ? m.Name.Substring (0, m.Name.Length - "Formatted".Length) : m.Name; } - } - - public override string Name { - get { return m.IsGetter ? (m.Name.StartsWith ("get_Is") && m.Name.Length > 6 && char.IsUpper (m.Name [6]) ? string.Empty : "Get") + NameBase.Substring (4) : m.IsSetter ? (m.Name.StartsWith ("set_Is") && m.Name.Length > 6 && char.IsUpper (m.Name [6]) ? string.Empty : "Set") + NameBase.Substring (4) : NameBase; } - set { throw new NotImplementedException (); } - } - - public override string ArgsType { - get { throw new NotImplementedException (); } - } - - public override string EventName { - get { throw new NotImplementedException (); } - } - - public override string JavaName { - get { return java_name; } - } - - public override bool IsAbstract { - get { return m.IsAbstract; } - } - - public override bool IsFinal { - get { return m.IsFinal; } - } - - public override bool IsStatic { - get { return m.IsStatic; } - } - - public override bool IsVirtual { - get { return m.IsVirtual; } - set { throw new NotImplementedException (); } - } - - public override string ManagedReturn { - get { return m.ReturnType.FullNameCorrected (); } - } - - public override sealed bool IsReturnEnumified { - get { return m.MethodReturnType.CustomAttributes.Any (c => c.AttributeType.FullName == "Android.Runtime.GeneratedEnumAttribute"); } - } - - public override string Return { - get { return java_return ?? m.ReturnType.FullNameCorrected (); } - } - - protected override string PropertyNameOverride { - get { return null; } - } - - public override int SourceApiLevel { - get { return 0; } - } - - public override bool Asyncify { - get { return false; } - } - - public override string CustomAttributes { - get { return null; } - } - } -#endif -} diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs new file mode 100644 index 000000000..00c1b000e --- /dev/null +++ b/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs @@ -0,0 +1,237 @@ +using System; +using System.Linq; +using Java.Interop.Tools.TypeNameMappings; +using Mono.Cecil; +using Mono.Collections.Generic; + +namespace MonoDroid.Generation +{ + class CecilApiImporter + { + public static ClassGen CreateClass (TypeDefinition t, CodeGenerationOptions opt) + { + var klass = new ClassGen (CreateGenBaseSupport (t, opt)) { + IsAbstract = t.IsAbstract, + IsFinal = t.IsSealed + }; + + foreach (var ifaceImpl in t.Interfaces) { + var iface = ifaceImpl.InterfaceType; + var def = ifaceImpl.InterfaceType.Resolve (); + + if (def != null && def.IsNotPublic) + continue; + + klass.AddImplementedInterface (iface.FullNameCorrected ()); + } + + var implements_charsequence = t.Interfaces.Any (it => it.InterfaceType.FullName == "Java.Lang.CharSequence"); + + foreach (var m in t.Methods) { + if (m.IsPrivate || m.IsAssembly || GetRegisterAttribute (m.CustomAttributes) == null) + continue; + if (implements_charsequence && t.Methods.Any (mm => mm.Name == m.Name + "Formatted")) + continue; + if (m.IsConstructor) + klass.Ctors.Add (CreateCtor (klass, m)); + else + klass.AddMethod (CreateMethod (klass, m)); + } + + foreach (var f in t.Fields) + if (!f.IsPrivate && GetRegisterAttribute (f.CustomAttributes) == null) + klass.AddField (CreateField (f)); + + TypeReference nominal_base_type; + + for (nominal_base_type = t.BaseType; nominal_base_type != null && (nominal_base_type.HasGenericParameters || nominal_base_type.IsGenericInstance); nominal_base_type = nominal_base_type.Resolve ().BaseType) + ; // iterate up to non-generic type, at worst System.Object. + + klass.BaseType = nominal_base_type?.FullNameCorrected (); + + return klass; + } + + public static Ctor CreateCtor (GenBase declaringType, MethodDefinition m) + { + var reg_attr = GetRegisterAttribute (m.CustomAttributes); + + var ctor = new Ctor (declaringType) { + AssemblyName = m.DeclaringType.Module.Assembly.FullName, + Deprecated = m.Deprecated (), + GenericArguments = m.GenericArguments (), + IsAcw = reg_attr != null, + // not a beautiful way to check static type, yes :| + IsNonStaticNestedType = m.DeclaringType.IsNested && !(m.DeclaringType.IsAbstract && m.DeclaringType.IsSealed), + Name = m.Name, + Visibility = m.Visibility () + }; + + // If 'elem' is a constructor for a non-static nested type, then + // the type of the containing class must be inserted as the first + // argument + if (ctor.IsNonStaticNestedType) + ctor.Parameters.AddFirst (CreateParameter (m.DeclaringType.DeclaringType.FullName, ctor.DeclaringType.JavaName)); + + foreach (var p in m.GetParameters (reg_attr)) + ctor.Parameters.Add (p); + + return ctor; + } + + public static Field CreateField (FieldDefinition f) + { + var obs_attr = GetObsoleteAttribute (f.CustomAttributes); + var reg_attr = GetRegisterAttribute (f.CustomAttributes); + + var field = new Field { + DeprecatedComment = GetObsoleteComment (obs_attr), + IsAcw = reg_attr != null, + IsDeprecated = obs_attr != null, + IsEnumified = GetGeneratedEnumAttribute (f.CustomAttributes) != null, + IsFinal = f.Constant != null, + IsStatic = f.IsStatic, + JavaName = reg_attr != null ? ((string) reg_attr.ConstructorArguments [0].Value).Replace ('/', '.') : f.Name, + Name = f.Name, + TypeName = f.FieldType.FullNameCorrected (), + Value = f.Constant == null ? null : f.FieldType.FullName == "System.String" ? '"' + f.Constant.ToString () + '"' : f.Constant.ToString (), + Visibility = f.IsPublic ? "public" : f.IsFamilyOrAssembly ? "protected internal" : f.IsFamily ? "protected" : f.IsAssembly ? "internal" : "private" + }; + + field.SetterParameter = CreateParameter (f.FieldType.Resolve ()?.FullName ?? f.FieldType.FullName, null); + field.SetterParameter.Name = "value"; + + return field; + } + + public static GenBaseSupport CreateGenBaseSupport (TypeDefinition t, CodeGenerationOptions opt) + { + var obs_attr = GetObsoleteAttribute (t.CustomAttributes); + var reg_attr = GetRegisterAttribute (t.CustomAttributes); + + var jn = reg_attr != null ? ((string) reg_attr.ConstructorArguments [0].Value).Replace ('/', '.') : t.FullNameCorrected (); + var idx = jn.LastIndexOf ('.'); + + var support = new GenBaseSupport { + IsAcw = reg_attr != null, + IsDeprecated = obs_attr != null, + IsGeneratable = false, + IsGeneric = t.HasGenericParameters, + IsObfuscated = false, // obfuscated types have no chance to be already bound in managed types. + Name = t.Name, + Namespace = t.Namespace, + PackageName = idx < 0 ? string.Empty : jn.Substring (0, idx), + TypeParameters = GenericParameterDefinitionList.FromMetadata (t.GenericParameters), + Visibility = t.IsPublic || t.IsNestedPublic ? "public" : "protected internal" + }; + + support.JavaSimpleName = SymbolTable.FilterPrimitiveFullName (t.FullNameCorrected ()); + + if (support.JavaSimpleName == null) { + support.JavaSimpleName = idx < 0 ? jn : jn.Substring (idx + 1); + support.FullName = t.FullNameCorrected (); + } else { + var sym = opt.SymbolTable.Lookup (support.JavaSimpleName); + support.FullName = sym != null ? sym.FullName : t.FullNameCorrected (); + } + + support.JavaSimpleName = support.JavaSimpleName.Replace ('$', '.'); + + if (support.IsDeprecated) + support.DeprecatedComment = GetObsoleteComment (obs_attr) ?? "This class is obsoleted in this android platform"; + + return support; + } + + public static InterfaceGen CreateInterface (TypeDefinition t, CodeGenerationOptions opt) + { + var reg_attr = GetRegisterAttribute (t.CustomAttributes); + + var iface = new InterfaceGen (CreateGenBaseSupport (t, opt)); + + foreach (var ifaceImpl in t.Interfaces) + iface.AddImplementedInterface (ifaceImpl.InterfaceType.FullNameCorrected ()); + + foreach (var m in t.Methods) { + if (m.IsPrivate || m.IsAssembly || GetRegisterAttribute (m.CustomAttributes) == null) + continue; + + iface.AddMethod (CecilApiImporter.CreateMethod (iface, m)); + } + + iface.MayHaveManagedGenericArguments = !iface.IsAcw; + + return iface; + } + + public static Method CreateMethod (GenBase declaringType, MethodDefinition m) + { + var reg_attr = GetRegisterAttribute (m.CustomAttributes); + + var method = new Method (declaringType) { + AssemblyName = m.DeclaringType.Module.Assembly.FullName, + Deprecated = m.Deprecated (), + GenerateAsyncWrapper = false, + GenericArguments = m.GenericArguments (), + IsAbstract = m.IsAbstract, + IsAcw = reg_attr != null, + IsFinal = m.IsFinal, + IsInterfaceDefaultMethod = GetJavaDefaultInterfaceMethodAttribute (m.CustomAttributes) != null, + IsReturnEnumified = GetGeneratedEnumAttribute (m.MethodReturnType.CustomAttributes) != null, + IsStatic = m.IsStatic, + IsVirtual = m.IsVirtual, + JavaName = reg_attr != null ? ((string) reg_attr.ConstructorArguments [0].Value) : m.Name, + ManagedReturn = m.ReturnType.FullNameCorrected (), + Return = m.ReturnType.FullNameCorrected (), + Visibility = m.Visibility () + }; + + foreach (var p in m.GetParameters (reg_attr)) + method.Parameters.Add (p); + + if (reg_attr != null) { + var jnisig = (string) (reg_attr.ConstructorArguments.Count > 1 ? reg_attr.ConstructorArguments [1].Value : reg_attr.Properties.First (p => p.Name == "JniSignature").Argument.Value); + var rt = JavaNativeTypeManager.ReturnTypeFromSignature (jnisig); + if (rt?.Type != null) + method.Return = rt.Type; + } + + method.FillReturnType (); + + // Strip "Formatted" from ICharSequence-based method. + var name_base = method.IsReturnCharSequence ? m.Name.Substring (0, m.Name.Length - "Formatted".Length) : m.Name; + + method.Name = m.IsGetter ? (m.Name.StartsWith ("get_Is") && m.Name.Length > 6 && char.IsUpper (m.Name [6]) ? string.Empty : "Get") + name_base.Substring (4) : m.IsSetter ? (m.Name.StartsWith ("set_Is") && m.Name.Length > 6 && char.IsUpper (m.Name [6]) ? string.Empty : "Set") + name_base.Substring (4) : name_base; + + return method; + } + + public static Parameter CreateParameter (ParameterDefinition p, string jnitype, string rawtype) + { + // FIXME: safe to use CLR type name? assuming yes as we often use it in metadatamap. + // FIXME: IsSender? + var isEnumType = GetGeneratedEnumAttribute (p.CustomAttributes) != null;; + return new Parameter (SymbolTable.MangleName (p.Name), jnitype ?? p.ParameterType.FullNameCorrected (), null, isEnumType, rawtype); + } + + public static Parameter CreateParameter (string managedType, string javaType) + { + return new Parameter ("__self", javaType ?? managedType, managedType, false); + } + + static CustomAttribute GetJavaDefaultInterfaceMethodAttribute (Collection attributes) => + attributes.FirstOrDefault (a => a.AttributeType.FullName == "Java.Interop.JavaInterfaceDefaultMethodAttribute"); + + static CustomAttribute GetGeneratedEnumAttribute (Collection attributes) => + attributes.FirstOrDefault (a => a.AttributeType.FullName == "Android.Runtime.GeneratedEnumAttribute"); + + static CustomAttribute GetObsoleteAttribute (Collection attributes) => + attributes.FirstOrDefault (a => a.AttributeType.FullNameCorrected () == "System.ObsoleteAttribute"); + + static string GetObsoleteComment (CustomAttribute attribute) => + attribute?.ConstructorArguments.Any () == true ? (string) attribute.ConstructorArguments [0].Value : null; + + static CustomAttribute GetRegisterAttribute (Collection attributes) => + attributes.FirstOrDefault (a => a.AttributeType.FullNameCorrected () == "Android.Runtime.RegisterAttribute"); + } +} diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/InterfaceXmlGenBaseSupport.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/InterfaceXmlGenBaseSupport.cs deleted file mode 100644 index f0f9d81c3..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/InterfaceXmlGenBaseSupport.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Xml.Linq; - -namespace MonoDroid.Generation -{ - public class InterfaceXmlGenBaseSupport : XmlGenBaseSupport - { - public InterfaceXmlGenBaseSupport (XElement pkg, XElement elem) - : base (pkg, elem) - { - } - - public override string TypeNamePrefix { - get { return (IsPrefixableName (RawName) ? "I" : string.Empty); } - } - } -} - - diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlClassGen.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlClassGen.cs deleted file mode 100644 index a8f986998..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlClassGen.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Xamarin.Android.Tools; -using System.Xml.Linq; - -namespace MonoDroid.Generation -{ - public class XmlClassGen : ClassGen { - bool is_abstract; - bool is_final; - string base_type; - - public XmlClassGen (XElement pkg, XElement elem) - : base (new XmlGenBaseSupport (pkg, elem))//FIXME: should not be xml specific - { - is_abstract = elem.XGetAttribute ("abstract") == "true"; - is_final = elem.XGetAttribute ("final") == "true"; - base_type = elem.XGetAttribute ("extends"); - foreach (var child in elem.Elements ()) { - switch (child.Name.LocalName) { - case "implements": - string iname = child.XGetAttribute ("name-generic-aware"); - iname = iname.Length > 0 ? iname : child.XGetAttribute ("name"); - AddInterface (iname); - break; - case "method": - AddMethod (new XmlMethod (this, child)); - break; - case "constructor": - Ctors.Add (new XmlCtor (this, child)); - break; - case "field": - AddField (new XmlField (child)); - break; - case "typeParameters": - break; // handled at GenBaseSupport - default: - Report.Warning (0, Report.WarningClassGen + 1, "unexpected class child {0}.", child.Name); - break; - } - } - } - - public override bool IsAbstract { - get { return is_abstract; } - } - - public override bool IsFinal { - get { return is_final; } - } - - public override string BaseType { - get { return base_type; } - set { base_type = value; } - } - } -} - diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlCtor.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlCtor.cs deleted file mode 100644 index eb948c2cc..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlCtor.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Xml.Linq; - -using Xamarin.Android.Tools; - -namespace MonoDroid.Generation -{ - public class XmlCtor : Ctor { - XElement elem; - string name; - bool nonStaticNestedType; - bool missing_enclosing_class; - string custom_attributes; - - public XmlCtor (GenBase declaringType, XElement elem) : base (declaringType) - { - this.elem = elem; - GenericArguments = elem.GenericArguments (); - name = elem.XGetAttribute ("name"); - int idx = name.LastIndexOf ('.'); - if (idx > 0) - name = name.Substring (idx + 1); - // If 'elem' is a constructor for a non-static nested type, then - // the type of the containing class must be inserted as the first - // argument - nonStaticNestedType = idx > 0 && elem.Parent.Attribute ("static").Value == "false"; - if (nonStaticNestedType) { - string declName = elem.Parent.XGetAttribute ("name"); - string expectedEnclosingName = declName.Substring (0, idx); - XElement enclosingType = GetPreviousClass (elem.Parent.PreviousNode, expectedEnclosingName); - if (enclosingType == null) { - missing_enclosing_class = true; - Report.Warning (0, Report.WarningCtor + 0, "For {0}, could not find enclosing type '{1}'.", name, expectedEnclosingName); - } - else - Parameters.AddFirst (Parameter.FromClassElement (enclosingType)); - } - - foreach (var child in elem.Elements ()) { - if (child.Name == "parameter") - Parameters.Add (Parameter.FromElement (child)); - } - - if (elem.Attribute ("customAttributes") != null) - custom_attributes = elem.XGetAttribute ("customAttributes"); - } - - static XElement GetPreviousClass (XNode n, string nameValue) - { - XElement e = null; - while (n != null && - ((e = n as XElement) == null || - e.Name != "class" || - !e.XGetAttribute ("name").StartsWith (nameValue, StringComparison.Ordinal) || - // this complicated check (instead of simple name string equivalence match) is required for nested class inside a generic class e.g. android.content.Loader.ForceLoadContentObserver. - (e.XGetAttribute ("name") != nameValue && e.XGetAttribute ("name").IndexOf ('<') < 0))) { - n = n.PreviousNode; - } - return (XElement) e; - } - - public override bool IsNonStaticNestedType { - get { return nonStaticNestedType; } - } - - public override string Name { - get { return name; } - set { name = value; } - } - - protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList tps, CodeGeneratorContext context) - { - if (missing_enclosing_class) - return false; - return base.OnValidate (opt, tps, context); - } - - public override string CustomAttributes { - get { return custom_attributes; } - } - - public override string Deprecated => elem.Deprecated (); - - public override string Visibility => elem.Visibility (); - } -} diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlField.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlField.cs deleted file mode 100644 index 42cef51f9..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlField.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Xml.Linq; -using Xamarin.Android.Tools; - -namespace MonoDroid.Generation -{ - public class XmlField : Field { - - XElement elem; - string java_name; - string name; - string enum_type; - - public XmlField (XElement elem) - { - this.elem = elem; - java_name = elem.XGetAttribute ("name"); - if (elem.Attribute ("managedName") != null) - name = elem.XGetAttribute ("managedName"); - else - name = SymbolTable.StudlyCase (Char.IsLower (java_name [0]) || java_name.ToLower ().ToUpper () != java_name ? java_name : java_name.ToLower ()); - if (elem.Attribute ("enumType") != null) - enum_type = elem.XGetAttribute ("enumType"); - } - - public override bool IsDeprecated { - get { return elem.XGetAttribute ("deprecated") != "not deprecated"; } - } - - public override string DeprecatedComment { - get { return elem.XGetAttribute ("deprecated"); } - } - - public override bool IsEnumified { - get { return enum_type != null; } - } - - public override bool IsFinal { - get { return elem.XGetAttribute ("final") == "true"; } - } - - public override bool IsStatic { - get { return elem.XGetAttribute ("static") == "true"; } - } - - public override string Name { - get { return name; } - set { name = value; } - } - - public override string JavaName { - get { return java_name; } - } - - public override string TypeName { - get { return enum_type ?? elem.XGetAttribute ("type"); } - } - - public override string Value { - get { - string val = elem.XGetAttribute ("value"); // do not trim - if (!String.IsNullOrEmpty (val) && Symbol != null && Symbol.FullName == "char") - val = "(char)" + val; - return val; - } - } - - public override string Visibility { - get { return elem.XGetAttribute ("visibility"); } - } - - protected override Parameter SetterParameter { - get { - var p = Parameter.FromElement (elem); - p.Name = "value"; - return p; - } - } - } -} diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlGenBaseSupport.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlGenBaseSupport.cs deleted file mode 100644 index 20d49046e..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlGenBaseSupport.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using System.Linq; - -using Xamarin.Android.Tools; - -using MonoDroid.Utils; -using System.Xml.Linq; - -namespace MonoDroid.Generation -{ - public class XmlGenBaseSupport : GenBaseSupport - { - public XmlGenBaseSupport (XElement pkg, XElement elem) - { - deprecated = elem.XGetAttribute ("deprecated") != "not deprecated"; - if (deprecated) { - deprecatedComment = elem.XGetAttribute ("deprecated"); - if (deprecatedComment == "deprecated") - deprecatedComment = "This class is obsoleted in this android platform"; - } - visibility = elem.XGetAttribute ("visibility"); - if (visibility == "protected") - visibility = "protected internal"; - - pkg_name = pkg.XGetAttribute ("name"); - java_name = elem.XGetAttribute ("name"); - if (pkg.Attribute ("managedName") != null) { - ns = pkg.XGetAttribute ("managedName"); - } else { - ns = StringRocks.PackageToPascalCase (PackageName); - } - - var tpn = elem.Element ("typeParameters"); - if (tpn != null) { - type_params = GenericParameterDefinitionList.FromXml (tpn); - is_generic = true; - int idx = java_name.IndexOf ('<'); - if (idx > 0) - java_name = java_name.Substring (0, idx); - } else { - int idx = java_name.IndexOf ('<'); - if (idx > 0) - throw new NotSupportedException ("Looks like old API XML is used, which we don't support anymore."); - } - - if (elem.Attribute ("managedName") != null) { - name = elem.XGetAttribute ("managedName"); - full_name = String.Format ("{0}.{1}", ns, name); - int idx = name.LastIndexOf ('.'); - name = idx > 0 ? name.Substring (idx + 1) : name; - raw_name = name; - } else { - int idx = java_name.LastIndexOf ('.'); - name = idx > 0 ? java_name.Substring (idx + 1) : java_name; - if (Char.IsLower (name[0])) - name = StringRocks.TypeToPascalCase (name); - raw_name = name; - name = TypeNamePrefix + raw_name; - full_name = String.Format ("{0}.{1}{2}", ns, idx > 0 ? StringRocks.TypeToPascalCase (java_name.Substring (0, idx + 1)) : String.Empty, name); - } - - obfuscated = IsObfuscatedName (pkg.Elements ().Count (), java_name) && elem.XGetAttribute ("obfuscated") != "false"; - } - - public override bool IsAcw { - get { return true; } - } - - bool deprecated; - public override bool IsDeprecated { - get { return deprecated; } - } - - string deprecatedComment; - public override string DeprecatedComment { - get { return deprecatedComment; } - } - - public override bool IsGeneratable { - get { return true; } - } - - bool obfuscated; - public override bool IsObfuscated { - get { return obfuscated; } - } - - string java_name; - public override string JavaSimpleName { - get { return java_name; } - } - - string pkg_name; - public override string PackageName { - get { return pkg_name; } - set { pkg_name = value; } - } - - string full_name; - public override string FullName { - get { return full_name; } - set { full_name = value; } - } - - string name; - public override string Name { - get { return name; } - set { name = value; } - } - string ns; - public override string Namespace { - get { return ns; } - } - - /* - string marshaler; - public override string Marshaler { - get { return marshaler; } - } - */ - - string raw_name; - internal string RawName { - get { return raw_name; } - } - - GenericParameterDefinitionList type_params; - public override GenericParameterDefinitionList TypeParameters { - get { return type_params; } - } - - bool is_generic; - public override bool IsGeneric { - get { return is_generic; } - } - - string visibility; - public override string Visibility { - get { return visibility; } - } - - public override bool OnValidate (CodeGenerationOptions opt) - { - if (!base.OnValidate (opt)) - return false; - string topmost; - int split = ns.LastIndexOf ('.'); - if (split < 0) - topmost = ns; - else - topmost = ns.Substring (split + 1); - if (topmost.Length == name.Length && string.Compare (topmost, 0, name, 0, topmost.Length, StringComparison.OrdinalIgnoreCase) == 0) { - // FIXME: this should really be prohibited. See https://app.asana.com/0/77259014259/1186053910891 - Report.Warning (0, Report.WarningGenBaseSupport + 0, "Type {0}.{1}: FxDG naming violation: Type name '{1}' matches namespace part '{2}'.", pkg_name, java_name, topmost); - // return false; - } - return true; - } - - bool IsObfuscatedName (int threshold, string name) - { - if (name.StartsWith ("R.", StringComparison.Ordinal)) - return false; - int idx = name.LastIndexOf ('.'); - string last = idx < 0 ? name : name.Substring (idx + 1); - // probably new proguard within Gradle tasks, used in recent GooglePlayServices in 2016 or later. - if (last.StartsWith ("zz", StringComparison.Ordinal)) - return true; - // do not expect any name with more than 3 letters is an 'obfuscated' one. - if (last.Length > 3) - return false; - // Only short ones ('a', 'b', 'c' ... 'aa', 'ab', ... 'zzz') are the targets. - if (!(last.Length == 3 && threshold > 26*26 || last.Length == 2 && threshold > 26 || last.Length == 1)) - return false; - if (last.Any (c => (c < 'a' || 'z' < c) && (c < '0' || '9' < c))) - return false; - return true; - } - } -} - - diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlInterfaceGen.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlInterfaceGen.cs deleted file mode 100644 index 7154422e4..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlInterfaceGen.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Xml.Linq; -using Xamarin.Android.Tools; - -namespace MonoDroid.Generation -{ - public class XmlInterfaceGen : InterfaceGen { - - string args_type; - - public XmlInterfaceGen (XElement pkg, XElement elem) - : base (new InterfaceXmlGenBaseSupport (pkg, elem)) - { - hasManagedName = elem.Attribute ("managedName") != null; - args_type = elem.XGetAttribute ("argsType"); - foreach (var child in elem.Elements ()) { - switch (child.Name.LocalName) { - case "implements": - string iname = child.XGetAttribute ("name-generic-aware"); - iname = iname.Length > 0 ? iname : child.XGetAttribute ("name"); - AddInterface (iname); - break; - case "method": - AddMethod (new XmlMethod (this, child)); - break; - case "field": - AddField (new XmlField (child)); - break; - case "typeParameters": - break; // handled at GenBaseSupport - default: - Report.Warning (0, Report.WarningInterfaceGen + 0, "unexpected interface child {0}.", child); - break; - } - } - } - - public override string ArgsType { - get { return args_type; } - } - } -} - diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlMethod.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlMethod.cs deleted file mode 100644 index 411646757..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/Xml/XmlMethod.cs +++ /dev/null @@ -1,142 +0,0 @@ -using MonoDroid.Utils; -using System.Text.RegularExpressions; -using System.Xml.Linq; -using Xamarin.Android.Tools; - -namespace MonoDroid.Generation -{ - public class XmlMethod : Method { - - XElement elem; - - public XmlMethod (GenBase declaringType, XElement elem) - : base (declaringType) - { - this.elem = elem; - GenericArguments = elem.GenericArguments (); - is_static = elem.XGetAttribute ("static") == "true"; - is_virtual = !is_static && elem.XGetAttribute ("final") == "false"; - if (elem.Attribute ("managedName") != null) - name = elem.XGetAttribute ("managedName"); - else - name = StringRocks.MemberToPascalCase (JavaName); - - is_abstract = elem.XGetAttribute ("abstract") == "true"; - if (declaringType is InterfaceGen) - is_interface_default_method = !is_abstract && !is_static; - - GenerateDispatchingSetter = elem.Attribute ("generateDispatchingSetter") != null; - - foreach (var child in elem.Elements ()) { - if (child.Name == "parameter") - Parameters.Add (Parameter.FromElement (child)); - } - FillReturnType (); - } - - // core XML-based properties - public override string Deprecated => elem.Deprecated (); - - public override string Visibility => elem.Visibility (); - - public override string ArgsType { - get { - var a = elem.Attribute ("argsType"); - if (a == null) - return null; - return a.Value; - } - } - - public override string EventName { - get { - var a = elem.Attribute ("eventName"); - if (a == null) - return null; - return a.Value; - } - } - - bool is_abstract; - public override bool IsAbstract { - get { return is_abstract; } - } - - public override bool IsFinal { - get { return elem.XGetAttribute ("final") == "true"; } - } - - bool is_interface_default_method; - public override bool IsInterfaceDefaultMethod { - get { return is_interface_default_method; } - } - - public override string JavaName { - get { return elem.XGetAttribute ("name"); } - } - - bool is_static; - public override bool IsStatic { - get { return is_static; } - } - - bool is_virtual; - public override bool IsVirtual { - get { return is_virtual; } - set { is_virtual = value; } - } - - string name; - public override string Name { - get { return name; } - set { name = value; } - } - - // FIXME: this should not require enumReturn. Somewhere in generator uses this property improperly. - public override string Return { - get { return IsReturnEnumified ? elem.XGetAttribute ("enumReturn") : elem.XGetAttribute ("return"); } - } - - public override string ManagedReturn { - get { return IsReturnEnumified ? elem.XGetAttribute ("enumReturn") : elem.XGetAttribute ("managedReturn"); } - } - - public override bool IsReturnEnumified { - get { return elem.Attribute ("enumReturn") != null; } - } - - protected override string PropertyNameOverride { - get { return elem.XGetAttribute ("propertyName"); } - } - - static readonly Regex ApiLevel = new Regex (@"api-(\d+).xml"); - public override int SourceApiLevel { - get { - string source = elem.XGetAttribute ("merge.SourceFile"); - if (source == null) - return 0; - Match m = ApiLevel.Match (source); - if (!m.Success) - return 0; - int api; - if (int.TryParse (m.Groups [1].Value, out api)) - return api; - return 0; - } - } - - public override bool Asyncify { - get { - if (IsOverride) - return false; - - return elem.Attribute ("generateAsyncWrapper") != null; - } - } - - public override string CustomAttributes { - get { return elem.XGetAttribute ("customAttributes"); } - } - } -} - diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs new file mode 100644 index 000000000..66f67aef0 --- /dev/null +++ b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs @@ -0,0 +1,344 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; +using System.Xml.Linq; +using MonoDroid.Utils; +using Xamarin.Android.Tools; + +namespace MonoDroid.Generation +{ + class XmlApiImporter + { + static readonly Regex api_level = new Regex (@"api-(\d+).xml"); + + public static ClassGen CreateClass (XElement pkg, XElement elem) + { + var klass = new ClassGen (CreateGenBaseSupport (pkg, elem, false)) { + BaseType = elem.XGetAttribute ("extends"), + FromXml = true, + IsAbstract = elem.XGetAttribute ("abstract") == "true", + IsFinal = elem.XGetAttribute ("final") == "true" + }; + + foreach (var child in elem.Elements ()) { + switch (child.Name.LocalName) { + case "implements": + var iname = child.XGetAttribute ("name-generic-aware"); + iname = iname.Length > 0 ? iname : child.XGetAttribute ("name"); + klass.AddImplementedInterface (iname); + break; + case "method": + klass.AddMethod (CreateMethod (klass, child)); + break; + case "constructor": + klass.Ctors.Add (CreateCtor (klass, child)); + break; + case "field": + klass.AddField (CreateField (child)); + break; + case "typeParameters": + break; // handled at GenBaseSupport + default: + Report.Warning (0, Report.WarningClassGen + 1, "unexpected class child {0}.", child.Name); + break; + } + } + + return klass; + } + + public static Ctor CreateCtor (GenBase declaringType, XElement elem) + { + var ctor = new Ctor (declaringType) { + CustomAttributes = elem.XGetAttribute ("customAttributes"), + Deprecated = elem.Deprecated (), + GenericArguments = elem.GenericArguments (), + Name = elem.XGetAttribute ("name"), + Visibility = elem.Visibility () + }; + + var idx = ctor.Name.LastIndexOf ('.'); + + if (idx > 0) + ctor.Name = ctor.Name.Substring (idx + 1); + + // If 'elem' is a constructor for a non-static nested type, then + // the type of the containing class must be inserted as the first argument + ctor.IsNonStaticNestedType = idx > 0 && elem.Parent.Attribute ("static").Value == "false"; + + if (ctor.IsNonStaticNestedType) { + string declName = elem.Parent.XGetAttribute ("name"); + string expectedEnclosingName = declName.Substring (0, idx); + XElement enclosingType = GetPreviousClass (elem.Parent.PreviousNode, expectedEnclosingName); + + if (enclosingType == null) { + ctor.MissingEnclosingClass = true; + Report.Warning (0, Report.WarningCtor + 0, "For {0}, could not find enclosing type '{1}'.", ctor.Name, expectedEnclosingName); + } else + ctor.Parameters.AddFirst (CreateParameterFromClassElement (enclosingType)); + } + + foreach (var child in elem.Elements ()) { + if (child.Name == "parameter") + ctor.Parameters.Add (CreateParameter (child)); + } + + return ctor; + } + + public static Field CreateField (XElement elem) + { + var field = new Field { + DeprecatedComment = elem.XGetAttribute ("deprecated"), + IsAcw = true, + IsDeprecated = elem.XGetAttribute ("deprecated") != "not deprecated", + IsFinal = elem.XGetAttribute ("final") == "true", + IsStatic = elem.XGetAttribute ("static") == "true", + JavaName = elem.XGetAttribute ("name"), + SetterParameter = CreateParameter (elem), + TypeName = elem.XGetAttribute ("type"), + Value = elem.XGetAttribute ("value"), // do not trim + Visibility = elem.XGetAttribute ("visibility") + }; + + field.SetterParameter.Name = "value"; + + if (elem.XGetAttribute ("enumType") != null) { + field.IsEnumified = true; + field.TypeName = elem.XGetAttribute ("enumType"); + } + + if (elem.Attribute ("managedName") != null) + field.Name = elem.XGetAttribute ("managedName"); + else + field.Name = SymbolTable.StudlyCase (char.IsLower (field.JavaName [0]) || field.JavaName.ToLower ().ToUpper () != field.JavaName ? field.JavaName : field.JavaName.ToLower ()); + + return field; + } + + public static GenBaseSupport CreateGenBaseSupport (XElement pkg, XElement elem, bool isInterface) + { + var support = new GenBaseSupport { + IsAcw = true, + IsDeprecated = elem.XGetAttribute ("deprecated") != "not deprecated", + IsGeneratable = true, + JavaSimpleName = elem.XGetAttribute ("name"), + PackageName = pkg.XGetAttribute ("name"), + Visibility = elem.XGetAttribute ("visibility") + }; + + if (support.IsDeprecated) { + support.DeprecatedComment = elem.XGetAttribute ("deprecated"); + + if (support.DeprecatedComment == "deprecated") + support.DeprecatedComment = "This class is obsoleted in this android platform"; + } + + if (support.Visibility == "protected") + support.Visibility = "protected internal"; + + if (pkg.Attribute ("managedName") != null) + support.Namespace = pkg.XGetAttribute ("managedName"); + else + support.Namespace = StringRocks.PackageToPascalCase (support.PackageName); + + var tpn = elem.Element ("typeParameters"); + + if (tpn != null) { + support.TypeParameters = GenericParameterDefinitionList.FromXml (tpn); + support.IsGeneric = true; + int idx = support.JavaSimpleName.IndexOf ('<'); + if (idx > 0) + support.JavaSimpleName = support.JavaSimpleName.Substring (0, idx); + } else { + int idx = support.JavaSimpleName.IndexOf ('<'); + if (idx > 0) + throw new NotSupportedException ("Looks like old API XML is used, which we don't support anymore."); + } + + string raw_name; + + if (elem.Attribute ("managedName") != null) { + support.Name = elem.XGetAttribute ("managedName"); + support.FullName = string.Format ("{0}.{1}", support.Namespace, support.Name); + int idx = support.Name.LastIndexOf ('.'); + support.Name = idx > 0 ? support.Name.Substring (idx + 1) : support.Name; + raw_name = support.Name; + } else { + int idx = support.JavaSimpleName.LastIndexOf ('.'); + support.Name = idx > 0 ? support.JavaSimpleName.Substring (idx + 1) : support.JavaSimpleName; + if (char.IsLower (support.Name [0])) + support.Name = StringRocks.TypeToPascalCase (support.Name); + raw_name = support.Name; + support.TypeNamePrefix = isInterface ? IsPrefixableName (raw_name) ? "I" : string.Empty : string.Empty; + support.Name = support.TypeNamePrefix + raw_name; + support.FullName = string.Format ("{0}.{1}{2}", support.Namespace, idx > 0 ? StringRocks.TypeToPascalCase (support.JavaSimpleName.Substring (0, idx + 1)) : string.Empty, support.Name); + } + + support.IsObfuscated = IsObfuscatedName (pkg.Elements ().Count (), support.JavaSimpleName) && elem.XGetAttribute ("obfuscated") != "false"; + + return support; + } + + public static InterfaceGen CreateInterface (XElement pkg, XElement elem) + { + var iface = new InterfaceGen (CreateGenBaseSupport (pkg, elem, true)) { + ArgsType = elem.XGetAttribute ("argsType"), + HasManagedName = elem.Attribute ("managedName") != null + }; + + foreach (var child in elem.Elements ()) { + switch (child.Name.LocalName) { + case "implements": + string iname = child.XGetAttribute ("name-generic-aware"); + iname = iname.Length > 0 ? iname : child.XGetAttribute ("name"); + iface.AddImplementedInterface (iname); + break; + case "method": + iface.AddMethod (CreateMethod (iface, child)); + break; + case "field": + iface.AddField (CreateField (child)); + break; + case "typeParameters": + break; // handled at GenBaseSupport + default: + Report.Warning (0, Report.WarningInterfaceGen + 0, "unexpected interface child {0}.", child); + break; + } + } + + return iface; + } + + public static Method CreateMethod (GenBase declaringType, XElement elem) + { + var method = new Method (declaringType) { + ArgsType = elem.Attribute ("argsType")?.Value, + CustomAttributes = elem.XGetAttribute ("customAttributes"), + Deprecated = elem.Deprecated (), + EventName = elem.Attribute ("eventName")?.Value, + GenerateAsyncWrapper = elem.Attribute ("generateAsyncWrapper") != null, + GenerateDispatchingSetter = elem.Attribute ("generateDispatchingSetter") != null, + GenericArguments = elem.GenericArguments (), + IsAbstract = elem.XGetAttribute ("abstract") == "true", + IsAcw = true, + IsFinal = elem.XGetAttribute ("final") == "true", + IsReturnEnumified = elem.Attribute ("enumReturn") != null, + IsStatic = elem.XGetAttribute ("static") == "true", + JavaName = elem.XGetAttribute ("name"), + ManagedReturn = elem.XGetAttribute ("managedReturn"), + PropertyNameOverride = elem.XGetAttribute ("propertyName"), + Return = elem.XGetAttribute ("return"), + SourceApiLevel = GetApiLevel (elem.XGetAttribute ("merge.SourceFile")), + Visibility = elem.Visibility () + }; + + method.IsVirtual = !method.IsStatic && elem.XGetAttribute ("final") == "false"; + + if (elem.Attribute ("managedName") != null) + method.Name = elem.XGetAttribute ("managedName"); + else + method.Name = StringRocks.MemberToPascalCase (method.JavaName); + + if (method.IsReturnEnumified) { + method.ManagedReturn = elem.XGetAttribute ("enumReturn"); + + // FIXME: this should not require enumReturn. Somewhere in generator uses this property improperly. + method.Return = method.ManagedReturn; + } + + if (declaringType is InterfaceGen) + method.IsInterfaceDefaultMethod = !method.IsAbstract && !method.IsStatic; + + foreach (var child in elem.Elements ()) { + if (child.Name == "parameter") + method.Parameters.Add (CreateParameter (child)); + } + + method.FillReturnType (); + + return method; + } + + public static Parameter CreateParameter (XElement elem) + { + string managedName = elem.XGetAttribute ("managedName"); + string name = !string.IsNullOrEmpty (managedName) ? managedName : SymbolTable.MangleName (elem.XGetAttribute ("name")); + string java_type = elem.XGetAttribute ("type"); + string enum_type = elem.Attribute ("enumType") != null ? elem.XGetAttribute ("enumType") : null; + string managed_type = elem.Attribute ("managedType") != null ? elem.XGetAttribute ("managedType") : null; + // FIXME: "enum_type ?? java_type" should be extraneous. Somewhere in generator uses it improperly. + var result = new Parameter (name, enum_type ?? java_type, enum_type ?? managed_type, enum_type != null, java_type); + if (elem.Attribute ("sender") != null) + result.IsSender = true; + return result; + } + + public static Parameter CreateParameterFromClassElement (XElement elem) + { + string name = "__self"; + string java_type = elem.XGetAttribute ("name"); + string java_package = elem.Parent.XGetAttribute ("name"); + return new Parameter (name, java_package + "." + java_type, null, false); + } + + static int GetApiLevel (string source) + { + if (source == null) + return 0; + + var m = api_level.Match (source); + + if (!m.Success) + return 0; + + if (int.TryParse (m.Groups [1].Value, out var api)) + return api; + + return 0; + } + + static XElement GetPreviousClass (XNode n, string nameValue) + { + XElement e = null; + + while (n != null && + ((e = n as XElement) == null || + e.Name != "class" || + !e.XGetAttribute ("name").StartsWith (nameValue, StringComparison.Ordinal) || + // this complicated check (instead of simple name string equivalence match) is required for nested class inside a generic class e.g. android.content.Loader.ForceLoadContentObserver. + (e.XGetAttribute ("name") != nameValue && e.XGetAttribute ("name").IndexOf ('<') < 0))) { + n = n.PreviousNode; + } + + return e; + } + + static bool IsObfuscatedName (int threshold, string name) + { + if (name.StartsWith ("R.", StringComparison.Ordinal)) + return false; + int idx = name.LastIndexOf ('.'); + string last = idx < 0 ? name : name.Substring (idx + 1); + // probably new proguard within Gradle tasks, used in recent GooglePlayServices in 2016 or later. + if (last.StartsWith ("zz", StringComparison.Ordinal)) + return true; + // do not expect any name with more than 3 letters is an 'obfuscated' one. + if (last.Length > 3) + return false; + // Only short ones ('a', 'b', 'c' ... 'aa', 'ab', ... 'zzz') are the targets. + if (!(last.Length == 3 && threshold > 26 * 26 || last.Length == 2 && threshold > 26 || last.Length == 1)) + return false; + if (last.Any (c => (c < 'a' || 'z' < c) && (c < '0' || '9' < c))) + return false; + return true; + } + + static bool IsPrefixableName (string name) + { + // IBlahBlah is not prefixed with 'I' + return name.Length <= 2 || name [0] != 'I' || !char.IsUpper (name [1]); + } + } +} diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs index ef17d8655..fc1c84ea5 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs @@ -7,61 +7,42 @@ namespace MonoDroid.Generation { - - public abstract class ClassGen : GenBase { - - bool needs_new; - bool inherits_object; - List ctors = new List (); - List explicitly_implemented_iface_methods = new List (); // do not initialize here; see FixupMethodOverides() + public class ClassGen : GenBase + { bool fill_explicit_implementation_started; - protected ClassGen (GenBaseSupport support) - : base (support) + public List Ctors { get; private set; } = new List (); + + public ClassGen (GenBaseSupport support) : base (support) { - inherits_object = true; - if (Namespace == "Java.Lang" && (Name == "Object" || Name == "Throwable")) - inherits_object = false; - } + InheritsObject = true; - public override string DefaultValue { - get { return "IntPtr.Zero"; } - } + if (Namespace == "Java.Lang" && (Name == "Object" || Name == "Throwable")) + InheritsObject = false; - internal bool InheritsObject { - get { return inherits_object; } - } - - public List ExplicitlyImplementedInterfaceMethods { - get { return explicitly_implemented_iface_methods; } + DefaultValue = "IntPtr.Zero"; + NativeType = "IntPtr"; } - public abstract bool IsAbstract { get; } - - public abstract bool IsFinal { get; } - - public override string NativeType { - get { return "IntPtr"; } + static void AddNestedInterfaceTypes (GenBase type, List nestedInterfaces) + { + foreach (var nt in type.NestedTypes) { + if (nt is InterfaceGen ni) + nestedInterfaces.Add (new InterfaceExtensionInfo { + DeclaringType = type.FullName.Substring (type.Namespace.Length + 1).Replace (".", "_"), + Type = ni + }); + else + AddNestedInterfaceTypes (nt, nestedInterfaces); + } } - public IList Ctors { - get { return ctors; } - } + public override ClassGen BaseGen => + (base_symbol is GenericSymbol ? (base_symbol as GenericSymbol).Gen : base_symbol) as ClassGen; - public abstract string BaseType { get; set; } + public string BaseType { get; set; } - public bool NeedsNew { - get => needs_new; - set => needs_new = value; - } - - public bool ContainsCtor (string jni_sig) - { - foreach (Ctor c in ctors) - if (c.JniSignature == jni_sig) - return true; - return false; - } + public bool ContainsCtor (string jni_sig) => Ctors.Any (c => c.JniSignature == jni_sig); public bool ContainsNestedType (GenBase gen) { @@ -71,73 +52,12 @@ public bool ContainsNestedType (GenBase gen) return HasNestedType (gen.Name); } - public override string ToNative (CodeGenerationOptions opt, string varname, Dictionary mappings = null) - { - return String.Format ("JNIEnv.ToLocalJniHandle ({0})", varname); - } - - public override string FromNative (CodeGenerationOptions opt, string varname, bool owned) - { - return String.Format ("global::Java.Lang.Object.GetObject<{0}> ({1}, {2})", opt.GetOutputName (FullName), varname, owned ? "JniHandleOwnership.TransferLocalRef" : "JniHandleOwnership.DoNotTransfer"); - } - - public override void ResetValidation () - { - validated = false; - base.ResetValidation (); - } - - protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) - { - if (validated) - return is_valid; - - validated = true; - - if (!support.OnValidate (opt)) { - is_valid = false; - return false; - } - - // We're validating this in prior to BaseType. - if (TypeParameters != null && !TypeParameters.Validate (opt, type_params, context)) { - is_valid = false; - return false; - } - - if (Char.IsNumber (Name [0])) { - // it is an anonymous class which does not need output. - is_valid = false; - return false; - } - - base_symbol = IsAnnotation ? opt.SymbolTable.Lookup ("java.lang.Object") : BaseType != null ? opt.SymbolTable.Lookup (BaseType) : null; - if (base_symbol == null && FullName != "Java.Lang.Object" && FullName != "System.Object") { - Report.Warning (0, Report.WarningClassGen + 2, "Class {0} has unknown base type {1}.", FullName, BaseType); - is_valid = false; - return false; - } - - if ((base_symbol != null && !base_symbol.Validate (opt, TypeParameters, context)) || !base.OnValidate (opt, type_params, context)) { - Report.Warning (0, Report.WarningClassGen + 3, "Class {0} has invalid base type {1}.", FullName, BaseType); - is_valid = false; - return false; - } - - List valid_ctors = new List (); - foreach (Ctor c in ctors) - if (c.Validate (opt, TypeParameters, context)) - valid_ctors.Add (c); - ctors = valid_ctors; - - return true; - } + public List ExplicitlyImplementedInterfaceMethods { get; } = new List (); // do not initialize here; see FixupMethodOverides() public override void FixupAccessModifiers (CodeGenerationOptions opt) { while (!IsAnnotation && !string.IsNullOrEmpty (BaseType)) { - var baseClass = opt.SymbolTable.Lookup (BaseType) as ClassGen; - if (baseClass != null && RawVisibility == "public" && baseClass.RawVisibility != "public") { + if (opt.SymbolTable.Lookup (BaseType) is ClassGen baseClass && RawVisibility == "public" && baseClass.RawVisibility != "public") { //Skip the BaseType and copy over any "missing" methods foreach (var baseMethod in baseClass.Methods) { var method = Methods.FirstOrDefault (m => m.Matches (baseMethod)); @@ -152,21 +72,20 @@ public override void FixupAccessModifiers (CodeGenerationOptions opt) base.FixupAccessModifiers (opt); } - + public override void FixupExplicitImplementation () { if (fill_explicit_implementation_started) return; // already done. fill_explicit_implementation_started = true; - if (BaseGen != null && BaseGen.explicitly_implemented_iface_methods == null) + if (BaseGen != null && BaseGen.ExplicitlyImplementedInterfaceMethods == null) BaseGen.FixupExplicitImplementation (); foreach (InterfaceGen iface in GetAllDerivedInterfaces ()) { if (iface.IsGeneric) { bool skip = false; foreach (ISymbol isym in Interfaces) { - var gs = isym as GenericSymbol; - if (gs != null && gs.IsConcrete && gs.Gen == iface) + if (isym is GenericSymbol gs && gs.IsConcrete && gs.Gen == iface) skip = true; } if (skip) @@ -182,10 +101,10 @@ public override void FixupExplicitImplementation () else if (m.IsGeneric) doExplicitly = true; if (doExplicitly) - explicitly_implemented_iface_methods.Add (sig); + ExplicitlyImplementedInterfaceMethods.Add (sig); } } - + // Keep in sync with Generate() that generates explicit iface method impl. foreach (ISymbol isym in Interfaces) { if (isym is GenericSymbol) { @@ -193,7 +112,7 @@ public override void FixupExplicitImplementation () if (gs.IsConcrete) { foreach (Method m in gs.Gen.Methods) if (m.IsGeneric) { - explicitly_implemented_iface_methods.Add (m.GetSignature ()); + ExplicitlyImplementedInterfaceMethods.Add (m.GetSignature ()); } } } @@ -203,38 +122,10 @@ public override void FixupExplicitImplementation () nt.FixupExplicitImplementation (); } - public override ClassGen BaseGen { - get { return (base_symbol is GenericSymbol ? (base_symbol as GenericSymbol).Gen : base_symbol) as ClassGen; } - } + public override string FromNative (CodeGenerationOptions opt, string varname, bool owned) => + $"global::Java.Lang.Object.GetObject<{opt.GetOutputName (FullName)}> ({varname}, {(owned ? "JniHandleOwnership.TransferLocalRef" : "JniHandleOwnership.DoNotTransfer")})"; - internal IEnumerable GetNestedInterfaceTypes () - { - var nestedInterfaces = new List (); - AddNestedInterfaceTypes (this, nestedInterfaces); - return nestedInterfaces; - } - - static void AddNestedInterfaceTypes (GenBase type, List nestedInterfaces) - { - foreach (GenBase nt in type.NestedTypes) { - InterfaceGen ni = nt as InterfaceGen; - if (ni != null) - nestedInterfaces.Add (new InterfaceExtensionInfo { - DeclaringType = type.FullName.Substring (type.Namespace.Length+1).Replace (".","_"), - Type = ni - }); - else - AddNestedInterfaceTypes (nt, nestedInterfaces); - } - } - - public bool IsExplicitlyImplementedMethod (string sig) - { - for (ClassGen c = this; c != null; c = c.BaseGen) - if (c.explicitly_implemented_iface_methods.Contains (sig)) - return true; - return false; - } + public bool FromXml { get; set; } public override void Generate (CodeGenerationOptions opt, GenerationInfo gen_info) { @@ -256,6 +147,14 @@ public override void Generate (CodeGenerationOptions opt, GenerationInfo gen_inf } } + public static void GenerateEnumList (GenerationInfo gen_info) + { + using (var sw = new StreamWriter (File.Create (Path.Combine (gen_info.CSharpDir, "enumlist")))) { + foreach (string e in gen_info.Enums.OrderBy (p => p, StringComparer.OrdinalIgnoreCase)) + sw.WriteLine (e); + } + } + public static void GenerateTypeRegistrations (CodeGenerationOptions opt, GenerationInfo gen_info) { using (var sw = gen_info.OpenStream (opt.GetFileName ("Java.Interop.__TypeRegistrations"))) { @@ -267,8 +166,7 @@ public static void GenerateTypeRegistrations (CodeGenerationOptions opt, Generat if (JavaNativeTypeManager.ToCliType (reg.Key) == reg.Value) continue; - List> v; - if (!mapping.TryGetValue (package, out v)) + if (!mapping.TryGetValue (package, out var v)) mapping.Add (package, v = new List> ()); v.Add (new KeyValuePair (reg.Key, reg.Value)); } @@ -334,21 +232,94 @@ public static void GenerateTypeRegistrations (CodeGenerationOptions opt, Generat } } - public static void GenerateEnumList (GenerationInfo gen_info) - { - using (var sw = new StreamWriter (File.Create (Path.Combine (gen_info.CSharpDir, "enumlist")))) { - foreach (string e in gen_info.Enums.OrderBy (p => p, StringComparer.OrdinalIgnoreCase)) - sw.WriteLine (e); - } - } - protected override bool GetEnumMappedMemberInfo () { foreach (var m in Ctors) return true; + return base.GetEnumMappedMemberInfo (); } - + + internal IEnumerable GetNestedInterfaceTypes () + { + var nestedInterfaces = new List (); + AddNestedInterfaceTypes (this, nestedInterfaces); + return nestedInterfaces; + } + + public bool InheritsObject { get; set; } + + public bool IsAbstract { get; set; } + + public bool IsExplicitlyImplementedMethod (string sig) + { + for (var c = this; c != null; c = c.BaseGen) + if (c.ExplicitlyImplementedInterfaceMethods.Contains (sig)) + return true; + return false; + } + + public bool IsFinal { get; set; } + + public bool NeedsNew { get; set; } + + protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) + { + if (validated) + return IsValid; + + validated = true; + + if (!support.OnValidate (opt)) { + IsValid = false; + return false; + } + + // We're validating this in prior to BaseType. + if (TypeParameters != null && !TypeParameters.Validate (opt, type_params, context)) { + IsValid = false; + return false; + } + + if (char.IsNumber (Name [0])) { + // it is an anonymous class which does not need output. + IsValid = false; + return false; + } + + base_symbol = IsAnnotation ? opt.SymbolTable.Lookup ("java.lang.Object") : BaseType != null ? opt.SymbolTable.Lookup (BaseType) : null; + if (base_symbol == null && FullName != "Java.Lang.Object" && FullName != "System.Object") { + Report.Warning (0, Report.WarningClassGen + 2, "Class {0} has unknown base type {1}.", FullName, BaseType); + IsValid = false; + return false; + } + + if ((base_symbol != null && !base_symbol.Validate (opt, TypeParameters, context)) || !base.OnValidate (opt, type_params, context)) { + Report.Warning (0, Report.WarningClassGen + 3, "Class {0} has invalid base type {1}.", FullName, BaseType); + IsValid = false; + return false; + } + + var valid_ctors = new List (); + + foreach (var c in Ctors) + if (c.Validate (opt, TypeParameters, context)) + valid_ctors.Add (c); + + Ctors = valid_ctors; + + return true; + } + + public override void ResetValidation () + { + validated = false; + base.ResetValidation (); + } + + public override string ToNative (CodeGenerationOptions opt, string varname, Dictionary mappings = null) => + $"JNIEnv.ToLocalJniHandle ({varname})"; + public override void UpdateEnumsInInterfaceImplementation () { foreach (InterfaceGen iface in GetAllDerivedInterfaces ()) { @@ -369,4 +340,3 @@ public override void UpdateEnumsInInterfaceImplementation () } } } - diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Ctor.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Ctor.cs index acd36a433..0848e9497 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Ctor.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Ctor.cs @@ -4,31 +4,29 @@ namespace MonoDroid.Generation { - - public abstract class Ctor : MethodBase { - - protected Ctor (GenBase declaringType) - : base (declaringType) + public class Ctor : MethodBase + { + public Ctor (GenBase declaringType) : base (declaringType) { } - - public abstract bool IsNonStaticNestedType { get; } - public abstract string CustomAttributes { get; } - string jni_sig; - public string JniSignature { - get { return jni_sig; } - } + public string CustomAttributes { get; set; } + public bool IsNonStaticNestedType { get; set; } + public string JniSignature { get; private set; } + public bool MissingEnclosingClass { get; set; } - public string ID { - get { return "id_ctor" + IDSignature; } - } + public string ID => "id_ctor" + IDSignature; protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList tps, CodeGeneratorContext context) { + if (MissingEnclosingClass) + return false; + if (!base.OnValidate (opt, tps, context)) return false; - jni_sig = "(" + Parameters.JniSignature + ")V"; + + JniSignature = "(" + Parameters.JniSignature + ")V"; + return true; } } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs index ad8a6cc56..b74ba3d8a 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs @@ -1,42 +1,58 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Xml; - using MonoDroid.Utils; namespace MonoDroid.Generation { + public class Field : ApiVersionsSupport.IApiAvailability + { + public string Annotation { get; set; } + public int ApiAvailableSince { get; set; } + public string DeprecatedComment { get; set; } + public bool IsAcw { get; set; } + public bool IsDeprecated { get; set; } + public bool IsEnumified { get; set; } + public bool IsFinal { get; set; } + public bool IsStatic { get; set; } + public ParameterList SetParameters { get; private set; } + public ISymbol Symbol { get; private set; } + public string JavaName { get; set; } + public string Name { get; set; } + public Parameter SetterParameter { get; set; } + public string TypeName { get; set; } + public string Value { get; set; } + public string Visibility { get; set; } - public abstract class Field : ApiVersionsSupport.IApiAvailability { - - public virtual bool IsAcw { - get { return true; } - } - - public abstract bool IsDeprecated { get; } - - public abstract string DeprecatedComment { get; } - - public abstract bool IsFinal { get; } + internal string GetMethodPrefix => (Symbol is SimpleSymbol || Symbol.IsEnum) ? StringRocks.MemberToPascalCase (Symbol.JavaName) : "Object"; - public abstract bool IsStatic { get; } + internal string ID => JavaName + "_jfieldId"; - public abstract string JavaName { get; } + public bool IsConst => IsFinal && IsStatic; - public abstract bool IsEnumified { get; } + public bool NeedsProperty => !IsStatic || !IsFinal || string.IsNullOrEmpty (Value) || Symbol.IsArray || !primitive_types.Contains (Symbol.JavaName); - public abstract string TypeName { get; } + public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) + { + Symbol = opt.SymbolTable.Lookup (TypeName, type_params); - public abstract string Name { get; set; } + if (Symbol == null || !Symbol.Validate (opt, type_params, context)) { + Report.Warning (0, Report.WarningField + 0, "unexpected field type {0} {1}.", TypeName, context.ContextString); + return false; + } - public abstract string Value { get; } + if (!string.IsNullOrEmpty (Value) && Symbol != null && Symbol.FullName == "char" && !Value.StartsWith ("(char)")) + Value = "(char)" + Value; - public abstract string Visibility { get; } + SetParameters = new ParameterList { + SetterParameter, + }; - public int ApiAvailableSince { get; set; } + if (!SetParameters.Validate (opt, type_params, context)) + throw new NotSupportedException ( + string.Format ("Unable to generate setter parameter list {0}", context.ContextString)); - protected abstract Parameter SetterParameter { get; } + return true; + } static readonly HashSet primitive_types = new HashSet { "boolean", @@ -52,54 +68,5 @@ public virtual bool IsAcw { // within the api.xml description. "java.lang.String", }; - - ISymbol symbol; - - ParameterList setParameters; - - internal string GetMethodPrefix { - get { return (Symbol is SimpleSymbol || Symbol.IsEnum) ? StringRocks.MemberToPascalCase (Symbol.JavaName) : "Object"; } - } - - public bool IsConst { - get { return IsFinal && IsStatic; } - } - - public bool NeedsProperty { - get { return !IsStatic || !IsFinal || String.IsNullOrEmpty (Value) || Symbol.IsArray || !primitive_types.Contains (Symbol.JavaName); } - } - - public ISymbol Symbol { - get { return symbol; } - } - - internal string ID { - get { return JavaName + "_jfieldId"; } - } - - internal ParameterList SetParameters { - get { return setParameters; } - } - - public string Annotation { get; internal set; } - - public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) - { - symbol = opt.SymbolTable.Lookup (TypeName, type_params); - - if (symbol == null || !symbol.Validate (opt, type_params, context)) { - Report.Warning (0, Report.WarningField + 0, "unexpected field type {0} {1}.", TypeName, context.ContextString); - return false; - } - - setParameters = new ParameterList () { - SetterParameter, - }; - if (!setParameters.Validate (opt, type_params, context)) - throw new NotSupportedException ( - string.Format ("Unable to generate setter parameter list {0}", context.ContextString)); - - return true; - } } } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index 611622baa..57377bb1c 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -1,436 +1,94 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Reflection; -using System.Xml; - -using MonoDroid.Utils; -using System.Runtime.InteropServices; -using System.Collections; -using System.Security.Policy; -using System.Text; using MonoDroid.Generation.Utilities; -namespace MonoDroid.Generation { - - public abstract class GenBase : IGeneratable, ApiVersionsSupport.IApiAvailability { - - protected GenBase (GenBaseSupport support) - { - this.support = support; - } - - protected GenBaseSupport support; - - Dictionary jni_sig_hash = new Dictionary (); - Dictionary prop_hash = new Dictionary (); - List fields = new List (); - List methods = new List (); - List props = new List (); - +namespace MonoDroid.Generation +{ + public abstract class GenBase : IGeneratable, ApiVersionsSupport.IApiAvailability + { + bool enum_updated; + bool property_filled; + bool property_filling; + protected internal ISymbol base_symbol; protected bool iface_validation_failed; - protected bool is_valid = true; + protected GenBaseSupport support; protected bool validated = false; - bool has_virtual_methods; - bool method_validation_failed; - bool property_filled; - bool? has_enum_mapped_members; - - public abstract string DefaultValue { get; } - - public bool HasEnumMappedMembers { - get { - if (has_enum_mapped_members == null) - has_enum_mapped_members = GetEnumMappedMemberInfo (); - return (bool) has_enum_mapped_members; - } - } - - public bool IsAcw { - get { return support.IsAcw; } - } - - public bool IsDeprecated { - get { return support.IsDeprecated; } - } - - public bool IsObfuscated { - get { return support.IsObfuscated; } - } - - public string DeprecatedComment { - get { return support.DeprecatedComment; } - } - - public bool IsGeneratable { - get { return support.IsGeneratable; } - } - - public virtual ClassGen BaseGen { - get { return null; } - } - - public bool ShouldGenerateAnnotationAttribute { - get { return IsAnnotation; } - } - - protected bool HasVirtualMethods { - get { return has_virtual_methods; } - } - - public bool IsGeneric { - get { return support.IsGeneric; } - } - - public string FullName { - get { return support.FullName; } - set { support.FullName = value; } - } - - public int ApiAvailableSince { get; set; } - - public bool IsEnum { - get { return false; } - } - - public bool IsArray { - get { return false; } - } - - public bool IsValid => is_valid; - - public string ElementType { - get { return null; } - } - - public string PackageName { - get { return support.PackageName; } - set { support.PackageName = value; } - } - - public string JavaSimpleName { - get { return support.JavaSimpleName; } - } - - public string JavaName { - get { return String.Format ("{0}.{1}", PackageName, JavaSimpleName); } - } - - public string TypeNamePrefix { - get { return support.TypeNamePrefix; } - } - - // not: not currently assembly qualified, but it uses needed - // Type.GetType() conventions such as '/' for nested types. - public string AssemblyQualifiedName { - get { return Namespace + "." + FullName.Substring (Namespace.Length + 1).Replace ('.', '/'); } - } - - public string RawJniName { - get { return PackageName.Replace ('.', '/') + "/" + JavaSimpleName.Replace ('.', '$'); } - } - - public string JniName { - get { return "L" + RawJniName + ";"; } - } - - /* - public string Marshaler { - get { return support.Marshaler; } - } - */ - - protected bool MethodValidationFailed { - get { return method_validation_failed; } - } - - public string Name { - get { return support.Name; } - set { support.Name = value; } - } - - public string Namespace { - get { return support.Namespace; } - } - - public abstract string NativeType { get; } - - public List Fields { - get { return fields; } - } - - List ifaces = new List (); - public List Interfaces { - get { return ifaces; } - } - - public bool IsAnnotation { - get { return iface_names.Any (n => n == "Java.Lang.Annotation.Annotation" || n == "java.lang.annotation.Annotation"); } - } - - public string MetadataXPathReference { - get { - string type = null; - if (this is ClassGen) - type = "class"; - if (this is InterfaceGen) - type = "interface"; - if (type == null) - throw new InvalidOperationException ("Uh...xpath? this is " + this.GetType ().FullName); - return string.Format ("/api/package[@name='{0}']/{1}[@name='{2}']", - PackageName, type, JavaSimpleName); - } - } - - public string GetObjectHandleProperty (string variable) - { - var handleType = "Java.Lang.Object"; - if (IsThrowable ()) - handleType = "Java.Lang.Throwable"; - - return $"((global::{handleType}) {variable}).Handle"; - } - - bool IsThrowable () - { - if (FullName == "Java.Lang.Throwable" || Ancestors ().Any (a => a.FullName == "Java.Lang.Throwable")) - return true; - return false; - } - public bool RequiresNew (string memberName) - { - if (ObjectRequiresNew.Contains (memberName)) { - return true; - } - if (IsThrowable () && ThrowableRequiresNew.Contains (memberName)) { - return true; - } - return false; - } + readonly List implemented_interfaces = new List (); + readonly Dictionary jni_sig_hash = new Dictionary (); + readonly Dictionary prop_hash = new Dictionary (); - protected internal IEnumerable GetAllImplementedInterfaces () + protected GenBase (GenBaseSupport support) { - var set = new HashSet (); - Action visit = null; - visit = isym => { - var gsym = isym as GenericSymbol; - var igen = (gsym != null ? gsym.Gen : isym) as InterfaceGen; - if (igen != null) - set.Add (igen); - GenBase b = isym as GenBase; - if (b == null) - return; - foreach (var i in b.Interfaces) { - visit (i); - } - }; - foreach (var i in Interfaces) - visit (i); - return set; - } - - public List Methods { - get { return methods; } - } - - public List Properties { - get { return props; } - } - - public GenericParameterDefinitionList TypeParameters { - get { return support.TypeParameters; } - } - - public string RawVisibility { - get { return support.Visibility; } - } - - public string Visibility { - get { return String.IsNullOrEmpty (support.Visibility) ? "public" : support.Visibility; } + this.support = support; } - protected void AddField (Field f) - { - fields.Add (f); - } + public List Fields { get; private set; } = new List (); + public List Interfaces { get; } = new List (); + public List Methods { get; private set; } = new List (); + public List NestedTypes { get; private set; } = new List (); + public List Properties { get; } = new List (); + public string DefaultValue { get; set; } + public bool HasVirtualMethods { get; set; } - List iface_names = new List (); - protected void AddInterface (string name) + public void AddField (Field f) { - iface_names.Add (name); - } - - List nested_types = new List (); - public List NestedTypes { - get { return nested_types; } + Fields.Add (f); } - protected internal bool HasNestedType (string name) + public void AddImplementedInterface (string name) { - foreach (GenBase g in NestedTypes) - if (g.Name == name) - return true; - return false; + implemented_interfaces.Add (name); } - protected void AddMethod (Method m) + public void AddMethod (Method m) { - methods.Add (m); + Methods.Add (m); } public virtual void AddNestedType (GenBase gen) { - foreach (GenBase nest in NestedTypes) { + foreach (var nest in NestedTypes) { if (gen.JavaName.StartsWith (nest.JavaName + ".")) { nest.AddNestedType (gen); return; } } - List removes = new List (); - foreach (GenBase nest in NestedTypes) { + var removes = new List (); + + foreach (var nest in NestedTypes) { if (nest.JavaName.StartsWith (gen.JavaName + ".")) { gen.AddNestedType (nest); removes.Add (nest); } } - foreach (GenBase rmv in removes) + foreach (var rmv in removes) NestedTypes.Remove (rmv); NestedTypes.Add (gen); } - public virtual string GetGenericType (Dictionary mappings) - { - return null; - } - - public abstract string FromNative (CodeGenerationOptions opt, string varname, bool owned); - public abstract string ToNative (CodeGenerationOptions opt, string varname, Dictionary mappings = null); - - public abstract void Generate (CodeGenerationOptions opt, GenerationInfo gen_info); - - public IEnumerable Invalidate () - { - is_valid = false; - validated = true; - - foreach (var nt in NestedTypes) { - foreach (var sub in nt.Invalidate ()) - yield return sub; - yield return nt; - } - } - - public bool ContainsMethod (string name_and_jnisig) - { - return jni_sig_hash.ContainsKey (name_and_jnisig); - } - - public bool ContainsMethod (Method method, bool check_ifaces) - { - return ContainsMethod (method, check_ifaces, true); - } - - public bool ContainsMethod (Method method, bool check_ifaces, bool check_base_ifaces) - { - // background: bug #10123. - // Visibility check was introduced - and required so far - to block "public overrides protected" methods - // (which is allowed in Java but not in C#). - // The problem is, it does not *always* result in error and generates callable code, and we depend on - // that fact in several classes that implements some interface that requires "public Object clone()". - // - // This visibility inconsistency results in 1) error for abstract methods and 2) warning for virtual methods. - // Hence, for abstract methods we dare to ignore visibility difference and treat it as override, - // *then* C# compiler will report this inconsistency as error that users need to fix manually, but - // with obvious message saying "it is because of visibility consistency", - // not "abstract member not implemented" (it is *implemented* in different visibility and brings confusion). - // For virtual methods, just check the visibility difference and treat as different method. - // Regardless of whether it is actually an override or not, we just invoke Java method. - if (jni_sig_hash.ContainsKey (method.JavaName + method.JniSignature)) { - var bm = jni_sig_hash [method.JavaName + method.JniSignature]; - if (bm.Visibility == method.Visibility || bm.IsAbstract) - return true; - } - if (check_ifaces) { - foreach (ISymbol isym in Interfaces) { - InterfaceGen igen = (isym is GenericSymbol ? (isym as GenericSymbol).Gen : isym) as InterfaceGen; - if (igen != null && igen.ContainsMethod (method, true)) - return true; - } - } - return BaseSymbol != null && BaseSymbol.ContainsMethod (method, check_base_ifaces, check_base_ifaces); - } - - public bool IsCovariantMethod (Method method) - { - return Methods.Any (m => m.Name == method.Name && ParameterList.Equals (m.Parameters, method.Parameters)); - // TODO: check that method.ReturnType is a superclass of m.ReturnType - } - - public bool ContainsProperty (string name, bool check_ifaces) - { - return ContainsProperty (name, check_ifaces, true); - } - - public Property GetPropertyByName (string name, bool check_ifaces) - { - return GetPropertyByName (name, check_ifaces, true); - } - - public bool ContainsProperty (string name, bool check_ifaces, bool check_base_ifaces) - { - return GetPropertyByName (name, check_ifaces, check_base_ifaces) != null; - } - - public Property GetPropertyByName (string name, bool check_ifaces, bool check_base_ifaces) - { - if (prop_hash.ContainsKey (name)) - return prop_hash [name]; - if (check_ifaces) { - foreach (ISymbol isym in Interfaces) { - InterfaceGen igen = (isym is GenericSymbol ? (isym as GenericSymbol).Gen : isym) as InterfaceGen; - if (igen == null) - continue; - var ret = igen.GetPropertyByName (name, true); - if (ret != null) - return ret; - } - } - return BaseSymbol != null ? BaseSymbol.GetPropertyByName (name, check_base_ifaces, check_base_ifaces) : null; - } - - public bool ContainsName (string name) - { - if (HasNestedType (name) || ContainsProperty (name, true)) - return true; - foreach (Method m in methods) - if (m.Name == name) - return true; - return false; - } - - bool ValidateMethod (CodeGenerationOptions opt, Method m, CodeGeneratorContext context) + void AdjustNestedTypeFullName (GenBase parent) { - if (!m.Validate (opt, TypeParameters, context)) { - return false; - } - return true; + if (parent is ClassGen) + foreach (var nested in parent.NestedTypes) + nested.FullName = parent.FullName + "." + nested.Name; } void AddPropertyAccessors () { // First pass extracts getters and creates property hash List unmatched = new List (); - foreach (Method m in methods) { + foreach (Method m in Methods) { if (m.IsPropertyAccessor) { string prop_name = m.PropertyName; - if (m.CanSet || prop_name == String.Empty || Name == prop_name || m.Name == "GetHashCode" || HasNestedType (prop_name) || IsInfrastructural (prop_name)) + if (m.CanSet || prop_name == string.Empty || Name == prop_name || m.Name == "GetHashCode" || HasNestedType (prop_name) || IsInfrastructural (prop_name)) unmatched.Add (m); - else if (BaseGen != null && !BaseGen.prop_hash.ContainsKey (prop_name) && BaseGen.Methods.Any (mm => mm.Name == m.Name && ReturnTypeMatches (m, BaseGen, mm) && ParameterList.Equals (mm.Parameters, m.Parameters))) + else if (BaseGen != null && !BaseGen.prop_hash.ContainsKey (prop_name) && BaseGen.Methods.Any (mm => mm.Name == m.Name && ReturnTypeMatches(m, mm) && ParameterList.Equals (mm.Parameters, m.Parameters))) // this is to filter out those method that was *not* a property // in the base type for some reason (e.g. name overlap). // For example, android.graphics.drawable.BitmapDrawable#getConstantState() @@ -446,28 +104,29 @@ void AddPropertyAccessors () prop_hash [prop_name].Getter = m; } } else { - Property prop = new Property (prop_name); - prop.Getter = m; + var prop = new Property (prop_name) { + Getter = m + }; prop_hash [prop_name] = prop; } } } else unmatched.Add (m); } - methods = unmatched; + Methods = unmatched; // Second pass adds setters unmatched = new List (); - foreach (Method m in methods) { + foreach (Method m in Methods) { if (!m.CanSet) { unmatched.Add (m); continue; } - - if (Ancestors ().All (a => !a.prop_hash.ContainsKey (m.PropertyName)) && Ancestors ().Any (a => a.Methods.Any (mm => mm.Name == m.Name && ReturnTypeMatches (m, a, mm) && ParameterList.Equals (mm.Parameters, m.Parameters)))) + + if (Ancestors ().All (a => !a.prop_hash.ContainsKey (m.PropertyName)) && Ancestors ().Any (a => a.Methods.Any (mm => mm.Name == m.Name && ReturnTypeMatches(m, mm) && ParameterList.Equals (mm.Parameters, m.Parameters)))) unmatched.Add (m); // base setter exists, and it was not a property. else if (prop_hash.ContainsKey (m.PropertyName)) { - Property baseProp = BaseGen != null ? BaseGen.Properties.FirstOrDefault (p => p.Name == m.PropertyName) : null; + Property baseProp = BaseGen?.Properties.FirstOrDefault (p => p.Name == m.PropertyName); var prop = prop_hash [m.PropertyName]; if (prop.Getter.RetVal.FullName == m.Parameters [0].Type && prop.Getter.IsAbstract == m.IsAbstract && // SearchIterator abstract getIndex() and non-abstract setIndex() @@ -494,33 +153,28 @@ void AddPropertyAccessors () if (m.GenerateDispatchingSetter && prop_hash.ContainsKey (m.PropertyName)) prop_hash [m.PropertyName].GenerateDispatchingSetter = true; } - methods = unmatched; + Methods = unmatched; } - + IEnumerable Ancestors () { for (var g = BaseGen; g != null; g = g.BaseGen) yield return g; } - IEnumerable Descendants (IList gens) - { - foreach (var directDescendants in gens.Where (x => x.BaseGen == this)) { - yield return directDescendants; - foreach (var indirectDescendants in directDescendants.Descendants (gens)) { - yield return indirectDescendants; - } - } - } + // not: not currently assembly qualified, but it uses needed + // Type.GetType() conventions such as '/' for nested types. + public string AssemblyQualifiedName => + $"{Namespace}.{FullName.Substring (Namespace.Length + 1).Replace ('.', '/')}"; - bool ReturnTypeMatches (Method m, GenBase gen, Method mm) - { - if (mm.RetVal.FullName == m.RetVal.FullName) - return true; - if (BaseSymbol.IsGeneric && mm.RetVal.IsGeneric) - return true; // sloppy but pass - return false; - } + public int ApiAvailableSince { get; set; } + + public virtual ClassGen BaseGen => null; + + public GenBase BaseSymbol => + (base_symbol is GenericSymbol ? (base_symbol as GenericSymbol).Gen : base_symbol) as GenBase; + + public string Call (CodeGenerationOptions opt, string var_name) => opt.GetSafeIdentifier (var_name); bool CanMethodBeIsStyleSetter (Method m) { @@ -532,181 +186,65 @@ bool CanMethodBeIsStyleSetter (Method m) return GetAllDerivedInterfaces ().All (iface => !iface.Properties.Any (p => p.Name == "Is" + m.PropertyName && p.Setter == null)); } - static readonly HashSet ObjectRequiresNew = new HashSet( - typeof (object) - .GetMethods () - .Where (m => !m.Attributes.HasFlag (MethodAttributes.SpecialName) && - !m.Attributes.HasFlag (MethodAttributes.RTSpecialName)) - .Select (m => m.Name) - .Concat (new[] { "Handle" }), - StringComparer.OrdinalIgnoreCase); - - static readonly HashSet ThrowableRequiresNew = new HashSet( - typeof (System.Exception) - .GetMethods () - .Where (m => !m.Attributes.HasFlag (MethodAttributes.SpecialName) && - !m.Attributes.HasFlag (MethodAttributes.RTSpecialName)) - .Select (m => m.Name) - .Concat (typeof (System.Exception).GetProperties ().Select (p => p.Name)) - .Concat (new[] { "Handle" }), - StringComparer.OrdinalIgnoreCase); - - bool IsInfrastructural (string name) - { - // some names are reserved for use by us, e.g. we don't want another - // Handle property, as that conflicts with Java.Lang.Object.Handle. - return ObjectRequiresNew.Contains (name); - } + public bool ContainsMethod (string name_and_jnisig) => jni_sig_hash.ContainsKey (name_and_jnisig); - protected internal ISymbol base_symbol; - public GenBase BaseSymbol { - get { return (base_symbol is GenericSymbol ? (base_symbol as GenericSymbol).Gen : base_symbol) as GenBase; } - } - - public List GetAllDerivedInterfaces () - { - List result = new List (); - GetAllDerivedInterfaces (result); - return result; - } + public bool ContainsMethod (Method method, bool check_ifaces) => ContainsMethod (method, check_ifaces, true); - void GetAllDerivedInterfaces (List ifaces) + public bool ContainsMethod (Method method, bool check_ifaces, bool check_base_ifaces) { - foreach (ISymbol isym in Interfaces) { - InterfaceGen iface = (isym is GenericSymbol ? (isym as GenericSymbol).Gen : isym) as InterfaceGen; - if (iface == null) - continue; - bool found = false; - foreach (InterfaceGen known in ifaces) - if (known.FullName == iface.FullName) - found = true; - if (found) - continue; - ifaces.Add (iface); - iface.GetAllDerivedInterfaces (ifaces); + // background: bug #10123. + // Visibility check was introduced - and required so far - to block "public overrides protected" methods + // (which is allowed in Java but not in C#). + // The problem is, it does not *always* result in error and generates callable code, and we depend on + // that fact in several classes that implements some interface that requires "public Object clone()". + // + // This visibility inconsistency results in 1) error for abstract methods and 2) warning for virtual methods. + // Hence, for abstract methods we dare to ignore visibility difference and treat it as override, + // *then* C# compiler will report this inconsistency as error that users need to fix manually, but + // with obvious message saying "it is because of visibility consistency", + // not "abstract member not implemented" (it is *implemented* in different visibility and brings confusion). + // For virtual methods, just check the visibility difference and treat as different method. + // Regardless of whether it is actually an override or not, we just invoke Java method. + if (jni_sig_hash.ContainsKey (method.JavaName + method.JniSignature)) { + var bm = jni_sig_hash [method.JavaName + method.JniSignature]; + if (bm.Visibility == method.Visibility || bm.IsAbstract) + return true; } - } - - public bool GetGenericMappings (InterfaceGen gen, Dictionary mappings) - { - foreach (ISymbol sym in Interfaces) { - if (sym is GenericSymbol) { - GenericSymbol gsym = (GenericSymbol) sym; - if (gsym.Gen.FullName == gen.FullName) { - for (int i = 0; i < gsym.TypeParams.Length; i++) - mappings [gsym.Gen.TypeParameters [i].Name] = gsym.TypeParams [i].FullName; - return true; - } else if (gsym.Gen.GetGenericMappings (gen, mappings)) { - string[] keys = new string [mappings.Keys.Count]; - mappings.Keys.CopyTo (keys, 0); - foreach (string tp in keys) - mappings [tp] = gsym.TypeParams [Array.IndexOf ((from gtp in gsym.Gen.TypeParameters select gtp.Name).ToArray (), mappings [tp])].FullName; + if (check_ifaces) { + foreach (ISymbol isym in Interfaces) { + if ((isym is GenericSymbol ? (isym as GenericSymbol).Gen : isym) is InterfaceGen igen && igen.ContainsMethod (method, true)) return true; - } } } - return false; - } - - public virtual void ResetValidation () - { - ifaces.Clear (); - iface_validation_failed = false; - foreach (var nt in NestedTypes) - nt.ResetValidation (); - } - - void AdjustNestedTypeFullName (GenBase parent) - { - if (parent is ClassGen) - foreach (var nested in parent.NestedTypes) - nested.FullName = parent.FullName + "." + nested.Name; + return BaseSymbol != null && BaseSymbol.ContainsMethod (method, check_base_ifaces, check_base_ifaces); } - public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) + public bool ContainsName (string name) { - context.ContextTypes.Push (this); - try { - return is_valid = OnValidate (opt, type_params, context); - } finally { - context.ContextTypes.Pop (); - } + if (HasNestedType (name) || ContainsProperty (name, true)) + return true; + + return Methods.Any (m => m.Name == name); } - protected virtual bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) - { - if (Name.Length > TypeNamePrefix.Length && - (Name [TypeNamePrefix.Length] == '.' || Char.IsDigit (Name [TypeNamePrefix.Length]))) // see bug #5111 - return false; - - if (!support.OnValidate (opt)) - return false; + public bool ContainsProperty (string name, bool check_ifaces) => ContainsProperty (name, check_ifaces, true); - List valid_nests = new List (); - foreach (GenBase gen in nested_types) { - if (gen.Validate (opt, TypeParameters, context)) - valid_nests.Add (gen); - } - nested_types = valid_nests; - - AdjustNestedTypeFullName (this); + public bool ContainsProperty (string name, bool check_ifaces, bool check_base_ifaces) => + GetPropertyByName (name, check_ifaces, check_base_ifaces) != null; - foreach (string iface_name in iface_names) { - ISymbol isym = opt.SymbolTable.Lookup (iface_name); - if (isym != null && isym.Validate (opt, TypeParameters, context)) - ifaces.Add (isym); - else { - if (isym == null) - Report.Warning (0, Report.WarningGenBase + 0, "For type {0}, base interface {1} does not exist.", FullName, iface_name); - else - Report.Warning (0, Report.WarningGenBase + 0, "For type {0}, base interface {1} is invalid.", FullName, iface_name); - iface_validation_failed = true; - } - } - - List valid_fields = new List (); - foreach (Field f in fields) { - if (!f.Validate (opt, TypeParameters, context)) - continue; - valid_fields.Add (f); - } - fields = valid_fields; + public string DeprecatedComment => support.DeprecatedComment; - int method_cnt = methods.Count; - methods = methods.Where (m => ValidateMethod (opt, m, context)).ToList (); - method_validation_failed = method_cnt != methods.Count; - foreach (Method m in methods) { - if (m.IsVirtual) - has_virtual_methods = true; - if (m.Name == "HashCode" && m.Parameters.Count == 0) { - m.IsOverride = true; - m.Name = "GetHashCode"; + IEnumerable Descendants (IList gens) + { + foreach (var directDescendants in gens.Where (x => x.BaseGen == this)) { + yield return directDescendants; + foreach (var indirectDescendants in directDescendants.Descendants (gens)) { + yield return indirectDescendants; } - jni_sig_hash [m.JavaName + m.JniSignature] = m; - if ((m.Name == "ToString" && m.Parameters.Count == 0) || (BaseSymbol != null && BaseSymbol.ContainsMethod (m, true))) - m.IsOverride = true; } - return true; - } - - bool property_filling; - - public void StripNonBindables () - { - // 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 (); - nested_types = nested_types.Where (n => !n.IsObfuscated && n.Visibility != "private").ToList (); - foreach (var n in nested_types) - n.StripNonBindables (); } - public virtual void FixupAccessModifiers (CodeGenerationOptions opt) - { - foreach (var nt in NestedTypes) - nt.FixupAccessModifiers (opt); - } + public string ElementType { get; set; } public void FillProperties () { @@ -726,29 +264,28 @@ public void FillProperties () var names = prop_hash.Keys; foreach (string name in names) - props.Add (prop_hash [name]); - props.Sort ((p1, p2) => string.CompareOrdinal (p1.Name, p2.Name)); + Properties.Add (prop_hash [name]); + Properties.Sort ((p1, p2) => string.CompareOrdinal (p1.Name, p2.Name)); property_filling = false; - + foreach (var nt in NestedTypes) nt.FillProperties (); } - - protected virtual bool GetEnumMappedMemberInfo () + + public virtual void FixupAccessModifiers (CodeGenerationOptions opt) + { + foreach (var nt in NestedTypes) + nt.FixupAccessModifiers (opt); + } + + public virtual void FixupExplicitImplementation () { - foreach (var f in Fields) - if (f.IsEnumified) - return true; - foreach (var m in Methods) - if (m.IsReturnEnumified | m.Parameters.Any (p => p.IsEnumified)) - return true; - return false; } - + public void FixupMethodOverrides (CodeGenerationOptions opt) { - foreach (Method m in methods.Where (m => !m.IsInterfaceDefaultMethod)) { - for (var bt = this.GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { + foreach (var m in Methods.Where (m => !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". m.IsOverride = true; @@ -758,8 +295,8 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) } // Interface default methods can be overriden. We want to process them differently. - foreach (Method m in methods.Where (m => m.IsInterfaceDefaultMethod)) { - foreach (var bt in this.GetAllDerivedInterfaces ()) { + 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)); if (bm != null) { m.IsInterfaceDefaultMethodOverride = true; @@ -768,7 +305,7 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) } } - foreach (Method m in methods) { + foreach (var m in Methods) { if (m.Name == Name || ContainsProperty (m.Name, true) || HasNestedType (m.Name)) m.Name = "Invoke" + m.Name; if ((m.Name == "ToString" && m.Parameters.Count == 0) || (BaseGen != null && BaseGen.ContainsMethod (m, true))) @@ -779,120 +316,224 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) nt.FixupMethodOverrides (opt); } - public virtual void FixupExplicitImplementation () - { + public abstract string FromNative (CodeGenerationOptions opt, string varname, bool owned); + + public string FullName { + get => support.FullName; + set => support.FullName = value; } - GenBase GetBaseGen (CodeGenerationOptions opt) + public abstract void Generate (CodeGenerationOptions opt, GenerationInfo gen_info); + + protected void GenerateAnnotationAttribute (CodeGenerationOptions opt, GenerationInfo gen_info) { - if (this is InterfaceGen) - return null; - if (this.BaseGen != null) - return this.BaseGen; - if (this.BaseSymbol == null) - return null; - var bg = opt.SymbolTable.Lookup (this.BaseSymbol.FullName) as GenBase; - if (bg != null && bg != this) - return bg; - return null; + if (ShouldGenerateAnnotationAttribute) { + var baseName = Namespace.Length > 0 ? FullName.Substring (Namespace.Length + 1) : FullName; + var attrClassNameBase = baseName.Substring (TypeNamePrefix.Length) + "Attribute"; + var localFullName = Namespace + (Namespace.Length > 0 ? "." : string.Empty) + attrClassNameBase; + + using (var sw = gen_info.OpenStream (opt.GetFileName (localFullName))) { + sw.WriteLine ("using System;"); + sw.WriteLine (); + sw.WriteLine ("namespace {0} {{", Namespace); + sw.WriteLine (); + sw.WriteLine ("\t[global::Android.Runtime.Annotation (\"{0}\")]", JavaName); + sw.WriteLine ("\t{0} partial class {1} : Attribute", Visibility, attrClassNameBase); + sw.WriteLine ("\t{"); + + // An Annotation attribute property is generated for each applicable annotation method, + // where *applicable* means java annotation compatible types. See IsTypeCommensurate(). + foreach (var method in Methods.Where (m => m.Parameters.Count == 0 && + IsTypeCommensurate (opt, opt.SymbolTable.Lookup (m.RetVal.JavaName)))) { + sw.WriteLine ("\t\t[global::Android.Runtime.Register (\"{0}\"{1})]", method.JavaName, method.AdditionalAttributeString ()); + sw.WriteLine ("\t\tpublic {0} {1} {{ get; set; }}", opt.GetOutputName (method.RetVal.FullName), method.Name); + sw.WriteLine (); + } + sw.WriteLine ("\t}"); + sw.WriteLine ("}"); + } + } } - bool enum_updated; + public List GetAllDerivedInterfaces () + { + var result = new List (); + GetAllDerivedInterfaces (result); + return result; + } - public virtual void UpdateEnums (CodeGenerationOptions opt, AncestorDescendantCache cache) + void GetAllDerivedInterfaces (List ifaces) { - if (enum_updated || !IsGeneratable) - return; - enum_updated = true; - var baseGen = GetBaseGen (opt); - if (baseGen != null) - baseGen.UpdateEnums (opt, cache); + foreach (var isym in Interfaces) { + if (!((isym is GenericSymbol ? (isym as GenericSymbol).Gen : isym) is InterfaceGen iface)) + continue; + + var found = false; + + foreach (var known in ifaces) + if (known.FullName == iface.FullName) + found = true; - foreach (Method m in methods) { - AutoDetectEnumifiedOverrideParameters (m, cache); - AutoDetectEnumifiedOverrideReturn (m, cache); + if (found) + continue; + + ifaces.Add (iface); + iface.GetAllDerivedInterfaces (ifaces); } - foreach (Property p in Properties) - AutoDetectEnumifiedOverrideProperties (p, cache); - UpdateEnumsInInterfaceImplementation (); - foreach (var ngen in NestedTypes) - ngen.UpdateEnums (opt, cache); } - public virtual void UpdateEnumsInInterfaceImplementation () + protected internal IEnumerable GetAllImplementedInterfaces () { + var set = new HashSet (); + + void visit (ISymbol isym) + { + if ((isym is GenericSymbol gsym ? gsym.Gen : isym) is InterfaceGen igen) + set.Add (igen); + + if (!(isym is GenBase b)) + return; + + foreach (var i in b.Interfaces) + visit (i); + } + + foreach (var i in Interfaces) + visit (i); + + return set; } - public string[] PreCallback (CodeGenerationOptions opt, string var_name, bool owned) + public IEnumerable GetAllMethods () => + Methods.Concat (Properties.Select (p => p.Getter)).Concat (Properties.Select (p => p.Setter).Where (m => m != null)); + + GenBase GetBaseGen (CodeGenerationOptions opt) { - var rgm = this as IRequireGenericMarshal; + if (this is InterfaceGen) + return null; - return new string[]{ - string.Format ("{0} {1} = {5}global::Java.Lang.Object.GetObject<{4}> ({2}, {3});", - opt.GetOutputName (FullName), - opt.GetSafeIdentifier (var_name), - opt.GetSafeIdentifier (SymbolTable.GetNativeName (var_name)), - owned ? "JniHandleOwnership.TransferLocalRef" : "JniHandleOwnership.DoNotTransfer", - opt.GetOutputName (rgm != null ? (rgm.GetGenericJavaObjectTypeOverride () ?? FullName) : FullName), - rgm != null ? "(" + opt.GetOutputName (FullName) + ")" : string.Empty) - }; + if (BaseGen != null) + return BaseGen; + + if (BaseSymbol == null) + return null; + + if (opt.SymbolTable.Lookup (BaseSymbol.FullName) is GenBase bg && bg != this) + return bg; + + return null; } - public string[] PostCallback (CodeGenerationOptions opt, string var_name) + protected virtual bool GetEnumMappedMemberInfo () { - return new string[]{ - }; + foreach (var f in Fields) + if (f.IsEnumified) + return true; + foreach (var m in Methods) + if (m.IsReturnEnumified | m.Parameters.Any (p => p.IsEnumified)) + return true; + return false; } - public string[] PreCall (CodeGenerationOptions opt, string var_name) + public bool GetGenericMappings (InterfaceGen gen, Dictionary mappings) { - return new string[]{ - }; + foreach (var sym in Interfaces) { + if (sym is GenericSymbol gsym) { + if (gsym.Gen.FullName == gen.FullName) { + for (int i = 0; i < gsym.TypeParams.Length; i++) + mappings [gsym.Gen.TypeParameters [i].Name] = gsym.TypeParams [i].FullName; + return true; + } else if (gsym.Gen.GetGenericMappings (gen, mappings)) { + string [] keys = new string [mappings.Keys.Count]; + mappings.Keys.CopyTo (keys, 0); + foreach (string tp in keys) + mappings [tp] = gsym.TypeParams [Array.IndexOf ((from gtp in gsym.Gen.TypeParameters select gtp.Name).ToArray (), mappings [tp])].FullName; + return true; + } + } + } + + return false; } - public string Call (CodeGenerationOptions opt, string var_name) + public virtual string GetGenericType (Dictionary mappings) { - return opt.GetSafeIdentifier (var_name); + return null; } - public string[] PostCall (CodeGenerationOptions opt, string var_name) + public string GetObjectHandleProperty (string variable) { - return new string[]{ - }; + var handleType = IsThrowable () ? "Java.Lang.Throwable" : "Java.Lang.Object"; + + return $"((global::{handleType}) {variable}).Handle"; } - public bool NeedsPrep { get { return true; } } + public Property GetPropertyByName (string name, bool check_ifaces) => + GetPropertyByName (name, check_ifaces, true); - protected void GenerateAnnotationAttribute (CodeGenerationOptions opt, GenerationInfo gen_info) + public Property GetPropertyByName (string name, bool check_ifaces, bool check_base_ifaces) { - if (ShouldGenerateAnnotationAttribute) { - var baseName = Namespace.Length > 0 ? FullName.Substring (Namespace.Length + 1) : FullName; - var attrClassNameBase = baseName.Substring (TypeNamePrefix.Length) + "Attribute"; - var localFullName = Namespace + (Namespace.Length > 0 ? "." : string.Empty) + attrClassNameBase; + if (prop_hash.ContainsKey (name)) + return prop_hash [name]; - using (var sw = gen_info.OpenStream (opt.GetFileName (localFullName))) { - sw.WriteLine ("using System;"); - sw.WriteLine (); - sw.WriteLine ("namespace {0} {{", Namespace); - sw.WriteLine (); - sw.WriteLine ("\t[global::Android.Runtime.Annotation (\"{0}\")]", JavaName); - sw.WriteLine ("\t{0} partial class {1} : Attribute", this.Visibility, attrClassNameBase); - sw.WriteLine ("\t{"); + if (check_ifaces) { + foreach (ISymbol isym in Interfaces) { + if (!((isym is GenericSymbol ? (isym as GenericSymbol).Gen : isym) is InterfaceGen igen)) + continue; - // An Annotation attribute property is generated for each applicable annotation method, - // where *applicable* means java annotation compatible types. See IsTypeCommensurate(). - foreach (var method in Methods.Where (m => m.Parameters.Count == 0 && - IsTypeCommensurate (opt, opt.SymbolTable.Lookup (m.RetVal.JavaName)))) { - sw.WriteLine ("\t\t[global::Android.Runtime.Register (\"{0}\"{1})]", method.JavaName, method.AdditionalAttributeString ()); - sw.WriteLine ("\t\tpublic {0} {1} {{ get; set; }}", opt.GetOutputName (method.RetVal.FullName), method.Name); - sw.WriteLine (); - } - sw.WriteLine ("\t}"); - sw.WriteLine ("}"); + var ret = igen.GetPropertyByName (name, true); + if (ret != null) + return ret; } } + + return BaseSymbol?.GetPropertyByName (name, check_base_ifaces, check_base_ifaces); } - + + public bool HasEnumMappedMembers => GetEnumMappedMemberInfo (); + + protected internal bool HasNestedType (string name) => NestedTypes.Any (g => g.Name == name); + + public IEnumerable Invalidate () + { + IsValid = false; + validated = true; + + foreach (var nt in NestedTypes) { + foreach (var sub in nt.Invalidate ()) + yield return sub; + yield return nt; + } + } + + public bool IsAcw => support.IsAcw; + + public bool IsAnnotation => + implemented_interfaces.Any (n => n == "Java.Lang.Annotation.Annotation" || n == "java.lang.annotation.Annotation"); + + public bool IsArray => false; + + // TODO: check that method.ReturnType is a superclass of m.ReturnType + public bool IsCovariantMethod (Method method) => + Methods.Any (m => m.Name == method.Name && ParameterList.Equals (m.Parameters, method.Parameters)); + + public bool IsDeprecated => support.IsDeprecated; + + public bool IsEnum => false; + + public bool IsGeneratable => support.IsGeneratable; + + public bool IsGeneric => support.IsGeneric; + + // some names are reserved for use by us, e.g. we don't want another + // Handle property, as that conflicts with Java.Lang.Object.Handle. + bool IsInfrastructural (string name) => ObjectRequiresNew.Contains (name); + + public bool IsObfuscated => support.IsObfuscated; + + bool IsThrowable () => + FullName == "Java.Lang.Throwable" || Ancestors ().Any (a => a.FullName == "Java.Lang.Throwable"); + // This is not a perfect match with Java language specification http://docs.oracle.com/javase/specs/jls/se5.0/html/interfaces.html#9.7 // as it does not cover java.lang.Enum. Though C# attributes cannot handle JLE. // Class literal (FooBar.class) cannot be supported either. @@ -905,19 +546,18 @@ static bool IsTypeCommensurate (CodeGenerationOptions opt, ISymbol sym) return true; if (sym is SimpleSymbol) { switch (sym.JavaName) { - case "boolean": - case "char": - case "byte": - case "short": - case "int": - case "long": - case "float": - case "double": - return true; + case "boolean": + case "char": + case "byte": + case "short": + case "int": + case "long": + case "float": + case "double": + return true; } } - var arr = sym as ArraySymbol; - if (arr != null) + if (sym is ArraySymbol arr) return IsTypeCommensurate (opt, opt.SymbolTable.Lookup (arr.ElementType)); if (sym is GenericSymbol) return sym.JavaName == "java.lang.Class"; @@ -929,90 +569,236 @@ static bool IsTypeCommensurate (CodeGenerationOptions opt, ISymbol sym) return false; } - public static string GetSignature (MethodBase method, CodeGenerationOptions opt) - { - StringBuilder sb = new StringBuilder (); - foreach (Parameter p in method.Parameters) { - if (sb.Length > 0) - sb.Append (", "); - if (p.IsEnumified) - sb.Append ("[global::Android.Runtime.GeneratedEnum] "); - if (p.Annotation != null) - sb.Append (p.Annotation); - sb.Append (opt.GetOutputName (p.Type)); - sb.Append (" "); - sb.Append (opt.GetSafeIdentifier (p.Name)); + public bool IsValid { get; set; } = true; + + public string JavaName => $"{PackageName}.{JavaSimpleName}"; + + public string JavaSimpleName => support.JavaSimpleName; + + public string JniName => $"L{RawJniName};"; + + public string MetadataXPathReference { + get { + string type = null; + + if (this is ClassGen) + type = "class"; + if (this is InterfaceGen) + type = "interface"; + if (type == null) + throw new InvalidOperationException ("Uh...xpath? this is " + GetType ().FullName); + + return $"/api/package[@name='{PackageName}']/{type}[@name='{JavaSimpleName}']"; } - return sb.ToString (); } - static IEnumerable GetAllMethods (GenBase t) - { - return t.Methods.Concat (t.Properties.Select (p => p.Getter)).Concat (t.Properties.Select (p => p.Setter).Where (m => m != null)); + public bool MethodValidationFailed { get; set; } + + public string Name { + get => support.Name; + set => support.Name = value; } - static string [] AutoDetectEnumifiedOverrideParameters (MethodBase method, AncestorDescendantCache cache) + public string Namespace => support.Namespace; + + public string NativeType { get; set; } + + public bool NeedsPrep => true; + + static readonly HashSet ObjectRequiresNew = new HashSet ( + typeof (object) + .GetMethods () + .Where (m => !m.Attributes.HasFlag (MethodAttributes.SpecialName) && + !m.Attributes.HasFlag (MethodAttributes.RTSpecialName)) + .Select (m => m.Name) + .Concat (new [] { "Handle" }), + StringComparer.OrdinalIgnoreCase); + + protected virtual bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) { - if (method.Parameters.All (p => p.Type != "int")) - return null; - var classes = cache.GetAncestorsAndDescendants (method.DeclaringType); - classes = classes.Concat (classes.SelectMany(x => x.GetAllImplementedInterfaces ())); - foreach (var t in classes) { - foreach (var candidate in GetAllMethods (t).Where (m => m.Name == method.Name - && m.Parameters.Count == method.Parameters.Count - && m.Parameters.Any (p => p.IsEnumified))) { - var ret = new string [method.Parameters.Count]; - bool mismatch = false; - for (int i = 0; i < method.Parameters.Count; i++) { - if (method.Parameters [i].Type == "int" && candidate.Parameters [i].IsEnumified) - ret [i] = candidate.Parameters [i].Type; - else if (method.Parameters [i].Type != candidate.Parameters [i].Type) { - mismatch = true; - break; - } - } - if (mismatch) - continue; - for (int i = 0; i < ret.Length; i++) - if (ret [i] != null) - method.Parameters [i].SetGeneratedEnumType (ret [i]); - return ret; + if (Name.Length > TypeNamePrefix.Length && + (Name [TypeNamePrefix.Length] == '.' || char.IsDigit (Name [TypeNamePrefix.Length]))) // see bug #5111 + return false; + + if (!support.OnValidate (opt)) + return false; + + List valid_nests = new List (); + foreach (GenBase gen in NestedTypes) { + if (gen.Validate (opt, TypeParameters, context)) + valid_nests.Add (gen); + } + NestedTypes = valid_nests; + + AdjustNestedTypeFullName (this); + + foreach (string iface_name in implemented_interfaces) { + ISymbol isym = opt.SymbolTable.Lookup (iface_name); + if (isym != null && isym.Validate (opt, TypeParameters, context)) + Interfaces.Add (isym); + else { + if (isym == null) + Report.Warning (0, Report.WarningGenBase + 0, "For type {0}, base interface {1} does not exist.", FullName, iface_name); + else + Report.Warning (0, Report.WarningGenBase + 0, "For type {0}, base interface {1} is invalid.", FullName, iface_name); + iface_validation_failed = true; } } - return null; - } - static string AutoDetectEnumifiedOverrideReturn (Method method, AncestorDescendantCache cache) - { - if (method.RetVal.FullName != "int") - return null; - var classes = cache.GetAncestorsAndDescendants (method.DeclaringType); - classes = classes.Concat (classes.SelectMany(x => x.GetAllImplementedInterfaces ())); - foreach (var t in classes) { - foreach (var candidate in GetAllMethods (t).Where (m => m.Name == method.Name && m.Parameters.Count == method.Parameters.Count)) { - if (method.JniSignature != candidate.JniSignature) - continue; - if (candidate.IsReturnEnumified) - method.RetVal.SetGeneratedEnumType (candidate.RetVal.FullName); + List valid_fields = new List (); + foreach (Field f in Fields) { + if (!f.Validate (opt, TypeParameters, context)) + continue; + valid_fields.Add (f); + } + Fields = valid_fields; + + int method_cnt = Methods.Count; + Methods = Methods.Where (m => ValidateMethod (opt, m, context)).ToList (); + MethodValidationFailed = method_cnt != Methods.Count; + foreach (Method m in Methods) { + if (m.IsVirtual) + HasVirtualMethods = true; + if (m.Name == "HashCode" && m.Parameters.Count == 0) { + m.IsOverride = true; + m.Name = "GetHashCode"; } + jni_sig_hash [m.JavaName + m.JniSignature] = m; + if ((m.Name == "ToString" && m.Parameters.Count == 0) || (BaseSymbol != null && BaseSymbol.ContainsMethod (m, true))) + m.IsOverride = true; } - return null; + return true; + } + + public string PackageName { + get => support.PackageName; + set => support.PackageName = value; + } + + public string [] PreCall (CodeGenerationOptions opt, string var_name) => new string [] { }; + + public string [] PreCallback (CodeGenerationOptions opt, string var_name, bool owned) + { + var rgm = this as IRequireGenericMarshal; + + return new string []{ + string.Format ("{0} {1} = {5}global::Java.Lang.Object.GetObject<{4}> ({2}, {3});", + opt.GetOutputName (FullName), + opt.GetSafeIdentifier (var_name), + opt.GetSafeIdentifier (SymbolTable.GetNativeName (var_name)), + owned ? "JniHandleOwnership.TransferLocalRef" : "JniHandleOwnership.DoNotTransfer", + opt.GetOutputName (rgm != null ? (rgm.GetGenericJavaObjectTypeOverride () ?? FullName) : FullName), + rgm != null ? "(" + opt.GetOutputName (FullName) + ")" : string.Empty) + }; + } + + public string [] PostCall (CodeGenerationOptions opt, string var_name) => new string [] { }; + + public string [] PostCallback (CodeGenerationOptions opt, string var_name) => new string [] { }; + + public string RawJniName => PackageName.Replace ('.', '/') + "/" + JavaSimpleName.Replace ('.', '$'); + + public string RawVisibility => support.Visibility; + + public bool RequiresNew (string memberName) + { + if (ObjectRequiresNew.Contains (memberName)) + return true; + + return IsThrowable () && ThrowableRequiresNew.Contains (memberName); + } + + public virtual void ResetValidation () + { + Interfaces.Clear (); + iface_validation_failed = false; + + foreach (var nt in NestedTypes) + nt.ResetValidation (); } - void AutoDetectEnumifiedOverrideProperties (Property prop, AncestorDescendantCache cache) + bool ReturnTypeMatches (Method m, Method mm) { - if (prop.Type != "int") + if (mm.RetVal.FullName == m.RetVal.FullName) + return true; + if (BaseSymbol.IsGeneric && mm.RetVal.IsGeneric) + return true; // sloppy but pass + return false; + } + + public bool ShouldGenerateAnnotationAttribute => IsAnnotation; + + public void StripNonBindables () + { + // 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 (); + NestedTypes = NestedTypes.Where (n => !n.IsObfuscated && n.Visibility != "private").ToList (); + foreach (var n in NestedTypes) + n.StripNonBindables (); + } + + static readonly HashSet ThrowableRequiresNew = new HashSet ( + typeof (System.Exception) + .GetMethods () + .Where (m => !m.Attributes.HasFlag (MethodAttributes.SpecialName) && + !m.Attributes.HasFlag (MethodAttributes.RTSpecialName)) + .Select (m => m.Name) + .Concat (typeof (System.Exception).GetProperties ().Select (p => p.Name)) + .Concat (new [] { "Handle" }), + StringComparer.OrdinalIgnoreCase); + + public abstract string ToNative (CodeGenerationOptions opt, string varname, Dictionary mappings = null); + + public string TypeNamePrefix => support.TypeNamePrefix; + + public GenericParameterDefinitionList TypeParameters => support.TypeParameters; + + public virtual void UpdateEnums (CodeGenerationOptions opt, AncestorDescendantCache cache) + { + if (enum_updated || !IsGeneratable) return; - var classes = cache.GetAncestorsAndDescendants (prop.Getter.DeclaringType); - classes = classes.Concat (classes.SelectMany(x => x.GetAllImplementedInterfaces ())); - foreach (var t in classes) { - foreach (var candidate in t.Properties.Where (p => p.Name == prop.Name)) { - if (prop.Getter.JniSignature != candidate.Getter.JniSignature) - continue; - if (candidate.Getter.IsReturnEnumified) - prop.Getter.RetVal.SetGeneratedEnumType (candidate.Getter.RetVal.FullName); - } + + enum_updated = true; + + var baseGen = GetBaseGen (opt); + + if (baseGen != null) + baseGen.UpdateEnums (opt, cache); + + foreach (var m in Methods) { + m.AutoDetectEnumifiedOverrideParameters (cache); + m.AutoDetectEnumifiedOverrideReturn (cache); } + + foreach (var p in Properties) + p.AutoDetectEnumifiedOverrideProperties (cache); + + UpdateEnumsInInterfaceImplementation (); + + foreach (var ngen in NestedTypes) + ngen.UpdateEnums (opt, cache); } + + public virtual void UpdateEnumsInInterfaceImplementation () + { + } + + public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) + { + context.ContextTypes.Push (this); + + try { + return IsValid = OnValidate (opt, type_params, context); + } finally { + context.ContextTypes.Pop (); + } + } + + bool ValidateMethod (CodeGenerationOptions opt, Method m, CodeGeneratorContext context) => + m.Validate (opt, TypeParameters, context); + + public string Visibility => string.IsNullOrEmpty (support.Visibility) ? "public" : support.Visibility; } } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBaseSupport.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBaseSupport.cs index f08964003..57526908a 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBaseSupport.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBaseSupport.cs @@ -1,47 +1,30 @@ using System; -using System.Collections.Generic; -using System.IO; -using System.Xml; namespace MonoDroid.Generation { - public abstract class GenBaseSupport + public class GenBaseSupport { - public abstract bool IsAcw { get; } - public abstract bool IsDeprecated { get; } - public abstract string DeprecatedComment { get; } - public abstract bool IsGeneratable { get; } - public abstract bool IsGeneric { get; } - public abstract bool IsObfuscated { get; } - public abstract string FullName { get; set; } - public abstract string Name { get; set; } - public abstract string Namespace { get; } - public abstract string JavaSimpleName { get; } - public abstract string PackageName { get; set; } - //public abstract string Marshaler { get; } - public abstract string Visibility { get; } - public abstract GenericParameterDefinitionList TypeParameters { get; } + public bool IsAcw { get; set; } + public bool IsDeprecated { get; set; } + public string DeprecatedComment { get; set; } + public bool IsGeneratable { get; set; } + public bool IsGeneric { get; set; } + public bool IsObfuscated { get; set; } + public string FullName { get; set; } + public string Name { get; set; } + public string Namespace { get; set; } + public string JavaSimpleName { get; set; } + public string PackageName { get; set; } + public string TypeNamePrefix { get; set; } = string.Empty; + public string Visibility { get; set; } + public GenericParameterDefinitionList TypeParameters { get; set; } - public virtual string TypeNamePrefix { - get { return String.Empty; } - } - public virtual bool OnValidate (CodeGenerationOptions opt) { // See com.google.inject.internal.util package for this case. // Some Java compiler-generated internals are named as $foobar (dollar prefixed). // Since our jar2xml replaces all '$' with '.', it results in ".." namespace. - if (this.FullName.Contains ("..")) - return false; - return true; - } - - public static bool IsPrefixableName (string name) - { - // IBlahBlah is not prefixed with 'I' - return name.Length <= 2 || name [0] != 'I' || !Char.IsUpper (name [1]); + return !FullName.Contains (".."); } } } - - diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs index e42193d9b..50786385d 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs @@ -1,32 +1,112 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Text; -using System.Xml; - using Xamarin.Android.Binder; namespace MonoDroid.Generation { + public class InterfaceGen : GenBase, IRequireGenericMarshal + { + public InterfaceGen (GenBaseSupport support) : base (support) + { + DefaultValue = "IntPtr.Zero"; + NativeType = "IntPtr"; + } + + public override void AddNestedType (GenBase gen) + { + base.AddNestedType (gen); + + var nest_name = gen.JavaName.Substring (JavaName.Length + 1); + + if (nest_name.IndexOf (".") < 0) { + if (gen is InterfaceGen) { + gen.FullName = FullName + gen.Name.Substring (1); + gen.Name = Name + gen.Name.Substring (1); + } else { + gen.FullName = FullName.Substring (0, FullName.Length - Name.Length) + Name.Substring (1) + gen.Name; + gen.Name = Name.Substring (1) + gen.Name; + } + } + } - public abstract class InterfaceGen : GenBase, IRequireGenericMarshal { + public string ArgsType { get; set; } - protected bool hasManagedName; + public override string FromNative (CodeGenerationOptions opt, string varname, bool owned) + { + return string.Format ("global::Java.Lang.Object.GetObject<{0}> ({1}, {2})", opt.GetOutputName (FullName), varname, owned ? "JniHandleOwnership.TransferLocalRef" : "JniHandleOwnership.DoNotTransfer"); + /* + if (String.IsNullOrEmpty (Marshaler)) + return String.Format ("global::Java.Lang.Object.GetObject<{0}> ({1}, {2})", opt.GetOutputName (FullName), varname, owned ? "JniHandleOwnership.TransferLocalRef" : "JniHandleOwnership.DoNotTransfer"); + else + return String.Format ("new {1} ({0})", varname, Marshaler); + */ + } - protected InterfaceGen (GenBaseSupport support) - : base (support) + public override void Generate (CodeGenerationOptions opt, GenerationInfo gen_info) { + using (var sw = gen_info.OpenStream (opt.GetFileName (FullName))) { + sw.WriteLine ("using System;"); + sw.WriteLine ("using System.Collections.Generic;"); + sw.WriteLine ("using Android.Runtime;"); + if (opt.CodeGenerationTarget != CodeGenerationTarget.XamarinAndroid) { + sw.WriteLine ("using Java.Interop;"); + } + sw.WriteLine (); + sw.WriteLine ("namespace {0} {{", Namespace); + sw.WriteLine (); + + var generator = opt.CreateCodeGenerator (sw); + generator.WriteInterface (this, "\t", gen_info); + + sw.WriteLine ("}"); + } + + GenerateAnnotationAttribute (opt, gen_info); } - - public abstract string ArgsType { get; } - public override string DefaultValue { - get { return "IntPtr.Zero"; } + internal string GetArgsName (Method m) + { + + string nameBase; + int start; + int trim = 0; + + if (Methods.Count > 1) { + if (!string.IsNullOrEmpty (m.ArgsType)) + return m.ArgsType; + if (m.IsSimpleEventHandler) + return "EventArgs"; + nameBase = m.AdjustedName; + start = nameBase.StartsWith ("On") ? 2 : 0; + } else { + if (!string.IsNullOrEmpty (ArgsType)) + return ArgsType; + if (m.IsSimpleEventHandler) + return "EventArgs"; + nameBase = Name; + start = Name.StartsWith ("IOn") ? 3 : 1; + trim = 8; // "Listener" + } + return nameBase.Substring (start, nameBase.Length - start - trim) + "EventArgs"; } - public bool HasManagedName => hasManagedName; + internal string GetEventDelegateName (Method m) + { + int start = Name.StartsWith ("IOn") ? 3 : 1; + if (m.RetVal.IsVoid) { + if (m.IsSimpleEventHandler) + return "EventHandler"; + else { + return "EventHandler<" + GetArgsName (m) + ">"; + } + } else if (m.IsEventHandlerWithHandledProperty) { + return "EventHandler<" + GetArgsName (m) + ">"; + } else { + string methodSpec = Methods.Count > 1 ? m.AdjustedName : string.Empty; + return Name.Substring (start, Name.Length - start - 8) + methodSpec + "Handler"; + } + } // These are fields that we currently support generating on the interface with DIM public IEnumerable GetGeneratableFields (CodeGenerationOptions options) @@ -38,7 +118,7 @@ public IEnumerable GetGeneratableFields (CodeGenerationOptions options) } public bool IsConstSugar { - get { + get { if (Methods.Count > 0 || Properties.Count > 0) return false; @@ -55,76 +135,23 @@ public bool IsConstSugar { } } - public bool IsListener { - // If there is a property it cannot generate valid implementor, so reject this at least so far. - get { return Name.EndsWith ("Listener") && Properties.Count == 0 && Interfaces.Count == 0; } - } - - public virtual bool MayHaveManagedGenericArguments { - get { return false; } - } - - public override string NativeType { - get { return "IntPtr"; } - } - - internal bool NeedsSender { - get { - return Methods.Any (m => (m.RetVal.IsVoid && !m.Parameters.HasSender) || - (m.IsEventHandlerWithHandledProperty && !m.Parameters.HasSender)); - } - } + // If there is a property it cannot generate valid implementor, so reject this at least so far. + public bool IsListener => Name.EndsWith ("Listener") && Properties.Count == 0 && Interfaces.Count == 0; - public override string ToNative (CodeGenerationOptions opt, string varname, Dictionary mappings = null) - { - return String.Format ("JNIEnv.ToLocalJniHandle ({0})", varname); - /* - if (String.IsNullOrEmpty (Marshaler)) - return String.Format ("JNIEnv.ToLocalJniHandle ({0})", varname); - else - return GetObjectHandleProperty (varname); - */ - } + public bool HasManagedName { get; set; } - public override string FromNative (CodeGenerationOptions opt, string varname, bool owned) - { - return String.Format ("global::Java.Lang.Object.GetObject<{0}> ({1}, {2})", opt.GetOutputName (FullName), varname, owned ? "JniHandleOwnership.TransferLocalRef" : "JniHandleOwnership.DoNotTransfer"); - /* - if (String.IsNullOrEmpty (Marshaler)) - return String.Format ("global::Java.Lang.Object.GetObject<{0}> ({1}, {2})", opt.GetOutputName (FullName), varname, owned ? "JniHandleOwnership.TransferLocalRef" : "JniHandleOwnership.DoNotTransfer"); - else - return String.Format ("new {1} ({0})", varname, Marshaler); - */ - } + public bool MayHaveManagedGenericArguments { get; set; } - public override void AddNestedType (GenBase gen) - { - base.AddNestedType (gen); - string nest_name = gen.JavaName.Substring (JavaName.Length + 1); - if (nest_name.IndexOf (".") < 0) { - if (gen is InterfaceGen) { - gen.FullName = FullName + gen.Name.Substring (1); - gen.Name = Name + gen.Name.Substring (1); - } else { - gen.FullName = FullName.Substring (0, FullName.Length - Name.Length) + Name.Substring (1) + gen.Name; - gen.Name = Name.Substring (1) + gen.Name; - } - } - } - - public override void ResetValidation () - { - validated = false; - base.ResetValidation (); - } + internal bool NeedsSender => + Methods.Any (m => (m.RetVal.IsVoid && !m.Parameters.HasSender) || (m.IsEventHandlerWithHandledProperty && !m.Parameters.HasSender)); protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) { if (validated) - return is_valid; + return IsValid; validated = true; - + // Due to demand to validate in prior to validate ClassGen's BaseType, it is *not* done at // GenBase. if (TypeParameters != null && !TypeParameters.Validate (opt, type_params, context)) @@ -137,75 +164,28 @@ protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterD Report.Warning (0, Report.WarningInterfaceGen + 3, "Invalidating {0} and all nested types because some of its methods were invalid.", FullName); foreach (GenBase nest in NestedTypes) nest.Invalidate (); - is_valid = false; + IsValid = false; return false; } return true; } - internal string GetEventDelegateName (Method m) - { - int start = Name.StartsWith ("IOn") ? 3 : 1; - if (m.RetVal.IsVoid) { - if (m.IsSimpleEventHandler) - return "EventHandler"; - else { - return "EventHandler<" + GetArgsName (m) + ">"; - } - } else if (m.IsEventHandlerWithHandledProperty) { - return "EventHandler<" + GetArgsName (m) + ">"; - } else { - string methodSpec = Methods.Count > 1 ? m.AdjustedName : String.Empty; - return Name.Substring (start, Name.Length - start - 8) + methodSpec + "Handler"; - } - } - - internal string GetArgsName (Method m) + public override void ResetValidation () { - - string nameBase; - int start; - int trim = 0; - if (Methods.Count > 1) { - if (!String.IsNullOrEmpty (m.ArgsType)) - return m.ArgsType; - if (m.IsSimpleEventHandler) - return "EventArgs"; - nameBase = m.AdjustedName; - start = nameBase.StartsWith ("On") ? 2 : 0; - } else { - if (!String.IsNullOrEmpty (ArgsType)) - return ArgsType; - if (m.IsSimpleEventHandler) - return "EventArgs"; - nameBase = Name; - start = Name.StartsWith ("IOn") ? 3 : 1; - trim = 8; // "Listener" - } - return nameBase.Substring (start, nameBase.Length - start - trim) + "EventArgs"; + validated = false; + base.ResetValidation (); } - public override void Generate (CodeGenerationOptions opt, GenerationInfo gen_info) + public override string ToNative (CodeGenerationOptions opt, string varname, Dictionary mappings = null) { - using (var sw = gen_info.OpenStream (opt.GetFileName (FullName))) { - sw.WriteLine ("using System;"); - sw.WriteLine ("using System.Collections.Generic;"); - sw.WriteLine ("using Android.Runtime;"); - if (opt.CodeGenerationTarget != CodeGenerationTarget.XamarinAndroid) { - sw.WriteLine ("using Java.Interop;"); - } - sw.WriteLine (); - sw.WriteLine ("namespace {0} {{", Namespace); - sw.WriteLine (); - - var generator = opt.CreateCodeGenerator (sw); - generator.WriteInterface (this, "\t", gen_info); - - sw.WriteLine ("}"); - } - - GenerateAnnotationAttribute (opt, gen_info); + return string.Format ("JNIEnv.ToLocalJniHandle ({0})", varname); + /* + if (String.IsNullOrEmpty (Marshaler)) + return String.Format ("JNIEnv.ToLocalJniHandle ({0})", varname); + else + return GetObjectHandleProperty (varname); + */ } #region IRequireGenericMarshal implementation. @@ -226,4 +206,3 @@ public string ToInteroperableJavaObject (string var_name) #endregion } } - diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs index 6de5e867a..3017e4124 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs @@ -1,75 +1,71 @@ using System; +using System.Linq; +using MonoDroid.Generation.Utilities; namespace MonoDroid.Generation { + public class Method : MethodBase + { + bool is_override; - public abstract class Method : MethodBase { - - protected Method (GenBase declaringType) - : base (declaringType) - { - } - - internal void FillReturnType () + public Method (GenBase declaringType) : base (declaringType) { - retval = new ReturnValue (this, Return, ManagedReturn, IsReturnEnumified); } - public bool GenerateDispatchingSetter { get; protected set; } - - public abstract string ArgsType { get; } - public abstract string EventName { get; } - public abstract bool IsAbstract { get; } - public abstract bool IsFinal { get; } - public abstract bool IsInterfaceDefaultMethod { get; } - public abstract string JavaName { get; } - public abstract bool IsStatic { get; } - public abstract bool IsVirtual { get; set; } - public abstract string Return { get; } - public abstract bool IsReturnEnumified { get; } - public abstract string ManagedReturn { get; } - protected abstract string PropertyNameOverride { get; } - public abstract int SourceApiLevel { get; } - public abstract bool Asyncify { get; } - public abstract string CustomAttributes { get; } - - // convenience properties - public bool CanAdd { - get { - return Name.Length > 3 && Name.StartsWith ("Add") && Name.EndsWith ("Listener") && Parameters.Count == 1 && IsVoid && - !(Parameters [0].IsArray); - } - } + public string ArgsType { get; set; } + public string CustomAttributes { get; set; } + public string EventName { get; set; } + public bool GenerateAsyncWrapper { get; set; } + public bool GenerateDispatchingSetter { get; set; } + public bool IsAbstract { get; set; } + public bool IsFinal { get; set; } + public bool IsInterfaceDefaultMethod { get; set; } + public bool IsInterfaceDefaultMethodOverride { get; set; } + public bool IsReturnEnumified { get; set; } + public bool IsStatic { get; set; } + public bool IsVirtual { get; set; } + public string JavaName { get; set; } + public string ManagedReturn { get; set; } + public string PropertyNameOverride { get; set; } + public string Return { get; set; } + public ReturnValue RetVal { get; set; } + public int SourceApiLevel { get; set; } - public bool CanSet { + // it used to be private though... + internal string AdjustedName => IsReturnCharSequence ? Name + "Formatted" : Name; + + public bool Asyncify { get { - return Name.Length > 3 && Name.StartsWith ("Set") && Parameters.Count == 1 && IsVoid && - !(Parameters [0].IsArray); - } - } + if (IsOverride) + return false; - public string DefaultReturn { - get { return RetVal.DefaultValue; } + return GenerateAsyncWrapper; + } } - public bool IsPropertyAccessor { - get { return CanGet || CanSet; } + public string AutoDetectEnumifiedOverrideReturn (AncestorDescendantCache cache) + { + if (RetVal.FullName != "int") + return null; + + var classes = cache.GetAncestorsAndDescendants (DeclaringType); + classes = classes.Concat (classes.SelectMany (x => x.GetAllImplementedInterfaces ())); + + foreach (var t in classes) { + foreach (var candidate in t.GetAllMethods ().Where (m => m.Name == Name && m.Parameters.Count == Parameters.Count)) { + if (JniSignature != candidate.JniSignature) + continue; + if (candidate.IsReturnEnumified) + RetVal.SetGeneratedEnumType (candidate.RetVal.FullName); + } + } + return null; } - public string PropertyName { + public bool CanAdd { get { - if (!IsPropertyAccessor) - throw new InvalidOperationException ("Not a property: " + Name); - var pn = PropertyNameOverride; - if (pn != null) - return pn; - var nameBase = Name; - if (CanAdd || CanSet || Name.StartsWith ("Get")) - nameBase = Name.Substring (3); - if (IsAbstract && (CanGet && RetVal.IsGeneric || CanSet && Parameters [0].IsGeneric) && - DeclaringType is ClassGen) // Interface methods cannot be RawXxx (because they are not generic so far...) - return "Raw" + nameBase; - return nameBase; + return Name.Length > 3 && Name.StartsWith ("Add") && Name.EndsWith ("Listener") && Parameters.Count == 1 && IsVoid && + !(Parameters [0].IsArray); } } @@ -78,73 +74,100 @@ public bool CanGet { return Parameters.Count == 0 && !IsVoid && !RetVal.IsArray && ((Name.Length > 4 && Name.StartsWith ("Get") && char.IsUpper (Name [3])) || - ((Name.Length > 4 && Name.StartsWith ("Has") && char.IsUpper (Name [3]) && retval.JavaName == "boolean") || - (Name.Length > 3 && Name.StartsWith ("Is") && char.IsUpper (Name [2]) && retval.JavaName == "boolean"))); + ((Name.Length > 4 && Name.StartsWith ("Has") && char.IsUpper (Name [3]) && RetVal.JavaName == "boolean") || + (Name.Length > 3 && Name.StartsWith ("Is") && char.IsUpper (Name [2]) && RetVal.JavaName == "boolean"))); } } - public override bool IsGeneric { - get { return base.IsGeneric || RetVal.IsGeneric; } + public bool CanSet { + get { + return Name.Length > 3 && Name.StartsWith ("Set") && Parameters.Count == 1 && IsVoid && + !(Parameters [0].IsArray); + } } - public bool IsListenerConnector { - get { return (CanAdd || CanSet) && Parameters [0].IsListener; } + internal string CalculateEventName (Func checkNameDuplicate) + { + string event_name = EventName; + if (event_name == null) { + var trimSize = Name.EndsWith ("Listener", StringComparison.Ordinal) ? 8 : 0; + event_name = Name.Substring (0, Name.Length - trimSize).Substring (3); + if (event_name.StartsWith ("On")) + event_name = event_name.Substring (2); + if (checkNameDuplicate (event_name)) + event_name += "Event"; + } + return event_name; } - internal bool IsReturnCharSequence { - get { return RetVal.FullName.StartsWith ("Java.Lang.ICharSequence"); } + public bool CanHaveStringOverload => IsReturnCharSequence || Parameters.HasCharSequence; + + public string ConnectorName => $"Get{Name}{IDSignature}Handler"; + + public string EscapedCallbackName => $"cb_{JavaName}{IDSignature}"; + + public string EscapedIdName => "id_" + JavaName.Replace ("<", "_x60_").Replace (">", "_x62_") + IDSignature; + + internal void FillReturnType () + { + RetVal = new ReturnValue (this, Return, ManagedReturn, IsReturnEnumified); } - internal bool IsSimpleEventHandler { - get { return RetVal.IsVoid && (Parameters.Count == 0 || (Parameters.HasSender && Parameters.Count == 1)); } + internal string GetAdapterName (CodeGenerationOptions opt, string adapter) + { + if (string.IsNullOrEmpty (adapter)) + return adapter; + if (AssemblyName == null) + return adapter + ", " + opt.AssemblyName; + return adapter + AssemblyName; } - - public bool IsEventHandlerWithHandledProperty { - get { return RetVal.JavaName == "boolean" && EventName != ""; } + + internal string GetDelegateType () + { + var parms = Parameters.DelegateTypeParams; + + if (IsVoid) + return $"Action"; + else + return $"Func"; } - bool is_override; + public string GetMetadataXPathReference (GenBase declaringType) => + $"{declaringType.MetadataXPathReference}/method[@name='{JavaName}'{Parameters.GetMethodXPathPredicate ()}]"; + + public string GetSignature () => $"n_{JavaName}:{JniSignature}:{ConnectorName}"; + + public bool IsEventHandlerWithHandledProperty => RetVal.JavaName == "boolean" && EventName != ""; + + public override bool IsGeneric => base.IsGeneric || RetVal.IsGeneric; + + public bool IsListenerConnector => (CanAdd || CanSet) && Parameters [0].IsListener; + public bool IsOverride { - get { return !IsStatic && is_override; } - set { is_override = value; } + get => !IsStatic && is_override; + set => is_override = value; } - public bool IsInterfaceDefaultMethodOverride { get; set; } + public bool IsPropertyAccessor => CanGet || CanSet; - public bool IsVoid { - get { return RetVal.JavaName == "void"; } - } + public bool IsReturnCharSequence => RetVal.FullName.StartsWith ("Java.Lang.ICharSequence"); - string jni_sig; - public string JniSignature { - get { - if (jni_sig == null) - jni_sig = "(" + Parameters.JniSignature + ")" + RetVal.JniName; - return jni_sig; - } - } + public bool IsSimpleEventHandler => RetVal.IsVoid && (Parameters.Count == 0 || (Parameters.HasSender && Parameters.Count == 1)); - public InterfaceGen ListenerType { - get { return Parameters [0].ListenerType; } - } + public bool IsVoid => RetVal.JavaName == "void"; - ReturnValue retval; - public ReturnValue RetVal { - get { return retval; } - } + public string JniSignature => "(" + Parameters.JniSignature + ")" + RetVal.JniName; - public string ReturnType { - get { return RetVal.FullName; } - } + public InterfaceGen ListenerType => Parameters [0].ListenerType; public override bool Matches (MethodBase other) { - bool ret = base.Matches (other); + var ret = base.Matches (other); + if (!ret) return ret; - var otherMethod = other as Method; - if (otherMethod == null) + if (!(other is Method otherMethod)) return false; if (RetVal.RawJavaType != otherMethod.RetVal.RawJavaType) @@ -153,98 +176,34 @@ public override bool Matches (MethodBase other) return true; } - public string GetMetadataXPathReference (GenBase declaringType) - { - return string.Format ("{0}/method[@name='{1}'{2}]", declaringType.MetadataXPathReference, JavaName, Parameters.GetMethodXPathPredicate ()); - } - - internal string CalculateEventName (Func checkNameDuplicate) - { - string event_name = EventName; - if (event_name == null) { - var trimSize = Name.EndsWith ("Listener", StringComparison.Ordinal) ? 8 : 0; - event_name = Name.Substring (0, Name.Length - trimSize).Substring (3); - if (event_name.StartsWith ("On")) - event_name = event_name.Substring (2); - if (checkNameDuplicate (event_name)) - event_name += "Event"; + public string PropertyName { + get { + if (!IsPropertyAccessor) + throw new InvalidOperationException ("Not a property: " + Name); + var pn = PropertyNameOverride; + if (pn != null) + return pn; + var nameBase = Name; + if (CanAdd || CanSet || Name.StartsWith ("Get")) + nameBase = Name.Substring (3); + if (IsAbstract && (CanGet && RetVal.IsGeneric || CanSet && Parameters [0].IsGeneric) && + DeclaringType is ClassGen) // Interface methods cannot be RawXxx (because they are not generic so far...) + return "Raw" + nameBase; + return nameBase; } - return event_name; } + public string ReturnType => RetVal.FullName; + protected override bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) { if (GenericArguments != null) GenericArguments.Validate (opt, type_params, context); var tpl = GenericParameterDefinitionList.Merge (type_params, GenericArguments); - if (!retval.Validate (opt, tpl, context)) + if (!RetVal.Validate (opt, tpl, context)) return false; return base.OnValidate (opt, tpl, context); } - - string connector_name; - public string ConnectorName { - get { - if (connector_name == null) - connector_name = "Get" + Name + IDSignature + "Handler"; - return connector_name; - } - } - - string escaped_cb_name; - internal string EscapedCallbackName { - get { - if (escaped_cb_name == null) - escaped_cb_name = "cb_" + JavaName + IDSignature; - return escaped_cb_name; - } - } - - string escaped_id_name; - internal string EscapedIdName { - get { - if (escaped_id_name == null) - escaped_id_name = "id_" + JavaName.Replace ("<", "_x60_").Replace (">", "_x62_") + IDSignature; - return escaped_id_name; - } - } - - string delegate_type; - internal string GetDelegateType () - { - if (delegate_type == null) { - string parms = Parameters.DelegateTypeParams; - if (IsVoid) - delegate_type = String.Format ("Action", parms); - else - delegate_type = String.Format ("Func", parms, RetVal.NativeType); - } - return delegate_type; - } - - // it used to be private though... - internal string AdjustedName { - get { return IsReturnCharSequence ? Name + "Formatted" : Name; } - } - - public string GetSignature () - { - return String.Format ("n_{0}:{1}:{2}", JavaName, JniSignature, ConnectorName); - } - - public bool CanHaveStringOverload { - get { return IsReturnCharSequence || Parameters.HasCharSequence; } - } - - internal string GetAdapterName (CodeGenerationOptions opt, string adapter) - { - if (String.IsNullOrEmpty (adapter)) - return adapter; - if (AssemblyName == null) - return adapter + ", " + opt.AssemblyName; - return adapter + AssemblyName; - } } } - diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs index 40f456423..d77cccc67 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs @@ -1,67 +1,83 @@ using System; +using System.Linq; +using System.Text; +using MonoDroid.Generation.Utilities; namespace MonoDroid.Generation { - public abstract class MethodBase : ApiVersionsSupport.IApiAvailability { - - ParameterList parms; - + public abstract class MethodBase : ApiVersionsSupport.IApiAvailability + { protected MethodBase (GenBase declaringType) { DeclaringType = declaringType; - parms = new ParameterList (); - } - - public virtual string AssemblyName { - get { return null; } - } - - public virtual bool IsAcw { - get { return true; } } - public GenBase DeclaringType { get; private set; } - - protected bool HasParameters { - get { return parms.Count > 0; } - } - - public abstract string Deprecated { - get; - } - - public virtual bool IsGeneric { - get { return parms.HasGeneric; } - } + public string Annotation { get; internal set; } + public int ApiAvailableSince { get; set; } + public string AssemblyName { get; set; } + public GenBase DeclaringType { get; } + public string Deprecated { get; set; } + public GenericParameterDefinitionList GenericArguments { get; set; } + public bool IsAcw { get; set; } + public bool IsValid { get; private set; } + public string Name { get; set; } + public ParameterList Parameters { get; } = new ParameterList (); + public string Visibility { get; set; } - string id_sig; - internal string IDSignature { - get { - if (id_sig == null) - id_sig = HasParameters ? "_" + Parameters.JniSignature.Replace ("/", "_").Replace ("`", "_").Replace (";", "_").Replace ("$", "_").Replace ("[", "array") : String.Empty; - return id_sig; + public string [] AutoDetectEnumifiedOverrideParameters (AncestorDescendantCache cache) + { + if (Parameters.All (p => p.Type != "int")) + return null; + + var classes = cache.GetAncestorsAndDescendants (DeclaringType); + classes = classes.Concat (classes.SelectMany (x => x.GetAllImplementedInterfaces ())); + + foreach (var t in classes) { + foreach (var candidate in t.GetAllMethods ().Where (m => m.Name == Name + && m.Parameters.Count == Parameters.Count + && m.Parameters.Any (p => p.IsEnumified))) { + var ret = new string [Parameters.Count]; + bool mismatch = false; + for (int i = 0; i < Parameters.Count; i++) { + if (Parameters [i].Type == "int" && candidate.Parameters [i].IsEnumified) + ret [i] = candidate.Parameters [i].Type; + else if (Parameters [i].Type != candidate.Parameters [i].Type) { + mismatch = true; + break; + } + } + if (mismatch) + continue; + for (int i = 0; i < ret.Length; i++) + if (ret [i] != null) + Parameters [i].SetGeneratedEnumType (ret [i]); + return ret; + } } + return null; } - public abstract string Name { get; set; } - - public ParameterList Parameters { - get { return parms; } - } - - public GenericParameterDefinitionList GenericArguments { - get; - internal protected set; - } - - public abstract string Visibility { - get; + public string GetSignature (CodeGenerationOptions opt) + { + var sb = new StringBuilder (); + + foreach (var p in Parameters) { + if (sb.Length > 0) + sb.Append (", "); + if (p.IsEnumified) + sb.Append ("[global::Android.Runtime.GeneratedEnum] "); + if (p.Annotation != null) + sb.Append (p.Annotation); + sb.Append (opt.GetOutputName (p.Type)); + sb.Append (" "); + sb.Append (opt.GetSafeIdentifier (p.Name)); + } + return sb.ToString (); } - public int ApiAvailableSince { get; set; } + internal string IDSignature => Parameters.Count > 0 ? "_" + Parameters.JniSignature.Replace ("/", "_").Replace ("`", "_").Replace (";", "_").Replace ("$", "_").Replace ("[", "array") : string.Empty; - public bool IsValid { get; private set; } - public string Annotation { get; internal set; } + public virtual bool IsGeneric => Parameters.HasGeneric; public virtual bool Matches (MethodBase other) { @@ -79,20 +95,10 @@ public virtual bool Matches (MethodBase other) return true; } - public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) - { - context.ContextMethod = this; - try { - return IsValid = OnValidate (opt, type_params, context); - } finally { - context.ContextMethod = null; - } - } - protected virtual bool OnValidate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) { var tpl = GenericParameterDefinitionList.Merge (type_params, GenericArguments); - if (!parms.Validate (opt, tpl, context)) + if (!Parameters.Validate (opt, tpl, context)) return false; if (Parameters.Count > 14) { Report.Warning (0, Report.WarningMethodBase + 0, "More than 16 parameters were found, which goes beyond the maximum number of parameters. ({0})", context.ContextString); @@ -100,5 +106,16 @@ protected virtual bool OnValidate (CodeGenerationOptions opt, GenericParameterDe } return true; } + + public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context) + { + context.ContextMethod = this; + + try { + return IsValid = OnValidate (opt, type_params, context); + } finally { + context.ContextMethod = null; + } + } } } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs index f6c98e57c..9c548aa16 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs @@ -265,42 +265,5 @@ public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList } return true; } - - public static Parameter FromElement (XElement elem) - { - string managedName = elem.XGetAttribute ("managedName"); - string name = !string.IsNullOrEmpty (managedName) ? managedName : SymbolTable.MangleName (elem.XGetAttribute ("name")); - string java_type = elem.XGetAttribute ("type"); - string enum_type = elem.Attribute ("enumType") != null ? elem.XGetAttribute ("enumType") : null; - string managed_type = elem.Attribute ("managedType") != null ? elem.XGetAttribute ("managedType") : null; - // FIXME: "enum_type ?? java_type" should be extraneous. Somewhere in generator uses it improperly. - var result = new Parameter (name, enum_type ?? java_type, enum_type ?? managed_type, enum_type != null, java_type); - if (elem.Attribute ("sender") != null) - result.IsSender = true; - return result; - } - - public static Parameter FromClassElement (XElement elem) - { - string name = "__self"; - string java_type = elem.XGetAttribute ("name"); - string java_package = elem.Parent.XGetAttribute ("name"); - return new Parameter (name, java_package + "." + java_type, null, false); - } - -#if HAVE_CECIL - public static Parameter FromManagedParameter (ParameterDefinition p, string jnitype, string rawtype) - { - // FIXME: safe to use CLR type name? assuming yes as we often use it in metadatamap. - // FIXME: IsSender? - bool isEnumType = p.CustomAttributes.Any (c => c.AttributeType.Name == "GeneratedEnumAttribute"); - return new Parameter (SymbolTable.MangleName (p.Name), jnitype ?? p.ParameterType.FullNameCorrected (), null, isEnumType, rawtype); - } - - public static Parameter FromManagedType (TypeDefinition t, string javaType) - { - return new Parameter ("__self", javaType ?? t.FullName, t.FullName, false); - } -#endif // HAVE_CECIL } } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs index 420ad4321..ae0f560e0 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs @@ -4,41 +4,48 @@ using System.Linq; using System.Text; using System.Xml; +using MonoDroid.Generation.Utilities; - -namespace MonoDroid.Generation { - - public class Property { - - string name; - +namespace MonoDroid.Generation +{ + public class Property + { public Property (string name) { - this.name = name; + Name = name; } public Method Getter {get; set;} public Method Setter {get; set;} - public bool IsGeneric { - get { return Getter.IsGeneric; } - } + public bool IsGeneric => Getter.IsGeneric; // This is a workaround for generaing compatibility for Android.Graphics.Drawables.ColorDrawable.SetColor (wrt bug #4288). public bool GenerateDispatchingSetter { get; set; } - internal string AdjustedName { - get { return Getter.ReturnType.StartsWith ("Java.Lang.ICharSequence") ? name + "Formatted" : name; } - } + internal string AdjustedName => + Getter.ReturnType.StartsWith ("Java.Lang.ICharSequence") ? Name + "Formatted" : Name; - public string Name { - get { return name; } - set { name = value; } - } + public string Name { get; set; } + + public string Type => Setter != null ? Setter.Parameters [0].Type : Getter.ReturnType; - public string Type { - get { return Setter != null ? Setter.Parameters [0].Type : Getter.ReturnType; } + public void AutoDetectEnumifiedOverrideProperties (AncestorDescendantCache cache) + { + if (Type != "int") + return; + + var classes = cache.GetAncestorsAndDescendants (Getter.DeclaringType); + classes = classes.Concat (classes.SelectMany (x => x.GetAllImplementedInterfaces ())); + + foreach (var t in classes) { + foreach (var candidate in t.Properties.Where (p => p.Name == Name)) { + if (Getter.JniSignature != candidate.Getter.JniSignature) + continue; + if (candidate.Getter.IsReturnEnumified) + Getter.RetVal.SetGeneratedEnumType (candidate.Getter.RetVal.FullName); + } + } } } } - diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/Parser.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/Parser.cs index 8038290db..d00e7a34c 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/Parser.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/Parser.cs @@ -105,12 +105,12 @@ List ParsePackage (XElement ns, Predicate p) case "class": if (elem.XGetAttribute ("obfuscated") == "true") continue; - gen = new XmlClassGen (ns, elem); + gen = XmlApiImporter.CreateClass (ns, elem); break; case "interface": if (elem.XGetAttribute ("obfuscated") == "true") continue; - gen = new XmlInterfaceGen (ns, elem); + gen = XmlApiImporter.CreateInterface (ns, elem); break; default: Report.Warning (0, Report.WarningParser + 3, "Unexpected node in package element: {0}.", elem.Name); diff --git a/tools/generator/Tests/Unit-Tests/ManagedTests.cs b/tools/generator/Tests/Unit-Tests/ManagedTests.cs index 9902cddde..7e50073d5 100644 --- a/tools/generator/Tests/Unit-Tests/ManagedTests.cs +++ b/tools/generator/Tests/Unit-Tests/ManagedTests.cs @@ -1,4 +1,4 @@ -using Android.Runtime; +using Android.Runtime; using Mono.Cecil; using MonoDroid.Generation; using NUnit.Framework; @@ -60,7 +60,7 @@ public void SetUp () options = new CodeGenerationOptions (); foreach (var type in module.Types.Where(t => t.IsClass && t.Namespace == "Java.Lang")) { - var @class = new ManagedClassGen (type, options); + var @class = CecilApiImporter.CreateClass (type, options); Assert.IsTrue (@class.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext()), "@class.Validate failed!"); options.SymbolTable.AddType (@class); } @@ -76,7 +76,7 @@ public void TearDown () [Test] public void Class () { - var @class = new ManagedClassGen (module.GetType ("Com.Mypackage.Foo"), options); + var @class = CecilApiImporter.CreateClass (module.GetType ("Com.Mypackage.Foo"), options); Assert.IsTrue (@class.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "@class.Validate failed!"); Assert.AreEqual ("public", @class.Visibility); @@ -93,8 +93,8 @@ public void Class () public void Method () { var type = module.GetType ("Com.Mypackage.Foo"); - var @class = new ManagedClassGen (type, options); - var method = new ManagedMethod (@class, type.Methods.First (m => m.Name == "Bar")); + var @class = CecilApiImporter.CreateClass (type, options); + var method = CecilApiImporter.CreateMethod (@class, type.Methods.First (m => m.Name == "Bar")); Assert.IsTrue (method.Validate (new CodeGenerationOptions (), new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "method.Validate failed!"); Assert.AreEqual ("public", method.Visibility); @@ -113,10 +113,10 @@ public void Method () public void Method_Matches_True () { var type = module.GetType ("Com.Mypackage.Foo"); - var @class = new ManagedClassGen (type, options); + var @class = CecilApiImporter.CreateClass (type, options); var unknownTypes = type.Methods.First (m => m.Name == "UnknownTypes"); - var methodA = new ManagedMethod (@class, unknownTypes); - var methodB = new ManagedMethod (@class, unknownTypes); + var methodA = CecilApiImporter.CreateMethod (@class, unknownTypes); + var methodB = CecilApiImporter.CreateMethod (@class, unknownTypes); Assert.IsTrue (methodA.Matches (methodB), "Methods should match!"); } @@ -124,12 +124,12 @@ public void Method_Matches_True () public void Method_Matches_False () { var type = module.GetType ("Com.Mypackage.Foo"); - var @class = new ManagedClassGen (type, options); + var @class = CecilApiImporter.CreateClass (type, options); var unknownTypesA = type.Methods.First (m => m.Name == "UnknownTypes"); var unknownTypesB = type.Methods.First (m => m.Name == "UnknownTypesReturn"); unknownTypesB.Name = "UnknownTypes"; - var methodA = new ManagedMethod (@class, unknownTypesA); - var methodB = new ManagedMethod (@class, unknownTypesB); + var methodA = CecilApiImporter.CreateMethod (@class, unknownTypesA); + var methodB = CecilApiImporter.CreateMethod (@class, unknownTypesB); //Everything the same besides return type Assert.IsFalse (methodA.Matches (methodB), "Methods should not match!"); } @@ -138,8 +138,8 @@ public void Method_Matches_False () public void MethodWithParameters () { var type = module.GetType ("Com.Mypackage.Foo"); - var @class = new ManagedClassGen (type, options); - var method = new ManagedMethod (@class, type.Methods.First (m => m.Name == "BarWithParams")); + var @class = CecilApiImporter.CreateClass (type, options); + var method = CecilApiImporter.CreateMethod (@class, type.Methods.First (m => m.Name == "BarWithParams")); Assert.IsTrue (method.Validate (new CodeGenerationOptions (), new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "method.Validate failed!"); Assert.AreEqual ("(ZID)Ljava/lang/String;", method.JniSignature); Assert.AreEqual ("java.lang.String", method.Return); @@ -168,8 +168,8 @@ public void MethodWithParameters () public void Ctor () { var type = module.GetType ("Com.Mypackage.Foo"); - var @class = new ManagedClassGen (type, options); - var ctor = new ManagedCtor (@class, type.Methods.First (m => m.IsConstructor && !m.IsStatic)); + var @class = CecilApiImporter.CreateClass (type, options); + var ctor = CecilApiImporter.CreateCtor (@class, type.Methods.First (m => m.IsConstructor && !m.IsStatic)); Assert.IsTrue (ctor.Validate (new CodeGenerationOptions (), new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "ctor.Validate failed!"); Assert.AreEqual ("public", ctor.Visibility); @@ -182,8 +182,8 @@ public void Ctor () public void Field () { var type = module.GetType ("Com.Mypackage.Foo"); - var @class = new ManagedClassGen (type, options); - var field = new ManagedField (type.Fields.First (f => f.Name == "Value")); + var @class = CecilApiImporter.CreateClass (type, options); + var field = CecilApiImporter.CreateField (type.Fields.First (f => f.Name == "Value")); Assert.IsTrue (field.Validate (new CodeGenerationOptions (), new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "field.Validate failed!"); Assert.AreEqual ("Value", field.Name); @@ -198,7 +198,7 @@ public void Field () public void Interface () { var type = module.GetType ("Com.Mypackage.IService"); - var @interface = new ManagedInterfaceGen (type, options); + var @interface = CecilApiImporter.CreateInterface (type, options); Assert.IsTrue (@interface.Validate (new CodeGenerationOptions (), new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "interface.Validate failed!"); Assert.AreEqual ("public", @interface.Visibility); diff --git a/tools/generator/Tests/Unit-Tests/SupportTypes.cs b/tools/generator/Tests/Unit-Tests/SupportTypes.cs index 73d3a992b..3dd968019 100644 --- a/tools/generator/Tests/Unit-Tests/SupportTypes.cs +++ b/tools/generator/Tests/Unit-Tests/SupportTypes.cs @@ -7,14 +7,10 @@ class TestClass : ClassGen { public TestClass (string baseType, string javaName) : base (new TestBaseSupport (javaName)) { - this.BaseType = baseType; + BaseType = baseType; + IsAbstract = false; + IsFinal = false; } - - public override bool IsAbstract => false; - - public override bool IsFinal => false; - - public override string BaseType { get; set; } } class TestBaseSupport : GenBaseSupport @@ -24,238 +20,145 @@ public TestBaseSupport (string javaName) var split = javaName.Split ('.'); Name = split.Last (); FullName = javaName; + JavaSimpleName = Name; PackageName = javaName.Substring (0, javaName.Length - Name.Length - 1); + Namespace = PackageName; + IsGeneratable = true; + Visibility = "public"; + TypeParameters = new GenericParameterDefinitionList (); } - - public override bool IsAcw => false; - - public override bool IsDeprecated => false; - - public override string DeprecatedComment => string.Empty; - - public override bool IsGeneratable => true; - - public override bool IsGeneric => false; - - public override bool IsObfuscated => false; - - public override string FullName { get; set; } - - public override string Name { get; set; } - - public override string Namespace => PackageName; - - public override string JavaSimpleName => Name; - - public override string PackageName { get; set; } - - public override string Visibility => "public"; - - GenericParameterDefinitionList typeParameters = new GenericParameterDefinitionList (); - - public override GenericParameterDefinitionList TypeParameters => typeParameters; } class TestField : Field { - bool isFinal, isStatic, isEnumified, isDeprecated; - string type, value, deprecatedComment, visibility = "public"; - Parameter setterParameter; - public TestField (string type, string name) { - this.type = type; + TypeName = type; + JavaName = name; Name = name; + Visibility = "public"; + + //NOTE: passing `type` for `managedType`, required since `SymbolTable` is no longer static + // This currently isn't causing any test failures + SetterParameter = new Parameter ("value", TypeName, TypeName, IsEnumified); } public TestField SetStatic () { - isStatic = true; + IsStatic = true; return this; } public TestField SetConstant (string value = null) { - isFinal = - isStatic = true; - this.value = value; + IsFinal = true; + IsStatic = true; + Value = value; return this; } public TestField SetEnumified () { - isEnumified = true; + IsEnumified = true; + SetterParameter = new Parameter ("value", TypeName, TypeName, IsEnumified); return this; } public TestField SetDeprecated (string comment = null) { - isDeprecated = true; - deprecatedComment = comment; + IsDeprecated = true; + DeprecatedComment = comment; return this; } public TestField SetVisibility (string visibility) { - this.visibility = visibility; + Visibility = visibility; return this; } public TestField SetValue (string value) { - this.value = value; + Value = value; return this; } - - public override bool IsDeprecated => isDeprecated; - - public override string DeprecatedComment => deprecatedComment; - - public override bool IsFinal => isFinal; - - public override bool IsStatic => isStatic; - - public override string JavaName => Name; - - public override bool IsEnumified => isEnumified; - - public override string TypeName => type; - - public override string Name { get; set; } - - public override string Value => value; - - public override string Visibility => visibility; - - protected override Parameter SetterParameter { - get { - if (setterParameter == null) { - //NOTE: passing `type` for `managedType`, required since `SymbolTable` is no longer static - // This currently isn't causing any test failures - setterParameter = new Parameter ("value", type, type, isEnumified); - } - return setterParameter; - } - } } class TestMethod : Method { - int apiLevel = 27; - string @return, managedReturn, visibility = "public", deprecated; - bool isAbstract, isFinal, isStatic, asyncify, isReturnEnumified; - public TestMethod (GenBase @class, string name, string @return = "void") : base (@class) { Name = name; - this.@return = @return; + JavaName = name; + SourceApiLevel = 27; + IsVirtual = true; + Visibility = "public"; + Return = @return; + FillReturnType (); } public TestMethod SetApiLevel (int apiLevel) { - this.apiLevel = apiLevel; + SourceApiLevel = apiLevel; return this; } public TestMethod SetManagedReturn (string managedReturn) { - this.managedReturn = managedReturn; + ManagedReturn = managedReturn; FillReturnType (); return this; } public TestMethod SetFinal () { - isFinal = true; + IsFinal = true; IsVirtual = false; return this; } public TestMethod SetAbstract () { - isAbstract = true; + IsAbstract = true; return this; } public TestMethod SetStatic () { - isFinal = - isStatic = true; + IsFinal = + IsStatic = true; IsVirtual = false; return this; } public TestMethod SetAsyncify () { - asyncify = true; + GenerateAsyncWrapper = true; return this; } public TestMethod SetVisibility (string visibility) { - this.visibility = visibility; + Visibility = visibility; return this; } public TestMethod SetDeprecated (string deprecated) { - this.deprecated = deprecated; + Deprecated = deprecated; return this; } public TestMethod SetReturnEnumified () { - this.isReturnEnumified = true; + IsReturnEnumified = true; return this; } - - public override string ArgsType => null; - - public override string EventName => null; - - public override bool IsAbstract => isAbstract; - - public override bool IsFinal => isFinal; - - public override bool IsInterfaceDefaultMethod => false; - - public override string JavaName => Name; - - public override bool IsStatic => isStatic; - - public override bool IsVirtual { get; set; } = true; - - public override string Return => @return; - - public override bool IsReturnEnumified => isReturnEnumified; - - public override string ManagedReturn => managedReturn; - - public override int SourceApiLevel => apiLevel; - - public override bool Asyncify => asyncify; - - public override string CustomAttributes => null; - - public override string Name { get; set; } - - protected override string PropertyNameOverride => null; - - public override string AssemblyName => null; - - public override string Deprecated => deprecated; - - public override string Visibility => visibility; } class TestCtor : Ctor { - string custom_attributes; - string deprecated; - bool is_non_static_nested_type; - string visibility; - public TestCtor (GenBase @class, string name) : base (@class) { Name = name; @@ -269,49 +172,35 @@ public TestCtor SetAnnotation (string value) public TestCtor SetCustomAttributes (string value) { - custom_attributes = value; + CustomAttributes = value; return this; } public TestCtor SetDeprecated (string value) { - deprecated = value; + Deprecated = value; return this; } public TestCtor SetIsNonStaticNestedType (bool value) { - is_non_static_nested_type = value; + IsNonStaticNestedType = value; return this; } public TestCtor SetVisibility (string value) { - visibility = value; + Visibility = value; return this; } - - public override string CustomAttributes => custom_attributes; - - public override string Deprecated => deprecated; - - public override bool IsNonStaticNestedType => is_non_static_nested_type; - - public override string Name { get; set; } - - public override string Visibility => visibility; } class TestInterface : InterfaceGen { - string args_type; - public TestInterface (string argsType, string javaName) : base (new TestBaseSupport (javaName)) { - args_type = argsType; + ArgsType = argsType; } - - public override string ArgsType => args_type; } static class SupportTypeBuilder diff --git a/tools/generator/Tests/Unit-Tests/XmlTests.cs b/tools/generator/Tests/Unit-Tests/XmlTests.cs index 84465fb85..ebcaf431f 100644 --- a/tools/generator/Tests/Unit-Tests/XmlTests.cs +++ b/tools/generator/Tests/Unit-Tests/XmlTests.cs @@ -1,4 +1,4 @@ -using MonoDroid.Generation; +using MonoDroid.Generation; using NUnit.Framework; using System.Collections.Generic; using System.IO; @@ -52,7 +52,7 @@ public void SetUp () options = new CodeGenerationOptions (); var javaLang = xml.Element ("api").Element ("package"); foreach (var type in javaLang.Elements("class")) { - var @class = new XmlClassGen (javaLang, type); + var @class = XmlApiImporter.CreateClass (javaLang, type); Assert.IsTrue (@class.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "@class.Validate failed!"); options.SymbolTable.AddType (@class); } @@ -64,7 +64,7 @@ public void SetUp () public void Class () { var element = package.Element ("class"); - var @class = new XmlClassGen (package, element); + var @class = XmlApiImporter.CreateClass (package, element); Assert.IsTrue (@class.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "@class.Validate failed!"); Assert.AreEqual ("public", @class.Visibility); @@ -81,8 +81,8 @@ public void Class () public void Method () { var element = package.Element ("class"); - var @class = new XmlClassGen (package, element); - var method = new XmlMethod (@class, element.Element ("method")); + var @class = XmlApiImporter.CreateClass (package, element); + var method = XmlApiImporter.CreateMethod (@class, element.Element ("method")); Assert.IsTrue (method.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "method.Validate failed!"); Assert.AreEqual ("public", method.Visibility); @@ -101,10 +101,10 @@ public void Method () public void Method_Matches_True () { var element = package.Element ("class"); - var @class = new XmlClassGen (package, element); + var @class = XmlApiImporter.CreateClass (package, element); var unknownTypes = element.Elements ("method").Where (e => e.Attribute ("name").Value == "unknownTypes").First (); - var methodA = new XmlMethod (@class, unknownTypes); - var methodB = new XmlMethod (@class, unknownTypes); + var methodA = XmlApiImporter.CreateMethod (@class, unknownTypes); + var methodB = XmlApiImporter.CreateMethod (@class, unknownTypes); Assert.IsTrue (methodA.Matches (methodB), "Methods should match!"); } @@ -112,12 +112,12 @@ public void Method_Matches_True () public void Method_Matches_False () { var element = package.Element ("class"); - var @class = new XmlClassGen (package, element); + var @class = XmlApiImporter.CreateClass (package, element); var unknownTypesA = element.Elements ("method").Where (e => e.Attribute ("name").Value == "unknownTypes").First (); var unknownTypesB = element.Elements ("method").Where (e => e.Attribute ("name").Value == "unknownTypesReturn").First (); unknownTypesB.Attribute ("name").Value = "unknownTypes"; - var methodA = new XmlMethod (@class, unknownTypesA); - var methodB = new XmlMethod (@class, unknownTypesB); + var methodA = XmlApiImporter.CreateMethod (@class, unknownTypesA); + var methodB = XmlApiImporter.CreateMethod (@class, unknownTypesB); //Everything the same besides return type Assert.IsFalse (methodA.Matches (methodB), "Methods should not match!"); } @@ -126,8 +126,8 @@ public void Method_Matches_False () public void MethodWithParameters () { var element = package.Element ("class"); - var @class = new XmlClassGen (package, element); - var method = new XmlMethod (@class, element.Elements ("method").Where (e => e.Attribute ("name").Value == "barWithParams").First ()); + var @class = XmlApiImporter.CreateClass (package, element); + var method = XmlApiImporter.CreateMethod (@class, element.Elements ("method").Where (e => e.Attribute ("name").Value == "barWithParams").First ()); Assert.IsTrue (method.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "method.Validate failed!"); Assert.AreEqual ("(ZID)Ljava/lang/String;", method.JniSignature); Assert.AreEqual ("java.lang.String", method.Return); @@ -156,8 +156,8 @@ public void MethodWithParameters () public void Ctor () { var element = package.Element ("class"); - var @class = new XmlClassGen (package, element); - var ctor = new XmlCtor (@class, element.Element ("constructor")); + var @class = XmlApiImporter.CreateClass (package, element); + var ctor = XmlApiImporter.CreateCtor (@class, element.Element ("constructor")); Assert.IsTrue (ctor.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "ctor.Validate failed!"); Assert.AreEqual ("public", ctor.Visibility); @@ -170,8 +170,8 @@ public void Ctor () public void Field () { var element = package.Element ("class"); - var @class = new XmlClassGen (package, element); - var field = new XmlField (element.Element ("field")); + var @class = XmlApiImporter.CreateClass (package, element); + var field = XmlApiImporter.CreateField (element.Element ("field")); Assert.IsTrue (field.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "field.Validate failed!"); Assert.AreEqual ("Value", field.Name); @@ -186,7 +186,7 @@ public void Field () public void Interface () { var element = package.Element ("interface"); - var @interface = new XmlInterfaceGen (package, element); + var @interface = XmlApiImporter.CreateInterface (package, element); Assert.IsTrue (@interface.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "interface.Validate failed!"); Assert.AreEqual ("public", @interface.Visibility); diff --git a/tools/generator/generator.csproj b/tools/generator/generator.csproj index 6ebfaff0d..65ca1979a 100644 --- a/tools/generator/generator.csproj +++ b/tools/generator/generator.csproj @@ -61,8 +61,9 @@ + + - @@ -94,13 +95,7 @@ - - - - - - @@ -119,13 +114,7 @@ - - - - - -