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