Author: jonpryor
Date: 2007-06-14 14:30:56 -0400 (Thu, 14 Jun 2007)
New Revision: 79600

Modified:
   trunk/monodoc/tools/ChangeLog
   trunk/monodoc/tools/monodocer.cs
Log:
  * monodocer.cs: Use XPathDocument instead of XmlDocument to process the ECMA
    documentation import.  This cuts down a -type:System.Array import from
    ~15-20s to ~10-12s (not great, bug better).  Fix importing of <exception/>
    elements -- previously we would skip them if the mono docs lacked them.


Modified: trunk/monodoc/tools/ChangeLog
===================================================================
--- trunk/monodoc/tools/ChangeLog       2007-06-14 18:25:09 UTC (rev 79599)
+++ trunk/monodoc/tools/ChangeLog       2007-06-14 18:30:56 UTC (rev 79600)
@@ -1,3 +1,10 @@
+2007-06-14  Jonathan Pryor  <[EMAIL PROTECTED]>
+
+       * monodocer.cs: Use XPathDocument instead of XmlDocument to process the 
ECMA
+         documentation import.  This cuts down a -type:System.Array import from
+         ~15-20s to ~10-12s (not great, bug better).  Fix importing of 
<exception/>
+         elements -- previously we would skip them if the mono docs lacked 
them.
+
 2007-06-12  Jonathan Pryor  <[EMAIL PROTECTED]>
 
        * monodocer.cs: The previous fix was buggy -- if the type parameters 
were

Modified: trunk/monodoc/tools/monodocer.cs
===================================================================
--- trunk/monodoc/tools/monodocer.cs    2007-06-14 18:25:09 UTC (rev 79599)
+++ trunk/monodoc/tools/monodocer.cs    2007-06-14 18:30:56 UTC (rev 79600)
@@ -11,6 +11,7 @@
 using System.Text;
 using System.Reflection;
 using System.Xml;
+using System.Xml.XPath;
 
 using Mono.GetOptions;
 
@@ -37,7 +38,7 @@
 
        static string name;
        static XmlDocument slashdocs;
-       static XmlDocument ecmadocs;
+       static XPathNavigator ecmadocs;
 
        static string since;
 
@@ -149,8 +150,8 @@
                        
                        if (opts.importecmadoc != null) {
                                try {
-                                       ecmadocs = new XmlDocument();
-                                       ecmadocs.Load(opts.importecmadoc);
+                                       XmlTextReader reader = new 
XmlTextReader (opts.importecmadoc);
+                                       ecmadocs = new XPathDocument 
(reader).CreateNavigator ();
                                } catch (Exception e) {
                                        Console.Error.WriteLine("Could not load 
XML file: " + e.Message);
                                        Environment.ExitCode = 1;
@@ -326,7 +327,7 @@
                        throw new InvalidOperationException("Error loading " + 
typefile + ": " + e.Message, e);
                }
                
-               XmlNode ecmaDocsType = GetEcmaDocsType (basefile);
+               XPathNavigator ecmaDocsType = GetEcmaDocsType (basefile);
                if (dest == null) {
                        DoUpdateType2(basefile, type, typefile, ecmaDocsType);
                } else if (dest == "-") {
@@ -336,32 +337,47 @@
                }       
        }
 
-       private static XmlNode GetEcmaDocsType (XmlNode source)
+       private static XPathNavigator GetEcmaDocsType (IXPathNavigable source)
        {
                return GetEcmaDocsMember ("//[EMAIL PROTECTED]"{0}\"]", source, 
"//Type/@FullName");
        }
 
-       private static XmlNode GetEcmaDocsType (Type type)
+       private static XPathNavigator GetEcmaDocsType (Type type)
        {
                return GetEcmaDocsMember ("//[EMAIL PROTECTED]"" + 
type.FullName + "\"]");
        }
        
-       private static XmlNode GetEcmaDocsMember (string xpathFormat, XmlNode 
source, params string[] args)
+       private static XPathNavigator GetEcmaDocsMember (string xpathFormat, 
IXPathNavigable source, params string[] args)
        {
                if (ecmadocs == null)
                        return null;
                string [] nargs = new string [args.Length];
+               XPathNavigator nav = source.CreateNavigator ();
                for (int i = 0; i < nargs.Length; ++i) {
-                       nargs [i] = source.SelectSingleNode (args [i]).Value;
+                       nargs [i] = SelectSingleNode (nav, args [i]).Value;
                }
-               return ecmadocs.SelectSingleNode (string.Format (xpathFormat, 
nargs));
+               return SelectSingleNode (ecmadocs, string.Format (xpathFormat, 
nargs));
        }
 
-       private static XmlNode GetEcmaDocsMember (string xpath)
+       private static XPathNavigator SelectSingleNode (XPathNavigator n, 
string xpath)
        {
+#if !NET_1_0
+               return n.SelectSingleNode (xpath);
+#else
+               XPathNodeIterator i = n.Select (xpath);
+               XPathNavigator r = null;
+               while (i.MoveNext ()) {
+                       r = i.Current;
+               }
+               return r;
+#endif
+       }
+
+       private static XPathNavigator GetEcmaDocsMember (string xpath)
+       {
                if (ecmadocs == null)
                        return null;
-               return ecmadocs.SelectSingleNode (xpath);
+               return SelectSingleNode (ecmadocs, xpath);
        }
 
        public static void DoUpdateNS(string ns, string nspath, string outpath) 
{
@@ -611,7 +627,7 @@
                }
        }
                
-       public static void DoUpdateType2(XmlDocument basefile, Type type, 
string output, XmlNode ecmaDocsType) {
+       public static void DoUpdateType2(XmlDocument basefile, Type type, 
string output, XPathNavigator ecmaDocsType) {
                Console.Error.WriteLine("Updating: " + type.FullName);
                
                Hashtable seenmembers = new Hashtable();
@@ -710,43 +726,56 @@
                writer.Close();
        }
 
-       private static DocsEnumerable GetDocumentationMembers (XmlDocument 
basefile, Type type, XmlNode ecmaDocsType)
+       private static DocsEnumerable GetDocumentationMembers (XmlDocument 
basefile, Type type, XPathNavigator ecmaDocsType)
        {
-               if (ecmadocs == null) {
-                       foreach (XmlElement oldmember in 
basefile.SelectNodes("Type/Members/Member")) {
-                               MemberInfo m = GetMember (type, oldmember);
-                               if (m == null) {
-                                       Console.Error.WriteLine ("Could not 
find MemberInfo for `{0}'s member `{1}'.", 
-                                                       type.FullName, 
-                                                       
oldmember.SelectSingleNode ("[EMAIL PROTECTED]"C#\"]/@Value").Value);
-                                       continue;
+               if (ecmadocs != null) {
+                       XPathNodeIterator iter = ecmaDocsType.Select 
("Members/Member");
+                       while (iter.MoveNext ()) {
+                               XPathNavigator ecmaDocsMember = iter.Current;
+                               string xp = GetXPathForMember (ecmaDocsMember);
+                               XmlElement oldmember = (XmlElement) 
basefile.SelectSingleNode (xp);
+                               MemberInfo m;
+                               if (oldmember == null) {
+                                       m = GetMember (type, ecmaDocsMember);
+                                       if (m == null) {
+                                               Console.Error.WriteLine ("Could 
not import ECMA docs for `{1}'s `{0}': MemberInfo not found.",
+                                                               
SelectSingleNode (ecmaDocsMember, "[EMAIL PROTECTED]"C#\"]/@Value").Value, 
type.FullName);
+                                               continue;
+                                       }
+                                       // oldmember lookup may have failed due 
to type parameter renames.
+                                       // Try again.
+                                       oldmember = (XmlElement) 
basefile.SelectSingleNode (GetXPathForMember (m));
+                                       if (oldmember == null) {
+#if NET_1_0
+                                               throw new 
InvalidOperationException (".NET 1.0 doesn't have XPathNavigator.InnerXml!");
+#else
+                                               oldmember = 
WriteElement(basefile.DocumentElement, "Type/Members/Member");
+                                               CopyNode (ecmaDocsMember.Clone 
(), oldmember);
+#endif
+                                       }
                                }
-                               yield return new DocsNodeInfo (oldmember, 
GetMember (type, oldmember));
+                               else {
+                                       oldmember.SetAttribute 
("__monodocer-seen__", "true");
+                                       m = GetMember (type, 
oldmember.CreateNavigator ());
+                               }
+                               DocsNodeInfo node = new DocsNodeInfo 
(oldmember, m);
+                               node.EcmaDocs = SelectSingleNode 
(ecmaDocsMember, "Docs");
+                               yield return node;
                        }
-                       yield break;
                }
-               foreach (XmlElement ecmaDocsMember in ecmaDocsType.SelectNodes 
("Members/Member")) {
-                       string xp = GetXPathForMember (ecmaDocsMember);
-                       XmlElement oldmember = (XmlElement) 
basefile.SelectSingleNode (xp);
-                       MemberInfo m;
-                       if (oldmember == null) {
-                               m = GetMember (type, ecmaDocsMember);
-                               if (m == null) {
-                                       Console.Error.WriteLine ("Could not 
import ECMA docs for `{1}'s `{0}': MemberInfo not found.",
-                                                       
ecmaDocsMember.SelectSingleNode ("[EMAIL PROTECTED]"C#\"]/@Value").Value, 
type.FullName);
-                                       continue;
-                               }
-                               // oldmember lookup may have failed due to type 
parameter renames.
-                               // Try again.
-                               oldmember = (XmlElement) 
basefile.SelectSingleNode (GetXPathForMember (m));
-                               if (oldmember == null)
-                                       oldmember = (XmlElement) CopyNode 
(ecmaDocsMember, basefile.SelectSingleNode ("/Type/Members"));
+               foreach (XmlElement oldmember in 
basefile.SelectNodes("Type/Members/Member")) {
+                       if (oldmember.GetAttribute ("__monodocer-seen__") == 
"true") {
+                               oldmember.RemoveAttribute 
("__monodocer-seen__");
+                               continue;
                        }
-                       else
-                               m = GetMember (type, oldmember);
-                       DocsNodeInfo node = new DocsNodeInfo (oldmember, m);
-                       node.EcmaDocs = ecmaDocsMember.SelectSingleNode 
("Docs");
-                       yield return node;
+                       MemberInfo m = GetMember (type, 
oldmember.CreateNavigator ());
+                       if (m == null) {
+                               Console.Error.WriteLine ("Could not find 
MemberInfo for `{0}'s member `{1}'.", 
+                                               type.FullName, 
+                                               oldmember.SelectSingleNode 
("[EMAIL PROTECTED]"C#\"]/@Value").Value);
+                               continue;
+                       }
+                       yield return new DocsNodeInfo (oldmember, m);
                }
        }
        
@@ -780,30 +809,32 @@
        // UPDATE HELPER FUNCTIONS      
        
        private static XmlElement FindMatchingMember(Type type, XmlElement 
newfile, XmlElement oldmember) {
-               MemberInfo oldmember2 = GetMember(type, oldmember);
+               MemberInfo oldmember2 = GetMember(type, 
oldmember.CreateNavigator ());
                if (oldmember2 == null) return null;
                
                string membername = oldmember.GetAttribute("MemberName");
                foreach (XmlElement newmember in 
newfile.SelectNodes("Members/[EMAIL PROTECTED]'" + membername + "']")) {
-                       if (GetMember(type, newmember) == oldmember2) return 
newmember;
+                       if (GetMember(type, newmember.CreateNavigator ()) == 
oldmember2) return newmember;
                }
                
                return null;
        }
        
-       private static MemberInfo GetMember(Type type, XmlElement member) {
-               string membertype = 
member.SelectSingleNode("MemberType").InnerText;
+       private static MemberInfo GetMember(Type type, XPathNavigator member) {
+               string membertype = SelectSingleNode(member, 
"MemberType").Value;
                
                string returntype = null;
-               XmlNode returntypenode = 
member.SelectSingleNode("ReturnValue/ReturnType");
-               if (returntypenode != null) returntype = 
returntypenode.InnerText;
+               XPathNavigator returntypenode = SelectSingleNode(member, 
"ReturnValue/ReturnType");
+               if (returntypenode != null) returntype = returntypenode.Value;
                
                // Get list of parameter types for member
                ArrayList memberparams = new ArrayList();
-               foreach (XmlElement param in 
member.SelectNodes("Parameters/Parameter"))
-                       memberparams.Add(param.GetAttribute("Type"));
+               XPathNodeIterator iter = member.Select ("Parameters/Parameter");
+               while (iter.MoveNext ()) {
+                       memberparams.Add(iter.Current.GetAttribute("Type", ""));
+               }
 
-               string docName = member.GetAttribute ("MemberName");
+               string docName = member.GetAttribute ("MemberName", "");
                string[] docTypeParams = GetTypeParameters (docName);
 
                // Loop through all members in this type with the same name
@@ -977,7 +1008,7 @@
        
        // CREATE A STUB DOCUMENTATION FILE     
 
-       public static XmlElement StubType(Type type, XmlNode ecmaDocsType) {
+       public static XmlElement StubType(Type type, XPathNavigator 
ecmaDocsType) {
                string typesig = MakeTypeSignature(type);
                if (typesig == null) return null; // not publicly visible
                
@@ -1003,7 +1034,7 @@
        
        // STUBBING/UPDATING FUNCTIONS
        
-       public static void UpdateType(XmlElement root, Type type, bool 
addmembers, XmlNode ecmaDocsType) {
+       public static void UpdateType(XmlElement root, Type type, bool 
addmembers, XPathNavigator ecmaDocsType) {
                root.SetAttribute("Name", GetDocTypeName (type));
                root.SetAttribute("FullName", GetDocTypeFullName (type));
 
@@ -1221,6 +1252,21 @@
                return copy;
        }
 
+       private static XmlElement CopyNode (XPathNavigator source, XmlElement 
dest)
+       {
+#if NET_1_0
+               throw new NotSupportedException ("Who cares about .NET 1.0?");
+#else
+               dest.InnerXml = source.InnerXml;
+               if (source.MoveToFirstAttribute ()) {
+                       do {
+                               dest.SetAttribute (source.Name, source.Value);
+                       } while (source.MoveToNextAttribute ());
+               }
+               return dest;
+#endif
+       }
+
        private static void WriteElementInitialText(XmlElement parent, string 
element, string value) {
                XmlElement node = (XmlElement)parent.SelectSingleNode(element);
                if (node != null)
@@ -1292,13 +1338,14 @@
                if (addremarks)
                        WriteElementInitialText(e, "remarks", "To be added.");
                
+#if !NET_1_0
                if (info.EcmaDocs != null) {
-                       foreach (XmlNode child in info.EcmaDocs.ChildNodes) {
+                       foreach (XPathNavigator child in 
info.EcmaDocs.SelectChildren (XPathNodeType.Element)) {
                                switch (child.Name) {
                                        case "param":
                                        case "typeparam": {
                                                XmlNode doc = 
e.SelectSingleNode (
-                                                               child.Name + 
"[EMAIL PROTECTED]'" + child.Attributes ["name"].Value + "']");
+                                                               child.Name + 
"[EMAIL PROTECTED]'" + child.GetAttribute ("name", "") + "']");
                                                if (doc != null)
                                                        doc.InnerXml = 
child.InnerXml.Replace ("\r", "");
                                                break;
@@ -1308,22 +1355,31 @@
                                        case "permission":
                                        case "seealso": {
                                                XmlNode doc = 
e.SelectSingleNode (
-                                                               child.Name + 
"[EMAIL PROTECTED]'" + child.Attributes ["cref"].Value + "']");
+                                                               child.Name + 
"[EMAIL PROTECTED]'" + child.GetAttribute ("cref", "") + "']");
                                                if (doc != null)
                                                        doc.InnerXml = 
child.InnerXml.Replace ("\r", "");
+                                               else {
+                                                       XmlElement n = 
e.OwnerDocument.CreateElement (child.Name);
+                                                       CopyNode (child.Clone 
(), n);
+                                                       e.AppendChild (n);
+                                               }
                                                break;
                                        }
                                        default: {
                                                XmlNode doc = e [child.Name];
                                                if (doc != null)
                                                        doc.InnerXml = 
child.InnerXml.Replace ("\r", "");
-                                               else
-                                                       CopyNode (child, e);
+                                               else {
+                                                       XmlElement n = 
e.OwnerDocument.CreateElement (child.Name);
+                                                       CopyNode (child.Clone 
(), n);
+                                                       e.AppendChild (n);
+                                               }
                                                break;
                                        }
                                }
                        }
                }
+#endif
                if (info.SlashDocs != null) {
                        XmlNode elem = info.SlashDocs;
                        if (elem != null) {
@@ -1864,27 +1920,28 @@
                public XmlElement Node;
                public bool AddRemarks = true;
                public XmlNode SlashDocs;
-               public XmlNode EcmaDocs;
+               public XPathNavigator EcmaDocs;
                public MemberInfo Member;
        }
 
-       public static string GetXPathForMember (XmlNode member)
+       public static string GetXPathForMember (XPathNavigator member)
        {
                StringBuilder xpath = new StringBuilder ();
                xpath.Append ("//[EMAIL PROTECTED]"")
-                       .Append (member.SelectSingleNode 
("../../@FullName").Value)
+                       .Append (SelectSingleNode (member, 
"../../@FullName").Value)
                        .Append ("\"]/");
                xpath.Append ("Members/[EMAIL PROTECTED]"")
-                       .Append (member.SelectSingleNode ("@MemberName").Value)
+                       .Append (SelectSingleNode (member, "@MemberName").Value)
                        .Append ("\"]");
-               XmlNodeList parameters = member.SelectNodes 
("Parameters/Parameter");
+               XPathNodeIterator parameters = member.Select 
("Parameters/Parameter");
                if (parameters.Count > 0) {
                        xpath.Append ("/Parameters[count(Parameter) = ")
                                .Append (parameters.Count);
-                       for (int i = 0; i < parameters.Count; ++i) {
-                               xpath.Append (" and Parameter [").Append 
(i+1).Append ("]/@Type=\"");
-                               xpath.Append (member.SelectSingleNode (
-                                                       "Parameters/Parameter[" 
+ (i+1) + "]/@Type").Value);
+                       int i = 0;
+                       while (parameters.MoveNext ()) {
+                               ++i;
+                               xpath.Append (" and Parameter [").Append 
(i).Append ("]/@Type=\"");
+                               xpath.Append (parameters.Current.Value);
                                xpath.Append ("\"");
                        }
                        xpath.Append ("]/..");

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to