Beispiel #1
0
 void ProcessPotentialName(ProcessedFieldInfo processedField)
 {
     if (RestrictedObjSelectors.IsImportantSelector(processedField.GetterName) || RestrictedObjSelectors.IsImportantSelector(processedField.SetterName))
     {
         string newName = "managed" + processedField.Name.PascalCase();
         Delayed.Add(ErrorHelper.CreateWarning(1051, $"Element {processedField.Name} is generated instead as {newName} because its name conflicts with an important objective-c selector."));
         processedField.NameOverride = newName;
     }
 }
        public override void Process(IEnumerable <Assembly> input)
        {
            base.Process(input);

            Types = Types.OrderBy((arg) => arg.Type.FullName).OrderBy((arg) => Types.HasClass(arg.Type.BaseType)).ToList();
            Console.WriteLine($"\t{Types.Count} types found");

            // proceed with extra adjustments before giving results to the generator
            foreach (var t in Types)
            {
                foreach (var uctor in GetUnavailableParentCtors(t))
                {
                    var c = new ProcessedConstructor(uctor.Constructor, this)
                    {
                        Unavailable = true
                    };
                    t.Constructors.Add(c);
                }
            }

            // we want to create wrappers only if the signature does not already exists, e.g. both `.ctor ()` and `.ctor (int i = 0)` can co-exists in .net
            foreach (var dv in members_with_default_values)
            {
                var pt = GetProcessedType(dv.DeclaringType);
                var ci = dv as ConstructorInfo;
                if (ci != null)
                {
                    foreach (var pc in AddDefaultValuesWrappers(ci))
                    {
                        if (!pt.SignatureExists(pc))
                        {
                            pt.Constructors.Add(pc);
                        }
                        else
                        {
                            Delayed.Add(ErrorHelper.CreateWarning(1021, $"Constructor `{ci}` has default values for which no wrapper is generated."));
                        }
                    }
                    continue;
                }
                var mi = dv as MethodInfo;
                foreach (var pm in AddDefaultValuesWrappers(mi))
                {
                    if (!pt.SignatureExists(pm))
                    {
                        pt.Methods.Add(pm);
                    }
                    else
                    {
                        Delayed.Add(ErrorHelper.CreateWarning(1032, $"Method `{mi}` has default values for which no wrapper is generated."));
                    }
                }
            }

            ErrorHelper.Show(Delayed);
        }
Beispiel #3
0
        void ProcessPotentialName(ProcessedProperty processedProperty)
        {
            string getSignature = processedProperty.HasGetter ? processedProperty.GetMethod.ObjCSignature : "";
            string setSignature = processedProperty.HasSetter ? processedProperty.SetMethod.ObjCSignature : "";

            if (RestrictedObjSelectors.IsImportantSelector(getSignature) || RestrictedObjSelectors.IsImportantSelector(setSignature))
            {
                string newName = "managed" + processedProperty.Name.PascalCase();
                Delayed.Add(ErrorHelper.CreateWarning(1051, $"Element {processedProperty.Name} is generated instead as {newName} because its name conflicts with an important objective-c selector."));
                processedProperty.NameOverride = newName;
            }
        }
 protected IEnumerable <PropertyInfo> GetProperties(Type t)
 {
     foreach (var pi in t.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly))
     {
         var pt = pi.PropertyType;
         if (!IsSupported(pt))
         {
             Delayed.Add(ErrorHelper.CreateWarning(1040, $"Property `{pi}` is not generated because of parameter type `{pt}` is not supported."));
             continue;
         }
         yield return(pi);
     }
 }
Beispiel #5
0
        protected IEnumerable <ProcessedProperty> PostProcessSubscriptProperties(IEnumerable <ProcessedProperty> properties)
        {
            foreach (ProcessedProperty processedProperty in properties)
            {
                if (Mapper.CheckForDuplicateSelectors(processedProperty) == DuplicationStatus.Unresolvable)
                {
                    Delayed.Add(ErrorHelper.CreateWarning(1052, $"Element {processedProperty.Name} is not generated as its name conflicts with other elements on the same class."));
                    continue;
                }

                Mapper.Register(processedProperty);

                yield return(processedProperty);
            }
        }
 protected IEnumerable <FieldInfo> GetFields(Type t)
 {
     foreach (var fi in t.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(fi);
     }
 }
Beispiel #7
0
        protected IEnumerable <ProcessedFieldInfo> PostProcessFields(IEnumerable <ProcessedFieldInfo> fields)
        {
            foreach (ProcessedFieldInfo processedField in fields)
            {
                ProcessPotentialName(processedField);

                if (Mapper.CheckForDuplicateSelectors(processedField) == DuplicationStatus.Unresolvable)
                {
                    Delayed.Add(ErrorHelper.CreateWarning(1052, $"Element {processedField.Name} is not generated as its name conflicts with other elements on the same class."));
                    continue;
                }

                Mapper.Register(processedField);

                yield return(processedField);
            }
        }
Beispiel #8
0
        protected IEnumerable <ProcessedMethod> PostProcessMethods(IEnumerable <ProcessedMethod> methods)
        {
            var equals = new HashSet <MethodInfo> ();

            foreach (var m in methods)
            {
                if (m.MethodType == MethodType.NSObjectProcotolIsEqual)
                {
                    equals.Add(m.Method);
                }
            }
            HashSet <MethodInfo> operatorToIgnore = new HashSet <MethodInfo> (OperatorOverloads.FindOperatorPairToIgnore(methods, equals));

            foreach (var processedMethod in methods)
            {
                var method = processedMethod.Method;
                if (operatorToIgnore.Contains(method))
                {
                    Delayed.Add(ErrorHelper.CreateWarning(1033, $"Method {method.Name} is not generated because another method exposes the operator with a friendly name"));
                    continue;
                }

                if (IsOperatorOrFriendlyVersion(method))
                {
                    processedMethod.IsOperator = true;
                }

                ProcessPotentialName(processedMethod);

                if (Mapper.CheckForDuplicateSelectors(processedMethod) == DuplicationStatus.Unresolvable)
                {
                    Delayed.Add(ErrorHelper.CreateWarning(1052, $"Element {method.Name} is not generated as its name conflicts with other elements on the same class."));
                    continue;
                }

                Mapper.Register(processedMethod);

                processedMethod.Freeze();
                yield return(processedMethod);
            }
        }
        protected IEnumerable <ProcessedMethod> PostProcessMethods(IEnumerable <ProcessedMethod> methods)
        {
            HashSet <string> duplicateNames = FindDuplicateNames(methods);

            var equals = new HashSet <MethodInfo> ();

            foreach (var m in methods)
            {
                if (m.MethodType == MethodType.NSObjectProcotolIsEqual)
                {
                    equals.Add(m.Method);
                }
            }
            HashSet <MethodInfo> operatorToIgnore = new HashSet <MethodInfo> (OperatorOverloads.FindOperatorPairToIgnore(methods, equals));

            foreach (var processedMethod in methods)
            {
                var method = processedMethod.Method;
                if (operatorToIgnore.Contains(method))
                {
                    Delayed.Add(ErrorHelper.CreateWarning(1033, $"Method {method.Name} is not generated because another method exposes the operator with a friendly name"));
                    continue;
                }

                if (duplicateNames.Contains(CreateStringRep(method)) && method.Name != "CompareTo")                   // HACK
                {
                    processedMethod.FallBackToTypeName = true;
                }

                if (IsOperatorOrFriendlyVersion(method))
                {
                    processedMethod.IsOperator = true;
                }

                ProcessPotentialNameOverride(processedMethod);

                yield return(processedMethod);
            }
        }
Beispiel #10
0
        void ProcessPotentialName(ProcessedMethod processedMethod)
        {
            MethodInfo method = processedMethod.Method;

            if (IsOperatorOrFriendlyVersion(method))
            {
                string nameOverride = OperatorOverloads.GetObjCName(processedMethod.Method.Name, processedMethod.Method.GetParameters().Length);
                if (nameOverride != null)
                {
                    processedMethod.NameOverride = nameOverride;
                }
            }

            string objCSignature = processedMethod.ObjCSignature;

            if (RestrictedObjSelectors.IsImportantSelector(objCSignature))
            {
                string newName = "managed" + method.Name.PascalCase();
                processedMethod.NameOverride = newName;
                Delayed.Add(ErrorHelper.CreateWarning(1051, $"Element {method.Name} is generated instead as {newName} because its name conflicts with an important objective-c selector."));
            }
        }
        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));
            }
        }
        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 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));
            }
        }
Beispiel #15
0
        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));
        }
Beispiel #16
0
        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);
        }