CSInterface BuildCSIface(ClassDeclaration cl, CSUsingPackages use)
        {
            var csName = NewClassCompiler.StubbedClassName(cl.ToFullyQualifiedName(true), typeMapper);
            var iface  = new CSInterface(CSVisibility.Public, csName);

            return(iface);
        }
        void CompileProp(PropertyDeclaration propDecl, ProtocolDeclaration proto, CSInterface iface, CSUsingPackages use)
        {
            var getter     = propDecl.GetGetter();
            var setter     = propDecl.GetSetter();
            var publicProp = topLevelFunctionCompiler.CompileProperty(use, null, getter, setter, CSMethodKind.None);

            publicProp = new CSProperty(publicProp.PropType, CSMethodKind.None, publicProp.Name,
                                        CSVisibility.None, new CSCodeBlock(), CSVisibility.None, setter != null ? new CSCodeBlock() : null);
            ExportAttribute(getter.ObjCSelector).AttachBefore(publicProp);
            if (!propDecl.IsOptional)
            {
                kAbstractAttribute.AttachBefore(publicProp);
            }
            iface.Properties.Add(publicProp);
        }
        void CompileFunc(FunctionDeclaration funcDecl, ProtocolDeclaration proto, CSInterface iface, CSUsingPackages use)
        {
            var homonymSuffix = Homonyms.HomonymSuffix(funcDecl, proto.Members.OfType <FunctionDeclaration> (), typeMapper);

            var publicMethod = topLevelFunctionCompiler.CompileMethod(funcDecl, use, swiftLibPath, null, null, false, false, false);

            // recast with no visibility and with the homonym suffix, if any
            publicMethod = new CSMethod(CSVisibility.None, CSMethodKind.Interface, publicMethod.Type,
                                        new CSIdentifier(publicMethod.Name.Name + homonymSuffix), publicMethod.Parameters, null);
            ExportAttribute(funcDecl.ObjCSelector).AttachBefore(publicMethod);
            if (!funcDecl.IsOptional)
            {
                kAbstractAttribute.AttachBefore(publicMethod);
            }
            iface.Methods.Add(publicMethod);
        }
        CSInterface CompileProtocol(ProtocolDeclaration proto, CSUsingPackages use)
        {
            var iface = new CSInterface(CSVisibility.Public, proto.Name);

            kProtocolAttribute.AttachBefore(iface);
            var filteredInheritance = proto.Inheritance.FindAll(inh => !TypeSpecIsAnyOrAnyObject(inh.InheritedTypeSpec));

            iface.Inheritance.AddRange(filteredInheritance.Select(inh => {
                var netIface = typeMapper.GetDotNetNameForTypeSpec(inh.InheritedTypeSpec);
                use.AddIfNotPresent(netIface.Namespace);
                return(new CSIdentifier(netIface.TypeName));
            }));

            foreach (var funcDecl in proto.AllMethodsNoCDTor())
            {
                if (funcDecl.IsProperty && !funcDecl.IsSubscript)
                {
                    continue;
                }
                try {
                    CompileFunc(funcDecl, proto, iface, use);
                } catch (Exception e) {
                    errors.Add(ErrorHelper.CreateWarning(ReflectorError.kWrappingBase + 14, e, $"Error compiling ObjC protocol method {proto.ToFullyQualifiedName ()}.{funcDecl.Name}"));
                }
            }

            foreach (var propDecl in proto.AllProperties())
            {
                try {
                    CompileProp(propDecl, proto, iface, use);
                } catch (Exception e) {
                    errors.Add(ErrorHelper.CreateWarning(ReflectorError.kWrappingBase + 14, e, $"Error compiling ObjC protocol property {proto.ToFullyQualifiedName ()}.{propDecl.Name}"));
                }
            }
            var anyRequired = proto.AllMethodsNoCDTor().Any(func => !func.IsOptional);

            if (anyRequired)
            {
                kAbstractAttribute.AttachBefore(iface);
            }

            return(iface);
        }
        /// <summary>
        /// Read assemblies to list members
        /// </summary>
        public void Read()
        {
            foreach (ProjectInfo projectInfo in ProjectInfos)
            {
                if (!projectInfo.BuildConfigurations.ContainsKey(BuildConfiguration))
                {
                    // TODO Logs warn
                    continue;
                }

                BuildConfiguration config = projectInfo.BuildConfigurations[BuildConfiguration];

                if (string.IsNullOrWhiteSpace(config.OutputPath))
                {
                    // TODO Logs warn
                    continue;
                }

                // Read assembly
                Assembly assembly = Assembly.LoadFile(Path.GetFullPath(config.OutputPath)); // Set full path in BuildConfiguration object

                // Create doc object
                XmlDoc doc = default;

                if (!string.IsNullOrWhiteSpace(config.DocumentationFilePath))
                {
                    doc = XmlDocDeserializer.Deserialize(config.DocumentationFilePath);
                }

                // Create assembly object
                CSAssembly csAssembly = new CSAssembly(assembly);
                CSMembers.Add(csAssembly);

                // Run through all the types
                foreach (TypeInfo type in assembly.DefinedTypes)
                {
                    // Get the namespace object from the list of members
                    CSNamespace csNamespace = CSMembers.Namespaces.FirstOrDefault(n => n.Name == type.Namespace);

                    // If the namespace object does not exist, create it
                    if (csNamespace == null)
                    {
                        csNamespace = new CSNamespace(type.Namespace);
                        CSMembers.Add(csNamespace);
                    }

                    // Create type object
                    CSType csType = default;
                    if (type.IsClass)
                    {
                        // TODO Create class object
                        csType = new CSClass(csAssembly, csNamespace, type);
                    }

                    // Create type object
                    if (type.IsInterface)
                    {
                        // TODO Create interface object
                        csType = new CSInterface(csAssembly, csNamespace, type);
                    }

                    // Create type object
                    if (type.IsEnum)
                    {
                        // TODO Create enumeration object
                        csType = new CSEnumeration(csAssembly, csNamespace, type);
                    }

                    // Read doc to get type summary
                    csType.Summary = doc?.Members.FirstOrDefault(m => m.Name == csType.XmlFullName)?.Summary.Value;

                    csAssembly.Types.Add(csType);
                    csNamespace.Types.Add(csType);
                    CSMembers.Add(csType);
                }
            }
        }