Merge pull request #498 from Unroll-Me/master
[mono.git] / mcs / tools / monkeydoc / Monkeydoc / generators / html / Ecma2Html.cs
1 using System;
2 using System.IO;
3 using System.Text;
4 using System.Linq;
5 using System.Xml;
6 using System.Xml.Xsl;
7 using System.Xml.XPath;
8 using System.Collections.Generic;
9
10 using Mono.Documentation;
11 using BF = System.Reflection.BindingFlags;
12
13 namespace MonkeyDoc.Generators.Html
14 {
15         public class Ecma2Html : IHtmlExporter
16         {
17                 static string css_ecma;
18                 static string js;
19                 static XslCompiledTransform ecma_transform;
20                 readonly ExtensionObject ExtObject = new ExtensionObject ();
21
22                 public Ecma2Html ()
23                 {
24                 }
25
26                 public string CssCode {
27                         get {
28                                 if (css_ecma != null)
29                                         return css_ecma;
30                                 var assembly = typeof(Ecma2Html).Assembly;
31                                 Stream str_css = assembly.GetManifestResourceStream ("mono-ecma.css");
32                                 css_ecma = (new StreamReader (str_css)).ReadToEnd();
33                                 return css_ecma;
34                         }
35                 }
36
37                 public string JsCode {
38                         get {
39                                 if (js != null)
40                                         return js;
41                                 var assembly = typeof(Ecma2Html).Assembly;
42                                 Stream str_js = assembly.GetManifestResourceStream ("helper.js");
43                                 js = (new StreamReader (str_js)).ReadToEnd();
44                                 return js;
45                         }
46                 }
47                 
48                 public string Htmlize (XmlReader ecma_xml, Dictionary<string, string> extraArgs)
49                 {
50                         var args = new XsltArgumentList ();
51                         args.AddExtensionObject("monodoc:///extensions", ExtObject);
52                         foreach (var kvp in extraArgs)
53                                 args.AddParam (kvp.Key, string.Empty, kvp.Value);
54
55                         return Htmlize(ecma_xml, args);
56                 }
57
58                 public string Htmlize (XmlReader ecma_xml, XsltArgumentList args)
59                 {
60                         EnsureTransform ();
61                 
62                         var output = new StringBuilder ();
63                         ecma_transform.Transform (ecma_xml, 
64                                                   args, 
65                                                   XmlWriter.Create (output, ecma_transform.OutputSettings),
66                                                   CreateDocumentResolver ());
67                         return output.ToString ();
68                 }
69                 
70                 protected virtual XmlResolver CreateDocumentResolver ()
71                 {
72                         // results in using XmlUrlResolver
73                         return null;
74                 }
75
76                 public string Export (Stream stream, Dictionary<string, string> extraArgs)
77                 {
78                         return Htmlize (XmlReader.Create (stream), extraArgs);
79                 }
80
81                 public string Export (string input, Dictionary<string, string> extraArgs)
82                 {
83                         return Htmlize (XmlReader.Create (new StringReader (input)), extraArgs);
84                 }
85                 
86                 static void EnsureTransform ()
87                 {
88                         if (ecma_transform == null) {
89                                 ecma_transform = new XslCompiledTransform ();
90                                 var assembly = System.Reflection.Assembly.GetCallingAssembly ();
91                         
92                                 Stream stream = assembly.GetManifestResourceStream ("mono-ecma-css.xsl");
93                                 XmlReader xml_reader = new XmlTextReader (stream);
94                                 XmlResolver r = new ManifestResourceResolver (".");
95                                 ecma_transform.Load (xml_reader, XsltSettings.TrustedXslt, r);                  
96                         }
97                 }
98
99                 public class ExtensionObject
100                 {
101                         bool quiet = true;
102
103                         public string Colorize(string code, string lang)
104                         {
105                                 return Mono.Utilities.Colorizer.Colorize(code,lang);
106                         }
107
108                         // Used by stylesheet to nicely reformat the <see cref=> tags. 
109                         public string MakeNiceSignature(string sig, string contexttype)
110                         {
111                                 if (sig.Length < 3)
112                                         return sig;
113                                 if (sig[1] != ':')
114                                         return sig;
115
116                                 char s = sig[0];
117                                 sig = sig.Substring(2);
118                         
119                                 switch (s) {
120                                 case 'N': return sig;
121                                 case 'T': return ShortTypeName (sig, contexttype);
122
123                                 case 'C': case 'M': case 'P': case 'F': case 'E':
124                                         string type, mem, arg;
125                                         
126                                         // Get arguments
127                                         int paren;
128                                         if (s == 'C' || s == 'M')
129                                                 paren = sig.IndexOf("(");
130                                         else if (s == 'P')
131                                                 paren = sig.IndexOf("[");
132                                         else
133                                                 paren = 0;
134                                         
135                                         if (paren > 0 && paren < sig.Length-1) {
136                                                 string[] args = sig.Substring(paren+1, sig.Length-paren-2).Split(',');                                          
137                                                 for (int i = 0; i < args.Length; i++)
138                                                         args[i] = ShortTypeName(args[i], contexttype);
139                                                 arg = "(" + String.Join(", ", args) + ")";
140                                                 sig = sig.Substring(0, paren); 
141                                         } else {
142                                                 arg = string.Empty;
143                                         }
144
145                                         // Get type and member names
146                                         int dot = sig.LastIndexOf(".");
147                                         if (s == 'C' || dot <= 0 || dot == sig.Length-1) {
148                                                 mem = string.Empty;
149                                                 type = sig;
150                                         } else {
151                                                 type = sig.Substring(0, dot);
152                                                 mem = sig.Substring(dot);
153                                         }
154                                                 
155                                         type = ShortTypeName(type, contexttype);
156                                         
157                                         return type + mem + arg;
158
159                                 default:
160                                         return sig;
161                                 }
162                         }
163
164                         static string ShortTypeName(string name, string contexttype)
165                         {
166                                 int dot = contexttype.LastIndexOf(".");
167                                 if (dot < 0) return name;
168                                 string contextns = contexttype.Substring(0, dot+1);
169
170                                 if (name == contexttype)
171                                         return name.Substring(dot+1);
172                         
173                                 if (name.StartsWith(contextns))
174                                         return name.Substring(contextns.Length);
175                         
176                                 return name.Replace("+", ".");
177                         }
178
179                         string MonoImpInfo(string assemblyname, string typename, string membername, string arglist, bool strlong)
180                         {
181                                 if (quiet)
182                                         return string.Empty;
183                                 
184                                 var a = new List<string> ();
185                                 if (!string.IsNullOrEmpty (arglist)) a.Add (arglist);
186                                 return MonoImpInfo(assemblyname, typename, membername, a, strlong);
187                         }
188
189                         string MonoImpInfo(string assemblyname, string typename, string membername, XPathNodeIterator itr, bool strlong)
190                         {
191                                 if (quiet)
192                                         return string.Empty;
193                                 
194                                 var rgs = itr.Cast<XPathNavigator> ().Select (nav => nav.Value).ToList ();
195                         
196                                 return MonoImpInfo (assemblyname, typename, membername, rgs, strlong);
197                         }
198                 
199                         string MonoImpInfo(string assemblyname, string typename, string membername, List<string> arglist, bool strlong)
200                         {
201                                 try {
202                                         System.Reflection.Assembly assembly = null;
203                                 
204                                         try {
205                                                 assembly = System.Reflection.Assembly.LoadWithPartialName(assemblyname);
206                                         } catch (Exception) {
207                                                 // nothing.
208                                         }
209                                 
210                                         if (assembly == null) {
211                                                 /*if (strlong) return "The assembly " + assemblyname + " is not available to MonoDoc.";
212                                                   else return string.Empty;*/
213                                                 return string.Empty; // silently ignore
214                                         }
215
216                                         Type t = assembly.GetType(typename, false);
217                                         if (t == null) {
218                                                 if (strlong)
219                                                         return typename + " has not been implemented.";
220                                                 else
221                                                         return "Not implemented.";
222                                         }
223
224                                         // The following code is flakey and fails to find existing members
225                                         return string.Empty;
226                                 } catch (Exception) {
227                                         return string.Empty;
228                                 }
229                         }
230                 
231                         string MonoImpInfo(System.Reflection.MemberInfo mi, string itemtype, bool strlong)
232                         {
233                                 if (quiet)
234                                         return string.Empty;
235                                 
236                                 string s = string.Empty;
237
238                                 object[] atts = mi.GetCustomAttributes(true);
239                                 int todoctr = 0;
240                                 foreach (object att in atts) if (att.GetType().Name == "MonoTODOAttribute") todoctr++;
241
242                                 if (todoctr > 0) {
243                                         if (strlong)
244                                                 s = "This " + itemtype + " is marked as being unfinished.<BR/>\n";
245                                         else 
246                                                 s = "Unfinished.";
247                                 }
248
249                                 return s;
250                         }
251
252                         public string MonoImpInfo(string assemblyname, string typename, bool strlong)
253                         {
254                                 if (quiet)
255                                         return string.Empty;
256                                 
257                                 try {
258                                         if (assemblyname == string.Empty)
259                                                 return string.Empty;
260
261                                         var assembly = System.Reflection.Assembly.LoadWithPartialName(assemblyname);
262                                         if (assembly == null)
263                                                 return string.Empty;
264
265                                         Type t = assembly.GetType(typename, false);
266                                         if (t == null) {
267                                                 if (strlong)
268                                                         return typename + " has not been implemented.";
269                                                 else
270                                                         return "Not implemented.";
271                                         }
272
273                                         string s = MonoImpInfo(t, "type", strlong);
274
275                                         if (strlong) {
276                                                 var mis = t.GetMembers (BF.Static | BF.Instance | BF.Public | BF.NonPublic);
277
278                                                 // Scan members for MonoTODO attributes
279                                                 int mctr = 0;
280                                                 foreach (var mi in mis) {
281                                                         string mii = MonoImpInfo(mi, null, false);
282                                                         if (mii != string.Empty) mctr++; 
283                                                 }
284                                                 if (mctr > 0) {
285                                                         s += "This type has " + mctr + " members that are marked as unfinished.<BR/>";
286                                                 }
287                                         }
288
289                                         return s;
290
291                                 } catch (Exception) {
292                                         return string.Empty;
293                                 }                       
294                         }
295
296                         public bool MonoEditing ()
297                         {
298                                 return false;
299                         }
300                 
301                         public bool IsToBeAdded(string text)
302                         {
303                                 return text.StartsWith ("To be added");
304                         }
305                 }
306         }
307 }