// // error-provider.cs // // Author: // Ben Maurer (bmaurer@users.sourceforge.net) // // (C) 2003 Ben Maurer // Copyright 2003-2011 Novell // Copyright 2011 Xamarin Inc // using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Xml; using System.Xml.Serialization; using System.Linq; using Lucene.Net.Index; using Lucene.Net.Documents; namespace MonkeyDoc.Providers { public class ErrorProviderConfig { public string FilesPath; public string Match; public int ErrorNumSubstringStart; public int ErrorNumSubstringLength; public string FriendlyFormatString; public override string ToString () { var sb = new StringBuilder (); var w = new StringWriter (sb); w.WriteLine ("FilesPath: {0}", FilesPath); w.WriteLine ("Match: {0}", Match); w.WriteLine ("Error Number Substring: {0} Length:{1}", ErrorNumSubstringStart, ErrorNumSubstringLength); w.WriteLine ("FriendlyFormatString: {0}", FriendlyFormatString); return w.ToString (); } public Dictionary Compile (HelpSource hs) { string[] files = Directory.GetFiles (FilesPath, Match); var ret = new Dictionary (); foreach (string s in files) { ErrorDocumentation d; int errorNum = 0; try { errorNum = int.Parse (Path.GetFileName (s).Substring (ErrorNumSubstringStart, ErrorNumSubstringLength)); } catch { Console.WriteLine ("Ignoring file {0}", s); } string errorName = String.Format (FriendlyFormatString, errorNum); if (!ret.TryGetValue (errorName, out d)) ret[errorName] = d = new ErrorDocumentation (errorName); if (d.Details == null) { string xmlFile = Path.ChangeExtension (s, "xml"); if (File.Exists (xmlFile)) { XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorDetails)); d.Details = (ErrorDetails)cfgRdr.Deserialize (new XmlTextReader (xmlFile)); } } // Encoding is same as used in MCS, so we will be able to do all those files using (StreamReader reader = new StreamReader (s, Encoding.GetEncoding (28591))) { d.Examples.Add (reader.ReadToEnd ()); } } return ret; } } public class ErrorDocumentation { public string ErrorName; public ErrorDetails Details; public List Examples = new List (); public ErrorDocumentation () {} public ErrorDocumentation (string ErrorName) { this.ErrorName = ErrorName; } } public class ErrorDetails { public XmlNode Summary; public XmlNode Details; } public class ErrorProvider : Provider { ErrorProviderConfig config; public ErrorProvider (string configFile) { config = ReadConfig (configFile); } public static ErrorProviderConfig ReadConfig (string file) { XmlSerializer cfgRdr = new XmlSerializer (typeof (ErrorProviderConfig)); ErrorProviderConfig ret = (ErrorProviderConfig)cfgRdr.Deserialize (new XmlTextReader (file)); // handle path rel to the config file ret.FilesPath = Path.Combine (Path.GetDirectoryName (file), ret.FilesPath); return ret; } public override void PopulateTree (Tree tree) { // everything is done in CloseTree so we can pack } public override void CloseTree (HelpSource hs, Tree tree) { var entries = config.Compile (hs); MemoryStream ms = new MemoryStream (); XmlSerializer writer = new XmlSerializer (typeof (ErrorDocumentation)); foreach (var de in entries) { ErrorDocumentation d = de.Value; string s = de.Key; tree.RootNode.GetOrCreateNode (s, "error:" + s); writer.Serialize (ms, d); ms.Position = 0; hs.Storage.Store (s, ms); ms.SetLength (0); } tree.RootNode.Sort (); } } public class ErrorHelpSource : HelpSource { public ErrorHelpSource (string base_file, bool create) : base (base_file, create) { } public override string GetText (string id) { return TreeDumper.ExportToTocXml (Tree.RootNode, "Compiler Error Reference", "In this section:"); } protected override string UriPrefix { get { return "error:"; } } public override bool IsGeneratedContent (string id) { return id == "root:"; } public override DocumentType GetDocumentTypeForId (string id, out Dictionary extraParams) { extraParams = null; return id == "root:" ? DocumentType.TocXml : DocumentType.ErrorXml; } public override string GetInternalIdForUrl (string url, out Node node) { var result = base.GetInternalIdForUrl (url, out node); return result.ToLower (); } public override void PopulateIndex (IndexMaker index_maker) { foreach (Node n in Tree.RootNode.Nodes) index_maker.Add (n.Caption, n.Caption, n.Element); } public override void PopulateSearchableIndex (IndexWriter writer) { foreach (Node n in Tree.RootNode.Nodes) { XmlSerializer reader = new XmlSerializer (typeof (ErrorDocumentation)); ErrorDocumentation d = (ErrorDocumentation)reader.Deserialize (GetHelpStream (n.Element.Substring (6))); SearchableDocument doc = new SearchableDocument (); doc.title = d.ErrorName; doc.url = n.Element; doc.text = d.Details != null ? d.Details.ToString () : string.Empty; doc.examples = d.Examples.Cast ().Aggregate ((e1, e2) => e1 + Environment.NewLine + e2); doc.hottext = d.ErrorName; writer.AddDocument (doc.LuceneDoc); } } } }