2 using System.Collections;
3 using System.Collections.Generic;
6 using System.Text.RegularExpressions;
11 namespace Mono.Documentation {
12 public class MDocToMSXDocConverter : MDocCommand {
14 public override void Run (IEnumerable<string> args)
17 var p = new OptionSet () {
19 "The XML {FILE} to generate.\n" +
20 "If not specified, will create a set of files in the curent directory " +
21 "based on the //AssemblyInfo/AssemblyName values within the documentation.\n" +
22 "Use '-' to write to standard output.",
25 List<string> directories = Parse (p, args, "export-slashdoc",
26 "[OPTIONS]+ DIRECTORIES",
27 "Export mdoc(5) documentation within DIRECTORIES into \n" +
28 "Microsoft XML Documentation format files.");
29 if (directories == null)
31 Run (file, directories);
34 public static void Run (string file, IEnumerable<string> dirs)
36 Dictionary<string, XmlElement> outputfiles = new Dictionary<string, XmlElement> ();
38 XmlDocument nsSummaries = new XmlDocument();
39 nsSummaries.LoadXml("<namespaces/>");
41 foreach (string dir in dirs)
42 Process (dir, outputfiles, nsSummaries, file == null);
44 if (outputfiles.Count > 0 && file != null) {
45 List<string> files = new List<string> (outputfiles.Keys);
47 XmlDocument d = new XmlDocument ();
48 d.AppendChild (d.CreateElement ("doc"));
49 d.FirstChild.AppendChild (
50 d.ImportNode (outputfiles [files [0]].SelectSingleNode ("/doc/assembly"), true));
51 XmlElement members = d.CreateElement ("members");
52 d.FirstChild.AppendChild (members);
53 foreach (string f in files) {
54 XmlElement from = (XmlElement) outputfiles [f];
55 foreach (XmlNode n in from.SelectNodes ("/doc/members/*"))
56 members.AppendChild (d.ImportNode (n, true));
58 using (TextWriter tw = file == "-" ? Console.Out : new StreamWriter (file))
59 WriteXml (d.DocumentElement, tw);
63 // Write out each of the assembly documents
64 foreach (string assemblyName in outputfiles.Keys) {
65 XmlElement members = (XmlElement)outputfiles[assemblyName];
66 Console.WriteLine(assemblyName + ".xml");
67 using(StreamWriter sw = new StreamWriter(assemblyName + ".xml")) {
68 WriteXml(members.OwnerDocument.DocumentElement, sw);
72 // Write out a namespace summaries file.
73 Console.WriteLine("NamespaceSummaries.xml");
74 using(StreamWriter writer = new StreamWriter("NamespaceSummaries.xml")) {
75 WriteXml(nsSummaries.DocumentElement, writer);
79 private static void Process (string basepath, Dictionary<string, XmlElement> outputfiles, XmlDocument nsSummaries, bool implicitFiles)
81 if (System.Environment.CurrentDirectory == System.IO.Path.GetFullPath(basepath) && implicitFiles) {
82 Console.WriteLine("Don't run this tool from your documentation directory, since some files could be accidentally overwritten.");
86 XmlDocument index_doc = new XmlDocument();
87 index_doc.Load(Path.Combine(basepath, "index.xml"));
88 XmlElement index = index_doc.DocumentElement;
90 foreach (XmlElement assmbly in index.SelectNodes("Assemblies/Assembly")) {
91 string assemblyName = assmbly.GetAttribute("Name");
92 if (outputfiles.ContainsKey (assemblyName))
94 XmlDocument output = new XmlDocument();
95 XmlElement output_root = output.CreateElement("doc");
96 output.AppendChild(output_root);
98 XmlElement output_assembly = output.CreateElement("assembly");
99 output_root.AppendChild(output_assembly);
100 XmlElement output_assembly_name = output.CreateElement("name");
101 output_assembly.AppendChild(output_assembly_name);
102 output_assembly_name.InnerText = assemblyName;
104 XmlElement members = output.CreateElement("members");
105 output_root.AppendChild(members);
107 outputfiles.Add (assemblyName, members);
110 foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace")) {
111 string ns = nsnode.GetAttribute("Name");
112 foreach (XmlElement typedoc in nsnode.SelectNodes("Type")) {
113 string typename = typedoc.GetAttribute("Name");
114 XmlDocument type = new XmlDocument();
115 type.Load(Path.Combine(Path.Combine(basepath, ns), typename) + ".xml");
117 string assemblyname = type.SelectSingleNode("Type/AssemblyInfo/AssemblyName").InnerText;
118 XmlElement members = outputfiles [assemblyname];
119 if (members == null) continue; // assembly is strangely not listed in the index
121 string typeName = XmlDocUtils.ToEscapedTypeName (type.SelectSingleNode("Type/@FullName").InnerText);
122 CreateMember("T:" + typeName, type.DocumentElement, members);
124 foreach (XmlElement memberdoc in type.SelectNodes("Type/Members/Member")) {
125 string name = typeName;
126 switch (memberdoc.SelectSingleNode("MemberType").InnerText) {
128 name = "C:" + name + MakeArgs(memberdoc);
131 name = "M:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName")) + MakeArgs(memberdoc);
132 if (memberdoc.GetAttribute("MemberName") == "op_Implicit" || memberdoc.GetAttribute("MemberName") == "op_Explicit")
133 name += "~" + XmlDocUtils.ToTypeName (memberdoc.SelectSingleNode("ReturnValue/ReturnType").InnerText, memberdoc);
136 name = "P:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName")) + MakeArgs(memberdoc);
139 name = "F:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName"));
142 name = "E:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName"));
146 CreateMember(name, memberdoc, members);
150 foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace")) {
151 AddNamespaceSummary(nsSummaries, basepath, nsnode.GetAttribute("Name"));
155 private static void AddNamespaceSummary(XmlDocument nsSummaries, string basepath, string currentNs) {
156 string filename = Path.Combine(basepath, currentNs + ".xml");
157 if (File.Exists(filename)) {
158 XmlDocument nsSummary = new XmlDocument();
159 nsSummary.Load(filename);
160 XmlElement ns = nsSummaries.CreateElement("namespace");
161 nsSummaries.DocumentElement.AppendChild(ns);
162 ns.SetAttribute("name", currentNs);
163 ns.InnerText = nsSummary.SelectSingleNode("/Namespace/Docs/summary").InnerText;
167 private static void CreateMember(string name, XmlElement input, XmlElement output) {
168 XmlElement member = output.OwnerDocument.CreateElement("member");
169 output.AppendChild(member);
171 member.SetAttribute("name", name);
173 foreach (XmlNode docnode in input.SelectSingleNode("Docs"))
174 member.AppendChild(output.OwnerDocument.ImportNode(docnode, true));
177 private static string MakeArgs (XmlElement member)
179 XmlNodeList parameters = member.SelectNodes ("Parameters/Parameter");
180 if (parameters.Count == 0)
182 StringBuilder args = new StringBuilder ();
184 args.Append (XmlDocUtils.ToTypeName (parameters [0].Attributes ["Type"].Value, member));
185 for (int i = 1; i < parameters.Count; ++i) {
187 args.Append (XmlDocUtils.ToTypeName (parameters [i].Attributes ["Type"].Value, member));
190 return args.ToString ();
193 private static void WriteXml(XmlElement element, System.IO.TextWriter output) {
194 XmlTextWriter writer = new XmlTextWriter(output);
195 writer.Formatting = Formatting.Indented;
196 writer.Indentation = 4;
197 writer.IndentChar = ' ';
198 element.WriteTo(writer);