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