Inheritance: MethodEntity
Example #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Monobjc.Tools.Generator.Model.Entities.FunctionEntity"/> class.
        /// </summary>
        public FunctionEntity(FunctionEntity functionEntity)
            : this()
        {
            this.MinAvailability = functionEntity.MinAvailability;
            this.Generate = functionEntity.Generate;
            this.Name = functionEntity.Name;
            this.ReturnsDocumentation = functionEntity.ReturnsDocumentation;
            this.ReturnType = functionEntity.ReturnType;
            this.Selector = functionEntity.Selector;
            this.Signature = functionEntity.Signature;
            this.Static = functionEntity.Static;
            this.Summary = new List<String> (functionEntity.Summary);

            foreach (MethodParameterEntity methodParameterEntity in functionEntity.Parameters) {
                MethodParameterEntity parameter = new MethodParameterEntity (methodParameterEntity);
                this.Parameters.Add (parameter);
            }

            this.GenerateConstructor = functionEntity.GenerateConstructor;
            this.SharedLibrary = functionEntity.SharedLibrary;
            this.EntryPoint = functionEntity.EntryPoint;
        }
Example #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Monobjc.Tools.Generator.Model.Entities.FunctionEntity"/> class.
        /// </summary>
        public FunctionEntity(FunctionEntity functionEntity) : this()
        {
            this.MinAvailability      = functionEntity.MinAvailability;
            this.Generate             = functionEntity.Generate;
            this.Name                 = functionEntity.Name;
            this.ReturnsDocumentation = functionEntity.ReturnsDocumentation;
            this.ReturnType           = functionEntity.ReturnType;
            this.Selector             = functionEntity.Selector;
            this.Signature            = functionEntity.Signature;
            this.Static               = functionEntity.Static;
            this.Summary              = new List <String> (functionEntity.Summary);

            foreach (MethodParameterEntity methodParameterEntity in functionEntity.Parameters)
            {
                MethodParameterEntity parameter = new MethodParameterEntity(methodParameterEntity);
                this.Parameters.Add(parameter);
            }

            this.GenerateConstructor = functionEntity.GenerateConstructor;
            this.SharedLibrary       = functionEntity.SharedLibrary;
            this.EntryPoint          = functionEntity.EntryPoint;
        }
        public FunctionEntity Parse(TypedEntity typedEntity, string name, IEnumerable<XElement> elements)
        {
            FunctionEntity functionEntity = new FunctionEntity ();

            XElement declarationElement = (from el in elements
                                           where el.Name == "div" &&
                el.Attribute ("class") != null &&
                el.Attribute ("class").Value == "declaration_indent"
                                           select el).FirstOrDefault ();
            declarationElement = declarationElement ?? (from el in elements
                                                        where el.Name == "pre"
                                                        select el).FirstOrDefault ();

            XElement parameterElement = (from el in elements
                                         where el.Name == "div" &&
                el.Attribute ("class") != null &&
                el.Attribute ("class").Value == "param_indent"
                                         select el).FirstOrDefault ();

            XElement returnValueElement = (from el in elements
                                           where el.Name == "h5" && el.Value.Trim () == "Return Value"
                                           select el).FirstOrDefault ();

            //XElement discussionElement = (from el in elements
            //                              where el.Name == "h5" && el.Value.Trim() == "Discussion"
            //                              select el).FirstOrDefault();

            XElement availabilityElement = (from el in elements
                                            let term = el.Descendants ("dt").FirstOrDefault ()
                                            let definition = el.Descendants ("dd").FirstOrDefault ()
                                            where el.Name == "dl" &&
                term != null &&
                term.Value.Trim () == "Availability"
                                            select definition).FirstOrDefault ();

            functionEntity.Name = name;

            String signature = declarationElement.TrimAll ();
            if (signature.StartsWith ("#define")) {
                this.Logger.WriteLine ("SKIPPING define statement: " + name);
                return null;
            }
            if (!signature.Contains ("(")) { // e.g. NS_DURING
                this.Logger.WriteLine ("SKIPPING non-function statement: " + name);
                return null;
            }

            // Trim down signature
            while (signature.IndexOf("  ") != -1) {
                signature = signature.Replace ("  ", " ");
            }
            functionEntity.Signature = signature;
            //Console.WriteLine("signature='" + signature + "'");

            // Extract abstract
            IEnumerable<XElement> abstractElements = elements.SkipWhile (el => el.Name != "p").TakeWhile (el => el.Name == "p");
            foreach (XElement element in abstractElements) {
                String line = element.TrimAll ();
                if (!String.IsNullOrEmpty (line)) {
                    functionEntity.Summary.Add (line);
                }
            }

            //// Extract discussion
            //if (discussionElement != null)
            //{
            //    IEnumerable<XElement> discussionElements = discussionElement.ElementsAfterSelf().TakeWhile(el => el.Name == "p");
            //    foreach (XElement element in discussionElements)
            //    {
            //        String line = element.TrimAll();
            //        if (!String.IsNullOrEmpty(line))
            //        {
            //            methodEntity.Summary.Add(line);
            //        }
            //    }
            //}

            // Parse signature
            signature = signature.Replace ("extern", String.Empty).Trim ();
            int pos = signature.IndexOf (name);
            if (pos == -1) {
                this.Logger.WriteLine ("MISMATCH between name and declaration: " + name);
                return null;
            }

            String returnType = signature.Substring (0, pos).Trim ();
            int paramsIndex = pos + name.Length;
            int paramsLength = signature.IndexOf(')') + 1 - paramsIndex; // Stop before getting to function body
            String parameters = signature.Substring (paramsIndex, paramsLength).Trim ();
            parameters = parameters.Trim (';', '(', ')').Trim();
            if (parameters != "void") {
                foreach (string parameter in parameters.Split(new []{','}, StringSplitOptions.RemoveEmptyEntries)) {
                    String parameterType = "NOTYPE";
                    String parameterName = "NONAME";

                    //Console.WriteLine("parameter='" + parameter + "'");
                    Match r = PARAMETER_REGEX.Match (parameter);
                    if (r.Success) {
                        parameterType = r.Groups [2].Value.Trim ();
                        parameterName = r.Groups [3].Value.Trim ();
                    } else if (parameter.Trim () == "...") {
                        parameterType = "params Object[]";
                        parameterName = "values";
                    } else {
                        this.Logger.WriteLine ("FAILED to parse parameter: " + parameter);
                        return null;
                    }

                    MethodParameterEntity parameterEntity = new MethodParameterEntity ();
                    bool isOut, isByRef, isBlock;
                    parameterEntity.Type = this.TypeManager.ConvertType (parameterType, out isOut, out isByRef, out isBlock, this.Logger);
                    parameterEntity.IsOut = isOut;
                    parameterEntity.IsByRef = isByRef;
                    parameterEntity.IsBlock = isBlock;
                    parameterEntity.Name = TypeManager.ConvertName(parameterName);
                    functionEntity.Parameters.Add (parameterEntity);
                }
            }

            // Extract return type
            functionEntity.ReturnType = this.TypeManager.ConvertType (returnType, this.Logger);

            if (functionEntity.Parameters.Count > 0 && parameterElement != null) {
                XElement termList = parameterElement.Descendants ("dl").FirstOrDefault ();
                if (termList != null) {
                    IEnumerable<XElement> dtList = from el in termList.Elements ("dt") select el;
                    IEnumerable<XElement> ddList = from el in termList.Elements ("dd") select el;

                    if (dtList.Count () == ddList.Count ()) {
                        // Iterate over definitions
                        for (int i = 0; i < dtList.Count(); i++) {
                            String term = dtList.ElementAt (i).TrimAll ();
                            //String summary = ddList.ElementAt(i).TrimAll();
                            IEnumerable<String> summaries = ddList.ElementAt (i).Elements ("p").Select (p => p.Value.TrimAll ());

                            // Find the parameter
                            MethodParameterEntity parameterEntity = functionEntity.Parameters.Find (p => String.Equals (p.Name, term));
                            if (parameterEntity != null) {
                                //parameterEntity.Summary.Add(summary);
                                foreach (string sum in summaries) {
                                    parameterEntity.Summary.Add (sum);
                                }
                            }
                        }
                    }
                }
            }

            // Fix the name only after looking for the documentation
            for (int i = 0; i < functionEntity.Parameters.Count; i++) {
                functionEntity.Parameters [i].Name = this.TypeManager.ConvertName (functionEntity.Parameters [i].Name);
            }

            // Get the summary for return type
            if (!String.Equals (functionEntity.ReturnType, "void", StringComparison.OrdinalIgnoreCase) && returnValueElement != null) {
                IEnumerable<XElement> returnTypeElements = returnValueElement.ElementsAfterSelf ().TakeWhile (el => el.Name == "p");
                functionEntity.ReturnsDocumentation = String.Empty;
                foreach (XElement element in returnTypeElements) {
                    String line = element.TrimAll ();
                    if (!String.IsNullOrEmpty (line)) {
                        functionEntity.ReturnsDocumentation += line;
                    }
                }
            }

            // Get the availability
            if (availabilityElement != null) {
                functionEntity.MinAvailability = CommentHelper.ExtractAvailability (availabilityElement.TrimAll ());
            }

            return functionEntity;
        }
        /// <summary>
        ///   Parses the specified method element.
        /// </summary>
        /// <param name = "functionElement">The function element.</param>
        /// <returns></returns>
        public FunctionEntity Parse(TypedEntity typedEntity, XElement functionElement)
        {
            FunctionEntity functionEntity = new FunctionEntity ();

            // Extract name
            String name = functionElement.TrimAll ();
            functionEntity.Name = name;

            this.Logger.WriteLine ("  Function '" + name + "'");

            // Extract abstract
            XElement abstractElement = (from el in functionElement.ElementsAfterSelf ("p")
                                        where (String)el.Attribute ("class") == "abstract"
                                        select el).FirstOrDefault ();
            functionEntity.Summary.Add (abstractElement.TrimAll ());

            // Extract declaration
            XElement declarationElement = (from el in functionElement.ElementsAfterSelf ("pre")
                                           where (String)el.Attribute ("class") == "declaration"
                                           select el).FirstOrDefault ();

            String signature = declarationElement.TrimAll ();
            if (signature.StartsWith ("#define")) {
                this.Logger.WriteLine ("SKIPPING define statement: " + name);
                return null;
            }
            if (signature.StartsWith ("typedef")) {
                this.Logger.WriteLine ("SKIPPING define statement: " + name);
                return null;
            }
            if (!signature.Contains ("(")) { // e.g. NS_DURING
                this.Logger.WriteLine ("SKIPPING non-function statement: " + name);
                return null;
            }

            // Trim down signature
            while (signature.IndexOf("  ") != -1) {
                signature = signature.Replace ("  ", " ");
            }
            while (signature.IndexOf(" (") != -1) {
                signature = signature.Replace (" (", "(");
            }
            functionEntity.Signature = signature;
            //Console.WriteLine("name='" + name + "' signature='" + signature + "'");

            // Parse signature
            int pos = signature.IndexOf (name + "(");
            if (pos == -1) {
                this.Logger.WriteLine ("MISMATCH between name and declaration: " + name);
                return null;
            }
            String returnType = signature.Substring (0, pos).Trim ();
            int paramsIndex = pos + name.Length;
            int paramsLength = signature.IndexOf(')') + 1 - paramsIndex; // Stop before getting to function body
            String parameters = signature.Substring (paramsIndex, paramsLength).Trim ();
            parameters = parameters.Trim (';', '(', ')').Trim();
            if (parameters != "void") {
                foreach (string parameter in parameters.Split(new []{','}, StringSplitOptions.RemoveEmptyEntries)) {
                    String parameterType = "NOTYPE";
                    String parameterName = "NONAME";

                    //Console.WriteLine("parameter='" + parameter + "'");
                    Match r = PARAMETER_REGEX.Match (parameter);
                    if (r.Success) {
                        parameterType = r.Groups [2].Value.Trim ();
                        parameterName = r.Groups [3].Value.Trim ();
                    } else if (parameter.Trim () == "...") {
                        parameterType = "params Object[]";
                        parameterName = "values";
                    } else {
                        this.Logger.WriteLine ("FAILED to parse parameter: " + parameter);
                        return null;
                    }
                    parameterType = parameterType.Trim ();

                    MethodParameterEntity parameterEntity = new MethodParameterEntity ();
                    bool isOut, isByRef, isBlock;
                    parameterEntity.Type = this.TypeManager.ConvertType (parameterType, out isOut, out isByRef, out isBlock, this.Logger);
                    parameterEntity.IsOut = isOut;
                    parameterEntity.IsByRef = isByRef;
                    parameterEntity.IsBlock = isBlock;
                    parameterEntity.Name = TypeManager.ConvertName(parameterName);
                    functionEntity.Parameters.Add (parameterEntity);
                }
            }

            // Extract return type
            functionEntity.ReturnType = this.TypeManager.ConvertType (returnType, this.Logger);

            // Extract parameter documentation
            if (functionEntity.Parameters.Count > 0) {
                XElement termList = (from el in functionElement.Elements ("div").Elements ("dl")
                                     where (String)el.Parent.Attribute ("class") == "api parameters"
                    && (String)el.Attribute ("class") == "termdef"
                                     select el).FirstOrDefault ();
                if (termList != null) {
                    IEnumerable<XElement> dtList = from el in termList.Elements ("dt") select el;
                    IEnumerable<XElement> ddList = from el in termList.Elements ("dd") select el;

                    if (dtList.Count () == ddList.Count ()) {
                        // Iterate over definitions
                        for (int i = 0; i < dtList.Count(); i++) {
                            String term = dtList.ElementAt (i).TrimAll ();
                            IEnumerable<String> summaries = ddList.ElementAt (i).Elements ("p").Select (p => p.Value.TrimAll ());

                            // Find the parameter
                            MethodParameterEntity parameterEntity = functionEntity.Parameters.Find (p => String.Equals (p.Name, term));
                            if (parameterEntity != null) {
                                foreach (string sum in summaries) {
                                    parameterEntity.Summary.Add (sum);
                                }
                            }
                        }
                    }
                }
            }

            // Fix the name only after looking for the documentation
            for (int i = 0; i < functionEntity.Parameters.Count; i++) {
                functionEntity.Parameters [i].Name = this.TypeManager.ConvertName (functionEntity.Parameters [i].Name);
            }

            // Get the summary for return type
            if (!String.Equals (functionEntity.ReturnType, "void", StringComparison.OrdinalIgnoreCase)) {
                XElement returnValueElement = (from el in functionElement.ElementsAfterSelf ("div")
                                               where (String)el.Attribute ("class") == "return_value"
                                               select el).FirstOrDefault ();
                if (returnValueElement != null) {
                    IEnumerable<String> documentations = returnValueElement.Elements ("p").Select (p => p.Value.TrimAll ());
                    functionEntity.ReturnsDocumentation = String.Join (String.Empty, documentations.ToArray ());
                }
            }

            //// Extract discussion
            //XElement discussionElement = (from el in functionElement.ElementsAfterSelf("div")
            //                              where (String) el.Attribute("class") == "api discussion"
            //                              select el).FirstOrDefault();
            //if (discussionElement != null)
            //{
            //    foreach (XElement paragraph in discussionElement.Elements("p"))
            //    {
            //        functionEntity.Summary.Add(paragraph.TrimAll());
            //    }
            //}

            // Get the availability
            XElement availabilityElement = (from el in functionElement.ElementsAfterSelf ("div")
                                            where (String)el.Attribute ("class") == "api availability"
                                            select el).FirstOrDefault ();
            XElement minAvailabilityElement = null;
            if (availabilityElement != null) {
                minAvailabilityElement = availabilityElement.Elements("ul").Elements("li").FirstOrDefault();
            }
            String minAvailability = "";
            if (minAvailabilityElement != null) {
                minAvailability = minAvailabilityElement.TrimAll();
            }
            functionEntity.MinAvailability = CommentHelper.ExtractAvailability (minAvailability);

            return functionEntity;
        }
        private void GenerateWrapperFunction(TypedEntity typedEntity, FunctionEntity functionEntity, FunctionEntity functionEntity32, FunctionEntity functionEntity64, bool needStorage)
        {
            bool useMixedInvocation = functionEntity32 != null && functionEntity64 != null;

            // Strip name if the prefix is the same
            String name = functionEntity.Name;
            if (name.StartsWith (typedEntity.Name)) {
                name = name.Substring (typedEntity.Name.Length);
            }

            StringBuilder signature = new StringBuilder ();
            signature.AppendFormat ("public static {0} {1}(", functionEntity.ReturnType, name);

            // Append parameters
            List<String> parameters = new List<String> ();
            foreach (MethodParameterEntity methodParameterEntity in functionEntity.Parameters.Where(p => p.Generate)) {
                parameters.Add (GetTypeSignature (methodParameterEntity));
            }
            signature.Append (String.Join (", ", parameters.ToArray ()));
            signature.Append (")");
            this.Writer.WriteLineFormat (2, signature.ToString ());
            this.Writer.WriteLineFormat (2, "{{");

            if (useMixedInvocation) {
            #if MIXED_MODE
                this.Writer.WriteLineFormat(3, "if (ObjectiveCRuntime.Is64Bits)");
                this.Writer.WriteLineFormat(3, "{{");

                this.GenerateFunctionBody(4, typedEntity, functionEntity, functionEntity64, needStorage, SUFFIX_64);

                this.Writer.WriteLineFormat(3, "}}");
                this.Writer.WriteLineFormat(3, "else");
                this.Writer.WriteLineFormat(3, "{{");
            #endif
                this.GenerateFunctionBody (4, typedEntity, functionEntity, functionEntity32, needStorage, SUFFIX_32);
            #if MIXED_MODE
                this.Writer.WriteLineFormat(3, "}}");
            #endif
            } else {
                this.GenerateFunctionBody (3, typedEntity, functionEntity, null, needStorage, SUFFIX_INNER);
            }

            this.Writer.WriteLineFormat (2, "}}");
            this.Writer.WriteLine ();
        }
        private void GenerateNativeFunction(TypedEntity typedEntity, FunctionEntity functionEntity, String suffix, bool isPublic)
        {
            // Strip name if the prefix is the same
            String name = functionEntity.Name;
            if (name.StartsWith (typedEntity.Name)) {
                name = name.Substring (typedEntity.Name.Length);
            }

            // TODO: Compute proper framework path...
            // TODO: Test with embedded frameworks...
            this.Writer.WriteLineFormat (2, "[DllImport(\"{0}\", EntryPoint=\"{1}\")]", GetFrameworkPath (typedEntity.Namespace), functionEntity.Name);

            // Add custom tag for return type
            if (TypeManager.HasClass (functionEntity.ReturnType)) {
                this.Writer.WriteLineFormat (2, "[return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (IdMarshaler<{0}>))]", functionEntity.ReturnType);
            }

            StringBuilder signature = new StringBuilder ();
            signature.AppendFormat ("{0} static extern {1} {2}(", isPublic ? "public" : "private", functionEntity.ReturnType, name + suffix ?? String.Empty);

            // Append parameters
            List<String> parameters = new List<String> ();
            foreach (MethodParameterEntity methodParameterEntity in functionEntity.Parameters.Where(p => p.Generate)) {
                if (methodParameterEntity.IsOut || methodParameterEntity.IsByRef) {
                    parameters.Add ("IntPtr " + methodParameterEntity.Name);
                } else if (methodParameterEntity.IsBlock) {
                    parameters.Add (String.Format ("[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (BlockMarshaler))] Block {0}", methodParameterEntity.Name));
                } else {
                    String parameter = GetTypeSignature (methodParameterEntity);
                    if (TypeManager.HasClass (methodParameterEntity.Type)) {
                        parameter = String.Format ("[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (IdMarshaler<{0}>))] {1}", methodParameterEntity.Type, parameter);
                    }
                    parameters.Add (parameter);
                }
            }
            signature.Append (String.Join (", ", parameters.ToArray ()));
            signature.Append (");");

            this.Writer.WriteLineFormat (2, signature.ToString ());
            this.Writer.WriteLine ();
        }
        private FunctionEntity DeriveFunctionEntity(FunctionEntity functionEntity, bool is64Bits)
        {
            FunctionEntity result = new FunctionEntity (functionEntity);

            result.ReturnType = this.GetRealType (result.ReturnType, is64Bits);
            foreach (MethodParameterEntity parameter in result.Parameters) {
                parameter.Type = GetRealType (parameter.Type, is64Bits);
            }

            return result;
        }
        private static string GetFunctionInvocation(TypedEntity typedEntity, FunctionEntity functionEntity, FunctionEntity innerFunctionEntity, String suffix = null)
        {
            // Strip name if the prefix is the same
            String name = functionEntity.Name;
            if (name.StartsWith (typedEntity.Name)) {
                name = name.Substring (typedEntity.Name.Length);
            }

            StringBuilder builder = new StringBuilder ();

            builder.AppendFormat ("{0}{1}(", name, suffix ?? String.Empty);
            builder.Append (GetMessageParameterList (functionEntity, innerFunctionEntity, false));
            builder.Append (");");

            return builder.ToString ();
        }
        protected void GenerateFunctionBody(int indent, TypedEntity typedEntity, FunctionEntity methodEntity, FunctionEntity innerMethodEntity, bool needStorage, String suffix = null)
        {
            bool hasReturn = !String.Equals (methodEntity.ReturnType, "void");
            bool mixed = (innerMethodEntity != null);
            bool mixedReturnType = mixed && !String.Equals (methodEntity.ReturnType, innerMethodEntity.ReturnType);

            this.GenerateLocalsAllocation (indent, methodEntity, innerMethodEntity);
            this.GenerateLocalsMarshalling (indent, methodEntity, innerMethodEntity);

            String invocation = GetFunctionInvocation (typedEntity, methodEntity, innerMethodEntity, suffix);
            if (hasReturn) {
                if (needStorage) {
                    String prefix = methodEntity.ReturnType + " __result = ";
                    if (mixedReturnType) {
                        prefix += "(" + methodEntity.ReturnType + ") ";
                    }
                    invocation = prefix + invocation;
                } else {
                    String prefix = "return ";
                    if (mixedReturnType) {
                        prefix += "(" + methodEntity.ReturnType + ") ";
                    }
                    invocation = prefix + invocation;
                }
            }
            this.Writer.WriteLineFormat (indent, invocation);

            this.GenerateLocalsUnmarshalling (indent, methodEntity, innerMethodEntity);
            this.GenerateLocalsDeallocation (indent, methodEntity, innerMethodEntity);

            if (hasReturn && needStorage) {
                this.Writer.WriteLineFormat (indent, "return __result;");
            }
        }
        //        /// <summary>
        //        ///   Generates the specified entity.
        //        /// </summary>
        //        /// <param name = "typedEntity">The type entity.</param>
        //        /// <param name = "functionEntity">The function entity.</param>
        //        public void GenerateOpaque (TypedEntity typedEntity, FunctionEntity functionEntity, String opaquePointer)
        //        {
        //            // Don't generate if required
        //            if (!functionEntity.Generate) {
        //                return;
        //            }
        //
        //            // Append static condition if needed
        //            this.AppendStartCondition (functionEntity);
        //            
        //            // Append documentation
        //            this.AppendDocumentation (functionEntity, false, true);
        //            
        //            // Append Obsolete attribute
        //            this.AppendObsoleteAttribute (functionEntity);
        //            
        //            // Create function signature
        //            StringBuilder signature = new StringBuilder ();
        //            
        //            // Append keywords
        //            String keywords = GetKeywords (functionEntity, true, false, false);
        //            signature.Append (keywords);
        //            
        //            String name = functionEntity.Name;
        //            if (name.StartsWith (typedEntity.Name)) {
        //                name = name.Substring (typedEntity.Name.Length);
        //            }
        //
        //            // Append return type and name
        //            String returnType = functionEntity.ReturnOpaque ? typedEntity.Name : functionEntity.ReturnType;
        //            signature.AppendFormat ("{0} {1}", returnType, name);
        //            signature.Append ("(");
        //            
        //            // Append parameters
        //            List<String> parameters = new List<String> ();
        //            bool first = true;
        //            foreach (MethodParameterEntity methodParameterEntity in functionEntity.Parameters.Where(p => p.Generate)) {
        //                if (first) {
        //                    first = false;
        //                    if (methodParameterEntity.IsOpaque) {
        //                        continue;
        //                    }
        //                } else {
        //                    if (methodParameterEntity.IsOpaque) {
        //                        methodParameterEntity.Type = typedEntity.Name;
        //                    }
        //                }
        //                parameters.Add (GetTypeSignature (methodParameterEntity));
        //            }
        //            signature.Append (String.Join (", ", parameters.ToArray ()));
        //            signature.Append (")");
        //
        //            this.Writer.WriteLineFormat (2, signature.ToString ());
        //
        //            // Output the body
        //            this.Writer.WriteLineFormat (2, "{{");
        //            StringBuilder invocation = new StringBuilder();
        //            bool hasReturn = !String.Equals (functionEntity.ReturnType, "void");
        //            if (functionEntity.ReturnOpaque) {
        //                invocation.AppendFormat("IntPtr value = ");
        //            } else if (hasReturn) {
        //                invocation.AppendFormat("return ");
        //            }
        //            invocation.AppendFormat("{0}(", name);
        //            first = true;
        //            foreach (MethodParameterEntity methodParameterEntity in functionEntity.Parameters.Where(p => p.Generate)) {
        //                if (first) {
        //                    first = false;
        //                    if (methodParameterEntity.IsOpaque) {
        //                        invocation.AppendFormat("this.{0}", opaquePointer);
        //                    } else {
        //                        invocation.AppendFormat("{0}", methodParameterEntity.Name);
        //                    }
        //                } else {
        //                    invocation.AppendFormat(", {0}", methodParameterEntity.Name);
        //                }
        //            }
        //            invocation.Append(");");
        //            this.Writer.WriteLineFormat (3, invocation.ToString());
        //
        //            if (functionEntity.ReturnOpaque) {
        //                this.Writer.WriteLineFormat (3, "return new {0}(value);", typedEntity.Name);
        //            }
        //
        //            this.Writer.WriteLineFormat (2, "}}");
        //
        //            // Append static condition if needed
        //            this.AppendEndCondition (functionEntity);
        //        }
        /// <summary>
        ///   Generates the specified entity.
        /// </summary>
        /// <param name = "typedEntity">The type entity.</param>
        /// <param name = "functionEntity">The function entity.</param>
        public void Generate(TypedEntity typedEntity, FunctionEntity functionEntity)
        {
            // Don't generate if required
            if (!functionEntity.Generate) {
                return;
            }

            if (functionEntity.MinAvailabilityAsVersion.IsGreaterThan(typedEntity.MinAvailabilityAsVersion)) {
                // Append static condition if needed
                this.AppendStartCondition(functionEntity);
            }

            // Append documentation
            this.AppendDocumentation (functionEntity);

            // Collect information
            bool needStorage = false;
            bool varargs = false;
            CollectInformations (functionEntity, ref needStorage, ref varargs);

            // Collect information on 32/64 bits invocations to check if they differ
            FunctionEntity functionEntity32 = DeriveFunctionEntity (functionEntity, false);
            FunctionEntity functionEntity64 = DeriveFunctionEntity (functionEntity, true);
            bool useMixedInvocation = !AreMethodTypesEqual (functionEntity32, functionEntity64);

            if (needStorage || useMixedInvocation) {
                if (useMixedInvocation) {
                    this.GenerateWrapperFunction (typedEntity, functionEntity, functionEntity32, functionEntity64, needStorage);
            #if MIXED_MODE
                    this.GenerateNativeFunction(typedEntity, functionEntity64, SUFFIX_64, false);
            #endif
                    this.GenerateNativeFunction (typedEntity, functionEntity32, SUFFIX_32, false);
                } else {
                    this.GenerateWrapperFunction (typedEntity, functionEntity, null, null, needStorage);

                    this.GenerateNativeFunction (typedEntity, functionEntity, SUFFIX_INNER, false);
                }
            } else {
                this.GenerateNativeFunction (typedEntity, functionEntity, null, true);
            }

            if (functionEntity.MinAvailabilityAsVersion.IsGreaterThan(typedEntity.MinAvailabilityAsVersion)) {
                // Append static condition if needed
                this.AppendEndCondition(functionEntity);
            }

            // Update statistics
            this.Statistics.Functions++;
        }