Merge pull request #517 from getsometoast/master
[mono.git] / mcs / tools / mdoc / Mono.Documentation / monodocs2slashdoc.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.IO;
5 using System.Text;
6 using System.Text.RegularExpressions;
7 using System.Xml;
8
9 using Monodoc;
10 using Mono.Options;
11
12 namespace Mono.Documentation {
13 public class MDocToMSXDocConverter : MDocCommand {
14
15         public override void Run (IEnumerable<string> args)
16         {
17                 string file = null;
18                 var p = new OptionSet () {
19                         { "o|out=", 
20                                 "The XML {FILE} to generate.\n" + 
21                                 "If not specified, will create a set of files in the curent directory " +
22                                 "based on the //AssemblyInfo/AssemblyName values within the documentation.\n" +
23                                 "Use '-' to write to standard output.",
24                                 v => file = v },
25                 };
26                 List<string> directories = Parse (p, args, "export-slashdoc", 
27                                 "[OPTIONS]+ DIRECTORIES",
28                                 "Export mdoc(5) documentation within DIRECTORIES into \n" +
29                                         "Microsoft XML Documentation format files.");
30                 if (directories == null)
31                         return;
32                 Run (file, directories);
33         }
34         
35         public static void Run (string file, IEnumerable<string> dirs)
36         {
37                 Dictionary<string, XmlElement> outputfiles = new Dictionary<string, XmlElement> ();
38
39                 XmlDocument nsSummaries = new XmlDocument();
40                 nsSummaries.LoadXml("<namespaces/>");
41
42                 foreach (string dir in dirs)
43                         Process (dir, outputfiles, nsSummaries, file == null);
44
45                 if (outputfiles.Count > 0 && file != null) {
46                         List<string> files = new List<string> (outputfiles.Keys);
47                         files.Sort ();
48                         XmlDocument d = new XmlDocument ();
49                         d.AppendChild (d.CreateElement ("doc"));
50                         d.FirstChild.AppendChild (
51                                         d.ImportNode (outputfiles [files [0]].SelectSingleNode ("/doc/assembly"), true));
52                         XmlElement members = d.CreateElement ("members");
53                         d.FirstChild.AppendChild (members);
54                         foreach (string f in files) {
55                                 XmlElement from = (XmlElement) outputfiles [f];
56                                 foreach (XmlNode n in from.SelectNodes ("/doc/members/*"))
57                                         members.AppendChild (d.ImportNode (n, true));
58                         }
59                         using (TextWriter tw = file == "-" ? Console.Out : new StreamWriter (file))
60                                 WriteXml (d.DocumentElement, tw);
61                         return;
62                 }
63
64                 // Write out each of the assembly documents
65                 foreach (string assemblyName in outputfiles.Keys) {
66                         XmlElement members = (XmlElement)outputfiles[assemblyName];
67                         Console.WriteLine(assemblyName + ".xml");
68                         using(StreamWriter sw = new StreamWriter(assemblyName + ".xml")) {
69                                 WriteXml(members.OwnerDocument.DocumentElement, sw);
70                         }
71                 }
72         
73                 // Write out a namespace summaries file.
74                 Console.WriteLine("NamespaceSummaries.xml");
75                 using(StreamWriter writer = new StreamWriter("NamespaceSummaries.xml")) {
76                         WriteXml(nsSummaries.DocumentElement, writer);
77                 }
78         }
79
80         private static void Process (string basepath, Dictionary<string, XmlElement> outputfiles, XmlDocument nsSummaries, bool implicitFiles)
81         {
82                 if (System.Environment.CurrentDirectory == System.IO.Path.GetFullPath(basepath) && implicitFiles) {
83                         Console.WriteLine("Don't run this tool from your documentation directory, since some files could be accidentally overwritten.");
84                         return;
85                 }
86
87                 XmlDocument index_doc = new XmlDocument();
88                 index_doc.Load(Path.Combine(basepath, "index.xml"));
89                 XmlElement index = index_doc.DocumentElement;
90                 
91                 foreach (XmlElement assmbly in index.SelectNodes("Assemblies/Assembly")) {
92                         string assemblyName = assmbly.GetAttribute("Name");
93                         if (outputfiles.ContainsKey (assemblyName))
94                                 continue;
95                         XmlDocument output = new XmlDocument();
96                         XmlElement output_root = output.CreateElement("doc");
97                         output.AppendChild(output_root);
98
99                         XmlElement output_assembly = output.CreateElement("assembly");
100                         output_root.AppendChild(output_assembly);
101                         XmlElement output_assembly_name = output.CreateElement("name");
102                         output_assembly.AppendChild(output_assembly_name);
103                         output_assembly_name.InnerText = assemblyName;
104                 
105                         XmlElement members = output.CreateElement("members");
106                         output_root.AppendChild(members);
107                         
108                         outputfiles.Add (assemblyName, members);
109                 }
110                         
111                 foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace")) {
112                         string ns = nsnode.GetAttribute("Name");
113                         foreach (XmlElement typedoc in nsnode.SelectNodes("Type")) {
114                                 string typename = typedoc.GetAttribute("Name");
115                                 XmlDocument type = new XmlDocument();
116                                 type.Load(Path.Combine(Path.Combine(basepath, ns), typename) + ".xml");
117                                 
118                                 string assemblyname = type.SelectSingleNode("Type/AssemblyInfo/AssemblyName").InnerText;
119                                 XmlElement members = outputfiles [assemblyname];
120                                 if (members == null) continue; // assembly is strangely not listed in the index
121                                 
122                                 //CreateMember(EcmaDoc.GetCref (type.DocumentElement), type.DocumentElement, members);
123                                         
124                                 foreach (XmlElement memberdoc in type.SelectNodes("Type/Members/Member")) {
125                                         //string name = EcmaDoc.GetCref (memberdoc);
126                                         // FIXME
127                                         string name = ns + "." + typename + "." + memberdoc.GetAttribute ("MemberName");
128                                         CreateMember(name, memberdoc, members);
129                                 }
130                         }
131                 }
132                 foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace")) {
133                         AddNamespaceSummary(nsSummaries, basepath, nsnode.GetAttribute("Name"));
134                 }
135         }
136         
137         private static void AddNamespaceSummary(XmlDocument nsSummaries, string basepath, string currentNs) {
138                 foreach (var filename in new [] {
139                                 Path.Combine(basepath, currentNs + ".xml"),
140                                 Path.Combine(basepath, "ns-" + currentNs + ".xml")}) {
141                         if (File.Exists(filename))      {
142                                 XmlDocument nsSummary = new XmlDocument();
143                                 nsSummary.Load(filename);
144                                 XmlElement ns = nsSummaries.CreateElement("namespace");
145                                 nsSummaries.DocumentElement.AppendChild(ns);
146                                 ns.SetAttribute("name", currentNs);
147                                 ns.InnerText = nsSummary.SelectSingleNode("/Namespace/Docs/summary").InnerText;
148                         }
149                 }
150         }
151         
152         private static void CreateMember(string name, XmlElement input, XmlElement output) {
153                 XmlElement member = output.OwnerDocument.CreateElement("member");
154                 output.AppendChild(member);
155                 
156                 member.SetAttribute("name", name);
157                 
158                 foreach (XmlNode docnode in input.SelectSingleNode("Docs"))
159                         member.AppendChild(output.OwnerDocument.ImportNode(docnode, true));
160         }
161
162         private static void WriteXml(XmlElement element, System.IO.TextWriter output) {
163                 XmlTextWriter writer = new XmlTextWriter(output);
164                 writer.Formatting = Formatting.Indented;
165                 writer.Indentation = 4;
166                 writer.IndentChar = ' ';
167                 element.WriteTo(writer);
168                 output.WriteLine();     
169         }
170 }
171
172 }