Prepping for monodoc move from monodoc/engine to mcs/class/monodoc...
[mono.git] / mcs / class / monodoc / error-provider.cs
1 //
2 // error-provider.cs
3 //
4 // Author:
5 //   Ben Maurer (bmaurer@users.sourceforge.net)
6 //
7 // (C) 2003 Ben Maurer
8 //
9
10 using System;
11 using System.Collections;
12 using System.Collections.Specialized;
13 using System.IO;
14 using System.Text;
15 using System.Xml;
16 using System.Xml.Serialization;
17
18 namespace Monodoc {
19
20 #region Data Model
21         public class ErrorDocumentation {
22                 public string ErrorName;
23                 public ErrorDetails Details;
24                 public StringCollection Examples = new StringCollection ();
25                 
26                 public ErrorDocumentation () {}
27                 public ErrorDocumentation (string ErrorName)
28                 {
29                         this.ErrorName = ErrorName;
30                 }
31                 
32                 public override string ToString ()
33                 {
34                         StringWriter w = new StringWriter ();
35                         
36                         w.WriteLine ("Error Name: {0}", ErrorName);
37                         w.WriteLine ("Details: \n", Details);
38                         
39                         w.WriteLine ("Examples: ");
40                         foreach (string s in Examples) {
41                                 w.WriteLine (s);
42                                 w.WriteLine ();
43                         }
44                         
45                         return w.ToString ();
46                 }
47                 
48                 public string RenderAsHtml ()
49                 {
50                         StringWriter sw = new StringWriter ();
51                         XmlWriter w = new XmlTextWriter (sw);
52                         if (HelpSource.use_css)
53                                 w.WriteRaw ("<div class=\"header\" id=\"error_ref\">" +
54                                 "       <div class=\"subtitle\">Compiler Error Reference</div> " +
55                                 "       <div class=\"title\">Error " + ErrorName + " </div></div>");
56                         else
57                         w.WriteRaw (@"
58                                 
59                                 <table width='100%'>
60                                         <tr bgcolor='#b0c4de'><td>
61                                         <i>Compiler Error Reference</i>
62                                         <h3>Error " + ErrorName + @"</h2>
63                                         </td></tr>
64                                 </table><br />");
65                         
66                         
67                         if (Details != null) {
68                                 if (HelpSource.use_css)
69                                         w.WriteRaw ("<div class=\"summary\">Summary</div>");
70                                 else
71                                 w.WriteRaw (@"<h3>Summary</h3>");
72                                 Details.Summary.WriteTo (w);
73                                 
74                                 if (HelpSource.use_css)
75                                         w.WriteRaw ("<div class=\"details\">Details</div>");
76                                 else
77                                 w.WriteRaw (@"<h3>Details</h3>");
78
79                                 Details.Details.WriteTo (w);
80                         }
81                         
82                         foreach (string xmp in Examples) {
83                                 if (HelpSource.use_css)
84                                         w.WriteRaw ("<div class=\"code_example\">" +
85                                                 "<div class=\"code_ex_title\">Example</div>");
86                                 else
87                                 w.WriteRaw (@"<table bgcolor='#f5f5dd' border='1'>
88                                                 <tr><td><b><font size='-1'>Example</font></b></td></tr>
89                                                 <tr><td><font size='-1'><pre>");
90                                 w.WriteRaw (Mono.Utilities.Colorizer.Colorize (xmp, "c#"));
91                                 if (HelpSource.use_css)
92                                         w.WriteRaw ("</div>");
93                                 else
94                                 w.WriteRaw (@"</pre></font></td></tr></table>");
95                         }
96                         
97                         w.Close ();
98                         
99                         return sw.ToString ();
100                 }
101         }
102         
103         public class ErrorDetails {
104                 public XmlNode Summary;
105                 public XmlNode Details;
106                         
107                 public override string ToString ()
108                 {
109                         StringWriter w = new StringWriter ();
110
111                         w.WriteLine ("Summary: \n {0}", Summary.OuterXml);
112                         w.WriteLine ("Details: \n {0}", Summary.OuterXml);
113                         
114                         return w.ToString ();
115                 }
116         }
117         
118         public class ErrorProviderConfig {
119                 public string FilesPath;
120                 public string Match;
121                 public int ErrorNumSubstringStart;
122                 public int ErrorNumSubstringLength;
123                 public string FriendlyFormatString;
124                 
125                 public override string ToString ()
126                 {
127                         StringWriter w = new StringWriter ();
128                         
129                         w.WriteLine ("FilesPath: {0}", FilesPath);
130                         w.WriteLine ("Match: {0}", Match);
131                         w.WriteLine ("Error Number Substring: {0} Length:{1}", ErrorNumSubstringStart, ErrorNumSubstringLength);
132                         w.WriteLine ("FriendlyFormatString: {0}", FriendlyFormatString);
133                         
134                         return w.ToString ();
135                 }
136                 
137                 public Hashtable Compile ()
138                 {
139                         string [] files = Directory.GetFiles (FilesPath, Match);
140                         Hashtable ret = new Hashtable ();
141                         
142                         foreach (string s in files) {
143                                 ErrorDocumentation d;
144                                 
145                                 Console.WriteLine (s);
146
147                                 int errorNum = 0;
148
149                                 try {
150                                         errorNum = int.Parse (Path.GetFileName (s).Substring (ErrorNumSubstringStart, ErrorNumSubstringLength));
151                                 } catch {
152                                         Console.WriteLine ("Ignoring file {0}", s);
153                                 }
154                                 
155                                 string errorName = String.Format (FriendlyFormatString, errorNum);
156                                 
157                                 d = (ErrorDocumentation)ret [errorName];
158                                 if (d == null)
159                                         ret [errorName] = d = new ErrorDocumentation (errorName);
160                                 
161                                 if (d.Details == null) {
162                                         string xmlFile = Path.ChangeExtension (s, "xml");
163                                         Console.WriteLine (xmlFile);
164                                         if (File.Exists (xmlFile)) {
165                                                 XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorDetails));
166                                                 d.Details = (ErrorDetails)cfgRdr.Deserialize (new XmlTextReader (xmlFile));
167                                         }
168                                 }
169                                 // Encoding is same as used in MCS, so we will be able to do all those files
170                                 using (StreamReader reader = new StreamReader (s, Encoding.GetEncoding (28591))) {
171                                         d.Examples.Add (reader.ReadToEnd ());
172                                 }
173                         }
174                         
175                         return ret;
176                 }
177         }
178         
179 #endregion
180
181 #region Monodoc Rendering
182         public class ErrorProvider : Provider {
183                 ErrorProviderConfig config;
184                 
185                 public ErrorProvider (string configFile)
186                 {
187                         config = ReadConfig (configFile);
188                 }
189                 
190                 public static ErrorProviderConfig ReadConfig (string file)
191                 {
192                         XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorProviderConfig));
193                         ErrorProviderConfig ret = (ErrorProviderConfig)cfgRdr.Deserialize (new XmlTextReader (file));
194                         // handle path rel to the config file
195                         ret.FilesPath = Path.Combine (Path.GetDirectoryName (file), ret.FilesPath);
196                         return ret;
197                 }
198         
199                 public override void PopulateTree (Tree tree)
200                 {
201                         // everything is done in CloseTree so we can pack
202                 }
203         
204                 public override void CloseTree (HelpSource hs, Tree tree)
205                 {
206                         Hashtable entries = config.Compile ();
207                         MemoryStream ms = new MemoryStream ();
208                         XmlSerializer writer = new XmlSerializer (typeof (ErrorDocumentation));
209                         
210                         foreach (DictionaryEntry de in entries) {
211                                 ErrorDocumentation d = (ErrorDocumentation)de.Value;
212                                 string s = (string)de.Key;
213
214                                 tree.LookupNode (s, "error:" + s);
215                                 
216                                 writer.Serialize (ms, d);
217                                 ms.Position = 0;
218                                 hs.PackStream (ms, s);
219                                 ms.SetLength (0);
220                         }
221                         
222                         tree.Sort ();
223                 }
224         }
225         
226         
227         public class ErrorHelpSource : HelpSource {
228                 
229                 public ErrorHelpSource (string base_file, bool create) : base (base_file, create) {}
230         
231                 public override string GetText (string url, out Node match_node)
232                 {
233                         match_node = null;
234                         
235                         if (url == "root:")
236                                 if (HelpSource.use_css)
237                                         return BuildHtml (css_error_code, "<div id=\"error_ref\" class=\"header\"><div class=\"title\">Compiler Error Reference</div></div>");
238                                 else
239                                         return BuildHtml (String.Empty, "<table width=\"100%\" bgcolor=\"#b0c4de\" cellpadding=\"5\"><tr><td><h3>Compiler Error Reference</h3></tr></td></table>");
240                         
241                         if (!url.StartsWith ("error:"))
242                                 return null;
243                                 
244                         foreach (Node n in Tree.Nodes) {
245                                 if (n.Element != url) continue;
246                                         
247                                 match_node = n;
248                                 XmlSerializer reader = new XmlSerializer (typeof (ErrorDocumentation));
249                                 ErrorDocumentation d = (ErrorDocumentation)reader.Deserialize (
250                                         GetHelpStream (n.Element.Substring (6))
251                                 );
252                                 return BuildHtml (css_error_code, d.RenderAsHtml ());
253                         }
254                         
255                         return null;
256                 }
257                 
258                 public override void PopulateIndex (IndexMaker index_maker)
259                 {
260                         foreach (Node n in Tree.Nodes)
261                                 index_maker.Add (n.Caption, n.Caption, n.Element);
262                 }
263
264                 public static string css_error_code = @"
265                                                                  #error_ref { 
266                                                                     background: #debcb0; 
267                                                                     border: 2px solid #782609; 
268                                                                  }
269                                                                  div.summary {
270                                                                          font-size: 110%;
271                                                                          font-weight: bolder;
272                                                                  }
273                                                                  div.details {
274                                                                          font-size: 110%;
275                                                                          font-weight: bolder;
276                                                                  }
277                                                                  div.code_example {
278                                                                         background: #f5f5dd;
279                                                                         border: 1px solid #cdcd82;
280                                                                         border: 1px solid black;
281                                                                         padding-left: 1em;
282                                                                         padding-bottom: 1em;
283                                                                         margin-top: 1em;
284                                                                         white-space: pre;
285                                                                         margin-bottom: 1em;
286                                                                  }
287                                                                  div.code_ex_title {
288                                                                         position: relative;
289                                                                         top: -1em;
290                                                                         left: 30%;
291                                                                         background: #cdcd82;
292                                                                         border: 1px solid black;
293                                                                         color: black;
294                                                                         font-size: 65%;
295                                                                         text-transform: uppercase;
296                                                                         width: 40%;
297                                                                         padding: 0.3em;
298                                                                         text-align: center;
299                                                                  }";
300         }
301 #endregion
302         
303 }