6a25518d2ddeab1b6037102fb373cbca517712dc
[mono.git] / mcs / class / monodoc / Monodoc / providers / 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 // Copyright 2003-2011 Novell
9 // Copyright 2011 Xamarin Inc
10 //
11
12 using System;
13 using System.Collections.Generic;
14 using System.IO;
15 using System.Text;
16 using System.Xml;
17 using System.Xml.Serialization;
18 using System.Linq;
19 using Lucene.Net.Index;
20 using Lucene.Net.Documents;
21
22 namespace Monodoc.Providers
23 {
24         public class ErrorProviderConfig
25         {
26                 public string FilesPath;
27                 public string Match;
28                 public int ErrorNumSubstringStart;
29                 public int ErrorNumSubstringLength;
30                 public string FriendlyFormatString;
31
32                 public override string ToString ()
33                 {
34                         var sb = new StringBuilder ();
35                         var w = new StringWriter (sb);
36                         
37                         w.WriteLine ("FilesPath: {0}", FilesPath);
38                         w.WriteLine ("Match: {0}", Match);
39                         w.WriteLine ("Error Number Substring: {0} Length:{1}", ErrorNumSubstringStart, ErrorNumSubstringLength);
40                         w.WriteLine ("FriendlyFormatString: {0}", FriendlyFormatString);
41                         
42                         return w.ToString ();
43                 }
44                 
45                 public Dictionary<string, ErrorDocumentation> Compile (HelpSource hs)
46                 {
47                         string[] files = Directory.GetFiles (FilesPath, Match);
48                         var ret = new Dictionary<string, ErrorDocumentation> ();
49                         
50                         foreach (string s in files) {
51                                 ErrorDocumentation d;
52                                 int errorNum = 0;
53
54                                 try {
55                                         errorNum = int.Parse (Path.GetFileName (s).Substring (ErrorNumSubstringStart, ErrorNumSubstringLength));
56                                 } catch {
57                                         Console.WriteLine ("Ignoring file {0}", s);
58                                 }
59                                 
60                                 string errorName = String.Format (FriendlyFormatString, errorNum);
61                                 
62                                 if (!ret.TryGetValue (errorName, out d))
63                                         ret[errorName] = d = new ErrorDocumentation (errorName);
64
65                                 if (d.Details == null) {
66                                         string xmlFile = Path.ChangeExtension (s, "xml");
67                                         if (File.Exists (xmlFile)) {
68                                                 XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorDetails));
69                                                 d.Details = (ErrorDetails)cfgRdr.Deserialize (new XmlTextReader (xmlFile));
70                                         }
71                                 }
72                                 // Encoding is same as used in MCS, so we will be able to do all those files
73                                 using (StreamReader reader = new StreamReader (s, Encoding.GetEncoding (28591))) {
74                                         d.Examples.Add (reader.ReadToEnd ());
75                                 }
76                         }
77                         
78                         return ret;
79                 }
80         }
81
82         public class ErrorDocumentation
83         {
84                 public string ErrorName;
85                 public ErrorDetails Details;
86                 public List<string> Examples = new List<string> ();
87                 
88                 public ErrorDocumentation () {}
89                 public ErrorDocumentation (string ErrorName)
90                 {
91                         this.ErrorName = ErrorName;
92                 }
93         }
94         
95         public class ErrorDetails
96         {
97                 public XmlNode Summary;
98                 public XmlNode Details;
99         }
100
101         public class ErrorProvider : Provider
102         {
103                 ErrorProviderConfig config;
104                 
105                 public ErrorProvider (string configFile)
106                 {
107                         config = ReadConfig (configFile);
108                 }
109                 
110                 public static ErrorProviderConfig ReadConfig (string file)
111                 {
112                         XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorProviderConfig));
113                         ErrorProviderConfig ret = (ErrorProviderConfig)cfgRdr.Deserialize (new XmlTextReader (file));
114                         // handle path rel to the config file
115                         ret.FilesPath = Path.Combine (Path.GetDirectoryName (file), ret.FilesPath);
116                         return ret;
117                 }
118         
119                 public override void PopulateTree (Tree tree)
120                 {
121                         // everything is done in CloseTree so we can pack
122                 }
123         
124                 public override void CloseTree (HelpSource hs, Tree tree)
125                 {
126                         var entries = config.Compile (hs);
127                         MemoryStream ms = new MemoryStream ();
128                         XmlSerializer writer = new XmlSerializer (typeof (ErrorDocumentation));
129                         
130                         foreach (var de in entries) {
131                                 ErrorDocumentation d = de.Value;
132                                 string s = de.Key;
133
134                                 tree.RootNode.GetOrCreateNode (s, "error:" + s);
135                                 
136                                 writer.Serialize (ms, d);
137                                 ms.Position = 0;
138                                 hs.Storage.Store (s, ms);
139                                 ms.SetLength (0);
140                         }
141                         
142                         tree.RootNode.Sort ();
143                 }
144         }
145         
146         public class ErrorHelpSource : HelpSource
147         {               
148                 public ErrorHelpSource (string base_file, bool create) : base (base_file, create)
149                 {
150                 }
151
152                 public override string GetText (string id)
153                 {
154                         return TreeDumper.ExportToTocXml (Tree.RootNode, "Compiler Error Reference", "In this section:");
155                 }
156                 
157                 protected override string UriPrefix {
158                         get {
159                                 return "error:";
160                         }
161                 }
162
163                 public override bool IsGeneratedContent (string id)
164                 {
165                         return id == "root:";
166                 }
167
168                 public override DocumentType GetDocumentTypeForId (string id)
169                 {
170                         return id == "root:" ? DocumentType.TocXml : DocumentType.ErrorXml;
171                 }
172
173                 public override string GetInternalIdForUrl (string url, out Node node, out Dictionary<string, string> context)
174                 {
175                         var result = base.GetInternalIdForUrl (url, out node, out context);
176                         return result.ToLower ();
177                 }
178                 
179                 public override void PopulateIndex (IndexMaker index_maker)
180                 {
181                         foreach (Node n in Tree.RootNode.ChildNodes)
182                                 index_maker.Add (n.Caption, n.Caption, n.Element);
183                 }
184
185                 public override void PopulateSearchableIndex (IndexWriter writer) 
186                 {
187                         foreach (Node n in Tree.RootNode.ChildNodes) {
188                                 XmlSerializer reader = new XmlSerializer (typeof (ErrorDocumentation));
189                                 ErrorDocumentation d = (ErrorDocumentation)reader.Deserialize (GetHelpStream (n.Element.Substring (6)));
190                                 SearchableDocument doc = new SearchableDocument ();
191                                 doc.Title = d.ErrorName;
192                                 doc.Url = n.Element;
193                                 doc.Text = d.Details != null ? d.Details.ToString () : string.Empty;
194                                 doc.Examples = d.Examples.Cast<string> ().Aggregate ((e1, e2) => e1 + Environment.NewLine + e2);
195                                 doc.HotText = d.ErrorName;
196                                 writer.AddDocument (doc.LuceneDoc);
197                         }
198                 }
199         }
200 }