[Bind] Move documentation generation to DocProcessor class

This de-duplicates a large amount of code that is shared between the
various ISpecWriter implementations.
This commit is contained in:
thefiddler 2014-03-31 17:09:30 +02:00
parent 8001d62599
commit d68c31a561
7 changed files with 113 additions and 124 deletions

View 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());
}
}

View 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());
}
}

View 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 =

View 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;

View 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

View 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());
}
}

View 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()