[Bind] Move documentation generation to DocProcessor class
authorthefiddler <stapostol@gmail.com>
Mon, 31 Mar 2014 15:09:30 +0000 (17:09 +0200)
committerthefiddler <stapostol@gmail.com>
Mon, 31 Mar 2014 15:09:30 +0000 (17:09 +0200)
This de-duplicates a large amount of code that is shared between the
various ISpecWriter implementations.

Source/Bind/CSharpSpecWriter.cs
Source/Bind/CppSpecWriter.cs
Source/Bind/DocProcessor.cs
Source/Bind/FuncProcessor.cs
Source/Bind/GL2/Generator.cs
Source/Bind/JavaSpecWriter.cs
Source/Bind/Structures/Function.cs

index 5095f20..9dce2ec 100644 (file)
@@ -41,7 +41,6 @@ namespace Bind
 
     sealed class CSharpSpecWriter : ISpecWriter
     {
-        readonly char[] numbers = "0123456789".ToCharArray();
         IBind Generator { get; set; }
         Settings Settings { get { return Generator.Settings; } }
 
@@ -268,48 +267,12 @@ namespace Bind
             sw.WriteLine("public static {0} {{ throw new NotImplementedException(); }}", GetDeclarationString(f, Settings.Compatibility));
         }
 
-        DocProcessor processor_;
-        DocProcessor Processor
-        {
-            get
-            {
-                if (processor_ == null)
-                    processor_ = new DocProcessor();
-                return processor_;
-            }
-        }
-        Dictionary<string, string> docfiles;
         void WriteDocumentation(BindStreamWriter sw, Function f)
         {
-            if (docfiles == null)
-            {
-                docfiles = new Dictionary<string, string>();
-                foreach (string file in Directory.GetFiles(Settings.DocPath))
-                {
-                    docfiles.Add(Path.GetFileName(file), file);
-                }
-            }
+            var docs = f.Documentation;
 
-            string docfile = null;
             try
             {
-                docfile = Settings.FunctionPrefix + f.WrappedDelegate.Name + ".xml";
-                if (!docfiles.ContainsKey(docfile))
-                    docfile = Settings.FunctionPrefix + f.TrimmedName + ".xml";
-                if (!docfiles.ContainsKey(docfile))
-                    docfile = Settings.FunctionPrefix + f.TrimmedName.TrimEnd(numbers) + ".xml";
-
-                Documentation docs = 
-                    (docfiles.ContainsKey(docfile) ?
-                        Processor.ProcessFile(docfiles[docfile]) :
-                        null) ?? 
-                    new Documentation
-                    {
-                        Summary = String.Empty,
-                        Parameters = f.Parameters.Select(p =>
-                            new DocumentationParameter(p.Name, String.Empty)).ToList()
-                    };
-
                 string warning = String.Empty;
                 string category = String.Empty;
                 if (f.Deprecated)
@@ -397,8 +360,8 @@ namespace Bind
                     else
                     {
                         Console.Error.WriteLine(
-                            "[Warning] Parameter '{0}' in function '{1}' not found in '{2}: {{{3}}}'",
-                            param.Name, f.Name, docfile,
+                            "[Warning] Parameter '{0}' in function '{1}' not found in documentation '{{{3}}}'",
+                            param.Name, f.Name,
                             String.Join(",", docs.Parameters.Select(p => p.Name).ToArray()));
                         sw.WriteLine("/// <param name=\"{0}\">{1}</param>",
                             param.Name, length);
@@ -407,7 +370,7 @@ namespace Bind
             }
             catch (Exception e)
             {
-                Console.WriteLine("[Warning] Error processing file {0}: {1}", docfile, e.ToString());
+                Console.WriteLine("[Warning] Error documenting function {0}: {1}", f.WrappedDelegate.Name, e.ToString());
             }   
         }
 
index 511900d..a70b82d 100644 (file)
@@ -41,7 +41,6 @@ namespace Bind
 
     sealed class CppSpecWriter : ISpecWriter
     {
-        readonly char[] numbers = "0123456789".ToCharArray();
         const string AllowDeprecated = "GLPP_COMPATIBLE";
         const string DigitPrefix = "T"; // Prefix for identifiers that start with a digit
         const string OutputFileHeader = "gl++.h";
@@ -665,47 +664,12 @@ typedef const char* GLstring;
             return sb.ToString();
         }
 
-        DocProcessor processor_;
-        DocProcessor Processor
-        {
-            get
-            {
-                if (processor_ == null)
-                    processor_ = new DocProcessor();
-                return processor_;
-            }
-        }
-        Dictionary<string, string> docfiles;
         void WriteDocumentation(BindStreamWriter sw, Function f)
         {
-            if (docfiles == null)
-            {
-                docfiles = new Dictionary<string, string>();
-                foreach (string file in Directory.GetFiles(Settings.DocPath))
-                {
-                    docfiles.Add(Path.GetFileName(file), file);
-                }
-            }
+            var docs = f.Documentation;
 
-            string docfile = null;
             try
             {
-                docfile = Settings.FunctionPrefix + f.WrappedDelegate.Name + ".xml";
-                if (!docfiles.ContainsKey(docfile))
-                    docfile = Settings.FunctionPrefix + f.TrimmedName + ".xml";
-                if (!docfiles.ContainsKey(docfile))
-                    docfile = Settings.FunctionPrefix + f.TrimmedName.TrimEnd(numbers) + ".xml";
-
-                Documentation docs = 
-                    (docfiles.ContainsKey(docfile) ?
-                        Processor.ProcessFile(docfiles[docfile]) : null) ?? 
-                    new Documentation
-                    {
-                        Summary = String.Empty,
-                        Parameters = f.Parameters.Select(p =>
-                            new DocumentationParameter(p.Name, String.Empty)).ToList()
-                    };
-
                 string warning = "[deprecated: v{0}]";
                 string category = "[requires: {0}]";
                 if (f.Deprecated)
@@ -749,7 +713,7 @@ typedef const char* GLstring;
             }
             catch (Exception e)
             {
-                Console.WriteLine("[Warning] Error processing file {0}: {1}", docfile, e.ToString());
+            Console.WriteLine("[Warning] Error documenting function {0}: {1}", f.WrappedDelegate.Name, e.ToString());
             }
         }
 
index 57350de..3e926d2 100644 (file)
@@ -15,6 +15,7 @@ namespace Bind
 {
     class DocProcessor
     {
+        static readonly char[] numbers = "0123456789".ToCharArray();
         static readonly Regex remove_mathml = new Regex(
             @"<(mml:math|inlineequation)[^>]*?>(?:.|\n)*?</\s*\1\s*>",
             RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
@@ -23,14 +24,65 @@ namespace Bind
         static readonly Regex remove_xmlns = new Regex(
             "xmlns=\".+\"", RegexOptions.Compiled);
 
+        readonly Dictionary<string, string> DocumentationFiles =
+            new Dictionary<string, string>();
+        readonly Dictionary<string, Documentation> DocumentationCache =
+            new Dictionary<string, Documentation>();
+
         Documentation Cached;
         string LastFile;
 
+        IBind Generator { get; set; }
+        Settings Settings { get { return Generator.Settings; } }
+
+        public DocProcessor(IBind generator)
+        {
+            if (generator == null)
+                throw new ArgumentNullException();
+
+            Generator = generator;
+            foreach (string file in Directory.GetFiles(Settings.DocPath))
+            {
+                DocumentationFiles.Add(Path.GetFileName(file), file);
+            }
+        }
+
+        public Documentation Process(Function f, EnumProcessor processor)
+        {
+            Documentation docs = null;
+
+            if (DocumentationCache.ContainsKey(f.WrappedDelegate.Name))
+            {
+                return DocumentationCache[f.WrappedDelegate.Name];
+            }
+            else
+            {
+                var file = Settings.FunctionPrefix + f.WrappedDelegate.Name + ".xml";
+                if (!DocumentationFiles.ContainsKey(file))
+                    file = Settings.FunctionPrefix + f.TrimmedName + ".xml";
+                if (!DocumentationFiles.ContainsKey(file))
+                    file = Settings.FunctionPrefix + f.TrimmedName.TrimEnd(numbers) + ".xml";
+
+                docs = 
+                    (DocumentationFiles.ContainsKey(file) ? ProcessFile(DocumentationFiles[file], processor) : null) ??
+                    new Documentation
+                    {
+                        Summary = String.Empty,
+                        Parameters = f.Parameters.Select(p =>
+                        new DocumentationParameter(p.Name, String.Empty)).ToList()
+                    };
+
+                DocumentationCache.Add(f.WrappedDelegate.Name, docs);
+            }
+
+            return docs;
+        }
+
         // Strips MathML tags from the source and replaces the equations with the content
         // found in the <!-- eqn: :--> comments in the docs.
         // Todo: Some simple MathML tags do not include comments, find a solution.
         // Todo: Some files include more than 1 function - find a way to map these extra functions.
-        public Documentation ProcessFile(string file)
+        Documentation ProcessFile(string file, EnumProcessor processor)
         {
             string text;
 
@@ -80,7 +132,7 @@ namespace Bind
             try
             {
                 doc = XDocument.Parse(text);
-                Cached = ToInlineDocs(doc);
+                Cached = ToInlineDocs(doc, processor);
                 return Cached;
             }
             catch (Exception e)
@@ -91,8 +143,28 @@ namespace Bind
             }
         }
 
-        Documentation ToInlineDocs(XDocument doc)
+        Documentation ToInlineDocs(XDocument doc, EnumProcessor enum_processor)
         {
+            if (doc == null || enum_processor == null)
+                throw new ArgumentNullException();
+
+            var no_const_processing = Settings.Legacy.NoAdvancedEnumProcessing | Settings.Legacy.ConstIntEnums;
+            if (!Generator.Settings.IsEnabled(no_const_processing))
+            {
+                // Translate all GL_FOO_BAR constants according to EnumProcessor
+                foreach (var e in doc.XPathSelectElements("//constant"))
+                {
+                    var c = e.Value;
+                    if (c.StartsWith(Settings.ConstantPrefix))
+                    {
+                        // Remove "GL_" from the beginning of the string
+                        c = c.Replace(Settings.ConstantPrefix, String.Empty);
+                    }
+                    e.Value = enum_processor.TranslateConstantName(c, false);
+                }
+            }
+
+            // Create inline documentation
             var inline = new Documentation
             {
                 Summary =
index 4f9a506..dac033c 100644 (file)
@@ -70,8 +70,8 @@ namespace Bind
             Overrides = overrides;
         }
 
-        public FunctionCollection Process(EnumProcessor enum_processor, DelegateCollection delegates, EnumCollection enums,
-            string apiname, string apiversion)
+        public FunctionCollection Process(EnumProcessor enum_processor, DocProcessor doc_processor,
+            DelegateCollection delegates, EnumCollection enums, string apiname, string apiversion)
         {
             Console.WriteLine("Processing delegates.");
             var nav = new XPathDocument(Overrides).CreateNavigator();
@@ -131,11 +131,27 @@ namespace Bind
             Console.WriteLine("Generating address table.");
             GenerateAddressTable(delegates);
 
+            Console.WriteLine("Generating documentation.");
+            GenerateDocumentation(wrappers, enum_processor, doc_processor);
+
             return wrappers;
         }
 
         #region Private Members
 
+        void GenerateDocumentation(FunctionCollection wrappers,
+            EnumProcessor enum_processor, DocProcessor doc_processor)
+        {
+            foreach (var list in wrappers)
+            {
+                foreach (var f in list.Value)
+                {
+                    f.Documentation = doc_processor.Process(f,
+                        enum_processor);
+                }
+            }
+        }
+
         void GenerateAddressTable(DelegateCollection delegates)
         {
             int slot = -1;
index 7a5ea1c..260848b 100644 (file)
@@ -113,9 +113,11 @@ namespace Bind.GL2
 
             var enum_processor = new EnumProcessor(this, overrides);
             var func_processor = new FuncProcessor(this, overrides);
+            var doc_processor = new DocProcessor(this);
 
             Enums = enum_processor.Process(Enums, Profile);
-            Wrappers = func_processor.Process(enum_processor, Delegates, Enums, Profile, Version);
+            Wrappers = func_processor.Process(enum_processor, doc_processor,
+                Delegates, Enums, Profile, Version);
         }
 
         #endregion
index 799ebb0..bf3e227 100644 (file)
@@ -41,7 +41,6 @@ namespace Bind
 
     sealed class JavaSpecWriter : ISpecWriter
     {
-        readonly char[] numbers = "0123456789".ToCharArray();
         const string DigitPrefix = "T"; // Prefix for identifiers that start with a digit
         const string OutputFileHeader = "GL.java";
 
@@ -316,47 +315,12 @@ namespace Bind
                 return f.ReturnType.CurrentType;
         }
 
-        DocProcessor processor_;
-        DocProcessor Processor
-        {
-            get
-            {
-                if (processor_ == null)
-                    processor_ = new DocProcessor();
-                return processor_;
-            }
-        }
-        Dictionary<string, string> docfiles;
         void WriteDocumentation(BindStreamWriter sw, Function f)
         {
-            if (docfiles == null)
-            {
-                docfiles = new Dictionary<string, string>();
-                foreach (string file in Directory.GetFiles(Settings.DocPath))
-                {
-                    docfiles.Add(Path.GetFileName(file), file);
-                }
-            }
+            var docs = f.Documentation;
 
-            string docfile = null;
             try
             {
-                docfile = Settings.FunctionPrefix + f.WrappedDelegate.Name + ".xml";
-                if (!docfiles.ContainsKey(docfile))
-                    docfile = Settings.FunctionPrefix + f.TrimmedName + ".xml";
-                if (!docfiles.ContainsKey(docfile))
-                    docfile = Settings.FunctionPrefix + f.TrimmedName.TrimEnd(numbers) + ".xml";
-
-                Documentation docs = 
-                    (docfiles.ContainsKey(docfile) ?
-                        Processor.ProcessFile(docfiles[docfile]) : null) ?? 
-                    new Documentation
-                {
-                    Summary = String.Empty,
-                    Parameters = f.Parameters.Select(p =>
-                        new DocumentationParameter(p.Name, String.Empty)).ToList()
-                };
-
                 string warning = "[deprecated: v{0}]";
                 string category = "[requires: {0}]";
                 if (f.Deprecated)
@@ -397,7 +361,8 @@ namespace Bind
             }
             catch (Exception e)
             {
-                Console.WriteLine("[Warning] Error processing file {0}: {1}", docfile, e.ToString());
+                Console.WriteLine("[Warning] Error documenting function {0}: {1}",
+                    f.WrappedDelegate.Name, e.ToString());
             }
         }
 
index 7512f7b..f49f3cb 100644 (file)
@@ -19,7 +19,7 @@ namespace Bind.Structures
         Delegate wrapped_delegate;
 
         #endregion
-        
+
         #region --- Constructors ---
 
         public Function(Delegate d)
@@ -38,6 +38,7 @@ namespace Bind.Structures
             TrimmedName = f.TrimmedName;
             Obsolete = f.Obsolete;
             CLSCompliant = f.CLSCompliant;
+            Documentation = f.Documentation;
             Body.AddRange(f.Body);
         }
 
@@ -99,6 +100,12 @@ namespace Bind.Structures
 
         #endregion
 
+        #region Documentation
+
+        public Documentation Documentation { get; set; }
+
+        #endregion
+
         #region ToString
 
         public override string ToString()