Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mcs / tools / monodoc / Monodoc / provider.cs
index 77d7ac9d5a63b86668a24455f6ffe83cdbc53dbb..180ae0d1f4eb2c6b158cba2780a5221680099aca 100644 (file)
@@ -5,6 +5,8 @@
 //   Miguel de Icaza (miguel@ximian.com)
 //
 // (C) 2002, Ximian, Inc.
+// Copyright 2003-2011 Novell
+// Copyright 2011 Xamarin Inc
 //
 // TODO:
 //   Each node should have a provider link
@@ -22,13 +24,12 @@ using System.Collections;
 using System.Diagnostics;
 using System.Configuration;
 using System.Reflection;
-using System.Text.RegularExpressions;
 using System.Xml;
 using System.Xml.XPath;
 using ICSharpCode.SharpZipLib.Zip;
 
-using Monodoc.Lucene.Net.Index;
-using Monodoc.Lucene.Net.Analysis.Standard;
+using Mono.Lucene.Net.Index;
+using Mono.Lucene.Net.Analysis.Standard;
 
 using Mono.Documentation;
 
@@ -393,13 +394,24 @@ public class Node : IComparable {
                if (other.position < 0)
                        other.LoadNode ();
 
-               Regex digits = new Regex (@"([\d]+)|([^\d]+)");
-               MatchEvaluator eval = delegate (Match m) {
-                       return (m.Value.Length > 0 && char.IsDigit (m.Value [0])) 
-                               ? m.Value.PadLeft (System.Math.Max (caption.Length, other.caption.Length)) 
-                               : m.Value;
-               };
-               return digits.Replace (caption, eval).CompareTo (digits.Replace (other.caption, eval));
+               var cap1 = caption;
+               var cap2 = other.caption;
+
+               /* Some node (notably from ecmaspec) have number prepended to them
+                * which we need to sort better by padding them to the same number
+                * of digits
+                */
+               if (char.IsDigit (cap1[0]) && char.IsDigit (cap2[0])) {
+                       int c1 = cap1.TakeWhile (char.IsDigit).Count ();
+                       int c2 = cap2.TakeWhile (char.IsDigit).Count ();
+
+                       if (c1 != c2) {
+                               cap1 = cap1.PadLeft (cap1.Length + Math.Max (0, c2 - c1), '0');
+                               cap2 = cap2.PadLeft (cap2.Length + Math.Max (0, c1 - c2), '0');
+                       }
+               }
+
+               return string.Compare (cap1, cap2, StringComparison.OrdinalIgnoreCase);
        }
 }
 
@@ -446,6 +458,7 @@ public class HelpSource {
        int source_id;
        DateTime zipFileWriteTime;
        string name;
+       string basepath;
        TraceLevel trace_level = TraceLevel.Warning;
        protected bool nozip;
        protected string base_dir;
@@ -453,6 +466,7 @@ public class HelpSource {
        public HelpSource (string base_filename, bool create)
        {
                this.name = Path.GetFileName (base_filename);
+               this.basepath = Path.GetDirectoryName (base_filename);
                tree_filename = base_filename + ".tree";
                zip_filename = base_filename + ".zip";
                base_dir = XmlDocUtils.GetCacheDirectory (base_filename);
@@ -497,10 +511,23 @@ public class HelpSource {
                }
        }
 
+       /* This gives the full path of the source/ directory */
+       public string BaseFilePath {
+               get {
+                       return basepath;
+               }
+       }
+
        public TraceLevel TraceLevel {
                get { return trace_level; }
                set { trace_level = value; }
        }
+
+       public string BaseDir {
+               get {
+                       return base_dir;
+               }
+       }
        
        ZipFile zip_file;
        
@@ -540,7 +567,7 @@ public class HelpSource {
        {
                if (nozip) {
                        Stream s = File.OpenRead (XmlDocUtils.GetCachedFileName (base_dir, id));
-                       string url = "monodoc:///" + SourceID + "@" + System.Web.HttpUtility.UrlEncode (id) + "@";
+                       string url = "monodoc:///" + SourceID + "@" + Uri.EscapeUriString (id) + "@";
                        return new XmlTextReader (url, s);
                }
 
@@ -550,7 +577,7 @@ public class HelpSource {
                ZipEntry entry = zip_file.GetEntry (id);
                if (entry != null) {
                        Stream s = zip_file.GetInputStream (entry);
-                       string url = "monodoc:///" + SourceID + "@" + System.Web.HttpUtility.UrlEncode (id) + "@";
+                       string url = "monodoc:///" + SourceID + "@" + Uri.EscapeUriString (id) + "@";
                        return new XmlTextReader (url, s);
                }
                return null;
@@ -560,7 +587,7 @@ public class HelpSource {
        {
                if (nozip) {
                        Stream s = File.OpenRead (XmlDocUtils.GetCachedFileName (base_dir, id));
-                       string url = "monodoc:///" + SourceID + "@" + System.Web.HttpUtility.UrlEncode (id) + "@";
+                       string url = "monodoc:///" + SourceID + "@" + Uri.EscapeUriString (id) + "@";
                        XmlReader r = new XmlTextReader (url, s);
                        XmlDocument ret = new XmlDocument ();
                        ret.Load (r);
@@ -573,7 +600,7 @@ public class HelpSource {
                ZipEntry entry = zip_file.GetEntry (id);
                if (entry != null) {
                        Stream s = zip_file.GetInputStream (entry);
-                       string url = "monodoc:///" + SourceID + "@" + System.Web.HttpUtility.UrlEncode (id) + "@";
+                       string url = "monodoc:///" + SourceID + "@" + Uri.EscapeUriString (id) + "@";
                        XmlReader r = new XmlTextReader (url, s);
                        XmlDocument ret = new XmlDocument ();
                        ret.Load (r);
@@ -854,6 +881,8 @@ public class RootTree : Tree {
        {
                return LoadTree (null);
        }
+
+       const string MacMonoDocDir = "/Library/Frameworks/Mono.framework/Versions/Current/lib/monodoc";
        
        //
        // Loads the tree layout
@@ -871,7 +900,13 @@ public class RootTree : Tree {
                                d.Load (cfgFile);
                                basedir = d.SelectSingleNode ("config/path").Attributes ["docsPath"].Value;
                        }
-                       basedir = "/Library/Frameworks/Mono.framework/Versions/Current/lib/monodoc/";
+                       // Temporary workaround for developers distributing a monodoc.dll themselves on Mac
+                       if (Directory.Exists (MacMonoDocDir)){
+                               Console.WriteLine ("MacDir exists");
+                               if (!File.Exists (Path.Combine (basedir, "monodoc.xml"))){
+                                       basedir = MacMonoDocDir;
+                               }
+                       }
                }
 
                //
@@ -881,12 +916,16 @@ public class RootTree : Tree {
                string layout = Path.Combine (basedir, "monodoc.xml");
                doc.Load (layout);
 
+               string osxExternalDir = "/Library/Frameworks/Mono.framework/External/monodoc";
+               string[] osxExternalSources = Directory.Exists (osxExternalDir)
+                       ? Directory.GetFiles (osxExternalDir, "*.source")
+                       : new string[0];
+
                return LoadTree (basedir, doc, 
-                               Directory.GetFiles (Path.Combine (basedir, "sources"))
-                               .Where (file => file.EndsWith (".source")));
+                               Directory.GetFiles (Path.Combine (basedir, "sources"), "*.source")
+                               .Concat (osxExternalSources));
        }
 
-
        // Compatibility shim w/ Mono 2.6
        public static RootTree LoadTree (string indexDir, XmlDocument docTree, IEnumerable sourceFiles)
        {
@@ -901,6 +940,7 @@ public class RootTree : Tree {
                                docTree.Load (defTree);
                }
 
+
                sourceFiles = sourceFiles ?? new string [0];
 
                //
@@ -960,8 +1000,13 @@ public class RootTree : Tree {
                }
        }
 
+       Dictionary<string,string> loadedSourceFiles = new Dictionary<string,string> ();
+       
        public void AddSourceFile (string sourceFile)
        {
+               if (loadedSourceFiles.ContainsKey (sourceFile))
+                       return;
+               
                Node third_party = LookupEntryPoint ("various") ?? this;
 
                XmlDocument doc = new XmlDocument ();
@@ -982,6 +1027,7 @@ public class RootTree : Tree {
                        Console.Error.WriteLine ("Error: No <source> section found in the {0} file", sourceFile);
                        return;
                }
+               loadedSourceFiles [sourceFile] = sourceFile;
                foreach (XmlNode source in sources){
                        XmlAttribute a = source.Attributes ["provider"];
                        if (a == null){
@@ -1187,7 +1233,7 @@ public class RootTree : Tree {
                        return lastHelpSourceTime;
                }
        }
-       
+
        public static bool GetNamespaceAndType (string url, out string ns, out string type)
        {
                int nsidx = -1;
@@ -1211,7 +1257,6 @@ public class RootTree : Tree {
                }
 
                if (nsidx == -1) {
-                       Console.Error.WriteLine ("Did not find dot in: " + url);
                        ns = null;
                        type = null;
                        return false;
@@ -1583,7 +1628,11 @@ public class RootTree : Tree {
 
        public static void MakeIndex ()
        {
-               RootTree root = LoadTree ();
+               MakeIndex (LoadTree ());
+       }
+
+       public static void MakeIndex (RootTree root)
+       {
                if (root == null)
                        return;
 
@@ -1611,7 +1660,7 @@ public class RootTree : Tree {
                        // No octal in C#, how lame is that
                        chmod (path, 0x1a4);
                }
-               Console.WriteLine ("Documentation index updated");
+               Console.WriteLine ("Documentation index at {0} updated", path);
        }
 
        static bool IsUnix {
@@ -1634,10 +1683,15 @@ public class RootTree : Tree {
        }
 
        public static void MakeSearchIndex ()
+       {
+               MakeSearchIndex (LoadTree ());
+       }
+
+       public static void MakeSearchIndex (RootTree root)
        {
                // Loads the RootTree
                Console.WriteLine ("Loading the monodoc tree...");
-               RootTree root = LoadTree ();
+
                if (root == null)
                        return;
 
@@ -1648,7 +1702,7 @@ public class RootTree : Tree {
                        if (!Directory.Exists (dir)) 
                                Directory.CreateDirectory (dir);
 
-                       writer = new IndexWriter(Lucene.Net.Store.FSDirectory.GetDirectory(dir, true), new StandardAnalyzer(), true);
+                       writer = new IndexWriter(Mono.Lucene.Net.Store.FSDirectory.GetDirectory(dir, true), new StandardAnalyzer(), true);
                } catch (UnauthorizedAccessException) {
                        //try in the .config directory
                        try {
@@ -1656,7 +1710,7 @@ public class RootTree : Tree {
                                if (!Directory.Exists (dir)) 
                                        Directory.CreateDirectory (dir);
 
-                               writer = new IndexWriter(Lucene.Net.Store.FSDirectory.GetDirectory(dir, true), new StandardAnalyzer(), true);
+                               writer = new IndexWriter(Mono.Lucene.Net.Store.FSDirectory.GetDirectory(dir, true), new StandardAnalyzer(), true);
                        } catch (UnauthorizedAccessException) {
                                Console.WriteLine ("You don't have permissions to write on " + dir);
                                return;