* . (svn:ignore), Test (svn:ignore): Ignore generated files.
[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 Mono.Options;
10
11 namespace Mono.Documentation {
12 public class MDocToMSXDocConverter {
13         
14         public static void Run (string file, IEnumerable<string> dirs)
15         {
16                 Dictionary<string, XmlElement> outputfiles = new Dictionary<string, XmlElement> ();
17
18                 XmlDocument nsSummaries = new XmlDocument();
19                 nsSummaries.LoadXml("<namespaces/>");
20
21                 foreach (string dir in dirs)
22                         Process (dir, outputfiles, nsSummaries, file == null);
23
24                 if (outputfiles.Count > 0 && file != null) {
25                         List<string> files = new List<string> (outputfiles.Keys);
26                         files.Sort ();
27                         XmlDocument d = new XmlDocument ();
28                         d.AppendChild (d.CreateElement ("doc"));
29                         d.FirstChild.AppendChild (
30                                         d.ImportNode (outputfiles [files [0]].SelectSingleNode ("/doc/assembly"), true));
31                         XmlElement members = d.CreateElement ("members");
32                         d.FirstChild.AppendChild (members);
33                         foreach (string f in files) {
34                                 XmlElement from = (XmlElement) outputfiles [f];
35                                 foreach (XmlNode n in from.SelectNodes ("/doc/members/*"))
36                                         members.AppendChild (d.ImportNode (n, true));
37                         }
38                         using (TextWriter tw = file == "-" ? Console.Out : new StreamWriter (file))
39                                 WriteXml (d.DocumentElement, tw);
40                         return;
41                 }
42
43                 // Write out each of the assembly documents
44                 foreach (string assemblyName in outputfiles.Keys) {
45                         XmlElement members = (XmlElement)outputfiles[assemblyName];
46                         Console.WriteLine(assemblyName + ".xml");
47                         using(StreamWriter sw = new StreamWriter(assemblyName + ".xml")) {
48                                 WriteXml(members.OwnerDocument.DocumentElement, sw);
49                         }
50                 }
51         
52                 // Write out a namespace summaries file.
53                 Console.WriteLine("NamespaceSummaries.xml");
54                 using(StreamWriter writer = new StreamWriter("NamespaceSummaries.xml")) {
55                         WriteXml(nsSummaries.DocumentElement, writer);
56                 }
57         }
58
59         private static void Process (string basepath, Dictionary<string, XmlElement> outputfiles, XmlDocument nsSummaries, bool implicitFiles)
60         {
61                 if (System.Environment.CurrentDirectory == System.IO.Path.GetFullPath(basepath) && implicitFiles) {
62                         Console.WriteLine("Don't run this tool from your documentation directory, since some files could be accidentally overwritten.");
63                         return;
64                 }
65
66                 XmlDocument index_doc = new XmlDocument();
67                 index_doc.Load(Path.Combine(basepath, "index.xml"));
68                 XmlElement index = index_doc.DocumentElement;
69                 
70                 foreach (XmlElement assmbly in index.SelectNodes("Assemblies/Assembly")) {
71                         string assemblyName = assmbly.GetAttribute("Name");
72                         if (outputfiles.ContainsKey (assemblyName))
73                                 continue;
74                         XmlDocument output = new XmlDocument();
75                         XmlElement output_root = output.CreateElement("doc");
76                         output.AppendChild(output_root);
77
78                         XmlElement output_assembly = output.CreateElement("assembly");
79                         output_root.AppendChild(output_assembly);
80                         XmlElement output_assembly_name = output.CreateElement("name");
81                         output_assembly.AppendChild(output_assembly_name);
82                         output_assembly_name.InnerText = assemblyName;
83                 
84                         XmlElement members = output.CreateElement("members");
85                         output_root.AppendChild(members);
86                         
87                         outputfiles.Add (assemblyName, members);
88                 }
89                         
90                 foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace")) {
91                         string ns = nsnode.GetAttribute("Name");
92                         foreach (XmlElement typedoc in nsnode.SelectNodes("Type")) {
93                                 string typename = typedoc.GetAttribute("Name");
94                                 XmlDocument type = new XmlDocument();
95                                 type.Load(Path.Combine(Path.Combine(basepath, ns), typename) + ".xml");
96                                 
97                                 string assemblyname = type.SelectSingleNode("Type/AssemblyInfo/AssemblyName").InnerText;
98                                 XmlElement members = outputfiles [assemblyname];
99                                 if (members == null) continue; // assembly is strangely not listed in the index
100                                 
101                                 string typeName = XmlDocUtils.ToEscapedTypeName (type.SelectSingleNode("Type/@FullName").InnerText);
102                                 CreateMember("T:" + typeName, type.DocumentElement, members);
103                                         
104                                 foreach (XmlElement memberdoc in type.SelectNodes("Type/Members/Member")) {
105                                         string name = typeName;
106                                         switch (memberdoc.SelectSingleNode("MemberType").InnerText) {
107                                                 case "Constructor":
108                                                         name = "C:" + name + MakeArgs(memberdoc);
109                                                         break;
110                                                 case "Method":
111                                                         name = "M:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName")) + MakeArgs(memberdoc);
112                                                         if (memberdoc.GetAttribute("MemberName") == "op_Implicit" || memberdoc.GetAttribute("MemberName") == "op_Explicit")
113                                                                 name += "~" + XmlDocUtils.ToTypeName (memberdoc.SelectSingleNode("ReturnValue/ReturnType").InnerText, memberdoc);
114                                                         break;
115                                                 case "Property":
116                                                         name = "P:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName")) + MakeArgs(memberdoc);
117                                                         break;
118                                                 case "Field":
119                                                         name = "F:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName"));
120                                                         break;
121                                                 case "Event":
122                                                         name = "E:" + name + "." + XmlDocUtils.ToEscapedMemberName (memberdoc.GetAttribute("MemberName"));
123                                                         break;
124                                         }
125                                         
126                                         CreateMember(name, memberdoc, members);
127                                 }
128                         }
129                 }
130                 foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace")) {
131                         AddNamespaceSummary(nsSummaries, basepath, nsnode.GetAttribute("Name"));
132                 }
133         }
134         
135         private static void AddNamespaceSummary(XmlDocument nsSummaries, string basepath, string currentNs) {
136                 string filename = Path.Combine(basepath, currentNs + ".xml");
137                 if (File.Exists(filename))      {
138                         XmlDocument nsSummary = new XmlDocument();
139                         nsSummary.Load(filename);
140                         XmlElement ns = nsSummaries.CreateElement("namespace");
141                         nsSummaries.DocumentElement.AppendChild(ns);
142                         ns.SetAttribute("name", currentNs);
143                         ns.InnerText = nsSummary.SelectSingleNode("/Namespace/Docs/summary").InnerText;
144                 }
145         }
146         
147         private static void CreateMember(string name, XmlElement input, XmlElement output) {
148                 XmlElement member = output.OwnerDocument.CreateElement("member");
149                 output.AppendChild(member);
150                 
151                 member.SetAttribute("name", name);
152                 
153                 foreach (XmlNode docnode in input.SelectSingleNode("Docs"))
154                         member.AppendChild(output.OwnerDocument.ImportNode(docnode, true));
155         }
156         
157         private static string MakeArgs (XmlElement member)
158         {
159                 XmlNodeList parameters = member.SelectNodes ("Parameters/Parameter");
160                 if (parameters.Count == 0)
161                         return "";
162                 StringBuilder args = new StringBuilder ();
163                 args.Append ("(");
164                 args.Append (XmlDocUtils.ToTypeName (parameters [0].Attributes ["Type"].Value, member));
165                 for (int i = 1; i < parameters.Count; ++i) {
166                         args.Append (",");
167                         args.Append (XmlDocUtils.ToTypeName (parameters [i].Attributes ["Type"].Value, member));
168                 }
169                 args.Append (")");
170                 return args.ToString ();
171         }
172
173         private static void WriteXml(XmlElement element, System.IO.TextWriter output) {
174                 XmlTextWriter writer = new XmlTextWriter(output);
175                 writer.Formatting = Formatting.Indented;
176                 writer.Indentation = 4;
177                 writer.IndentChar = ' ';
178                 element.WriteTo(writer);
179                 output.WriteLine();     
180         }
181 }
182
183 }