/// <summary> /// This method parses comments from C# XML documentation into the appropriate /// cHelpText properties. /// </summary> /// <returns></returns> public bool ParseXmlProperties(DotnetObject PassedObject) { string xPath; DotnetObject Object; XmlDocument oDom = new XmlDocument(); try { oDom.Load("file://" + cXmlFilename); } catch (Exception ex) { cErrorMsg = "Unable to load XML Documentation file." + ex.Message; return(false); } // *** Get object descriptions for (int Objs = 0; Objs < nObjectCount; Objs++) { XmlNode Match = null; XmlNode SubMatch = null; if (PassedObject == null) { Object = aObjects[Objs]; } else { Object = PassedObject; Objs = nObjectCount - 1; } if (PassedObject != null && PassedObject.Name.ToLower() != Object.Name.ToLower()) { continue; } try { Match = oDom.SelectSingleNode("/doc/members/member[@name='" + "T:" + Object.RawSignature + "']"); Object.HelpText = GetNodeValue(Match, "summary"); Object.Remarks = GetNodeValue(Match, "remarks"); Object.Example = GetExampleCode(Match); Object.SeeAlso = FixupSeeAlsoLinks(ref Object.HelpText) + FixupSeeAlsoLinks(ref Object.Remarks); Object.Contract = GetContracts(Match); Match = null; } catch (Exception ex) { string lcError = ex.Message; } // *** Loop through the methods for (int lnMethods = 0; lnMethods < Object.MethodCount; lnMethods++) { ObjectMethod method = Object.Methods[lnMethods]; // *** Strip off empty method parens string methodSignature = method.Signature.Replace("()", ""); // *** Replace Reference of Reflection for the one use by XML docs methodSignature = methodSignature.Replace("&", "@"); if (method.RawParameters == "") { xPath = "/doc/members/member[@name='" + "M:" + methodSignature + "']"; // .cNamespace + "." + loObject.cName + "." + loMethod.cName + "']"; } else { xPath = "/doc/members/member[@name='" + "M:" + methodSignature + "']"; } // "M:" + loObject.cNamespace + "." + loObject.cName + "." + loMethod.cName + // "(" + loMethod.cRawParameters + ")']"; try { Match = oDom.SelectSingleNode(xPath); if (Match == null) { continue; } method.HelpText = GetNodeValue(Match, "summary"); method.Remarks = GetNodeValue(Match, "remarks"); method.Example = GetExampleCode(Match); method.Contract = GetContracts(Match); method.SeeAlso = FixupSeeAlsoLinks(ref method.HelpText) + FixupSeeAlsoLinks(ref method.Remarks); //this.GetNodeValue(Match, "example"); // *** Only update returns if the return comment is actually set // *** Otherwise leave the type intact method.ReturnDescription = GetNodeValue(Match, "returns"); // *** Parse the parameters string lcParmDescriptions = ""; for (int x = 0; x < method.ParameterCount; x++) { string parm = method.ParameterList[x].Trim(); lcParmDescriptions = lcParmDescriptions + "**" + parm + "** \r\n"; SubMatch = Match.SelectSingleNode("param[@name='" + parm + "']"); if (SubMatch != null) { string lcValue = SubMatch.InnerText; if (lcValue.Length > 0) { lcValue = lcValue.Trim(' ', '\t', '\r', '\n'); lcParmDescriptions = lcParmDescriptions + lcValue + "\r\n\r\n"; } else { // empty line lcParmDescriptions = lcParmDescriptions + "\r\n"; } } } method.DescriptiveParameters = lcParmDescriptions; string Exceptions = ""; XmlNodeList ExceptionMatches = null; try { ExceptionMatches = Match.SelectNodes("exception"); } catch {; } if (ExceptionMatches != null) { foreach (XmlNode Node in ExceptionMatches) { XmlAttribute Ref = Node.Attributes["cref"]; if (Ref != null) { Exceptions += "**" + Ref.Value.Replace("T:", "").Replace("!:", "") + "** \r\n"; } if (!string.IsNullOrEmpty(Node.InnerText)) { Exceptions += GetNodeValue(Node, "") + "\r\n"; } Exceptions += "\r\n"; } method.Exceptions = Exceptions.TrimEnd('\r', '\n'); } Match = null; } catch (Exception ex) { string lcError = ex.Message; } } // for methods // *** Loop through the properties for (int lnFields = 0; lnFields < Object.PropertyCount; lnFields++) { ObjectProperty property = Object.Properties[lnFields]; string fieldPrefix = "F:"; if (property.FieldOrProperty != "Field") { fieldPrefix = "P:"; } xPath = "/doc/members/member[@name='" + fieldPrefix + property.Signature + "']"; Match = oDom.SelectSingleNode(xPath); property.HelpText = GetNodeValue(Match, "summary"); property.Remarks = GetNodeValue(Match, "remarks"); property.Example = GetExampleCode(Match); property.Contract = GetContracts(Match); property.SeeAlso = FixupSeeAlsoLinks(ref property.HelpText) + FixupSeeAlsoLinks(ref property.Remarks); string value = GetNodeValue(Match, "value"); if (!string.IsNullOrEmpty(value)) { property.DefaultValue = value; } Match = null; } // for properties // *** Loop through the fields for (int lnFields = 0; lnFields < Object.EventCount; lnFields++) { ObjectEvent loEvent = Object.Events[lnFields]; string lcFieldPrefix = "E:"; xPath = "/doc/members/member[@name='" + lcFieldPrefix + loEvent.Signature + "']"; Match = oDom.SelectSingleNode(xPath); loEvent.HelpText = GetNodeValue(Match, "summary"); loEvent.Remarks = GetNodeValue(Match, "remarks"); loEvent.Example = GetExampleCode(Match); loEvent.SeeAlso = FixupSeeAlsoLinks(ref loEvent.HelpText) + FixupSeeAlsoLinks(ref loEvent.Remarks); Match = null; } // for events } // for objects return(true); } // ParseXMLProperties (method)
private void ParseMethodsOnType(DotnetObject dotnetObject, Collection <MethodDefinition> methods, TypeDefinition dotnetType) { var methodList = new List <ObjectMethod>(); foreach (var mi in methods) { var meth = new ObjectMethod(); var miRef = mi.GetElementMethod(); if (NoInheritedMembers && miRef.DeclaringType != dotnetType) { continue; } meth.Name = mi.Name; if (meth.Name.StartsWith("<") || mi.IsGetter || mi.IsSetter || mi.IsAddOn || mi.IsRemoveOn || mi.IsPrivate) { continue; } meth.Classname = mi.DeclaringType.Name; if (mi.IsConstructor) { // no static or base class constructors if (mi.IsStatic || mi.DeclaringType.FullName != dotnetObject.TypeDefinition.FullName) { continue; // don't document static constructors } meth.IsConstructor = true; meth.Name = dotnetObject.Name; } if (mi.IsPublic) { meth.Scope = "public"; } // TODO: Internal Protected needs to be addressed else if (mi.IsAssembly || mi.IsFamilyOrAssembly) { meth.Scope = "internal"; meth.Internal = true; } else if (mi.IsPrivate) { meth.Scope = "private"; } if (mi.IsAbstract) { meth.Other += "abstract "; } if (mi.IsVirtual && !mi.IsAbstract) { meth.Other += "virtual "; } if (mi.IsStatic) { meth.Static = mi.IsStatic; meth.Other += "static "; } if (mi.IsFinal) { meth.Other += "sealed "; } if (mi.HasGenericParameters || mi.ContainsGenericParameter) { meth.GenericParameters = "<"; var genericParms = miRef.GenericParameters; foreach (var genericArg in genericParms) { meth.GenericParameters += genericArg.Name + ","; } meth.GenericParameters = meth.GenericParameters.TrimEnd(','); meth.GenericParameters += ">"; if (meth.GenericParameters == "<>") { meth.GenericParameters = ""; } } foreach (var parm in mi.Parameters) { var methodParm = new MethodParameter(); methodParm.Name = parm.Name; if (methodParm.Name.EndsWith("&")) { methodParm.Other = "ref "; methodParm.Name = methodParm.Name.TrimEnd('&'); } methodParm.ShortTypeName = FixupStringTypeName(parm.ParameterType.Name); if (parm.ParameterType.IsGenericInstance) { methodParm.ShortTypeName = DotnetObject.GetGenericTypeName(parm.ParameterType.GetElementType(), GenericTypeNameFormats.TypeName); } methodParm.Type = parm.ParameterType.FullName; meth.ParameterList.Add(methodParm); } meth.ReturnType = mi.ReturnType.FullName; var simpleRetName = mi.ReturnType.Name; if (!mi.ReturnType.IsGenericParameter) { simpleRetName = FixupStringTypeName(simpleRetName); } var sbSyntax = new StringBuilder(); sbSyntax.Append($"{dotnetObject.Scope} {dotnetObject.Other} {simpleRetName} {meth.Name}{meth.GenericParameters}("); var parmCounter = 0; foreach (var parm in meth.ParameterList) { sbSyntax.Append($"{parm.ShortTypeName} {parm.Name}, "); parmCounter++; if (parmCounter % 2 == 0) { sbSyntax.Append("\r\n\t\t\t"); } } meth.Syntax = sbSyntax.ToString(); meth.Syntax = meth.Syntax.TrimEnd(' ', ',', '\r', '\n', '\t') + ")"; meth.Syntax = meth.Syntax.Replace(" ", " ").Replace(" ", " "); if (meth.IsConstructor) { meth.Signature = mi.DeclaringType.FullName + ".#ctor"; } string parameters = ""; string rawParameters = ""; meth.Signature = mi.FullName; // strip off return type var idx = meth.Signature.IndexOf(' '); if (idx > -1) { meth.Signature = meth.Signature.Substring(idx).TrimStart(); } // fix up ctor meth.Signature = meth.Signature.Replace("::.ctor", ".#ctor"); // fix up object member syntax and double conversions meth.Signature = meth.Signature .Replace("::", ".") .Replace("..", ".") .Trim(); // fix up parameters if (meth.Signature.EndsWith("()")) { // no parms has no parens ie. .method meth.Signature = meth.Signature.Substring(0, meth.Signature.Length - 2); } else { // fix up parameters for generics // from: .method(System.Collections.Generic.IDictionary`2(System.String,System.Object),System.String) // to: .method(System.Collections.Generic.IDictionary{System.String,System.Object},System.String) var origParms = StringUtils.ExtractString(meth.Signature, "(", ")", returnDelimiters: true); var newParms = origParms; if (origParms.Contains("`")) { var regEx = new Regex("`.*?<(.*?)>"); var matches = regEx.Matches(meth.Signature); foreach (Match match in matches) { var orig = match.Value; var type = match.Groups[1].Value; newParms = newParms.Replace(orig, "{" + type + "}"); } } if (!newParms.Equals(origParms)) { meth.Signature = meth.Signature.Replace(origParms, newParms); } } methodList.Add(meth); } dotnetObject.AllMethods.AddRange(methodList .OrderBy(ml => !ml.IsConstructor) .ThenBy(ml => ml.Name.ToLowerInvariant())); }