/// <summary>
 /// Initialize a new instance of the <see cref="MessageProcessedEventArgs"/> class.
 /// </summary>
 /// <param name="message">The message.</param>
 /// <param name="ordinal">Zero-based message ordinal.</param>
 /// <param name="count">
 /// The total number of messages to be
 /// sent by the calling method.
 /// </param>
 /// <param name="processedType">Indicates whether the message was sent or skipped.</param>
 public MessageProcessedEventArgs(MimeMessage message, int ordinal, int count, ProcessedType processedType)
 {
     Message       = message ?? throw new ArgumentNullException(nameof(message));
     Count         = count >= -1 ? count : throw new ArgumentOutOfRangeException(nameof(count));
     Ordinal       = ordinal >= 0 ? ordinal : throw new ArgumentOutOfRangeException(nameof(ordinal));
     ProcessedType = processedType;
 }
        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 void DefineSlotNameTwice()
        {
            ProcessedType processedType = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_DefineSlotNameTwice));
            TemplateCache cache         = new TemplateCache(Setup("App"));

            Assert.DoesNotThrow(() => { cache.GetParsedTemplate(processedType); });
        }
        public void ParseNamespace()
        {
            ProcessedType    processedType = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_Namespace));
            TemplateCache    cache         = new TemplateCache(Setup("App"));
            TemplateRootNode templateRoot  = cache.GetParsedTemplate(processedType);

            Assert.AreEqual(typeof(UIDivElement), templateRoot.children[0].processedType.rawType);
        }
        public void ParseNamespace_NotThere()
        {
            ParseException exception = Assert.Throws <ParseException>(() => {
                ProcessedType processedType = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_Namespace_Unknown));
                TemplateCache cache         = new TemplateCache(Setup("App"));
                cache.GetParsedTemplate(processedType);
            });

            Assert.IsTrue(exception.Message.Contains(ParseException.UnresolvedTagName("Data/XMLTemplateParsing/XMLTemplateParsing_Namespaces.xml", new TemplateLineInfo(11, 10), "NotHere:Div").Message));
        }
        void GenerateEnum(ProcessedType type)
        {
            Type t               = type.Type;
            var  managed_name    = type.ObjCName;
            var  underlying_type = t.GetEnumUnderlyingType();
            var  base_type       = NameGenerator.GetTypeName(underlying_type);

            // it's nicer to expose flags as unsigned integers - but .NET defaults to `int`
            bool flags = t.HasCustomAttribute("System", "FlagsAttribute");

            if (flags)
            {
                switch (Type.GetTypeCode(underlying_type))
                {
                case TypeCode.SByte:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                    base_type = "unsigned " + base_type;
                    break;
                }
            }

            var macro = flags ? "NS_OPTIONS" : "NS_ENUM";

            headers.WriteLine($"/** Enumeration {managed_name}");
            headers.WriteLine($" *  Corresponding .NET Qualified Name: `{t.AssemblyQualifiedName}`");
            headers.WriteLine(" */");
            headers.WriteLine($"typedef {macro}({base_type}, {managed_name}) {{");
            headers.Indent++;
            foreach (var name in t.GetEnumNames())
            {
                var value = t.GetField(name).GetRawConstantValue();
                headers.Write($"{managed_name}{name} = ");
                if (flags)
                {
                    headers.Write($"0x{value:x}");
                }
                else
                {
                    headers.Write(value);
                }
                headers.WriteLine(',');
            }
            headers.Indent--;
            headers.WriteLine("};");
            headers.WriteLine();
        }
        public void ExpandedTemplate()
        {
            ProcessedType    processedType    = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_ExpandTemplate));
            TemplateCache    cache            = new TemplateCache(Setup("App"));
            TemplateRootNode templateRootRoot = cache.GetParsedTemplate(processedType);

            Assert.AreEqual(3, templateRootRoot.ChildCount);

            AssertAndReturn <TextNode>(templateRootRoot[0]);

            ExpandedTemplateNode expandedTemplate = AssertAndReturn <ExpandedTemplateNode>(templateRootRoot[1]);

            Assert.AreEqual(typeof(XMLTemplateParsing_ExpandedTemplateChild), expandedTemplate.processedType.rawType);

            AssertAndReturn <TextNode>(templateRootRoot[2]);
        }
        public void OverrideSlot()
        {
            ProcessedType    processedType    = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_OverrideSlot));
            TemplateCache    cache            = new TemplateCache(Setup("App"));
            TemplateRootNode templateRootRoot = cache.GetParsedTemplate(processedType);

            Assert.AreEqual(3, templateRootRoot.ChildCount);

            AssertTrimmedText("Hello Before", templateRootRoot[0]);
            AssertTrimmedText("Hello After", templateRootRoot[2]);

            ExpandedTemplateNode expandedTemplateNode = AssertAndReturn <ExpandedTemplateNode>(templateRootRoot[1]);
            SlotNode             overrideNode         = AssertAndReturn <SlotNode>(expandedTemplateNode.slotOverrideNodes[0]);

            Assert.AreEqual("my-slot", overrideNode.slotName);
            Assert.AreEqual(SlotType.Override, overrideNode.slotType);
            AssertTrimmedText("Hello Between", overrideNode[0]);
        }
        // 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);
        }
Example #10
0
        public void Process()
        {
            var generatorTypes = _typesToGenerate.Select(t => new { BaseData = t, generatorType = ReflectionHelper.FindBaseDataGeneratorType(t) })
                                 .ToDictionary(t => t.BaseData, t => t.generatorType);

            var metadataResolverTypes = _typesToGenerate.Select(t => new { BaseData = t, metadataResolverType = ReflectionHelper.FindBaseDataMetadataResolverType(t) })
                                        .ToDictionary(t => t.BaseData, t => t.metadataResolverType);

            var typesToProcess = _typesToGenerate.ToList();
            var processedTypes = new Dictionary <Type, ProcessedType>();

            var baseTypeConstructorArgumentsLength = typeof(DataGenerator <>).GetConstructors().First().GetParameters().Length;

            bool doneAny;

            do
            {
                doneAny = false;
                for (int i = 0; i < typesToProcess.Count; i++)
                {
                    var type = typesToProcess[i];

                    var generatorType = generatorTypes[type];

                    var constructorToUse    = generatorType.GetConstructors().First();
                    var parameters          = constructorToUse.GetParameters();
                    var additionalArguments = new List <object>();

                    // Iterate over any arguments in the constructor that are after the required base type arguments
                    // Find any arguments that can be set from other type values
                    for (int j = baseTypeConstructorArgumentsLength; j < parameters.Length; j++)
                    {
                        if (GetProcessedTypeForParameter(parameters[j], processedTypes, out var argument))
                        {
                            additionalArguments.Add(argument);
                        }
                        else
                        {
                            break;
                        }
                    }

                    // If there are enough arguments to satisfy the parameters then a generator can be instantiated
                    if (baseTypeConstructorArgumentsLength + additionalArguments.Count == parameters.Length)
                    {
                        if (!metadataResolverTypes.ContainsKey(type))
                        {
                            throw new InvalidOperationException($"Unable to find a MetadataResolver type for {type.Name}");
                        }

                        dynamic metadataResolver = Activator.CreateInstance(metadataResolverTypes[type]);

                        var arguments = new[]
                        {
                            Logger,
                            PathResolver,
                            metadataResolver
                        }.Union(additionalArguments).ToArray();

                        dynamic dataGenerator = constructorToUse.Invoke(arguments);

                        var result = dataGenerator.Generate();

                        var processedType = new ProcessedType
                        {
                            MetadataResolver = metadataResolver,
                            Output           = result
                        };

                        processedTypes.Add(type, processedType);

                        doneAny = true;
                        typesToProcess.RemoveAt(i);
                        i--;
                    }
                }
            } while (typesToProcess.Count > 0 && doneAny);

            Logger.LogSection("Types where a BaseDataGenerator could not be instantiated", typesToProcess.Select(t => t.FullName ?? t.Name));

            Logger.LogSection("Type Summary", processedTypes.Select(t => $"{t.Key.Name} {((dynamic)t.Value.Output).Count}"));

            ProcessOperations(processedTypes);
        }
        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));
        }
Example #12
0
 public static CompileException UnresolvableGenericElement(ProcessedType processedType, string value)
 {
     return(new CompileException($"{processedType.rawType} requires a class attribute of type {nameof(GenericElementTypeResolvedByAttribute)} in order to be used in a template and a value that is not null or default also declared in the template"));
 }
        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.ParameterCount).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.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();

            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;
        }
Example #14
0
 public static CompileException GenericElementMissingResolver(ProcessedType processedType)
 {
     return(new CompileException($"{processedType.rawType} requires a class attribute of type {nameof(GenericElementTypeResolvedByAttribute)} in order to be used in a template"));
 }
Example #15
0
 public TemplateNotFoundException(ProcessedType processedType, string xmlPath) : base($"Unable to find default template for type {processedType.rawType}. Searched using default resolver at paths: \n[{xmlPath}]")
 {
 }
        protected override void Generate(ProcessedType type)
        {
            Type t           = type.Type;
            var  aname       = t.Assembly.GetName().Name.Sanitize();
            var  static_type = t.IsSealed && t.IsAbstract;

            var managed_name = NameGenerator.GetObjCName(t);

            List <string> conformed_protocols = new List <string> ();

            foreach (var i in t.GetInterfaces())
            {
                if (protocols.Contains(i))
                {
                    conformed_protocols.Add(NameGenerator.GetObjCName(i));
                }
            }

            var tbuilder = new ClassHelper(headers, implementation)
            {
                AssemblyQualifiedName = t.AssemblyQualifiedName,
                AssemblyName          = aname,
                BaseTypeName          = NameGenerator.GetTypeName(t.BaseType),
                Name            = NameGenerator.GetTypeName(t),
                Namespace       = t.Namespace,
                ManagedName     = t.Name,
                Protocols       = conformed_protocols,
                IsBaseTypeBound = types.Contains(t.BaseType),
                IsStatic        = t.IsSealed && t.IsAbstract,
                MetadataToken   = t.MetadataToken,
            };

            tbuilder.BeginHeaders();
            tbuilder.BeginImplementation();

            var default_init = false;
            List <ProcessedConstructor> constructors;

            if (ctors.TryGetValue(t, out constructors))
            {
                // First get the unavailable init ctor selectors in parent class
                var unavailableCtors = GetUnavailableParentCtors(t, constructors);
                if (unavailableCtors.Count() > 0)
                {
                    // TODO: Print a #pragma mark once we have a well defined header structure http://nshipster.com/pragma/
                    foreach (var uctor in unavailableCtors)
                    {
                        var    ctorparams = uctor.Constructor.GetParameters();
                        string name       = "init";
                        string signature  = ".ctor()";
                        if (ctorparams.Length > 0)
                        {
                            GetSignatures("initWith", uctor.Constructor.Name, uctor.Constructor, ctorparams, uctor.FallBackToTypeName, false, out name, out signature);
                        }
                        headers.WriteLine("/** This initializer is not available as it was not re-exposed from the base type");
                        headers.WriteLine(" *  For more details consult https://github.com/mono/Embeddinator-4000/blob/master/docs/ObjC.md#constructors-vs-initializers");
                        headers.WriteLine(" */");
                        headers.WriteLine($"- (nullable instancetype){name} NS_UNAVAILABLE;");
                        headers.WriteLine();
                    }
                }

                foreach (var ctor in constructors)
                {
                    var pcount = ctor.Constructor.ParameterCount;
                    default_init |= pcount == 0;

                    var    parameters = ctor.Constructor.GetParameters();
                    string name       = "init";
                    string signature  = ".ctor()";
                    if (parameters.Length > 0)
                    {
                        GetSignatures("initWith", ctor.Constructor.Name, ctor.Constructor, parameters, ctor.FallBackToTypeName, false, out name, out signature);
                    }

                    var builder = new MethodHelper(headers, implementation)
                    {
                        AssemblySafeName = aname,
                        ReturnType       = "nullable instancetype",
                        ManagedTypeName  = t.FullName,
                        MetadataToken    = ctor.Constructor.MetadataToken,
                        MonoSignature    = signature,
                        ObjCSignature    = name,
                        ObjCTypeName     = managed_name,
                        IsConstructor    = true,
                        IsValueType      = t.IsValueType,
                        IgnoreException  = true,
                    };

                    builder.WriteHeaders();

                    builder.BeginImplementation();
                    builder.WriteMethodLookup();

                    // TODO: this logic will need to be update for managed NSObject types (e.g. from XI / XM) not to call [super init]
                    implementation.WriteLine("if (!_object) {");
                    implementation.Indent++;
                    implementation.WriteLine($"MonoObject* __instance = mono_object_new (__mono_context.domain, {managed_name}_class);");

                    string postInvoke = String.Empty;
                    var    args       = "nil";
                    if (pcount > 0)
                    {
                        Generate(parameters, false, out postInvoke);
                        args = "__args";
                    }
                    builder.WriteInvoke(args);
                    implementation.Write(postInvoke);
                    implementation.WriteLine("_object = mono_embeddinator_create_object (__instance);");
                    implementation.Indent--;
                    implementation.WriteLine("}");
                    if (types.Contains(t.BaseType))
                    {
                        implementation.WriteLine("return self = [super initForSuper];");
                    }
                    else
                    {
                        implementation.WriteLine("return self = [super init];");
                    }
                    builder.EndImplementation();

                    headers.WriteLine();

                    if (members_with_default_values.Contains(ctor.Constructor))
                    {
                        default_init |= GenerateDefaultValuesWrappers(name, ctor.Constructor);
                    }
                }
            }

            // generate an `init` for a value type (even if none was defined, the default one is usable)
            if (!default_init && t.IsValueType)
            {
                var builder = new MethodHelper(headers, implementation)
                {
                    AssemblySafeName = aname,
                    ReturnType       = "nullable instancetype",
                    ManagedTypeName  = t.FullName,
                    MonoSignature    = ".ctor()",
                    ObjCSignature    = "init",
                    ObjCTypeName     = managed_name,
                    IsConstructor    = true,
                    IsValueType      = t.IsValueType,
                    IgnoreException  = true,
                };

                builder.WriteHeaders();
                builder.BeginImplementation();
                // no call to `WriteMethodLookup` since there is not such method if we reached this case

                implementation.WriteLine("if (!_object) {");
                implementation.Indent++;
                implementation.WriteLine($"MonoObject* __instance = mono_object_new (__mono_context.domain, {managed_name}_class);");
                // no call to `WriteInvoke` since there is not such method if we reached this case
                implementation.WriteLine("_object = mono_embeddinator_create_object (__instance);");
                implementation.Indent--;
                implementation.WriteLine("}");
                if (types.Contains(t.BaseType))
                {
                    implementation.WriteLine("return self = [super initForSuper];");
                }
                else
                {
                    implementation.WriteLine("return self = [super init];");
                }
                builder.EndImplementation();

                headers.WriteLine();
                default_init = true;
            }

            if (!default_init || static_type)
            {
                tbuilder.DefineNoDefaultInit();
            }

            List <ProcessedProperty> props;

            if (properties.TryGetValue(t, out props))
            {
                headers.WriteLine();
                foreach (var pi in props)
                {
                    Generate(pi);
                }
            }

            List <ProcessedFieldInfo> f;

            if (fields.TryGetValue(t, out f))
            {
                headers.WriteLine();
                foreach (var fi in f)
                {
                    Generate(fi);
                }
            }

            List <ProcessedProperty> s;

            if (subscriptProperties.TryGetValue(t, out s))
            {
                headers.WriteLine();
                foreach (var si in s)
                {
                    GenerateSubscript(si);
                }
            }

            List <ProcessedMethod> meths;

            if (methods.TryGetValue(t, out meths))
            {
                headers.WriteLine();
                foreach (var mi in meths)
                {
                    Generate(mi);
                }
            }

            MethodInfo m;

            if (icomparable.TryGetValue(t, out m))
            {
                var pt      = m.GetParameters() [0].ParameterType;
                var builder = new ComparableHelper(headers, implementation)
                {
                    ObjCSignature    = $"compare:({managed_name} * _Nullable)other",
                    AssemblySafeName = aname,
                    MetadataToken    = m.MetadataToken,
                    ObjCTypeName     = managed_name,
                    ManagedTypeName  = t.FullName,
                    MonoSignature    = $"CompareTo({NameGenerator.GetMonoName (pt)})",
                };
                builder.WriteHeaders();
                builder.WriteImplementation();
            }

            if (equals.TryGetValue(t, out m))
            {
                var builder = new EqualsHelper(headers, implementation)
                {
                    AssemblySafeName = aname,
                    MetadataToken    = m.MetadataToken,
                    ObjCTypeName     = managed_name,
                    ManagedTypeName  = t.FullName,
                };

                builder.WriteHeaders();
                builder.WriteImplementation();
            }

            if (hashes.TryGetValue(t, out m))
            {
                var builder = new HashHelper(headers, implementation)
                {
                    AssemblySafeName = aname,
                    MetadataToken    = m.MetadataToken,
                    ObjCTypeName     = managed_name,
                    ManagedTypeName  = t.FullName,
                };

                builder.WriteHeaders();
                builder.WriteImplementation();
            }

            tbuilder.EndHeaders();
            tbuilder.EndImplementation();
        }
        void GenerateProtocol(ProcessedType type)
        {
            Type t        = type.Type;
            var  pbuilder = new ProtocolHelper(headers, implementation)
            {
                AssemblyQualifiedName = t.AssemblyQualifiedName,
                AssemblyName          = t.Assembly.GetName().Name.Sanitize(),
                ProtocolName          = NameGenerator.GetTypeName(t),
                Namespace             = t.Namespace,
                ManagedName           = t.Name,
                MetadataToken         = t.MetadataToken,
            };

            pbuilder.BeginHeaders();

            // no need to iterate constructors or fields as they cannot be part of net interfaces
            // do not generate implementations for protocols
            implementation.Enabled = false;

            List <ProcessedProperty> props;

            if (properties.TryGetValue(t, out props))
            {
                headers.WriteLine();
                foreach (var pi in props)
                {
                    Generate(pi);
                }
            }

            List <ProcessedMethod> meths;

            if (methods.TryGetValue(t, out meths))
            {
                headers.WriteLine();
                foreach (var mi in meths)
                {
                    Generate(mi);
                }
            }

            pbuilder.EndHeaders();

            // wrappers are internal so not part of the headers
            headers.Enabled        = false;
            implementation.Enabled = true;

            pbuilder.BeginImplementation();

            if (properties.TryGetValue(t, out props))
            {
                implementation.WriteLine();
                foreach (var pi in props)
                {
                    Generate(pi);
                }
            }

            if (methods.TryGetValue(t, out meths))
            {
                implementation.WriteLine();
                foreach (var mi in meths)
                {
                    Generate(mi);
                }
            }

            pbuilder.EndImplementation();
            headers.Enabled = true;
        }
        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));
            }
        }
Example #19
0
 public static CompileException UnresolvedGenericElement(ProcessedType processedType, TemplateNodeDebugData data)
 {
     return(new CompileException($"Unable to resolve the concrete type for " + processedType.rawType + $"\n\nFailed parsing {data.tagName} at {data.fileName}:{data.lineInfo}\n" +
                                 $"You can try to fix this by providing the type explicitly. (add an attribute generic:type=\"your,types,here\""));
 }