2 using System.Collections;
3 using System.Collections.Generic;
6 using System.Text.RegularExpressions;
11 namespace Mono.Documentation {
12 public class Monodocs2SlashDoc {
14 public static void Main(string[] args) {
16 bool showHelp = false;
17 OptionSet 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 "Show this message and exit.",
26 v => showHelp = v != null },
28 List<string> extra = p.Parse (args);
29 if (extra.Count == 0 || showHelp) {
30 Console.WriteLine ("usage: monodocs2slashdoc [OPTION]* DIRECTORIES");
32 Console.WriteLine ("Converts mdoc(5)-style XML documentation into Microsoft XML Documentation.");
34 Console.WriteLine ("Available Options:");
35 p.WriteOptionDescriptions (Console.Out);
39 Process (extra, file);
42 private static void Process (List<string> dirs, string file)
44 Dictionary<string, XmlElement> outputfiles = new Dictionary<string, XmlElement> ();
46 XmlDocument nsSummaries = new XmlDocument();
47 nsSummaries.LoadXml("<namespaces/>");
49 foreach (string dir in dirs)
50 Process (dir, outputfiles, nsSummaries, file == null);
52 if (outputfiles.Count > 0 && file != null) {
53 List<string> files = new List<string> (outputfiles.Keys);
55 XmlDocument d = new XmlDocument ();
56 d.AppendChild (d.CreateElement ("doc"));
57 d.FirstChild.AppendChild (
58 d.ImportNode (outputfiles [files [0]].SelectSingleNode ("/doc/assembly"), true));
59 XmlElement members = d.CreateElement ("members");
60 d.FirstChild.AppendChild (members);
61 foreach (string f in files) {
62 XmlElement from = (XmlElement) outputfiles [f];
63 foreach (XmlNode n in from.SelectNodes ("/doc/members/*"))
64 members.AppendChild (d.ImportNode (n, true));
66 using (TextWriter tw = file == "-" ? Console.Out : new StreamWriter (file))
67 WriteXml (d.DocumentElement, tw);
71 // Write out each of the assembly documents
72 foreach (string assemblyName in outputfiles.Keys) {
73 XmlElement members = (XmlElement)outputfiles[assemblyName];
74 Console.WriteLine(assemblyName + ".xml");
75 using(StreamWriter sw = new StreamWriter(assemblyName + ".xml")) {
76 WriteXml(members.OwnerDocument.DocumentElement, sw);
80 // Write out a namespace summaries file.
81 Console.WriteLine("NamespaceSummaries.xml");
82 using(StreamWriter writer = new StreamWriter("NamespaceSummaries.xml")) {
83 WriteXml(nsSummaries.DocumentElement, writer);
87 private static void Process (string basepath, Dictionary<string, XmlElement> outputfiles, XmlDocument nsSummaries, bool implicitFiles)
89 if (System.Environment.CurrentDirectory == System.IO.Path.GetFullPath(basepath) && implicitFiles) {
90 Console.WriteLine("Don't run this tool from your documentation directory, since some files could be accidentally overwritten.");
94 XmlDocument index_doc = new XmlDocument();
95 index_doc.Load(Path.Combine(basepath, "index.xml"));
96 XmlElement index = index_doc.DocumentElement;
98 foreach (XmlElement assmbly in index.SelectNodes("Assemblies/Assembly")) {
99 string assemblyName = assmbly.GetAttribute("Name");
100 if (outputfiles.ContainsKey (assemblyName))
102 XmlDocument output = new XmlDocument();
103 XmlElement output_root = output.CreateElement("doc");
104 output.AppendChild(output_root);
106 XmlElement output_assembly = output.CreateElement("assembly");
107 output_root.AppendChild(output_assembly);
108 XmlElement output_assembly_name = output.CreateElement("name");
109 output_assembly.AppendChild(output_assembly_name);
110 output_assembly_name.InnerText = assemblyName;
112 XmlElement members = output.CreateElement("members");
113 output_root.AppendChild(members);
115 outputfiles.Add (assemblyName, members);
118 foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace")) {
119 string ns = nsnode.GetAttribute("Name");
120 foreach (XmlElement typedoc in nsnode.SelectNodes("Type")) {
121 string typename = typedoc.GetAttribute("Name");
122 XmlDocument type = new XmlDocument();
123 type.Load(Path.Combine(Path.Combine(basepath, ns), typename) + ".xml");
125 string assemblyname = type.SelectSingleNode("Type/AssemblyInfo/AssemblyName").InnerText;
126 XmlElement members = outputfiles [assemblyname];
127 if (members == null) continue; // assembly is strangely not listed in the index
129 string typeName = XmlDocUtils.ToEscapedTypeName (type.SelectSingleNode("Type/@FullName").InnerText);
130 CreateMember("T:" + typeName, type.DocumentElement, members);
132 foreach (XmlElement memberdoc in type.SelectNodes("Type/Members/Member")) {
133 string name = typeName;
134 switch (memberdoc.SelectSingleNode("MemberType").InnerText) {
136 name = "C:" + name + MakeArgs(memberdoc);
139 name = "M:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName")) + MakeArgs(memberdoc);
140 if (memberdoc.GetAttribute("MemberName") == "op_Implicit" || memberdoc.GetAttribute("MemberName") == "op_Explicit")
141 name += "~" + XmlDocUtils.ToTypeName (memberdoc.SelectSingleNode("ReturnValue/ReturnType").InnerText, memberdoc);
144 name = "P:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName")) + MakeArgs(memberdoc);
147 name = "F:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName"));
150 name = "E:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName"));
154 CreateMember(name, memberdoc, members);
158 foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace")) {
159 AddNamespaceSummary(nsSummaries, basepath, nsnode.GetAttribute("Name"));
163 private static void AddNamespaceSummary(XmlDocument nsSummaries, string basepath, string currentNs) {
164 string filename = Path.Combine(basepath, currentNs + ".xml");
165 if (File.Exists(filename)) {
166 XmlDocument nsSummary = new XmlDocument();
167 nsSummary.Load(filename);
168 XmlElement ns = nsSummaries.CreateElement("namespace");
169 nsSummaries.DocumentElement.AppendChild(ns);
170 ns.SetAttribute("name", currentNs);
171 ns.InnerText = nsSummary.SelectSingleNode("/Namespace/Docs/summary").InnerText;
175 private static void CreateMember(string name, XmlElement input, XmlElement output) {
176 XmlElement member = output.OwnerDocument.CreateElement("member");
177 output.AppendChild(member);
179 member.SetAttribute("name", name);
181 foreach (XmlNode docnode in input.SelectSingleNode("Docs"))
182 member.AppendChild(output.OwnerDocument.ImportNode(docnode, true));
185 private static string MakeArgs (XmlElement member)
187 XmlNodeList parameters = member.SelectNodes ("Parameters/Parameter");
188 if (parameters.Count == 0)
190 StringBuilder args = new StringBuilder ();
192 args.Append (XmlDocUtils.ToTypeName (parameters [0].Attributes ["Type"].Value, member));
193 for (int i = 1; i < parameters.Count; ++i) {
195 args.Append (XmlDocUtils.ToTypeName (parameters [i].Attributes ["Type"].Value, member));
198 return args.ToString ();
201 private static void WriteXml(XmlElement element, System.IO.TextWriter output) {
202 XmlTextWriter writer = new XmlTextWriter(output);
203 writer.Formatting = Formatting.Indented;
204 writer.Indentation = 4;
205 writer.IndentChar = ' ';
206 element.WriteTo(writer);