diff options
Diffstat (limited to 'mdoc/Mono.Documentation/Updater/EcmaDocumentationEnumerator.cs')
-rw-r--r-- | mdoc/Mono.Documentation/Updater/EcmaDocumentationEnumerator.cs | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/mdoc/Mono.Documentation/Updater/EcmaDocumentationEnumerator.cs b/mdoc/Mono.Documentation/Updater/EcmaDocumentationEnumerator.cs new file mode 100644 index 00000000..86cce337 --- /dev/null +++ b/mdoc/Mono.Documentation/Updater/EcmaDocumentationEnumerator.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml; + +using Mono.Cecil; + +using Mono.Documentation.Util; + +namespace Mono.Documentation.Updater +{
+ class EcmaDocumentationEnumerator : DocumentationEnumerator + { + + XmlReader ecmadocs; + MDocUpdater app; + + public EcmaDocumentationEnumerator (MDocUpdater app, XmlReader ecmaDocs) + { + this.app = app; + this.ecmadocs = ecmaDocs; + } + + public override IEnumerable<TypeDefinition> GetDocumentationTypes (AssemblyDefinition assembly, List<string> forTypes) + { + HashSet<string> seen = new HashSet<string> (); + return GetDocumentationTypes (assembly, forTypes, seen) + .Concat (base.GetDocumentationTypes (assembly, forTypes, seen)); + } + + new IEnumerable<TypeDefinition> GetDocumentationTypes (AssemblyDefinition assembly, List<string> forTypes, HashSet<string> seen) + { + int typeDepth = -1; + while (ecmadocs.Read ()) + { + switch (ecmadocs.Name) + { + case "Type": + { + if (typeDepth == -1) + typeDepth = ecmadocs.Depth; + if (ecmadocs.NodeType != XmlNodeType.Element) + continue; + if (typeDepth != ecmadocs.Depth) // nested <TypeDefinition/> element? + continue; + string typename = ecmadocs.GetAttribute ("FullName"); + string typename2 = MDocUpdater.GetTypeFileName (typename); + if (forTypes != null && + forTypes.BinarySearch (typename) < 0 && + typename != typename2 && + forTypes.BinarySearch (typename2) < 0) + continue; + TypeDefinition t; + if ((t = assembly.GetType (typename)) == null && + (t = assembly.GetType (typename2)) == null) + continue; + seen.Add (typename); + if (typename != typename2) + seen.Add (typename2); + Console.WriteLine (" Import: {0}", t.FullName); + if (ecmadocs.Name != "Docs") + { + int depth = ecmadocs.Depth; + while (ecmadocs.Read ()) + { + if (ecmadocs.Name == "Docs" && ecmadocs.Depth == depth + 1) + break; + } + } + if (!ecmadocs.IsStartElement ("Docs")) + throw new InvalidOperationException ("Found " + ecmadocs.Name + "; expecting <Docs/>!"); + yield return t; + break; + } + default: + break; + } + } + } + + public override IEnumerable<DocsNodeInfo> GetDocumentationMembers (XmlDocument basefile, TypeDefinition type) + { + return GetMembers (basefile, type) + .Concat (base.GetDocumentationMembers (basefile, type)); + } + + private IEnumerable<DocsNodeInfo> GetMembers (XmlDocument basefile, TypeDefinition type) + { + while (ecmadocs.Name != "Members" && ecmadocs.Read ()) + { + // do nothing + } + if (ecmadocs.IsEmptyElement) + yield break; + + int membersDepth = ecmadocs.Depth; + bool go = true; + while (go && ecmadocs.Read ()) + { + switch (ecmadocs.Name) + { + case "Member": + { + if (membersDepth != ecmadocs.Depth - 1 || ecmadocs.NodeType != XmlNodeType.Element) + continue; + DocumentationMember dm = new DocumentationMember (ecmadocs); + + string xp = MDocUpdater.GetXPathForMember (dm); + XmlElement oldmember = (XmlElement)basefile.SelectSingleNode (xp); + MemberReference m; + if (oldmember == null) + { + m = GetMember (type, dm); + if (m == null) + { + app.Warning ("Could not import ECMA docs for `{0}'s `{1}': Member not found.", + type.FullName, dm.MemberSignatures["C#"]); + // SelectSingleNode (ecmaDocsMember, "MemberSignature[@Language=\"C#\"]/@Value").Value); + continue; + } + // oldmember lookup may have failed due to type parameter renames. + // Try again. + oldmember = (XmlElement)basefile.SelectSingleNode (MDocUpdater.GetXPathForMember (m)); + if (oldmember == null) + { + XmlElement members = MDocUpdater.WriteElement (basefile.DocumentElement, "Members"); + oldmember = basefile.CreateElement ("Member"); + oldmember.SetAttribute ("MemberName", dm.MemberName); + members.AppendChild (oldmember); + foreach (string key in MDocUpdater.Sort (dm.MemberSignatures.Keys)) + { + XmlElement ms = basefile.CreateElement ("MemberSignature"); + ms.SetAttribute ("Language", key); + ms.SetAttribute ("Value", (string)dm.MemberSignatures[key]); + oldmember.AppendChild (ms); + } + oldmember.SetAttribute ("__monodocer-seen__", "true"); + Console.WriteLine ("Member Added: {0}", oldmember.SelectSingleNode ("MemberSignature[@Language='C#']/@Value").InnerText); + app.additions++; + } + } + else + { + m = GetMember (type, new DocumentationMember (oldmember)); + if (m == null) + { + app.Warning ("Could not import ECMA docs for `{0}'s `{1}': Member not found.", + type.FullName, dm.MemberSignatures["C#"]); + continue; + } + oldmember.SetAttribute ("__monodocer-seen__", "true"); + } + DocsNodeInfo node = new DocsNodeInfo (oldmember, m); + if (ecmadocs.Name != "Docs") + throw new InvalidOperationException ("Found " + ecmadocs.Name + "; expected <Docs/>!"); + yield return node; + break; + } + case "Members": + if (membersDepth == ecmadocs.Depth && ecmadocs.NodeType == XmlNodeType.EndElement) + { + go = false; + } + break; + } + } + } + } +}
\ No newline at end of file |