[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [assemblygen] src: Moved all code concerning generation of documentation to the Documentation class.
From: Dimitar Dobrev <dpldobrev () yahoo ! com>
Date: 2012-12-16 21:55:58
Message-ID: 20121216215558.95A70A60F7 () git ! kde ! org
[Download RAW message or body]
Git commit a771f84274b8265cba4b0bf8d4f6ecc736195864 by Dimitar Dobrev.
Committed on 13/12/2012 at 21:52.
Pushed by ddobrev into branch 'master'.
Moved all code concerning generation of documentation to the Documentation class.
Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
M +1 -1 src/MethodsGenerator.cs
M +0 -26 src/Util.cs
M +391 -2 src/plugins/qyoto/Documentation.cs
M +3 -18 src/plugins/qyoto/PropertyGenerator.cs
M +10 -320 src/plugins/qyoto/QyotoHooks.cs
http://commits.kde.org/assemblygen/a771f84274b8265cba4b0bf8d4f6ecc736195864
diff --git a/src/MethodsGenerator.cs b/src/MethodsGenerator.cs
index 1ee5796..cb0ccac 100644
--- a/src/MethodsGenerator.cs
+++ b/src/MethodsGenerator.cs
@@ -1154,7 +1154,7 @@ public unsafe class MethodsGenerator
string oldArgName = parameter.Name;
int index = oldArgName.IndexOf(" = ", StringComparison.Ordinal);
string nameOnly = index > 0 ? oldArgName.Substring(0, index) : oldArgName;
- if (nameOnly.Length == 4 && nameOnly.StartsWith("arg") && \
char.IsDigit(nameOnly[3])) + if (nameOnly.Length == 4 && nameOnly.StartsWith("arg", \
StringComparison.Ordinal) && char.IsDigit(nameOnly[3])) {
string name = args[i];
if (!string.IsNullOrEmpty(name))
diff --git a/src/Util.cs b/src/Util.cs
index 3713131..4150427 100644
--- a/src/Util.cs
+++ b/src/Util.cs
@@ -156,30 +156,4 @@ public static class Util
{
return GetAbstractMethods(smoke, classId).Count > 0;
}
-
- public static void FormatComment(string docs, CodeTypeMember cmp, bool obsolete = \
false, string tag = "summary")
- {
- StringBuilder obsoleteMessageBuilder = new StringBuilder();
- cmp.Comments.Add(new CodeCommentStatement(string.Format("<{0}>", tag), true));
- foreach (string line in \
HtmlEncoder.HtmlEncode(docs).Split(Environment.NewLine.ToCharArray(), \
StringSplitOptions.None))
- {
- cmp.Comments.Add(new CodeCommentStatement(string.Format("<para>{0}</para>", \
line), true));
- if (obsolete && (line.Contains("instead") || line.Contains("deprecated")))
- {
- obsoleteMessageBuilder.Append(HtmlEncoder.HtmlDecode(line));
- obsoleteMessageBuilder.Append(' ');
- }
- }
- cmp.Comments.Add(new CodeCommentStatement(string.Format("</{0}>", tag), true));
- if (obsolete)
- {
- if (obsoleteMessageBuilder.Length > 0)
- {
- obsoleteMessageBuilder.Remove(obsoleteMessageBuilder.Length - 1, 1);
- }
- CodeTypeReference obsoleteAttribute = new \
CodeTypeReference(typeof(ObsoleteAttribute));
- CodePrimitiveExpression obsoleteMessage = new \
CodePrimitiveExpression(obsoleteMessageBuilder.ToString());
- cmp.CustomAttributes.Add(new CodeAttributeDeclaration(obsoleteAttribute, new \
CodeAttributeArgument(obsoleteMessage)));
- }
- }
}
diff --git a/src/plugins/qyoto/Documentation.cs b/src/plugins/qyoto/Documentation.cs
index 4b0ff66..0d14f67 100644
--- a/src/plugins/qyoto/Documentation.cs
+++ b/src/plugins/qyoto/Documentation.cs
@@ -18,16 +18,379 @@
*/
using System;
+using System.CodeDom;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
+using System.Text.RegularExpressions;
+using System.Web.Util;
using Mono.Data.Sqlite;
using zlib;
-public class Documentation
+public unsafe class Documentation
{
- public static IDictionary<string, string> Get(string docsPath)
+ private readonly GeneratorData data;
+ private readonly Translator translator;
+ private readonly Dictionary<CodeTypeDeclaration, List<string>> memberDocumentation \
= new Dictionary<CodeTypeDeclaration, List<string>>(); + private readonly \
List<string> staticDocumentation = new List<string>(); +
+ public Documentation(GeneratorData data, Translator translator)
+ {
+ this.data = data;
+ this.translator = translator;
+ this.GatherDocs();
+ }
+
+ public void DocumentEnumMember(Smoke* smoke, Smoke.Method* smokeMethod, \
CodeMemberField cmm, CodeTypeDeclaration type) + {
+ CodeTypeDeclaration parentType = this.memberDocumentation.Keys.FirstOrDefault(t => \
t.Name == (string) type.UserData["parent"]); + if (parentType != null)
+ {
+ IList<string> docs = this.memberDocumentation[parentType];
+ string typeName = Regex.Escape(parentType.Name) + "::" + Regex.Escape(type.Name);
+ if (type.Comments.Count == 0)
+ {
+ for (int i = 0; i < docs.Count; i++)
+ {
+ const string enumDoc = @"enum {0}(\s*flags \
{1}::\w+\s+)?(?<docsStart>.*?)(\n){{3}}"; + Match matchEnum = \
Regex.Match(docs[i], string.Format(enumDoc, typeName, parentType.Name), + \
RegexOptions.Singleline | RegexOptions.ExplicitCapture); + if (matchEnum.Success)
+ {
+ string doc = (matchEnum.Groups["docsStart"].Value + \
matchEnum.Groups["docsEnd1"].Value).Trim(); + doc = Regex.Replace(doc,
+ @"(The \S+ type is a typedef for QFlags<\S+>\. It stores an OR \
combination of \S+ values\.)", + string.Empty);
+ doc = Regex.Replace(doc,
+ @"ConstantValue(Description)?.*?(((\n){2})|$)",
+ string.Empty, RegexOptions.Singleline | \
RegexOptions.ExplicitCapture).Trim(); + if (!string.IsNullOrEmpty(doc))
+ {
+ FormatComment(doc, type, i > 0);
+ break;
+ }
+ }
+ }
+ }
+ string memberName = Regex.Escape(parentType.Name) + "::" +
+ Regex.Escape(ByteArrayManager.GetString(smoke->methodNames[smokeMethod->name]));
+ const string memberDoc = @"enum {0}.*{1}\t[^\t\n]+\t(?<docs>.*?)(&\w+;)?(\n)";
+ for (int i = 0; i < docs.Count; i++)
+ {
+ Match match = Regex.Match(docs[i], string.Format(memberDoc, typeName, \
memberName), + RegexOptions.Singleline | RegexOptions.ExplicitCapture);
+ if (match.Success)
+ {
+ string doc = match.Groups["docs"].Value.Trim();
+ if (!string.IsNullOrEmpty(doc))
+ {
+ FormatComment(Char.ToUpper(doc[0]) + doc.Substring(1), cmm, i > 0);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public void DocumentProperty(CodeTypeDeclaration type, string propertyName, string \
propertyType, CodeMemberProperty cmp) + {
+ if (this.memberDocumentation.ContainsKey(type))
+ {
+ IList<string> docs = this.memberDocumentation[type];
+ for (int i = 0; i < docs.Count; i++)
+ {
+ Match match = Regex.Match(docs[i],
+ propertyName + " : (const )?" + propertyType +
+ @"\n(?<docs>This.*?)\nAccess functions:",
+ RegexOptions.Singleline | RegexOptions.ExplicitCapture);
+ if (match.Success)
+ {
+ FormatComment(match.Groups["docs"].Value, cmp, i > 0);
+ break;
+ }
+ }
+ }
+ }
+
+ public void DocumentAttributeProperty(CodeTypeMember cmm, CodeTypeDeclaration type)
+ {
+ if (this.memberDocumentation.ContainsKey(type))
+ {
+ IList<string> docs = this.memberDocumentation[type];
+ string typeName = Regex.Escape(type.Name);
+ string originalName = Char.ToLowerInvariant(cmm.Name[0]) + cmm.Name.Substring(1);
+ const string memberDoc = @"{0}::{1}\n\W*(?<docs>.*?)(\n\s*){{3}}";
+ for (int i = 0; i < docs.Count; i++)
+ {
+ Match match = Regex.Match(docs[i], string.Format(memberDoc, typeName, \
originalName), + RegexOptions.Singleline | RegexOptions.ExplicitCapture);
+ if (match.Success)
+ {
+ FormatComment(match.Groups["docs"].Value, cmm, i > 0);
+ break;
+ }
+ }
+ }
+ }
+
+ public void DocumentMember(Smoke* smoke, Smoke.Method* smokeMethod, CodeTypeMember \
cmm, CodeTypeDeclaration type) + {
+ if (type.Name == this.data.GlobalSpaceClassName || \
this.translator.NamespacesAsClasses.Contains(type.Name)) + {
+ this.DocumentMember(smoke, smokeMethod, cmm, @"\w+", this.staticDocumentation, \
false); + }
+ else
+ {
+ if (this.memberDocumentation.ContainsKey(type))
+ {
+ this.DocumentMember(smoke, smokeMethod, cmm, type.Name, \
this.memberDocumentation[type]); + }
+ }
+ }
+
+ private void DocumentMember(Smoke* smoke, Smoke.Method* smokeMethod, CodeTypeMember \
cmm, string type, IEnumerable<string> docs, bool markObsolete = true) + {
+ string methodName = \
Regex.Escape(ByteArrayManager.GetString(smoke->methodNames[smokeMethod->name])); \
+ string[] argTypes = smoke->GetArgs(smokeMethod).Split(new[] { ", " }, \
StringSplitOptions.RemoveEmptyEntries); + docs.Where((t, i) => this.TryMatch(type, \
methodName, cmm, t, i > 0 && markObsolete, argTypes)).Any(); + }
+
+ private bool TryMatch(string type, string methodName, CodeTypeMember cmm, string \
docs, bool markObsolete, IEnumerable<string> argTypes) + {
+ const string memberDoc = @"(^|( --)|\n)\n([\w :*&<>,]+)?(({0}(\s*&)?::)| \
){1}(const)?( \[(\w+\s*)+\])?\n\W*(?<docs>.*?)(\n\s*){{1,2}}((&?\S* \
--)|((\n\s*){{2}}))"; + const string separator = @",\s*";
+ StringBuilder signatureRegex = new StringBuilder(methodName).Append(@"\s*\(\s*(");
+ bool anyArgs = false;
+ foreach (string argType in argTypes)
+ {
+ if (!anyArgs)
+ {
+ signatureRegex.Append("?<args>");
+ anyArgs = true;
+ }
+ signatureRegex.Append(this.GetTypeRegex(argType)).Append(@"(\s+\w+(\s*=\s*[^,\r\n]+(\(\s*\))?)?)?");
+ signatureRegex.Append(separator);
+ }
+ if (anyArgs)
+ {
+ signatureRegex.Insert(signatureRegex.Length - separator.Length, '(');
+ }
+ else
+ {
+ signatureRegex.Append('(');
+ }
+ signatureRegex.Append(@"[\w :*&<>]+\s*=\s*[^,\r\n]+(\(\s*\))?(,\s*)?)*)\s*\)\s*");
+ Match match = Regex.Match(docs, string.Format(memberDoc, type, signatureRegex),
+ RegexOptions.Singleline | RegexOptions.ExplicitCapture);
+ if (match.Success)
+ {
+ FormatComment(match.Groups["docs"].Value, cmm, markObsolete);
+ FillMissingParameterNames(cmm, match.Groups["args"].Value);
+ return true;
+ }
+ return false;
+ }
+
+ private string GetTypeRegex(string argType)
+ {
+ StringBuilder typeBuilder = new StringBuilder(argType);
+ this.FormatType(typeBuilder);
+ typeBuilder.Insert(0, "((");
+ typeBuilder.Append(')');
+ if (this.data.TypeDefsPerType.ContainsKey(argType))
+ {
+ foreach (StringBuilder typeDefBuilder in from typedef in \
this.data.TypeDefsPerType[argType] + select new StringBuilder(typedef))
+ {
+ this.FormatType(typeDefBuilder);
+ typeBuilder.Append("|(").Append(typeDefBuilder).Append(')');
+ }
+ }
+ typeBuilder.Append(')');
+ return typeBuilder.ToString();
+ }
+
+ private void FormatType(StringBuilder typeBuilder)
+ {
+ int indexOfLt = Int32.MinValue;
+ int indexOfGt = Int32.MinValue;
+ int indexOfColon = Int32.MinValue;
+ int firstColonIndex = Int32.MinValue;
+ List<char> templateType = new List<char>(typeBuilder.Length);
+ for (int i = typeBuilder.Length - 1; i >= 0; i--)
+ {
+ char @char = typeBuilder[i];
+ switch (@char)
+ {
+ case '<':
+ indexOfLt = i;
+ break;
+ case '>':
+ indexOfGt = i;
+ break;
+ case ':':
+ if (firstColonIndex < 0)
+ {
+ firstColonIndex = i;
+ }
+ else
+ {
+ if (i == firstColonIndex - 1)
+ {
+ indexOfColon = firstColonIndex;
+ firstColonIndex = Int32.MinValue;
+ }
+ }
+ break;
+ }
+ if (i > indexOfLt && i < indexOfGt)
+ {
+ typeBuilder.Remove(i, 1);
+ templateType.Insert(0, @char);
+ }
+ }
+ if (indexOfGt > indexOfLt)
+ {
+ typeBuilder.Replace("(", @"\(").Replace(")", @"\)");
+ typeBuilder.Replace(@"*", @"\s*(\*|(\[\]))").Replace(@"&", @"\s*&").Replace(",", \
@",\s*"); + typeBuilder.Insert(indexOfLt + 1, this.GetTypeRegex(new \
string(templateType.ToArray()))); + }
+ else
+ {
+ if (indexOfColon > 0)
+ {
+ int parentTypeStart = Math.Max(indexOfLt + 1, 0);
+ typeBuilder.Remove(parentTypeStart, indexOfColon + 1 - parentTypeStart);
+ typeBuilder.Insert(parentTypeStart, @"(const )?(\w+::)?");
+ typeBuilder.Replace(@"*", @"\s*(\*|(\[\]))").Replace(@"&", @"\s*&").Replace(",", \
@",\s*"); + }
+ else
+ {
+ typeBuilder.Replace("(", @"\(").Replace(")", @"\)");
+ typeBuilder.Replace(@"*", @"\s*(\*|(\[\]))").Replace(@"&", @"\s*&").Replace(",", \
@",\s*"); + }
+ }
+ }
+
+ private static void FillMissingParameterNames(CodeTypeMember cmm, string signature)
+ {
+ CodeMemberMethod method = cmm as CodeMemberMethod;
+ if (method == null)
+ {
+ return;
+ }
+ List<string> args = new List<string>(signature.Split(','));
+ if (args.Count < method.Parameters.Count)
+ {
+ // operator
+ args.Insert(0, "one");
+ }
+ const string regex = @"^(.+?\s+)(?<name>\w+)(\s*=\s*[^\(,\s]+(\(\s*\))?)?\s*$";
+ MethodsGenerator.RenameParameters(method, (from arg in args
+ select Regex.Match(arg, regex).Groups["name"].Value).ToList());
+ }
+
+ private void GatherDocs()
+ {
+ IDictionary<string, string> documentation = Get(this.data.Docs);
+ foreach (CodeTypeDeclaration type in from smokeType in this.data.SmokeTypeMap
+ where string.IsNullOrEmpty((string) smokeType.Value.UserData["parent"])
+ select smokeType.Value)
+ {
+ foreach (CodeTypeDeclaration nestedType in \
type.Members.OfType<CodeTypeDeclaration>().Where(t => !t.IsEnum)) + {
+ this.GetClassDocs(nestedType, string.Format("{0}::{1}", type.Name, \
nestedType.Name), + string.Format("{0}-{1}", type.Name, nestedType.Name), \
documentation); + }
+ this.GetClassDocs(type, type.Name, type.Name, documentation);
+ }
+ this.staticDocumentation.AddRange(from k in \
this.translator.TypeStringMap.Keys.SelectMany(k => new[] { k + ".html", k + \
"-obsolete.html", k + "-qt3.html" }) + let key = k.ToLowerInvariant()
+ where documentation.ContainsKey(key)
+ select StripTags(documentation[key]));
+ this.staticDocumentation.AddRange(from pair in documentation
+ where pair.Key.StartsWith("q", StringComparison.Ordinal) &&
+ pair.Key.EndsWith("-h.html", StringComparison.Ordinal)
+ select StripTags(pair.Value));
+ }
+
+ private void GetClassDocs(CodeTypeDeclaration type, string typeName, string \
fileName, IDictionary<string, string> documentation) + {
+ List<string> docs = new List<string>();
+ foreach (string docFile in new[] { fileName + ".html", fileName + \
"-obsolete.html", fileName + "-qt3.html" }) + {
+ if (documentation.ContainsKey(docFile.ToLowerInvariant()))
+ {
+ string classDocs = StripTags(documentation[docFile.ToLowerInvariant()]);
+ Match match = Regex.Match(classDocs, string.Format(@"(?<class>((The {0})|(This \
class)).+?)More\.\.\..*?\n" + + @"Detailed \
Description\s+(?<detailed>.*?)(\n){{3,}}" + + @"((\w+ )*\w+ \
Documentation\n(?<members>.+))", typeName), + RegexOptions.Singleline | \
RegexOptions.ExplicitCapture); + if (match.Success)
+ {
+ type.Comments.Add(new CodeCommentStatement("<summary>", true));
+ string summary = match.Groups["class"].Value.Trim();
+ type.Comments.Add(new CodeCommentStatement(HtmlEncoder.HtmlEncode(summary), \
true)); + type.Comments.Add(new CodeCommentStatement("</summary>", true));
+ string detailed = match.Groups["detailed"].Value.Replace(summary, \
string.Empty); + FormatComment(detailed.Replace("\n/", "\n /"), type, false, \
"remarks"); + string members = match.Groups["members"].Value;
+ docs.Add(members);
+ Match matchStatic = Regex.Match(members, "Related Non-Members(?<static>.+)",
+ RegexOptions.Singleline | RegexOptions.ExplicitCapture);
+ if (matchStatic.Success)
+ {
+ this.staticDocumentation.Add(matchStatic.Groups["static"].Value);
+ }
+ }
+ else
+ {
+ docs.Add(classDocs);
+ }
+ }
+ }
+ this.memberDocumentation[type] = docs;
+ }
+
+ private static string StripTags(string source)
+ {
+ char[] array = new char[source.Length];
+ List<char> tagArray = new List<char>();
+ int arrayIndex = 0;
+ bool inside = false;
+
+ foreach (char @let in source)
+ {
+ if (@let == '<')
+ {
+ inside = true;
+ continue;
+ }
+ if (@let == '>')
+ {
+ inside = false;
+ continue;
+ }
+ if (inside)
+ {
+ tagArray.Add(@let);
+ }
+ else
+ {
+ string tag = new string(tagArray.ToArray());
+ if (tag.Contains("/tdtd"))
+ {
+ array[arrayIndex++] = '\t';
+ }
+ tagArray.Clear();
+ array[arrayIndex++] = @let;
+ }
+ }
+ return HtmlEncoder.HtmlDecode(new string(array, 0, arrayIndex));
+ }
+
+ private static IDictionary<string, string> Get(string docsPath)
{
if (!Directory.Exists(docsPath))
{
@@ -95,4 +458,30 @@ public class Documentation
}
}
}
+
+ private static void FormatComment(string docs, CodeTypeMember cmp, bool obsolete = \
false, string tag = "summary") + {
+ StringBuilder obsoleteMessageBuilder = new StringBuilder();
+ cmp.Comments.Add(new CodeCommentStatement(string.Format("<{0}>", tag), true));
+ foreach (string line in \
HtmlEncoder.HtmlEncode(docs).Split(Environment.NewLine.ToCharArray(), \
StringSplitOptions.None)) + {
+ cmp.Comments.Add(new CodeCommentStatement(string.Format("<para>{0}</para>", \
line), true)); + if (obsolete && (line.Contains("instead") || \
line.Contains("deprecated"))) + {
+ obsoleteMessageBuilder.Append(HtmlEncoder.HtmlDecode(line));
+ obsoleteMessageBuilder.Append(' ');
+ }
+ }
+ cmp.Comments.Add(new CodeCommentStatement(string.Format("</{0}>", tag), true));
+ if (obsolete)
+ {
+ if (obsoleteMessageBuilder.Length > 0)
+ {
+ obsoleteMessageBuilder.Remove(obsoleteMessageBuilder.Length - 1, 1);
+ }
+ CodeTypeReference obsoleteAttribute = new \
CodeTypeReference(typeof(ObsoleteAttribute)); + CodePrimitiveExpression \
obsoleteMessage = new CodePrimitiveExpression(obsoleteMessageBuilder.ToString()); \
+ cmp.CustomAttributes.Add(new CodeAttributeDeclaration(obsoleteAttribute, new \
CodeAttributeArgument(obsoleteMessage))); + }
+ }
}
diff --git a/src/plugins/qyoto/PropertyGenerator.cs \
b/src/plugins/qyoto/PropertyGenerator.cs index f14dbb8..517e045 100644
--- a/src/plugins/qyoto/PropertyGenerator.cs
+++ b/src/plugins/qyoto/PropertyGenerator.cs
@@ -25,7 +25,6 @@ using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.CodeDom;
using System.Linq;
-using System.Text.RegularExpressions;
public unsafe class PropertyGenerator
{
@@ -56,9 +55,9 @@ public unsafe class PropertyGenerator
private readonly GeneratorData data;
private readonly Translator translator;
- private readonly Dictionary<CodeTypeDeclaration, List<string>> documentation;
+ private readonly Documentation documentation;
- public PropertyGenerator(GeneratorData data, Translator translator, \
Dictionary<CodeTypeDeclaration, List<string>> documentation) + public \
PropertyGenerator(GeneratorData data, Translator translator, Documentation \
documentation) {
this.data = data;
this.translator = translator;
@@ -119,21 +118,7 @@ public unsafe class PropertyGenerator
continue;
}
- if (documentation.ContainsKey(type))
- {
- IList<string> docs = documentation[type];
- for (int i = 0; i < docs.Count; i++)
- {
- Match match = Regex.Match(docs[i],
- prop.Name + " : (const )?" + prop.Type +
- @"\n(?<docs>This.*?)\nAccess functions:", RegexOptions.Singleline | \
RegexOptions.ExplicitCapture);
- if (match.Success)
- {
- Util.FormatComment(match.Groups["docs"].Value, cmp, i > 0);
- break;
- }
- }
- }
+ this.documentation.DocumentProperty(type, prop.Name, prop.Type, cmp);
cmp.Name = prop.Name;
// capitalize the first letter
StringBuilder builder = new StringBuilder(cmp.Name);
diff --git a/src/plugins/qyoto/QyotoHooks.cs b/src/plugins/qyoto/QyotoHooks.cs
index 582314e..20ea971 100644
--- a/src/plugins/qyoto/QyotoHooks.cs
+++ b/src/plugins/qyoto/QyotoHooks.cs
@@ -69,8 +69,12 @@ public unsafe class QyotoHooks : IHookProvider
public Translator Translator { get; set; }
public GeneratorData Data { get; set; }
private readonly Dictionary<string, CodeMemberMethod> eventMethods = new \
Dictionary<string, CodeMemberMethod>();
- private readonly Dictionary<CodeTypeDeclaration, List<string>> memberDocumentation \
= new Dictionary<CodeTypeDeclaration, List<string>>();
- private readonly List<string> staticDocumentation = new List<string>();
+ private Documentation documentation;
+
+ private Documentation Documentation
+ {
+ get { return this.documentation ?? (this.documentation = new \
Documentation(this.Data, this.Translator)); } + }
public void PreMembersHook(Smoke* smoke, Smoke.Class* klass, CodeTypeDeclaration \
type) {
@@ -312,68 +316,10 @@ public unsafe class QyotoHooks : IHookProvider
public void PreClassesHook()
{
- IDictionary<string, string> documentation = Documentation.Get(Data.Docs);
- foreach (CodeTypeDeclaration type in from smokeType in this.Data.SmokeTypeMap
- where string.IsNullOrEmpty((string) smokeType.Value.UserData["parent"])
- select smokeType.Value)
- {
- foreach (CodeTypeDeclaration nestedType in \
type.Members.OfType<CodeTypeDeclaration>().Where(t => !t.IsEnum))
- {
- this.GetClassDocs(nestedType, string.Format("{0}::{1}", type.Name, \
nestedType.Name),
- string.Format("{0}-{1}", type.Name, nestedType.Name), \
documentation);
- }
- this.GetClassDocs(type, type.Name, type.Name, documentation);
- }
- this.staticDocumentation.AddRange(from k in \
this.Translator.TypeStringMap.Keys.SelectMany(k => new[] { k + ".html", k + \
"-obsolete.html", k + "-qt3.html" })
- let key = k.ToLowerInvariant()
- where documentation.ContainsKey(key)
- select StripTags(documentation[key]));
- this.staticDocumentation.AddRange(from pair in documentation
- where pair.Key.StartsWith("q", \
StringComparison.Ordinal) &&
- pair.Key.EndsWith("-h.html", \
StringComparison.Ordinal)
- select StripTags(pair.Value));
- PropertyGenerator pg = new PropertyGenerator(Data, Translator, \
this.memberDocumentation); + PropertyGenerator pg = new PropertyGenerator(Data, \
Translator, this.Documentation); pg.Run();
}
- private void GetClassDocs(CodeTypeDeclaration type, string typeName, string \
fileName, IDictionary<string, string> documentation)
- {
- List<string> docs = new List<string>();
- foreach (string docFile in new[] { fileName + ".html", fileName + \
"-obsolete.html", fileName + "-qt3.html" })
- {
- if (documentation.ContainsKey(docFile.ToLowerInvariant()))
- {
- string classDocs = StripTags(documentation[docFile.ToLowerInvariant()]);
- Match match = Regex.Match(classDocs, string.Format(@"(?<class>((The {0})|(This \
class)).+?)More\.\.\..*?\n" +
- @"Detailed \
Description\s+(?<detailed>.*?)(\n){{3,}}" +
- @"((\w+ )*\w+ \
Documentation\n(?<members>.+))", typeName),
- RegexOptions.Singleline | \
RegexOptions.ExplicitCapture);
- if (match.Success)
- {
- type.Comments.Add(new CodeCommentStatement("<summary>", true));
- string summary = match.Groups["class"].Value.Trim();
- type.Comments.Add(new CodeCommentStatement(HtmlEncoder.HtmlEncode(summary), \
true));
- type.Comments.Add(new CodeCommentStatement("</summary>", true));
- string detailed = match.Groups["detailed"].Value.Replace(summary, \
string.Empty);
- Util.FormatComment(detailed.Replace("\n/", "\n /"), type, false, "remarks");
- string members = match.Groups["members"].Value;
- docs.Add(members);
- Match matchStatic = Regex.Match(members, "Related Non-Members(?<static>.+)",
- RegexOptions.Singleline | \
RegexOptions.ExplicitCapture);
- if (matchStatic.Success)
- {
- this.staticDocumentation.Add(matchStatic.Groups["static"].Value);
- }
- }
- else
- {
- docs.Add(classDocs);
- }
- }
- }
- this.memberDocumentation[type] = docs;
- }
-
void PostClassesHook()
{
if (!Data.CSharpTypeMap.ContainsKey("QAbstractScrollArea"))
@@ -389,274 +335,18 @@ public unsafe class QyotoHooks : IHookProvider
private void PostEnumMemberHook(Smoke* smoke, Smoke.Method* smokeMethod, \
CodeMemberField cmm, CodeTypeDeclaration type) {
- CodeTypeDeclaration parentType = this.memberDocumentation.Keys.FirstOrDefault(t => \
t.Name == (string) type.UserData["parent"]);
- if (parentType != null)
- {
- IList<string> docs = this.memberDocumentation[parentType];
- string typeName = Regex.Escape(parentType.Name) + "::" + Regex.Escape(type.Name);
- if (type.Comments.Count == 0)
- {
- for (int i = 0; i < docs.Count; i++)
- {
- const string enumDoc = @"enum {0}(\s*flags \
{1}::\w+\s+)?(?<docsStart>.*?)(\n){{3}}";
- Match matchEnum = Regex.Match(docs[i], string.Format(enumDoc, typeName, \
parentType.Name),
- RegexOptions.Singleline | \
RegexOptions.ExplicitCapture);
- if (matchEnum.Success)
- {
- string doc = (matchEnum.Groups["docsStart"].Value + \
matchEnum.Groups["docsEnd1"].Value).Trim();
- doc = Regex.Replace(doc,
- @"(The \S+ type is a typedef for QFlags<\S+>\. It stores \
an OR combination of \S+ values\.)",
- string.Empty);
- doc = Regex.Replace(doc,
- @"ConstantValue(Description)?.*?(((\n){2})|$)",
- string.Empty, RegexOptions.Singleline | \
RegexOptions.ExplicitCapture).Trim();
- if (!string.IsNullOrEmpty(doc))
- {
- Util.FormatComment(doc, type, i > 0);
- break;
- }
- }
- }
- }
- string memberName = Regex.Escape(parentType.Name) + "::" +
- \
Regex.Escape(ByteArrayManager.GetString(smoke->methodNames[smokeMethod->name]));
- const string memberDoc = @"enum {0}.*{1}\t[^\t\n]+\t(?<docs>.*?)(&\w+;)?(\n)";
- for (int i = 0; i < docs.Count; i++)
- {
- Match match = Regex.Match(docs[i], string.Format(memberDoc, typeName, \
memberName),
- RegexOptions.Singleline | \
RegexOptions.ExplicitCapture);
- if (match.Success)
- {
- string doc = match.Groups["docs"].Value.Trim();
- if (!string.IsNullOrEmpty(doc))
- {
- Util.FormatComment(char.ToUpper(doc[0]) + doc.Substring(1), cmm, i > 0);
- break;
- }
- }
- }
- }
+ this.Documentation.DocumentEnumMember(smoke, smokeMethod, cmm, type);
}
private void PostMethodBodyHooks(Smoke* smoke, Smoke.Method* smokeMethod, \
CodeMemberMethod cmm, CodeTypeDeclaration type) {
- this.CommentMember(smoke, smokeMethod, cmm, type);
+ this.Documentation.DocumentMember(smoke, smokeMethod, cmm, type);
GenerateEvent(cmm, cmm.Name, type, true);
}
private void PostAttributePropertyHook(CodeTypeMember cmm, CodeTypeDeclaration \
type) {
- if (this.memberDocumentation.ContainsKey(type))
- {
- IList<string> docs = this.memberDocumentation[type];
- string typeName = Regex.Escape(type.Name);
- string originalName = char.ToLowerInvariant(cmm.Name[0]) + cmm.Name.Substring(1);
- const string memberDoc = @"{0}::{1}\n\W*(?<docs>.*?)(\n\s*){{3}}";
- for (int i = 0; i < docs.Count; i++)
- {
- Match match = Regex.Match(docs[i], string.Format(memberDoc, typeName, \
originalName),
- RegexOptions.Singleline | \
RegexOptions.ExplicitCapture);
- if (match.Success)
- {
- Util.FormatComment(match.Groups["docs"].Value, cmm, i > 0);
- break;
- }
- }
- }
- }
-
- private void CommentMember(Smoke* smoke, Smoke.Method* smokeMethod, CodeTypeMember \
cmm, CodeTypeDeclaration type)
- {
- if (type.Name == Data.GlobalSpaceClassName || \
Translator.NamespacesAsClasses.Contains(type.Name))
- {
- this.CommentMember(smoke, smokeMethod, cmm, @"\w+", this.staticDocumentation, \
false);
- }
- else
- {
- if (this.memberDocumentation.ContainsKey(type))
- {
- this.CommentMember(smoke, smokeMethod, cmm, type.Name, \
this.memberDocumentation[type]);
- }
- }
- }
-
- private void CommentMember(Smoke* smoke, Smoke.Method* smokeMethod, CodeTypeMember \
cmm, string type, IEnumerable<string> docs, bool markObsolete = true)
- {
- string methodName = \
Regex.Escape(ByteArrayManager.GetString(smoke->methodNames[smokeMethod->name]));
- string[] argTypes = smoke->GetArgs(smokeMethod).Split(new[] { ", " }, \
StringSplitOptions.RemoveEmptyEntries);
- docs.Where((t, i) => TryMatch(type, methodName, cmm, t, i > 0 && markObsolete, \
argTypes)).Any();
- }
-
- private bool TryMatch(string type, string methodName, CodeTypeMember cmm, string \
docs, bool markObsolete, IEnumerable<string> argTypes)
- {
- const string memberDoc = @"(^|( --)|\n)\n([\w :*&<>,]+)?(({0}(\s*&)?::)| \
){1}(const)?( \[(\w+\s*)+\])?\n\W*(?<docs>.*?)(\n\s*){{1,2}}((&?\S* \
--)|((\n\s*){{2}}))";
- const string separator = @",\s*";
- StringBuilder signatureRegex = new StringBuilder(methodName).Append(@"\s*\(\s*(");
- bool anyArgs = false;
- foreach (string argType in argTypes)
- {
- if (!anyArgs)
- {
- signatureRegex.Append("?<args>");
- anyArgs = true;
- }
- signatureRegex.Append(this.GetTypeRegex(argType)).Append(@"(\s+\w+(\s*=\s*[^,\r\n]+(\(\s*\))?)?)?");
- signatureRegex.Append(separator);
- }
- if (anyArgs)
- {
- signatureRegex.Insert(signatureRegex.Length - separator.Length, '(');
- }
- else
- {
- signatureRegex.Append('(');
- }
- signatureRegex.Append(@"[\w :*&<>]+\s*=\s*[^,\r\n]+(\(\s*\))?(,\s*)?)*)\s*\)\s*");
- Match match = Regex.Match(docs, string.Format(memberDoc, type, signatureRegex),
- RegexOptions.Singleline | RegexOptions.ExplicitCapture);
- if (match.Success)
- {
- Util.FormatComment(match.Groups["docs"].Value, cmm, markObsolete);
- FillMissingParameterNames(cmm, match.Groups["args"].Value);
- return true;
- }
- return false;
- }
-
- private string GetTypeRegex(string argType)
- {
- StringBuilder typeBuilder = new StringBuilder(argType);
- FormatType(typeBuilder);
- typeBuilder.Insert(0, "((");
- typeBuilder.Append(')');
- if (this.Data.TypeDefsPerType.ContainsKey(argType))
- {
- foreach (StringBuilder typeDefBuilder in from typedef in \
this.Data.TypeDefsPerType[argType]
- select new StringBuilder(typedef))
- {
- FormatType(typeDefBuilder);
- typeBuilder.Append("|(").Append(typeDefBuilder).Append(')');
- }
- }
- typeBuilder.Append(')');
- return typeBuilder.ToString();
- }
-
- private void FormatType(StringBuilder typeBuilder)
- {
- int indexOfLt = int.MinValue;
- int indexOfGt = int.MinValue;
- int indexOfColon = int.MinValue;
- int firstColonIndex = int.MinValue;
- List<char> templateType = new List<char>(typeBuilder.Length);
- for (int i = typeBuilder.Length - 1; i >= 0; i--)
- {
- char @char = typeBuilder[i];
- switch (@char)
- {
- case '<':
- indexOfLt = i;
- break;
- case '>':
- indexOfGt = i;
- break;
- case ':':
- if (firstColonIndex < 0)
- {
- firstColonIndex = i;
- }
- else
- {
- if (i == firstColonIndex - 1)
- {
- indexOfColon = firstColonIndex;
- firstColonIndex = int.MinValue;
- }
- }
- break;
- }
- if (i > indexOfLt && i < indexOfGt)
- {
- typeBuilder.Remove(i, 1);
- templateType.Insert(0, @char);
- }
- }
- if (indexOfGt > indexOfLt)
- {
- typeBuilder.Replace("(", @"\(").Replace(")", @"\)");
- typeBuilder.Replace(@"*", @"\s*(\*|(\[\]))").Replace(@"&", @"\s*&").Replace(",", \
@",\s*");
- typeBuilder.Insert(indexOfLt + 1, this.GetTypeRegex(new \
string(templateType.ToArray())));
- }
- else
- {
- if (indexOfColon > 0)
- {
- int parentTypeStart = Math.Max(indexOfLt + 1, 0);
- typeBuilder.Remove(parentTypeStart, indexOfColon + 1 - parentTypeStart);
- typeBuilder.Insert(parentTypeStart, @"(const )?(\w+::)?");
- typeBuilder.Replace(@"*", @"\s*(\*|(\[\]))").Replace(@"&", @"\s*&").Replace(",", \
@",\s*");
- }
- else
- {
- typeBuilder.Replace("(", @"\(").Replace(")", @"\)");
- typeBuilder.Replace(@"*", @"\s*(\*|(\[\]))").Replace(@"&", @"\s*&").Replace(",", \
@",\s*");
- }
- }
- }
-
- private static void FillMissingParameterNames(CodeTypeMember cmm, string signature)
- {
- CodeMemberMethod method = cmm as CodeMemberMethod;
- if (method == null)
- {
- return;
- }
- List<string> args = new List<string>(signature.Split(','));
- if (args.Count < method.Parameters.Count)
- {
- // operator
- args.Insert(0, "one");
- }
- const string regex = @"^(.+?\s+)(?<name>\w+)(\s*=\s*[^\(,\s]+(\(\s*\))?)?\s*$";
- MethodsGenerator.RenameParameters(method, (from arg in args
- select Regex.Match(arg, \
regex).Groups["name"].Value).ToList());
- }
-
- private static string StripTags(string source)
- {
- char[] array = new char[source.Length];
- List<char> tagArray = new List<char>();
- int arrayIndex = 0;
- bool inside = false;
-
- foreach (char @let in source)
- {
- if (@let == '<')
- {
- inside = true;
- continue;
- }
- if (@let == '>')
- {
- inside = false;
- continue;
- }
- if (inside)
- {
- tagArray.Add(@let);
- }
- else
- {
- string tag = new string(tagArray.ToArray());
- if (tag.Contains("/tdtd"))
- {
- array[arrayIndex++] = '\t';
- }
- tagArray.Clear();
- array[arrayIndex++] = @let;
- }
- }
- return HtmlEncoder.HtmlDecode(new string(array, 0, arrayIndex));
+ this.Documentation.DocumentAttributeProperty(cmm, type);
}
private void GenerateEvent(CodeMemberMethod cmm, string name, CodeTypeDeclaration \
type, bool isVirtual)
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic