2 // msitomsx.cs: Microsoft Internal XML to Microsoft XML Documentation
4 // Arguably this doesn't belong in mdoc, but I'd rather not do some
5 // stand-alone tool either, especially since the primary reason it exists is
6 // to facilitate generating ECMA documentation via mdoc-update and
7 // mdoc-update-ecma-xml...
10 // Jonathan Pryor <jpryor@novell.com>
12 // Copyright (c) 2010 Novell, Inc. (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Collections.Generic;
37 using System.Reflection;
40 using System.Xml.Linq;
45 namespace Mono.Documentation {
47 class MsidocToMsxdocConverter : MDocCommand {
49 XslCompiledTransform msiToMsxTransform = new XslCompiledTransform ();
51 public MsidocToMsxdocConverter ()
53 using (var r = XmlReader.Create (
54 Assembly.GetExecutingAssembly ().GetManifestResourceStream ("msitomsx.xsl")))
55 msiToMsxTransform.Load (r);
58 public override void Run (IEnumerable<string> args)
60 var types = new List<string> ();
63 var options = new OptionSet () {
65 "{DIRECTORY} to create Microsoft XML assembly.xml documentation files.",
68 "Ignored for compatibility with update-ecma-xml.",
71 "The full {TYPE} name of a type to copy into the output file.",
74 var sources = Parse (options, args, "export-ecma-xml",
75 "[OPTIONS]+ DIRECTORIES",
76 "Convert Microsoft internal XML documentation within DIRECTORIES into\n" +
77 "Microsoft XML documentation.\n" +
79 "Microsoft internal XML documentation is a custom XML dialect (yay) with\n" +
80 "a specific directory structure:\n" +
82 "\tROOT/dotted.namespace/asset.xml\n" +
84 "where ROOT is a directory that can be passed as one of the DIRECTORIES\n" +
85 "arguments to x-msitomsx, dotted.namespace is the lowercased namespace\n" +
86 "in dotted form, e.g. 'system.threading', and asset.xml is the name of \n" +
87 "the \"asset\" being documented. The asset.xml basename is a GUID, and\n" +
88 "the file contains type/namespace/etc. documentation, one file per asset.\n" +
90 "There is no separation of assemblies in this format, only namespaces.\n" +
91 "Types from all assemblies are intermixed with each other.\n" +
93 "The output of x-msitomsx will be a set of files in the --out directory,\n" +
94 "one file per assembly (normal 'csc /doc' convention). For example,\n" +
96 "\tmdoc x-msitomsx -o docs import-root --type System.String\n" +
98 "will create the file 'docs/mscorlib.dll' which will contain the converted\n" +
99 "documentation for the System.String type.");
102 if (sources.Count == 0)
103 Error ("No directories specified.");
105 Error ("No output directory specified. Please use --out=DIRECTORY.");
109 Dictionary<string, XDocument> docs = Convert (sources, types);
110 foreach (KeyValuePair<string, XDocument> e in docs) {
111 using (var o = CreateWriter (Path.Combine (outdir, e.Key + ".xml")))
116 private Dictionary<string, XDocument> Convert (List<string> sources, List<string> types)
118 var docs = new Dictionary<string, XDocument> ();
120 foreach (var source in sources) {
121 foreach (var dir in Directory.GetDirectories (source)) {
122 foreach (var file in Directory.GetFiles (dir, "*.xml")) {
123 ConvertDocs (docs, types, file);
131 private void ConvertDocs (Dictionary<string, XDocument> docs, List<string> types, string file)
133 var doc = LoadFile (file);
134 var type = doc.Root.Element ("members").Element ("member").Attribute ("name").Value;
136 if (type.StartsWith ("N:"))
139 if (!type.StartsWith ("T:"))
140 throw new InvalidOperationException ("File '" + file + "' doesn't contain type documentation, it contains docs for: " + type);
142 type = type.Substring (2);
143 if (types.Count > 0 && types.BinarySearch (type) < 0)
146 var assembly = doc.Root.Element ("assembly").Element ("name").Value;
148 if (!docs.TryGetValue (assembly, out asmdocs)) {
150 asmdocs = new XDocument (
152 new XElement ("assembly",
153 new XElement ("name", assembly)),
154 new XElement ("members"))));
157 var import = new XDocument ();
158 msiToMsxTransform.Transform (doc.CreateReader (), import.CreateWriter ());
160 asmdocs.Root.Element ("members").Add (import.Root.Element ("members").Elements ("member"));
163 static XDocument LoadFile (string file)
165 using (XmlReader r = XmlReader.Create (file))
166 return XDocument.Load (r);
169 static XmlWriter CreateWriter (string file)
171 var settings = new XmlWriterSettings {
172 Encoding = new UTF8Encoding (false),
175 NewLineChars = "\r\n",
176 OmitXmlDeclaration = true,
179 return XmlWriter.Create (file, settings);