Exemplo n.º 1
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);
        }
Exemplo n.º 2
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);
        }