diff options
author | Joel Martinez <joelmartinez@gmail.com> | 2017-09-15 00:01:50 +0300 |
---|---|---|
committer | Joel Martinez <joelmartinez@gmail.com> | 2017-09-15 00:01:50 +0300 |
commit | 1b452b9185083e7255d58a04a60fb5ddec398445 (patch) | |
tree | 7fe185dee5baf81e4e2871a8b4d3e5ad0e814415 | |
parent | 2c1edaf8a0396c0f6f4f8bf9d54526d6be8d6f4d (diff) |
mdoc: Improves member/xml node matching on members with modopt/modreq.preview-5.0.0.23
Additionally, duplicate members that differ very slightly (as in the case of members with modopt/modreq made with older versions of mdoc) will now be deleted instead of simply raisining a warning. Closes #107
-rw-r--r-- | mdoc/Consts.cs | 2 | ||||
-rw-r--r-- | mdoc/Mono.Documentation/monodocer.cs | 77 | ||||
-rw-r--r-- | mdoc/mdoc.Test/AssemblyGenerator.workbook | 86 |
3 files changed, 141 insertions, 24 deletions
diff --git a/mdoc/Consts.cs b/mdoc/Consts.cs index 2a014973..eebed4e0 100644 --- a/mdoc/Consts.cs +++ b/mdoc/Consts.cs @@ -3,6 +3,6 @@ namespace Mono.Documentation { public static class Consts { - public static string MonoVersion = "5.0.0.22"; + public static string MonoVersion = "5.0.0.23"; } } diff --git a/mdoc/Mono.Documentation/monodocer.cs b/mdoc/Mono.Documentation/monodocer.cs index a7842815..859e2833 100644 --- a/mdoc/Mono.Documentation/monodocer.cs +++ b/mdoc/Mono.Documentation/monodocer.cs @@ -1309,10 +1309,9 @@ class MDocUpdater : MDocCommand if (object.ReferenceEquals (oldmember, seenmembers [sig])) { // ignore, already seen } - else if (DefaultMemberComparer.Compare (oldmember, seenmembers [sig]) == 0) + else DeleteMember ("Duplicate Member Found", output, oldmember, todelete, type); - else - Warning ("TODO: found a duplicate member '{0}', but it's not identical to the prior member found!", sig); + continue; } @@ -4227,6 +4226,24 @@ class DocumentationMember { public string MemberName; public string MemberType; + /// <summary>Removes modreq and modopt from ReturnType, Parameters, and TypeParameters</summary> + private void CleanTypes() { + ReturnType = MemberFormatter.RemoveMod (ReturnType); + MemberType = MemberFormatter.RemoveMod (MemberType); + + if (Parameters != null) + { + for (var i = 0; i < Parameters.Count; i++) + Parameters[i] = MemberFormatter.RemoveMod (Parameters[i]); + } + + if (TypeParameters != null) + { + for (var i = 0; i < TypeParameters.Count; i++) + TypeParameters[i] = MemberFormatter.RemoveMod (TypeParameters[i]); + } + } + public DocumentationMember (XmlReader reader) { MemberName = reader.GetAttribute ("MemberName"); @@ -4279,6 +4296,8 @@ class DocumentationMember { } else { DiscernTypeParameters (); } + + CleanTypes (); } public DocumentationMember (XmlNode node) @@ -4311,6 +4330,8 @@ class DocumentationMember { else { DiscernTypeParameters (); } + + CleanTypes (); } void DiscernTypeParameters () @@ -4390,32 +4411,42 @@ public abstract class MemberFormatter { } protected virtual string GetTypeName (TypeReference type, DynamicParserContext context) - { - if (type == null) - throw new ArgumentNullException (nameof (type)); + { + if (type == null) + throw new ArgumentNullException (nameof (type)); - var typeName = _AppendTypeName (new StringBuilder (type.Name.Length), type, context).ToString (); + var typeName = _AppendTypeName (new StringBuilder (type.Name.Length), type, context).ToString (); + typeName = RemoveMod (typeName); - // For custom modifiers (modopt/modreq), we are just excising them - // via string manipulation for simplicity; since these cannot be - // expressed in C#. If finer control is needed in the future, you can - // use IModifierType, PointerType, ByReferenceType, etc. + return typeName; + } - int modIndex = Math.Max (typeName.LastIndexOf ("modopt(", StringComparison.Ordinal), typeName.LastIndexOf ("modreq(", StringComparison.Ordinal)); - if (modIndex > 0) { - var tname = typeName.Substring (0, modIndex-1); - var parenIndex = typeName.LastIndexOf (')'); - if (parenIndex == typeName.Length - 2) { // see if there's metadata like a pointer - tname += typeName.Last (); - } - typeName = tname; - } + public static string RemoveMod (string typeName) + { + if (string.IsNullOrWhiteSpace (typeName)) return typeName; - return typeName; - } + // For custom modifiers (modopt/modreq), we are just excising them + // via string manipulation for simplicity; since these cannot be + // expressed in C#. If finer control is needed in the future, you can + // use IModifierType, PointerType, ByReferenceType, etc. + + int modIndex = Math.Max (typeName.LastIndexOf ("modopt(", StringComparison.Ordinal), typeName.LastIndexOf ("modreq(", StringComparison.Ordinal)); + if (modIndex > 0) + { + var tname = typeName.Substring (0, modIndex - 1); + var parenIndex = typeName.LastIndexOf (')'); + if (parenIndex == typeName.Length - 2) + { // see if there's metadata like a pointer + tname += typeName.Last (); + } + typeName = tname; + } + + return typeName; + } - protected virtual char[] ArrayDelimeters { + protected virtual char[] ArrayDelimeters { get {return new char[]{'[', ']'};} } diff --git a/mdoc/mdoc.Test/AssemblyGenerator.workbook b/mdoc/mdoc.Test/AssemblyGenerator.workbook new file mode 100644 index 00000000..9a65e07b --- /dev/null +++ b/mdoc/mdoc.Test/AssemblyGenerator.workbook @@ -0,0 +1,86 @@ +--- +id: c70709d1-d0a6-4dec-9ce5-de04540e5de6 +title: AssemblyGenerator +uti: com.xamarin.workbook +platforms: +- Console +--- + +From [this article](https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.isudtreturn\(v=vs.110\).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1) + +```csharp +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using System.Threading; +``` + +```csharp +class CodeEmitter { + AssemblyBuilder asmBuilder; + string asmName; + ModuleBuilder modBuilder; + public CodeEmitter(string name) { + asmName = name; + AssemblyName aname = new AssemblyName { Name = name }; + AppDomain currentDomain = Thread.GetDomain(); + asmBuilder = currentDomain.DefineDynamicAssembly(aname, AssemblyBuilderAccess.RunAndSave); + modBuilder = asmBuilder.DefineDynamicModule(asmName); + } + + public TypeBuilder CreateType(string name) { + return modBuilder.DefineType(name, TypeAttributes.Public); + } + + public void WriteAssembly(MethodBuilder entryPoint) { + asmBuilder.SetEntryPoint(entryPoint); + asmBuilder.Save(asmName); + } +} +``` + +```csharp +void main() { + CodeEmitter e = new CodeEmitter("test-mod.exe"); + TypeBuilder mainClass = e.CreateType("MainClass"); + + // main method + MethodBuilder mBuilder = mainClass.DefineMethod("mainMethod", MethodAttributes.Static); + ILGenerator ilGen = mBuilder.GetILGenerator(); + ilGen.Emit(OpCodes.Ldstr, "Hello World"); + Type[] type = new [] {typeof(string)}; + MethodInfo writeMI = typeof(Console).GetMethod("WriteLine", type); + ilGen.EmitCall(OpCodes.Call, writeMI, null); + ilGen.Emit(OpCodes.Ret); + + Type[] fType = new [] { typeof(IsUdtReturn)}; + + // operator overload + MethodBuilder sBuilder = mainClass.DefineMethod( + "op_Decrement", + MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.Public, + CallingConventions.Any, + Type.GetType("System.Void"), + fType, // rtype required mods + null, // rtype optional mods + null, // parameters + null, // parameter modreq + null); // parameters modopt + + var silGen = sBuilder.GetILGenerator(); + silGen.Emit(OpCodes.Ret); + + // field + //Type[] fType = new [] { typeof(IsUdtReturn)}; + mainClass.DefineField("modifiedInteger", Type.GetType("System.Type"), fType, null, FieldAttributes.Public); + + // write + mainClass.CreateType(); + e.WriteAssembly(mBuilder); + Console.WriteLine("Assembly created"); +} +``` + +```csharp +main(); +```
\ No newline at end of file |