public ProcessedProperty(PropertyInfo property, Processor processor, ProcessedType declaringType) : base(processor, declaringType) { Property = property; getMethod = new CachedValue <ProcessedMethod> (() => { var getter = Property.GetGetMethod(); if (getter != null) { return(new ProcessedMethod(getter, Processor, declaringType) { NameOverride = GetterName, IsPropertyImplementation = true }); } return(null); }); setMethod = new CachedValue <ProcessedMethod> (() => { var setter = Property.GetSetMethod(); if (setter != null) { return(new ProcessedMethod(setter, Processor, declaringType) { NameOverride = SetterName, IsPropertyImplementation = true }); } return(null); }); }
bool AddDecimalSupport(Type t) { if (system_decimal != null) { return(true); } var corlib = GetMscorlib(t); system_decimal = new ProcessedType(t) { Assembly = corlib, // this is tracked because the linker (if enabled) needs to be aware of the requirement // but we do not want any code to be generated (it's referenced only from native/glue code) IsNativeReference = true, Methods = new List <ProcessedMethod> (), }; // we don't want to being everything from System.Decimal, but only the bits the support code can call var string_type = corlib.Assembly.GetType("System.String"); var iformatprovider_type = corlib.Assembly.GetType("System.IFormatProvider"); var parse = t.GetMethod("Parse", new Type [] { string_type, iformatprovider_type }); system_decimal.Methods.Add(new ProcessedMethod(parse, this)); var tostring = t.GetMethod("ToString", new Type [] { iformatprovider_type }); system_decimal.Methods.Add(new ProcessedMethod(tostring, this)); AddExtraType(system_decimal); return(true); }
public ProcessedMethod(MethodInfo method, Processor processor, ProcessedType declaringType) : base(processor, declaringType) { Method = method; MethodType = MethodType.Normal; Parameters = method.GetParameters(); FirstDefaultParameter = -1; }
Dictionary <string, ProcessedMemberBase> GetRegistrationForType(ProcessedType t) { Dictionary <string, ProcessedMemberBase> data; if (MappedTypes.TryGetValue(t, out data)) { return(data); } return(null); }
protected IEnumerable <ProcessedFieldInfo> GetFields(ProcessedType t) { foreach (var fi in t.Type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { if (!fi.IsPublic) { continue; } var ft = fi.FieldType; if (!IsSupported(ft)) { Delayed.Add(ErrorHelper.CreateWarning(1050, $"Field `{fi}` is not generated because of field type `{ft}` is not supported.")); continue; } yield return(new ProcessedFieldInfo(fi, this, t)); } }
IEnumerable <ProcessedMethod> AddDefaultValuesWrappers(MethodInfo mi, ProcessedType containingType) { // parameters with default values must be at the end and there can be many of them var parameters = mi.GetParameters(); for (int i = parameters.Length - 1; i >= 0; i--) { if (!parameters [i].HasDefaultValue) { continue; } var pm = new ProcessedMethod(mi, this, containingType) { MethodType = MethodType.DefaultValueWrapper, FirstDefaultParameter = i, }; yield return(pm); } }
bool AddDateTimeSupport(Type t) { if (system_datetime != null) { return(true); } var corlib = GetMscorlib(t); system_datetime = new ProcessedType(t) { Assembly = corlib, // this is tracked because the linker (if enabled) needs to be aware of the requirement // but we do not want any code to be generated (it's referenced only from native/glue code) IsNativeReference = true, Methods = new List <ProcessedMethod> (), Properties = new List <ProcessedProperty> (), Constructors = new List <ProcessedConstructor> (), }; var ticks = t.GetProperty("Ticks"); system_datetime.Properties.Add(new ProcessedProperty(ticks, this, system_datetime)); var kind = t.GetProperty("Kind"); system_datetime.Properties.Add(new ProcessedProperty(kind, this, system_datetime)); var dtk = corlib.Assembly.GetType("System.DateTimeKind"); var longT = corlib.Assembly.GetType("System.Int64"); var ctorLongKind = t.GetConstructor(new Type [] { longT, dtk }); system_datetime.Constructors.Add(new ProcessedConstructor(ctorLongKind, this, system_datetime)); var toUniversalTime = t.GetMethod("ToUniversalTime"); system_datetime.Methods.Add(new ProcessedMethod(toUniversalTime, this, system_datetime)); AddExtraType(system_datetime); return(true); }
protected IEnumerable <ProcessedConstructor> GetConstructors(ProcessedType processedType) { Type t = processedType.Type; foreach (var ctor in t.GetConstructors()) { // .cctor not to be called directly by native code if (ctor.IsStatic) { continue; } if (!ctor.IsPublic) { continue; } bool pcheck = true; foreach (var p in ctor.GetParameters()) { var pt = p.ParameterType; if (!IsSupported(pt)) { Delayed.Add(ErrorHelper.CreateWarning(1020, $"Constructor `{ctor}` is not generated because of parameter type `{pt}` is not supported.")); pcheck = false; } else if (p.HasDefaultValue) { members_with_default_values.Add(ctor); } } if (!pcheck) { continue; } yield return(new ProcessedConstructor(ctor, this, processedType)); } }
// post processing logic IEnumerable <ProcessedConstructor> GetUnavailableParentCtors(ProcessedType pt) { var type = pt.Type; var baseType = type.BaseType; if ((baseType == null) || (baseType.Namespace == "System" && baseType.Name == "Object")) { return(Enumerable.Empty <ProcessedConstructor> ()); } var baseProcessedType = GetProcessedType(baseType); if ((baseProcessedType == null) || !baseProcessedType.HasConstructors) { return(Enumerable.Empty <ProcessedConstructor> ()); } var typeCtors = pt.Constructors; List <ProcessedConstructor> parentCtors = baseProcessedType.Constructors; var finalList = new List <ProcessedConstructor> (); foreach (var pctor in parentCtors) { var pctorParams = pctor.Parameters; foreach (var ctor in typeCtors) { var ctorParams = ctor.Parameters; if (pctorParams.Any(pc => !ctorParams.Any(p => p.Position == pc.Position && pc.ParameterType == p.ParameterType))) { finalList.Add(pctor); break; } } } return(finalList); }
public void Process(ProcessedAssembly a) { if (!a.UserCode) { return; } Logger.Log($"Processing Assembly: {a.Name}"); foreach (var t in GetTypes(a.Assembly)) { var pt = new ProcessedType(t) { Assembly = a, }; Types.Add(pt); foreach (var nt in t.GetNestedTypes()) { var pnt = new ProcessedType(nt) { Assembly = a }; Types.Add(pnt); } } // we can add new types while processing some (e.g. categories) foreach (var type in Types) { typeQueue.Enqueue(type); } Types.Clear(); // reuse while (typeQueue.Count > 0) { Process(typeQueue.Dequeue()); } }
IEnumerable <ProcessedConstructor> AddDefaultValuesWrappers(ConstructorInfo ci, ProcessedType containingType) { // parameters with default values must be at the end and there can be many of them var parameters = ci.GetParameters(); for (int i = parameters.Length - 1; i >= 0; i--) { if (!parameters [i].HasDefaultValue) { continue; } var pc = new ProcessedConstructor(ci, this, containingType) { ConstructorType = ConstructorType.DefaultValueWrapper, FirstDefaultParameter = i, }; yield return(pc); } }
public override void Process(ProcessedType pt) { 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(t).OrderBy((arg) => arg.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 <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.GetParameters().Length > 0) || ((setter != null) && setter.GetParameters().Length > 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(); 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(t).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) { 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) { DeclaringType = type, MethodType = MethodType.IEquatable, }); continue; } if (mi.Match("System.Int32", "GetHashCode")) { yield return(new ProcessedMethod(mi, this) { 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)); continue; } } yield return(new ProcessedMethod(mi, this)); } }
protected void AddExtraType(ProcessedType pt) { typeQueue.Enqueue(pt); // extra types are (most likely) outside the input list of assemblies AddIfUnique(pt.Assembly); }
public abstract void Process(ProcessedType pt);
public ProcessedConstructor(ConstructorInfo constructor, Processor processor, ProcessedType declaringType) : base(processor, declaringType) { Constructor = constructor; Parameters = Constructor.GetParameters(); FirstDefaultParameter = -1; }
public ProcessedFieldInfo(FieldInfo field, Processor processor, ProcessedType declaringType) : base(processor, declaringType) { Field = field; TypeName = ObjC.NameGenerator.GetTypeName(Field.DeclaringType); ObjCName = ObjC.NameGenerator.GetObjCName(Field.DeclaringType); }
public ProcessedMemberWithParameters(Processor processor, ProcessedType declaringType) : base(processor, declaringType) { objCSignature = new CachedValue <string> (() => GetObjcSignature(true)); objCSelector = new CachedValue <string> (() => GetObjcSignature(false)); monoSignature = new CachedValue <string> (GetMonoSignature); }
protected abstract void Generate(ProcessedType t);
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 "DateTime": // FIXME: NSDateTime 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); case "Decimal": return(AddDecimalSupport(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)); }
public ProcessedMemberBase(Processor processor, ProcessedType declaringType) { Processor = processor; DeclaringType = declaringType; }