public void ParseCompoundDefElement(XmlElement e) { Symbol s = new Symbol(); s.id = e.GetAttribute("id"); s.kind = e.GetAttribute("kind"); s.visibilityLevel = ParseVisibilityLevel(e.GetAttribute("prot")); s.classMemberIndexTitle = s.name = GetXmlElementChildNodeValue(e, "compoundname"); // The "author" section. XmlElement author = e.FirstGrandChildElementOfTypeAndAttribute("simplesect", "kind", "author"); if (author != null) { s.author = author.InnerXml; author.ParentNode.RemoveChild(author); } s.briefDescription = GetXmlElementChildNodeValue(e, "briefdescription"); s.inbodyDescription = GetXmlElementChildNodeValue(e, "inbodydescription"); s.detailedDescription = GetXmlElementChildNodeValue(e, "detaileddescription"); symbols[s.id] = s; symbolsByName[s.name] = s; ProcessDocGeneratorCommentDirectives(s); foreach(XmlElement child in e.ChildNodes) { if (child.Name == "sectiondef") ParseSectionDefElement(s, child); } // Also has the following members: // <collaborationgraph> // <location> // <listofallmembers> // <includes> }
/// <summary> /// Goes through the given symbol and find all DocGenerator-style directives present in the comments /// and applies them. These directives are of form [foo]. /// </summary> private void ProcessDocGeneratorCommentDirectives(Symbol s) { // string[] comments = s.Comments(); string[] comments = new string[3] { s.briefDescription, s.detailedDescription, s.inbodyDescription }; for (int i = 0; i < comments.Length; ++i) { comments[i] = comments[i].Trim(); if (comments[i].EndsWith("<br/>")) comments[i] = comments[i].Substring(0, comments[i].Length - 5); if (comments[i].EndsWith("<br />")) comments[i] = comments[i].Substring(0, comments[i].Length - 6); comments[i] = comments[i].Trim(); int endIdx; int startIndex = 0; while (startIndex < comments[i].Length) { string directive = FindStringInBetween(comments[i], startIndex, "[", "]", out endIdx); if (endIdx == -1) break; int directiveStartIndex = endIdx - directive.Length - 1; directive = directive.Trim(); string[] st = directive.Split(':'); string directiveParam = ""; if (st.Length == 2) directiveParam = st[1].Trim(); if (directive.ToLower().StartsWith("similaroverload") && directiveParam.Length > 0) { Symbol similarOverloadSymbol = s.parent.FindChildByName(directiveParam); if (similarOverloadSymbol != null) { if (s.similarOverload == null) { s.similarOverload = similarOverloadSymbol; similarOverloadSymbol.otherOverloads.Add(s); } } else { // Console.WriteLine("Can't find similarOverload " + directiveParam + " for member " + s.FullQualifiedSymbolName()); } comments[i] = CutDocGeneratorCommentDirective(comments[i], directiveStartIndex - 1, endIdx + 1 - directiveStartIndex); startIndex = 0; // Don't update startIndex since we deleted the "[]" block. } else if (directive.ToLower().StartsWith("indextitle") && directiveParam.Length > 0) { s.classMemberIndexTitle = directiveParam; comments[i] = CutDocGeneratorCommentDirective(comments[i], directiveStartIndex - 1, endIdx + 1 - directiveStartIndex); startIndex = 0; } else if (directive.ToLower().StartsWith("hideindex")) { s.classMemberIndexTitle = ""; comments[i] = CutDocGeneratorCommentDirective(comments[i], directiveStartIndex - 1, endIdx + 1 - directiveStartIndex); startIndex = 0; } else if (directive.ToLower().StartsWith("category")) { s.documentationCategory = directiveParam; comments[i] = CutDocGeneratorCommentDirective(comments[i], directiveStartIndex - 1, endIdx + 1 - directiveStartIndex); startIndex = 0; } else if (directive.ToLower().StartsWith("groupsyntax")) { s.groupSyntax = true; comments[i] = CutDocGeneratorCommentDirective(comments[i], directiveStartIndex - 1, endIdx + 1 - directiveStartIndex); startIndex = 0; } else { startIndex = endIdx; } } } s.briefDescription = comments[0]; s.detailedDescription = comments[1]; s.inbodyDescription = comments[2]; }
public void ParseSectionDefElement(Symbol parent, XmlElement e) { foreach(XmlElement child in e.ChildNodes) { if (child.Name == "memberdef") { Symbol member = new Symbol(); member.parent = parent; member.id = child.GetAttribute("id"); member.kind = child.GetAttribute("kind"); member.visibilityLevel = ParseVisibilityLevel(child.GetAttribute("prot")); member.isStatic = (child.GetAttribute("static") == "yes"); member.isConst = (child.GetAttribute("const") == "yes"); member.isMutable = (child.GetAttribute("mutable") == "yes"); member.isExplicit = (child.GetAttribute("explicit") == "yes"); member.virtualness = ParseVirtualness(child.GetAttribute("virt")); member.type = GetXmlElementChildNodeValue(child, "type", true); member.fullDefinition = GetXmlElementChildNodeValue(child, "definition"); member.argList = GetXmlElementChildNodeValue(child, "argsstring"); // Sanitate return type of certain MathGeoLib constructs if (member.kind == "function") { member.type = member.type.Replace("CONST_WIN32", ""); member.type = member.type.Replace("MUST_USE_RESULT", ""); } member.classMemberIndexTitle = member.name = GetXmlElementChildNodeValue(child, "name"); if (member.name.StartsWith("@")) continue; // Doxygen creates items with names starting with '@' at least for unnamed unions, ignore those altogether. symbols[member.id] = member; //symbolsByName[member.name] = member; parent.children.Add(member); // Function parameters. foreach(XmlElement param in child.ChildNodes.OfType<XmlElement>()) if (param.Name == "param") { Parameter p = new Parameter(); if (member.kind == "define") // This is a #define macro. { p.type = ""; p.name = GetXmlElementChildNodeValue(param, "defname"); } else // This is a real function { p.type = GetXmlElementChildNodeValue(param, "type", true); p.name = GetXmlElementChildNodeValue(param, "declname"); p.defaultValue = GetXmlElementChildNodeValue(param, "defval", true); } member.parameters.Add(p); } // Enum special handling if (member.kind == "enum") { int lastEnumInitializer = -1; foreach (XmlElement value in child.ChildNodes.OfType<XmlElement>()) { if (value.Name == "enumvalue") { Symbol valueSymbol = new Symbol(); valueSymbol.parent = member; valueSymbol.id = value.GetAttribute("id"); valueSymbol.name = GetXmlElementChildNodeValue(value, "name", true); valueSymbol.kind = "enumvalue"; valueSymbol.value = GetXmlElementChildNodeValue(value, "initializer", true).Replace("= ", ""); if (valueSymbol.value.Length == 0) { ++lastEnumInitializer; valueSymbol.value = lastEnumInitializer.ToString(); } else Int32.TryParse(valueSymbol.value, out lastEnumInitializer); member.children.Add(valueSymbol); } } enumsByName[member.name] = member; } // If this is a #define macro, get the macro body code. if (member.kind == "define") { member.macroBody = GetXmlElementChildNodeValue(child, "initializer"); // Create the argList from scratch, because it is not present in the xml in same form than for functions. member.argList = member.ArgStringWithoutTypes(); } // Function parameter comments. List<XmlElement> parameters = child.AllGrandChildElementsOfTypeAndAttribute("parameterlist", "kind", "param"); if (parameters != null && parameters.Count > 0) { foreach (XmlElement paramNode in parameters.OfType<XmlElement>()) { foreach (XmlElement param in paramNode.ChildNodes.OfType<XmlElement>()) { if (param.Name == "parameteritem") { string paramName = param.FirstChildElementOfType("parameternamelist").FirstChildElementOfType("parametername").InnerText.Trim(); Parameter p = member.FindParamByName(paramName); if (p != null) p.comment = param.FirstChildElementOfType("parameterdescription").InnerText; } } // Remove the parameterlist from the detailed description node so that it won't appear in the 'detailedDescription' documentation string. // The detailed description is created manually. paramNode.ParentNode.RemoveChild(paramNode); } } // TODOs ^ BUGs List<XmlElement> xrefsects = child.AllGrandChildElementsOfType("xrefsect"); if (xrefsects != null) { foreach (XmlElement elem in xrefsects) { if (GetXmlElementChildNodeValue(elem, "xreftitle") == "Todo") member.todos.Add(GetXmlElementChildNodeValue(elem, "xrefdescription")); if (GetXmlElementChildNodeValue(elem, "xreftitle") == "Bug") member.bugs.Add(GetXmlElementChildNodeValue(elem, "xrefdescription")); elem.ParentNode.RemoveChild(elem); } } // @notes. List<XmlElement> notesects = child.AllGrandChildElementsOfTypeAndAttribute("simplesect", "kind", "note"); if (notesects != null) { foreach (XmlElement elem in notesects) { member.notes.Add(elem.InnerText); elem.ParentNode.RemoveChild(elem); } } // Function return value. XmlElement retVal = child.FirstGrandChildElementOfTypeAndAttribute("simplesect", "kind", "return"); if (retVal != null) { member.returnComment = retVal.InnerText; retVal.ParentNode.RemoveChild(retVal); } // The "see also" section. XmlElement see = child.FirstGrandChildElementOfTypeAndAttribute("simplesect", "kind", "see"); if (see != null) { member.seeAlsoDocumentation = see.InnerXml; see.ParentNode.RemoveChild(see); } member.briefDescription = GetXmlElementChildNodeValue(child, "briefdescription").Trim(); member.inbodyDescription = GetXmlElementChildNodeValue(child, "inbodydescription").Trim(); member.detailedDescription = GetXmlElementChildNodeValue(child, "detaileddescription").Trim(); XmlElement loc = child.FirstChildElementOfType("location"); if (loc != null) { member.sourceFilename = loc.GetAttribute("bodyfile"); int.TryParse(loc.GetAttribute("bodystart"), out member.sourceFileStartLine); int.TryParse(loc.GetAttribute("bodyend"), out member.sourceFileEndLine); if (member.sourceFileEndLine == -1) member.sourceFileEndLine = member.sourceFileStartLine; } ProcessDocGeneratorCommentDirectives(member); ///\todo Add location. } } }
void GroupSimilarOverloads(Symbol s) { for(int i = 0; i < s.children.Count; ++i) for(int j = i+1; j < s.children.Count; ++j) { Symbol master = s.children[i]; Symbol child = s.children[j]; if (master.similarOverload == null && child.similarOverload == null && child.otherOverloads.Count == 0) { if (master.name == child.name) { if (child.Comments().Length == 0 || child.groupSyntax) { child.similarOverload = master; master.otherOverloads.Add(child); } else break; } } } }