Example #1
0
        /// <summary>
        ///   Parses the specified notification element.
        /// </summary>
        /// <param name = "notificationElement">The notification element.</param>
        /// <returns></returns>
        public ConstantEntity Parse(TypedEntity typedEntity, XElement notificationElement)
        {
            ConstantEntity notificationEntity = new ConstantEntity();

            notificationEntity.Type = "NSString";

            // Get the name
            notificationEntity.Name = notificationElement.TrimAll();

            this.Logger.WriteLine("  Notification '" + notificationEntity.Name + "'");

            // Get the content and the discussion
            XElement summaryElement = (from el in notificationElement.ElementsAfterSelf("section")
                                       where (String)el.Attribute("class") == "spaceabove"
                                       select el).FirstOrDefault();

            if (summaryElement != null)
            {
                foreach (XElement element in summaryElement.Elements())
                {
                    notificationEntity.Summary.Add(element.Value.TrimAll());
                }
            }

            // Get the availability
            String minAvailability = (from el in notificationElement.ElementsAfterSelf("div").Elements("ul").Elements("li")
                                      where (String)el.Parent.Parent.Attribute("class") == "api availability"
                                      select el.Value).FirstOrDefault();

            notificationEntity.MinAvailability = CommentHelper.ExtractAvailability(minAvailability.TrimAll());

            return(notificationEntity);
        }
 /// <summary>
 ///   Appends the comment.
 /// </summary>
 /// <param name = "entity">The entity.</param>
 /// <param name = "node">The node.</param>
 /// <param name = "comments">The comments.</param>
 protected static void AppendComment(BaseEntity entity, IEnumerable <Comment> comments)
 {
     foreach (Comment comment in comments)
     {
         String c = comment.CommentText.Trim();
         if (CommentHelper.IsSummary(c))
         {
             continue;
         }
         if (CommentHelper.IsAvailability(c))
         {
             String str = c;
             foreach (String s in new[] { "<para>", "</para>", "&lt;para&gt;", "&lt;/para&gt;" })
             {
                 str = str.Replace(s, String.Empty);
             }
             entity.MinAvailability = CommentHelper.ExtractAvailability(str.Trim());
         }
         else if (CommentHelper.IsParameter(c) || CommentHelper.IsReturn(c) || CommentHelper.IsSignature(c))
         {
             // Do nothing
         }
         else if (CommentHelper.IsParagraph(c))
         {
             String str = c;
             foreach (String s in new[] { "<para>", "</para>", "&lt;para&gt;", "&lt;/para&gt;" })
             {
                 str = str.Replace(s, String.Empty);
             }
             entity.Summary.Add(str.Trim());
         }
         else if (CommentHelper.IsRemarks(c))
         {
             String str = c;
             foreach (String s in new[] { "<remarks>", "</remarks>", "&lt;remarks&gt;", "&lt;/remarks&gt;" })
             {
                 str = str.Replace(s, String.Empty);
             }
             entity.Summary.Add(str.Trim());
         }
         else
         {
             entity.Summary.Add(c);
         }
     }
 }
Example #3
0
        /// <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("  ", " ");
            }
            functionEntity.Signature = signature;
            //Console.WriteLine("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();
            String minAvailability = availabilityElement.Elements("ul").Elements("li").FirstOrDefault().TrimAll();

            functionEntity.MinAvailability = CommentHelper.ExtractAvailability(minAvailability);

            return(functionEntity);
        }
        private List <BaseEntity> ExtractConstants(XElement constantElement, String name, String summary, String declaration)
        {
            List <BaseEntity> constants = new List <BaseEntity> ();

            // Extract types and names
            string[] declarations = declaration.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string part in declarations)
            {
                //this.Logger.WriteLine("Parsing constant '{0}'...", part.Trim());

                String stripped = part.Trim();
                stripped = stripped.Replace("extern", String.Empty);
                stripped = stripped.Replace("const", String.Empty);
                stripped = stripped.TrimAll();

                Match r = CONSTANT_REGEX.Match(stripped);
                if (r.Success)
                {
                    String type = r.Groups [1].Value.Trim(' ', '*', ' ');

                    bool isOut;
                    bool isByRef;
                    bool isBlock;
                    type = this.TypeManager.ConvertType(type, out isOut, out isByRef, out isBlock, this.Logger);

                    ConstantEntity constantEntity = new ConstantEntity();
                    constantEntity.Type = type;
                    constantEntity.Name = r.Groups [2].Value.Trim();
                    constants.Add(constantEntity);

                    //this.Logger.WriteLine("Constant found '{0}' of type '{1}'", constantEntity.Name, constantEntity.Type);
                }
                else
                {
                    this.Logger.WriteLine("FAILED to parse constant '{0}'", stripped);
                    return(null);
                }
            }

            // Get the definitions
            XElement termDefinitions = (from el in constantElement.ElementsAfterSelf("dl")
                                        where (String)el.Attribute("class") == "termdef"
                                        select el).FirstOrDefault();

            if (termDefinitions == null)
            {
                this.Logger.WriteLine("MISSING terms");
                return(null);
            }

            IEnumerable <XElement> termName       = termDefinitions.Elements("dt");
            IEnumerable <XElement> termDefinition = termDefinitions.Elements("dd");

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

                    // Find the enumeration value
                    BaseEntity baseEntity = constants.Find(c => c.Name == term);
                    if (baseEntity != null)
                    {
                        foreach (string sum in summaries)
                        {
                            if (CommentHelper.IsAvailability(sum))
                            {
                                baseEntity.MinAvailability = CommentHelper.ExtractAvailability(sum);
                                break;
                            }
                            baseEntity.Summary.Add(sum);
                        }
                    }
                    else
                    {
                        this.Logger.WriteLine("Term with no match '" + term + "'");
                    }
                }
            }
            else
            {
                this.Logger.WriteLine("MISMATCH in terms");
                return(null);
            }

            return(constants);
        }
        private List <BaseEntity> ExtractEnumeration(XElement constantElement, String name, String summary, String declaration)
        {
            declaration = declaration.Trim(';');

            // Default values
            String type   = "NOTYPE";
            String values = String.Empty;

            // Match the enumeration definition
            bool result = this.SplitEnumeration(declaration, ref name, ref type, ref values);

            if (!result)
            {
                return(null);
            }

            if (type == "NOTYPE")
            {
                type = RefineEnumBaseType(values);
            }

            // Create the enumeration
            EnumerationEntity enumerationEntity = new EnumerationEntity();

            enumerationEntity.Name      = name;
            enumerationEntity.BaseType  = type;
            enumerationEntity.Namespace = "MISSING";
            enumerationEntity.Summary.Add(summary);

            // Parse the values
            var pairs = values.Split(new [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string immutablePair in pairs)
            {
                String key;
                String value = String.Empty;
                String pair  = immutablePair.Replace(",", "");

                // Handle value assignment
                if (pair.IndexOf('=') != -1)
                {
                    string[] parts = pair.Split(new [] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                    key   = parts [0].Trim();
                    value = parts [1].Trim();
                }
                else
                {
                    key = pair.Trim();
                }

                // Add a new value
                EnumerationValueEntity enumerationValueEntity = new EnumerationValueEntity();
                enumerationValueEntity.Name = key;

                if (value.Length == 6 && value.StartsWith("'") && value.EndsWith("'"))
                {
                    String v = value.Trim('\'');
                    enumerationValueEntity.Value = "0x" + FourCharToInt(v).ToString("X8");
                }
                else
                {
                    enumerationValueEntity.Value = value;
                }

                // Convert number qualifiers from native to managed
                enumerationValueEntity.Value = ConvertNumericQualifier(enumerationValueEntity.Value);

                enumerationEntity.Values.Add(enumerationValueEntity);
            }

            // Get the definitions
            XElement termList = (from el in constantElement.ElementsAfterSelf("dl")
                                 where (String)el.Attribute("class") == "termdef"
                                 select el).FirstOrDefault();

            if (termList != null)
            {
                IEnumerable <XElement> dtList = termList.Elements("dt");
                IEnumerable <XElement> ddList = termList.Elements("dd");

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

                        // Find the enumeration value
                        EnumerationValueEntity enumerationValueEntity = enumerationEntity.Values.Find(v => v.Name == term);
                        if (enumerationValueEntity != null)
                        {
                            foreach (string sum in summaries)
                            {
                                if (CommentHelper.IsAvailability(sum))
                                {
                                    enumerationValueEntity.MinAvailability = CommentHelper.ExtractAvailability(sum);
                                    break;
                                }
                                enumerationValueEntity.Summary.Add(sum);
                            }
                        }
                        else
                        {
                            this.Logger.WriteLine("Term with no match '" + term + "'");
                        }
                    }
                }
                else
                {
                    this.Logger.WriteLine("MISMATCH in terms");
                }
            }

            // Make sure availability is ok
            enumerationEntity.AdjustAvailability();

            return(new List <BaseEntity> {
                enumerationEntity
            });
        }
Example #6
0
        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);
            }
            functionEntity.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();
            String parameters = signature.Substring(pos + name.Length).Trim();

            parameters = parameters.Trim(';', '(', ')');
            if (parameters != "void")
            {
                foreach (string parameter in parameters.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    String parameterType = "NOTYPE";
                    String parameterName = "NONAME";

                    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);
        }
        public ConstantEntity Parse(TypedEntity typedEntity, string constantElement, IEnumerable <XElement> elements)
        {
            ConstantEntity constantEntity = new ConstantEntity();

            XElement declarationElement = (from el in elements
                                           where el.Name == "div" &&
                                           el.Attribute("class") != null &&
                                           el.Attribute("class").Value == "declaration_indent"
                                           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();

            String stripped = declarationElement.TrimAll();

            stripped = stripped.Trim(';');
            while (stripped.Contains("  "))
            {
                stripped = stripped.Replace("  ", " ");
            }
            stripped = stripped.Replace("extern", String.Empty);
            stripped = stripped.Replace("const", String.Empty);
            stripped = stripped.TrimAll();

            Match r = CONSTANT_REGEX.Match(stripped);

            if (r.Success)
            {
                String type = r.Groups[1].Value.Trim(' ', '*', ' ');

                bool isOut;
                bool isByRef;
                bool isBlock;
                type = this.TypeManager.ConvertType(type, out isOut, out isByRef, out isBlock, this.Logger);

                constantEntity.Type = type;
                constantEntity.Name = r.Groups[2].Value.Trim();
            }
            else
            {
                this.Logger.WriteLine("FAILED to parse constant '{0}'", stripped);
                return(constantEntity);
            }

            // 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))
                {
                    constantEntity.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))
            //        {
            //            constantEntity.Summary.Add(line);
            //        }
            //    }
            //}

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

            return(constantEntity);
        }
Example #8
0
        /// <summary>
        ///   Parses the specified entity.
        /// </summary>
        /// <param name = "entity">The entity.</param>
        /// <param name = "reader">The reader.</param>
        public override void Parse(BaseEntity entity, TextReader reader)
        {
            ClassEntity classEntity = (ClassEntity)entity;

            if (classEntity == null)
            {
                throw new ArgumentException("ClassEntity expected", "entity");
            }

            using (XmlTextReader xmlTextReader = new XmlTextReader(reader)) {
                XElement root = XElement.Load(xmlTextReader);

                // Get the spec box
                XElement specElement = (from el in root.Descendants("div")
                                        where el.Attribute("class").Contains("spec_sheet_info_box")
                                        select el).FirstOrDefault();
                if (specElement != null)
                {
                    // Availability
                    XElement availabilityElement = (from el in specElement.Descendants("td")
                                                    let prev = el.ElementsBeforeSelf("td").FirstOrDefault()
                                                               where prev != null && prev.Value.TrimAll() == "Availability"
                                                               select el).FirstOrDefault();
                    if (availabilityElement != null)
                    {
                        entity.MinAvailability = CommentHelper.ExtractAvailability(availabilityElement.TrimAll());
                    }

                    // Inherits
                    XElement inheritElement = (from el in specElement.Descendants("td")
                                               let prev = el.ElementsBeforeSelf("td").FirstOrDefault()
                                                          where prev != null && prev.Value.TrimAll() == "Inherits from"
                                                          select el).FirstOrDefault();
                    if (inheritElement != null)
                    {
                        string   hierarchy = inheritElement.TrimAll();
                        string[] parents   = hierarchy.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                        classEntity.BaseType = parents [0].Trim();
                    }

                    // Conforms To
                    XElement conformsElements = (from el in specElement.Descendants("td")
                                                 let prev = el.ElementsBeforeSelf("td").FirstOrDefault()
                                                            where prev != null && prev.Value.TrimAll() == "Conforms to"
                                                            select el).FirstOrDefault();
                    if (conformsElements != null)
                    {
                        List <String> protocols = new List <string> ();
                        foreach (XElement conformsElement in conformsElements.Descendants("span"))
                        {
                            String protocol = conformsElement.TrimAll();
                            if (protocol.Contains("(NSObject)") || protocol.Contains("(NSProxy)"))
                            {
                                continue;
                            }
                            int pos = protocol.IndexOf('(');
                            if (pos != -1)
                            {
                                protocol = protocol.Substring(0, pos).Trim();
                            }
                            protocols.Add(protocol);
                        }
                        classEntity.ConformsTo = String.Join(",", protocols.Distinct().ToArray());
                    }
                }

                // Class Methods
                this.ExtractClassMethods(classEntity, root);

                // Instance Methods
                this.ExtractInstanceMethods(classEntity, root);

                // Delegate Methods
                this.ExtractDelegateMethods(classEntity, root);

                // Properties
                this.ExtractProperties(classEntity, root);

                // Constants
                this.ExtractConstants(classEntity, root);

                // Notifications
                this.ExtractNotifications(classEntity, root);

                // Functions
                this.ExtractFunctions(classEntity, root);
            }

            // Extract getter and search for setter
            List <String>       notGetterMethods = this.Settings ["NotGetterMethods"].Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            List <MethodEntity> methodModels     = new List <MethodEntity> (classEntity.Methods);

            foreach (MethodEntity methodModel in methodModels)
            {
                if (notGetterMethods.Contains(methodModel.Name) || !methodModel.IsGetter)
                {
                    continue;
                }

                classEntity.Methods.Remove(methodModel);
                MethodEntity getter = methodModel;

                // TODO: Refactor to use the IsSetterFor with an optional parameter to strip the prefix
                MethodEntity setter = classEntity.Methods.Find(m => String.Equals("Set" + getter.Name, m.Name) &&
                                                               String.Equals(m.ReturnType, "void") &&
                                                               m.Parameters.Count == 1 &&
                                                               m.Static == getter.Static);
                if (setter == null)
                {
                    setter = classEntity.Methods.Find(m => m.IsSetterFor(getter));
                }
                if (setter != null)
                {
                    classEntity.Methods.Remove(setter);
                }

                PropertyEntity property = new PropertyEntity();
                property.Name            = getter.Name;
                property.Type            = getter.ReturnType;
                property.Summary         = getter.Summary;
                property.MinAvailability = getter.MinAvailability;
                property.Static          = getter.Static;
                property.Getter          = getter;
                property.Setter          = setter;

                classEntity.Properties.Add(property);
            }

            // Ensure that availability is set on entity.
            entity.AdjustAvailability();
        }
        public EnumerationEntity Parse(TypedEntity typedEntity, String name, IEnumerable <XElement> elements)
        {
            EnumerationEntity enumerationEntity = new EnumerationEntity();

            XElement declarationElement = (from el in elements
                                           where el.Name == "div" &&
                                           el.Attribute("class") != null &&
                                           el.Attribute("class").Value == "declaration_indent"
                                           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 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();

            String declaration = declarationElement.TrimAll();
            String type        = "NOTYPE";
            String values      = String.Empty;

            bool result = this.SplitEnumeration(declaration, ref name, ref type, ref values);

            if (!result)
            {
                return(null);
            }

            enumerationEntity.Name      = name;
            enumerationEntity.BaseType  = type;
            enumerationEntity.Namespace = "MISSING";

            // 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))
                {
                    enumerationEntity.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))
            //        {
            //            enumerationEntity.Summary.Add(line);
            //        }
            //    }
            //}

            // Parse the values
            string[] pairs = values.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string pair in pairs)
            {
                if (String.Equals(pair.TrimAll(), String.Empty))
                {
                    continue;
                }

                String key;
                String value = String.Empty;
                if (pair.IndexOf('=') != -1)
                {
                    string[] parts = pair.Split(new [] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                    key   = parts [0].Trim();
                    value = parts [1].Trim();
                }
                else
                {
                    key = pair.Trim();
                }

                // Add a new value
                EnumerationValueEntity enumerationValueEntity = new EnumerationValueEntity();
                enumerationValueEntity.Name = key;

                if (value.Length == 6 && value.StartsWith("'") && value.EndsWith("'"))
                {
                    String v = value.Trim('\'');
                    enumerationValueEntity.Value = "0x" + FourCharToInt(v).ToString("X8");
                }
                else
                {
                    enumerationValueEntity.Value = value;
                }

                enumerationEntity.Values.Add(enumerationValueEntity);
            }

            XElement termList = parameterElement != null?parameterElement.Descendants("dl").FirstOrDefault() : null;

            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
                        EnumerationValueEntity enumerationValueEntity = enumerationEntity.Values.Find(p => String.Equals(p.Name, term));
                        if (enumerationValueEntity != null)
                        {
                            foreach (string sum in summaries)
                            {
                                enumerationValueEntity.Summary.Add(sum);
                            }
                        }
                    }
                }
            }

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

            return(enumerationEntity);
        }
        /// <summary>
        ///   Parses the specified property element.
        /// </summary>
        /// <param name = "propertyElement">The property element.</param>
        /// <returns></returns>
        public PropertyEntity Parse(TypedEntity typedEntity, XElement propertyElement)
        {
            XElement nameElement = propertyElement.Element("h3");
            String   name        = nameElement.TrimAll();

            // Extract the declaration
            XElement signatureElement = (from el in propertyElement.Elements("div")
                                         where (String)el.Attribute("class") == "declaration"
                                         select el).FirstOrDefault();
            // Extract the abstract
            XElement abstractElement = (from el in propertyElement.Elements("p")
                                        where (String)el.Attribute("class") == "abstract"
                                        select el).FirstOrDefault();

            //// Extract discussion
            //XElement discussionElement = (from el in propertyElement.Elements("div")
            //                              where (String) el.Attribute("class") == "api discussion"
            //                              select el).FirstOrDefault();

            // Get the availability
            XElement availabilityElement = (from el in propertyElement.Elements("div")
                                            where (String)el.Attribute("class") == "api availability"
                                            select el).FirstOrDefault();

            String signature = signatureElement.TrimAll();

            List <String> summary = new List <String>();

            summary.Add(abstractElement.TrimAll());

            //if (discussionElement != null)
            //{
            //    foreach (XElement paragraph in discussionElement.Elements("p"))
            //    {
            //        summary.Add(paragraph.TrimAll());
            //    }
            //}

            String minAvailability = availabilityElement.Elements("ul").Elements("li").FirstOrDefault().TrimAll();

            minAvailability = CommentHelper.ExtractAvailability(minAvailability);

            // Extract property's attribute
            List <String> attributes      = new List <String>();
            int           attributesStart = signature.IndexOf('(');
            int           attributesEnd   = signature.IndexOf(')');

            if (attributesStart > 0 && attributesEnd > attributesStart)
            {
                String attributesAll = signature.Substring(attributesStart + 1, attributesEnd - attributesStart - 1);
                attributes.AddRange(attributesAll.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(attr => attr.Trim()));
            }
            int    typeStart  = attributesEnd > 0 ? (attributesEnd + 1) : "@property".Length;
            int    typeEnd    = signature.LastIndexOf(name);
            string returnType = (typeStart > 0 && typeEnd > typeStart) ? signature.Substring(typeStart, typeEnd - typeStart).Trim() : "MISSING";

            // Is the property readonly ?
            bool readOnly = attributes.Contains("readonly");

            // Is there an explicit getter
            String getterSelector = attributes.Find(a => a.Contains("getter"));

            if (getterSelector != null)
            {
                getterSelector = getterSelector.Substring(getterSelector.IndexOf('=') + 1);
            }
            else
            {
                getterSelector = name;
            }

            // Alter the name
            name = name.UpperCaseFirstLetter();

            // Is there an explicit setter
            String setterSelector = attributes.Find(a => a.Contains("setter"));

            if (setterSelector != null)
            {
                setterSelector = setterSelector.Substring(setterSelector.IndexOf('=') + 1);
            }
            else
            {
                setterSelector = "set" + name + ":";
            }

            bool   isOut, isByRef, isBlock;
            String type = this.TypeManager.ConvertType(returnType, out isOut, out isByRef, out isBlock, this.Logger);

            PropertyEntity propertyEntity = new PropertyEntity();

            propertyEntity.MinAvailability = minAvailability;
            propertyEntity.Name            = getterSelector.UpperCaseFirstLetter();
            propertyEntity.Static          = false;
            propertyEntity.Summary         = summary;
            propertyEntity.Type            = type;

            propertyEntity.Getter           = new MethodEntity();
            propertyEntity.Getter.Signature = signature;
            propertyEntity.Getter.Selector  = getterSelector;

            if (readOnly)
            {
                propertyEntity.Setter = null;
            }
            else
            {
                propertyEntity.Setter           = new MethodEntity();
                propertyEntity.Setter.Signature = signature;
                propertyEntity.Setter.Selector  = setterSelector;
            }

            return(propertyEntity);
        }
        public PropertyEntity Parse(TypedEntity typedEntity, string name, IEnumerable <XElement> elements)
        {
            XElement declarationElement = (from el in elements
                                           where el.Name == "div" &&
                                           el.Attribute("class") != null &&
                                           el.Attribute("class").Value == "declaration_indent"
                                           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();

            String signature = declarationElement.TrimAll();

            // Extract abstract
            List <String>          summary          = new List <String>();
            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))
                {
                    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))
                    {
                        summary.Add(line);
                    }
                }
            }

            // Get the availability
            String minAvailability = "MISSING";

            if (availabilityElement != null)
            {
                minAvailability = CommentHelper.ExtractAvailability(availabilityElement.TrimAll());
            }

            // Extract property's attribute
            List <String> attributes      = new List <String>();
            int           attributesStart = signature.IndexOf('(');
            int           attributesEnd   = signature.IndexOf(')');

            if (attributesStart > 0 && attributesEnd > attributesStart)
            {
                String attributesAll = signature.Substring(attributesStart + 1, attributesEnd - attributesStart - 1);
                attributes.AddRange(attributesAll.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(attr => attr.Trim()));
            }
            int    typeStart  = attributesEnd > 0 ? (attributesEnd + 1) : "@property".Length;
            int    typeEnd    = signature.LastIndexOf(name);
            string returnType = (typeStart > 0 && typeEnd > typeStart) ? signature.Substring(typeStart, typeEnd - typeStart).Trim() : "MISSING";

            // Is the property readonly ?
            bool readOnly = attributes.Contains("readonly");

            // Is there an explicit getter
            String getterSelector = attributes.Find(a => a.Contains("getter"));

            if (getterSelector != null)
            {
                getterSelector = getterSelector.Substring(getterSelector.IndexOf('=') + 1);
            }
            else
            {
                getterSelector = name;
            }

            // Alter the name
            name = name.UpperCaseFirstLetter();

            // Is there an explicit setter
            String setterSelector = attributes.Find(a => a.Contains("setter"));

            if (setterSelector != null)
            {
                setterSelector = setterSelector.Substring(setterSelector.IndexOf('=') + 1);
            }
            else
            {
                setterSelector = "set" + name + ":";
            }

            bool   isOut, isByRef, isBlock;
            String type = this.TypeManager.ConvertType(returnType, out isOut, out isByRef, out isBlock, this.Logger);

            PropertyEntity propertyEntity = new PropertyEntity();

            propertyEntity.MinAvailability = minAvailability;
            propertyEntity.Name            = getterSelector.UpperCaseFirstLetter();
            propertyEntity.Static          = false;
            propertyEntity.Summary         = summary;
            propertyEntity.Type            = type;

            propertyEntity.Getter           = new MethodEntity();
            propertyEntity.Getter.Signature = signature;
            propertyEntity.Getter.Selector  = getterSelector;

            if (readOnly)
            {
                propertyEntity.Setter = null;
            }
            else
            {
                propertyEntity.Setter           = new MethodEntity();
                propertyEntity.Setter.Signature = signature;
                propertyEntity.Setter.Selector  = setterSelector;
            }

            return(propertyEntity);
        }
Example #12
0
        /// <summary>
        ///   Parses the specified method element.
        /// </summary>
        /// <param name = "methodElement">The method element.</param>
        /// <returns></returns>
        public MethodEntity Parse(TypedEntity typedEntity, XElement methodElement)
        {
            MethodEntity methodEntity = new MethodEntity();

            XElement selectorElement = methodElement.Element("h3");

            methodEntity.Selector = selectorElement.TrimAll();
            methodEntity.Name     = GetMethodName(methodEntity);

            this.Logger.WriteLine("  Method '" + methodEntity.Selector + "'");

            // Extract signature
            XElement signatureElement = (from el in methodElement.Elements("div")
                                         where (String)el.Attribute("class") == "declaration"
                                         select el).FirstOrDefault();

            methodEntity.Signature = signatureElement.TrimAll();
            methodEntity.Signature = methodEntity.Signature.TrimEnd(';');
            methodEntity.Signature = methodEntity.Signature.Replace(", ...", ",..."); // MethodParametersEnumerator needs this format

            methodEntity.Static = methodEntity.Signature.StartsWith("+");

            // Extract abstract
            XElement abstractElement = (from el in methodElement.Elements("p")
                                        where (String)el.Attribute("class") == "abstract"
                                        select el).FirstOrDefault();

            methodEntity.Summary.Add(abstractElement.TrimAll());

            //// Extract discussion
            //IEnumerable<XElement> paragraphs = (from el in methodElement.Elements("p").Elements("p")
            //                                    where (String) el.Parent.Attribute("class") == "api discussion"
            //                                    select el);
            //foreach (XElement paragraph in paragraphs)
            //{
            //    methodEntity.Summary.Add(paragraph.TrimAll());
            //}

            // Extract return type
            MethodSignatureEnumerator signatureEnumerator = new MethodSignatureEnumerator(methodEntity.Signature);

            if (signatureEnumerator.MoveNext())
            {
                methodEntity.ReturnType = this.TypeManager.ConvertType(signatureEnumerator.Current.TrimAll(), this.Logger);
            }
            else
            {
                methodEntity.ReturnType = "Id";
            }

            // Extract parameter type and name
            MethodParametersEnumerator parameterTypesEnumerator = new MethodParametersEnumerator(methodEntity.Signature, false);
            MethodParametersEnumerator parameterNamesEnumerator = new MethodParametersEnumerator(methodEntity.Signature, true);

            while (parameterTypesEnumerator.MoveNext() && parameterNamesEnumerator.MoveNext())
            {
                MethodParameterEntity parameterEntity = new MethodParameterEntity();
                bool isOut, isByRef, isBlock;
                parameterEntity.Type    = this.TypeManager.ConvertType(parameterTypesEnumerator.Current, out isOut, out isByRef, out isBlock, this.Logger);
                parameterEntity.IsOut   = isOut;
                parameterEntity.IsByRef = isByRef;
                parameterEntity.IsBlock = isBlock;
                parameterEntity.Name    = parameterNamesEnumerator.Current.Trim();
                methodEntity.Parameters.Add(parameterEntity);

                // Correct names that end in a single period
                if (parameterEntity.Name.EndsWith(".") && !parameterEntity.Name.EndsWith(".."))
                {
                    parameterEntity.Name = parameterEntity.Name.Substring(0, parameterEntity.Name.Length - 1);
                }

                // Handle variadic parameters
                Match r = VARARG_PARAMETER_REGEX.Match(parameterEntity.Name);
                if (r.Success)
                {
                    // Fix the last parameter name by removing "..."
                    parameterEntity.Name = r.Groups [1].Value.Trim();

                    // Add a new variadic parameter
                    parameterEntity      = new MethodParameterEntity();
                    parameterEntity.Type = "params Object[]";
                    parameterEntity.Name = "values";
                    parameterEntity.Summary.Add("Variable argument values");
                    methodEntity.Parameters.Add(parameterEntity);
                }
            }

            // Extract parameter documentation
            if (methodEntity.Parameters.Count > 0)
            {
                XElement termList = (from el in methodElement.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();
                            //String summary = ddList.ElementAt(i).TrimAll();
                            IEnumerable <String> summaries = ddList.ElementAt(i).Elements("p").Select(p => p.Value.TrimAll());

                            // Find the parameter
                            MethodParameterEntity parameterEntity = methodEntity.Parameters.Find(p => String.Equals(p.Name, term) || (VARARG_PARAMETER_REGEX.Match(term).Success&& term.StartsWith(p.Name)));
                            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 < methodEntity.Parameters.Count; i++)
            {
                methodEntity.Parameters[i].Name = this.TypeManager.ConvertName(methodEntity.Parameters[i].Name);
            }

            // Get the summary for return type
            if (!String.Equals(methodEntity.ReturnType, "void", StringComparison.OrdinalIgnoreCase))
            {
                IEnumerable <String> documentations = (from el in methodElement.Elements("div").Elements("p")
                                                       where (String)el.Parent.Attribute("class") == "return_value"
                                                       select el.Value.TrimAll());
                methodEntity.ReturnsDocumentation = String.Join(" ", documentations.ToArray());
            }

            // Get the availability
            String minAvailability = (from el in methodElement.Elements("div").Elements("ul").Elements("li")
                                      where (String)el.Parent.Parent.Attribute("class") == "api availability"
                                      select el.Value).FirstOrDefault();

            methodEntity.MinAvailability = CommentHelper.ExtractAvailability(minAvailability.TrimAll());

            return(methodEntity);
        }
        public MethodEntity Parse(TypedEntity typedEntity, String selector, IEnumerable <XElement> elements)
        {
            MethodEntity methodEntity = new MethodEntity();

            XElement declarationElement = (from el in elements
                                           where el.Name == "div" &&
                                           el.Attribute("class") != null &&
                                           el.Attribute("class").Value == "declaration_indent"
                                           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();

            methodEntity.Selector = selector;
            methodEntity.Name     = GetMethodName(methodEntity);

            methodEntity.Signature = declarationElement.TrimAll();
            methodEntity.Signature = methodEntity.Signature.TrimEnd(';');

            methodEntity.Static = methodEntity.Signature.StartsWith("+");

            // 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))
                {
                    methodEntity.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);
            //        }
            //    }
            //}

            // Extract return type
            MethodSignatureEnumerator signatureEnumerator = new MethodSignatureEnumerator(methodEntity.Signature);

            if (signatureEnumerator.MoveNext())
            {
                methodEntity.ReturnType = this.TypeManager.ConvertType(signatureEnumerator.Current.TrimAll(), this.Logger);
            }
            else
            {
                methodEntity.ReturnType = "Id";
            }

            // Extract parameter type and name
            MethodParametersEnumerator parameterTypesEnumerator = new MethodParametersEnumerator(methodEntity.Signature, false);
            MethodParametersEnumerator parameterNamesEnumerator = new MethodParametersEnumerator(methodEntity.Signature, true);

            while (parameterTypesEnumerator.MoveNext() && parameterNamesEnumerator.MoveNext())
            {
                MethodParameterEntity parameterEntity = new MethodParameterEntity();
                bool isOut, isByRef, isBlock;
                parameterEntity.Type    = this.TypeManager.ConvertType(parameterTypesEnumerator.Current, out isOut, out isByRef, out isBlock, this.Logger);
                parameterEntity.IsOut   = isOut;
                parameterEntity.IsByRef = isByRef;
                parameterEntity.IsBlock = isBlock;
                parameterEntity.Name    = parameterNamesEnumerator.Current.Trim();
                methodEntity.Parameters.Add(parameterEntity);
            }

            if (methodEntity.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 = methodEntity.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 < methodEntity.Parameters.Count; i++)
            {
                methodEntity.Parameters[i].Name = this.TypeManager.ConvertName(methodEntity.Parameters[i].Name);
            }

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

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

            return(methodEntity);
        }