/// <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>", "<para>", "</para>" }) { 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>", "<para>", "</para>" }) { 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>", "<remarks>", "</remarks>" }) { str = str.Replace(s, String.Empty); } entity.Summary.Add(str.Trim()); } else { entity.Summary.Add(c); } } }
/// <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 }); }
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); }
/// <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); }
/// <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); }