public override void Process(ProcessedType pt) { Logger.Log($"Processing Type: {pt.TypeName}"); Types.Add(pt); if (pt.IsNativeReference) { return; } var t = pt.Type; if (t.IsEnum) { return; } extension_type = t.HasCustomAttribute("System.Runtime.CompilerServices", "ExtensionAttribute"); implement_system_icomparable = t.Implements("System", "IComparable"); implement_system_icomparable_t = t.Implements("System", "IComparable`1"); implement_system_iequatable_t = t.Implements("System", "IEquatable`1"); var constructors = GetConstructors(pt).OrderBy((arg) => arg.Constructor.GetParameters().Length).ToList(); var processedConstructors = PostProcessConstructors(constructors).ToList(); pt.Constructors = processedConstructors; var meths = GetMethods(pt).OrderBy((arg) => arg.Method.Name).ToList(); var processedMethods = PostProcessMethods(meths).ToList(); pt.Methods = processedMethods; var props = new List <ProcessedProperty> (); var subscriptProps = new List <ProcessedProperty> (); foreach (var pi in GetProperties(t)) { var getter = pi.GetGetMethod(); var setter = pi.GetSetMethod(); // setter only property are valid in .NET and we need to generate a method in ObjC (there's no writeonly properties) if (getter == null) { continue; } // indexers are implemented as methods and object subscripting if ((getter.GetParameters().Length > 0) || ((setter != null) && setter.GetParameters().Length > 1)) { subscriptProps.Add(new ProcessedProperty(pi, this, pt)); continue; } // we can do better than methods for the more common cases (readonly and readwrite) processedMethods.RemoveAll(x => x.Method == getter); processedMethods.RemoveAll(x => x.Method == setter); props.Add(new ProcessedProperty(pi, this, pt)); } props = props.OrderBy((arg) => arg.Name).ToList(); var processedProperties = PostProcessProperties(props).ToList(); pt.Properties = processedProperties; if (subscriptProps.Count > 0) { if (subscriptProps.Count > 1) { Delayed.Add(ErrorHelper.CreateWarning(1041, $"Indexed properties on {t.Name} is not generated because multiple indexed properties not supported.")); } else { subscriptProperties.Add(t, PostProcessSubscriptProperties(subscriptProps).ToList()); } } // fields will need to be wrapped within properties var f = GetFields(pt).OrderBy((arg) => arg.Name).ToList(); var processedFields = PostProcessFields(f).ToList(); pt.Fields = processedFields; }
protected IEnumerable <ProcessedMethod> GetMethods(ProcessedType type) { var t = type.Type; foreach (var mi in t.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { if (!mi.IsPublic) { continue; } // handle special cases where we can implement something better, e.g. a better match if (implement_system_icomparable_t) { // for X we prefer `IComparable<X>` to `IComparable` - since it will be exposed identically to ObjC if (mi.Match("System.Int32", "CompareTo", t.FullName)) { icomparable [t] = mi; continue; } } if (implement_system_icomparable && mi.Match("System.Int32", "CompareTo", "System.Object")) { // don't replace CompareTo(T) with CompareTo(Object) if (!icomparable.ContainsKey(t)) { icomparable.Add(t, mi); } continue; } if (mi.Match("System.Boolean", "Equals", "System.Object")) { yield return(new ProcessedMethod(mi, this, type) { DeclaringType = type, MethodType = MethodType.NSObjectProcotolIsEqual, }); continue; } if (implement_system_iequatable_t && mi.Match("System.Boolean", "Equals", new string [] { null })) { yield return(new ProcessedMethod(mi, this, type) { DeclaringType = type, MethodType = MethodType.IEquatable, }); continue; } if (mi.Match("System.Int32", "GetHashCode")) { yield return(new ProcessedMethod(mi, this, type) { DeclaringType = type, MethodType = MethodType.NSObjectProcotolHash, }); continue; } var rt = mi.ReturnType; if (!IsSupported(rt)) { Delayed.Add(ErrorHelper.CreateWarning(1030, $"Method `{mi}` is not generated because return type `{rt}` is not supported.")); continue; } bool pcheck = true; foreach (var p in mi.GetParameters()) { var pt = p.ParameterType; if (!IsSupported(pt)) { Delayed.Add(ErrorHelper.CreateWarning(1031, $"Method `{mi}` is not generated because of parameter type `{pt}` is not supported.")); pcheck = false; } else if (p.HasDefaultValue) { members_with_default_values.Add(mi); } } if (!pcheck) { continue; } // handle extension methods if (extension_type && mi.HasCustomAttribute("System.Runtime.CompilerServices", "ExtensionAttribute")) { var extended_type = mi.GetParameters() [0].ParameterType; if (extended_type.IsPrimitive) { Delayed.Add(ErrorHelper.CreateWarning(1034, $"Extension method `{mi}` is not generated inside a category because they cannot be created on primitive type `{extended_type}`. A normal, static method was generated.")); } else { Dictionary <Type, List <ProcessedMethod> > extensions; if (!extensions_methods.TryGetValue(t, out extensions)) { extensions = new Dictionary <Type, List <ProcessedMethod> > (); extensions_methods.Add(t, extensions); } List <ProcessedMethod> extmethods; if (!extensions.TryGetValue(extended_type, out extmethods)) { extmethods = new List <ProcessedMethod> (); extensions.Add(extended_type, extmethods); } extmethods.Add(new ProcessedMethod(mi, this, type) { IsExtension = true }); continue; } } yield return(new ProcessedMethod(mi, this, type)); } }
bool IsSupported(Type t) { if (t.IsByRef) { return(IsSupported(t.GetElementType())); } if (t.IsArray) { return(IsSupported(t.GetElementType())); } if (unsupported.Contains(t)) { return(false); } if (t.IsPointer) { Delayed.Add(ErrorHelper.CreateWarning(1010, $"Type `{t}` is not generated because `unsafe pointers` are not supported.")); unsupported.Add(t); return(false); } if (t.IsGenericParameter || t.IsGenericType) { Delayed.Add(ErrorHelper.CreateWarning(1010, $"Type `{t}` is not generated because `generics` are not supported.")); unsupported.Add(t); return(false); } switch (t.Namespace) { case "System": switch (t.Name) { case "Object": // we cannot accept arbitrary NSObject (which we might not have bound) into mono case "DBNull": case "Exception": case "Type": Delayed.Add(ErrorHelper.CreateWarning(1011, $"Type `{t}` is not generated because it lacks a native counterpart.")); unsupported.Add(t); return(false); case "Decimal": return(AddDecimalSupport(t)); case "DateTime": return(AddDateTimeSupport(t)); case "TimeSpan": if (system_timespan == null) { system_timespan = new ProcessedType(t) { Assembly = GetMscorlib(t), }; AddExtraType(system_timespan); } return(true); case "IFormatProvider": if (system_iformatprovider == null) { system_iformatprovider = new ProcessedType(t) { Assembly = GetMscorlib(t), }; AddExtraType(system_iformatprovider); } return(true); } break; case "System.Globalization": switch (t.Name) { case "TimeSpanStyles": // enum for TimeSpan support if (system_globalization_timespanstyles == null) { system_globalization_timespanstyles = new ProcessedType(t) { Assembly = GetMscorlib(t), }; AddExtraType(system_globalization_timespanstyles); } return(true); } break; } var base_type = t.BaseType; return((base_type == null) || base_type.Is("System", "Object") ? true : IsSupported(base_type)); }
bool IsSupported(Type t) { if (t.IsByRef) { return(IsSupported(t.GetElementType())); } if (unsupported.Contains(t)) { return(false); } if (t.IsArray) { delayed.Add(ErrorHelper.CreateWarning(1010, $"Type `{t}` is not generated because `arrays` are not supported.")); unsupported.Add(t); return(false); } if (t.IsPointer) { delayed.Add(ErrorHelper.CreateWarning(1010, $"Type `{t}` is not generated because `unsafe pointers` are not supported.")); unsupported.Add(t); return(false); } if (t.IsGenericParameter || t.IsGenericType) { delayed.Add(ErrorHelper.CreateWarning(1010, $"Type `{t}` is not generated because `generics` are not supported.")); unsupported.Add(t); return(false); } switch (t.Namespace) { case "System": switch (t.Name) { case "Object": // we cannot accept arbitrary NSObject (which we might not have bound) into mono case "DBNull": case "Exception": case "IFormatProvider": case "Type": delayed.Add(ErrorHelper.CreateWarning(1011, $"Type `{t}` is not generated because it lacks a native counterpart.")); unsupported.Add(t); return(false); case "DateTime": // FIXME: NSDateTime case "Decimal": // FIXME: NSDecimal case "TimeSpan": delayed.Add(ErrorHelper.CreateWarning(1012, $"Type `{t}` is not generated because it lacks a marshaling code with a native counterpart.")); unsupported.Add(t); return(false); } break; } var base_type = t.BaseType; return((base_type == null) || base_type.Is("System", "Object") ? true : IsSupported(base_type)); }
public override void Process(IEnumerable <Assembly> input) { foreach (var a in input) { var pa = new ProcessedAssembly(a); // ignoring/warning one is not an option as they could be different (e.g. different builds/versions) if (!AddIfUnique(pa)) { throw ErrorHelper.CreateError(12, $"The assembly name `{pa.Name}` is not unique"); } foreach (var t in GetTypes(a)) { if (t.IsEnum) { enums.Add(new ProcessedType(t)); continue; } if (t.IsInterface) { protocols.Add(new ProcessedType(t)); } else { types.Add(new ProcessedType(t)); } extension_type = t.HasCustomAttribute("System.Runtime.CompilerServices", "ExtensionAttribute"); implement_system_icomparable = t.Implements("System", "IComparable"); implement_system_icomparable_t = t.Implements("System", "IComparable`1"); var constructors = GetConstructors(t).OrderBy((arg) => arg.ParameterCount).ToList(); var processedConstructors = PostProcessConstructors(constructors).ToList(); if (processedConstructors.Count > 0) { ctors.Add(t, processedConstructors); } var typeEquals = equals.Where(x => x.Key == t).Select(x => x.Value); var meths = GetMethods(t).OrderBy((arg) => arg.Name).ToList(); var processedMethods = PostProcessMethods(meths, typeEquals).ToList(); if (processedMethods.Count > 0) { methods.Add(t, processedMethods); } var props = new List <PropertyInfo> (); var subscriptProps = new List <PropertyInfo> (); foreach (var pi in GetProperties(t)) { var getter = pi.GetGetMethod(); var setter = pi.GetSetMethod(); // setter only property are valid in .NET and we need to generate a method in ObjC (there's no writeonly properties) if (getter == null) { continue; } // indexers are implemented as methods and object subscripting if ((getter.ParameterCount > 0) || ((setter != null) && setter.ParameterCount > 1)) { subscriptProps.Add(pi); continue; } // we can do better than methods for the more common cases (readonly and readwrite) processedMethods.RemoveAll(x => x.Method == getter); processedMethods.RemoveAll(x => x.Method == setter); props.Add(pi); } props = props.OrderBy((arg) => arg.Name).ToList(); var processedProperties = PostProcessProperties(props).ToList(); if (processedProperties.Count > 0) { properties.Add(t, processedProperties); } if (subscriptProps.Count > 0) { if (subscriptProps.Count > 1) { delayed.Add(ErrorHelper.CreateWarning(1041, $"Indexed properties on {t.Name} is not generated because multiple indexed properties not supported.")); } else { subscriptProperties.Add(t, PostProcessSubscriptProperties(subscriptProps).ToList()); } } // fields will need to be wrapped within properties var f = GetFields(t).OrderBy((arg) => arg.Name).ToList(); var processedFields = PostProcessFields(f).ToList(); if (processedFields.Count > 0) { fields.Add(t, processedFields); } } } types = types.OrderBy((arg) => arg.Type.FullName).OrderBy((arg) => types.Contains(arg.Type.BaseType)).ToList(); Console.WriteLine($"\t{types.Count} types found"); ErrorHelper.Show(delayed); }
public EmbeddinatorException(int code, bool error, Exception innerException, string message, params object [] args) : base(String.Format(message, args), innerException) { Code = code; Error = error || ErrorHelper.GetWarningLevel(code) == ErrorHelper.WarningLevel.Error; }