From 0a113eee7262e2036cc0287d797d471866b68226 Mon Sep 17 00:00:00 2001 From: Min Huang Date: Mon, 14 Mar 2022 16:28:49 +0800 Subject: [PATCH 01/13] Support C# 9 nint/nuint --- mdoc/Consts.cs | 1 + .../Updater/AttributeParserContext.cs | 36 ++++++++++++++++--- .../Updater/EmptyAttributeParserContext.cs | 5 +++ .../Formatters/CSharpFullMemberFormatter.cs | 16 +++++++-- .../CSharpNativeTypeMemberFormatter.cs | 2 +- .../Updater/IAttributeParserContext.cs | 1 + mdoc/mdoc.Test/FormatterTests.cs | 19 ++++++++++ .../mdoc.Test/SampleClasses/NativeIntClass.cs | 30 ++++++++++++++++ 8 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 mdoc/mdoc.Test/SampleClasses/NativeIntClass.cs diff --git a/mdoc/Consts.cs b/mdoc/Consts.cs index e047f2afb..cc165d1fe 100644 --- a/mdoc/Consts.cs +++ b/mdoc/Consts.cs @@ -51,5 +51,6 @@ public static class Consts public const string InAttribute = "System.Runtime.InteropServices.InAttribute"; public const string TupleElementNamesAttribute = "System.Runtime.CompilerServices.TupleElementNamesAttribute"; public const string IsExternalInit = "System.Runtime.CompilerServices.IsExternalInit"; + public const string NativeIntegerAttribute = "System.Runtime.CompilerServices.NativeIntegerAttribute"; } } diff --git a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs index e294d7cb8..c1bf4b3ad 100644 --- a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs +++ b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs @@ -12,10 +12,12 @@ public class AttributeParserContext : IAttributeParserContext private int nullableAttributeIndex; private int dynamicAttributeIndex; private int tupleNameAttributeIndex; + private int nativeIntegerAttributeIndex; private ICustomAttributeProvider provider; private ReadOnlyCollection nullableAttributeFlags; private ReadOnlyCollection dynamicAttributeFlags; private string[] tupleElementNames; + private bool[] nativeIntegerFlags; private AttributeParserContext(ICustomAttributeProvider provider) { @@ -24,6 +26,7 @@ private AttributeParserContext(ICustomAttributeProvider provider) ReadDynamicAttribute(); ReadNullableAttribute(); ReadTupleElementNames(); + ReadNativeIntegerAttribute(); } private bool ExistsNullableAttribute @@ -82,6 +85,11 @@ public string GetTupleElementName() return (tupleElementNames == null || tupleNameAttributeIndex >= tupleElementNames.Length) ? null : tupleElementNames[tupleNameAttributeIndex++]; } + public bool IsNativeInteger() + { + return (nativeIntegerFlags == null || nativeIntegerAttributeIndex >= nativeIntegerFlags.Length) ? false : nativeIntegerFlags[nativeIntegerAttributeIndex++]; + } + private void ReadDynamicAttribute() { DynamicTypeProvider dynamicTypeProvider = new DynamicTypeProvider(provider); @@ -99,16 +107,36 @@ private void ReadNullableAttribute() } private void ReadTupleElementNames() + { + tupleElementNames = ReadCustomAttributeValue( + () => null, + Consts.TupleElementNamesAttribute); + } + + private void ReadNativeIntegerAttribute() + { + nativeIntegerFlags = ReadCustomAttributeValue( + () => new bool[] { true }, + Consts.NativeIntegerAttribute); + } + + private T[] ReadCustomAttributeValue(Func init, string attributeName) { if (provider != null && provider.HasCustomAttributes) { - var tupleNamesAttr = provider.CustomAttributes.Where(attr => attr.AttributeType.FullName == Consts.TupleElementNamesAttribute).FirstOrDefault(); - if (tupleNamesAttr != null) + var customAttribute = provider.CustomAttributes.Where(attr => attr.AttributeType.FullName == attributeName).FirstOrDefault(); + if (customAttribute != null) { - var constructorArgs = tupleNamesAttr.ConstructorArguments.FirstOrDefault().Value as CustomAttributeArgument[]; - tupleElementNames = constructorArgs?.Select(arg => arg.Value as string).ToArray(); + T[] result = init(); + if (customAttribute.HasConstructorArguments) + { + var constructorArgs = customAttribute.ConstructorArguments[0].Value as CustomAttributeArgument[]; + result = constructorArgs?.Select(arg => (T)arg.Value).ToArray(); + } + return result; } } + return null; } } } \ No newline at end of file diff --git a/mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs index 71b638fd7..c21a82225 100644 --- a/mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs +++ b/mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs @@ -31,5 +31,10 @@ public string GetTupleElementName() { return null; } + + public bool IsNativeInteger() + { + return false; + } } } diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs index 3a36a5e73..c1a4c155a 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs @@ -25,7 +25,7 @@ protected override StringBuilder AppendNamespace (StringBuilder buf, TypeReferen return buf; } - protected virtual string GetCSharpType (string t) + protected virtual string GetCSharpType(string t, IAttributeParserContext context = null) { // make sure there are no modifiers in the type string (add them back before returning) string typeToCompare = t; @@ -56,6 +56,18 @@ protected virtual string GetCSharpType (string t) case "System.Void": typeToCompare = "void"; break; case "System.String": typeToCompare = "string"; break; case "System.Object": typeToCompare = "object"; break; + case "System.IntPtr": + if (context != null && context.IsNativeInteger()) + { + typeToCompare = "nint"; + } + break; + case "System.UIntPtr": + if (context != null && context.IsNativeInteger()) + { + typeToCompare = "nuint"; + } + break; } if (splitType != null) @@ -83,7 +95,7 @@ protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReferenc return base.AppendTypeName (buf, type, context); } - string s = GetCSharpType (t); + string s = GetCSharpType (t, context); if (s != null) { context.NextDynamicFlag(); diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpNativeTypeMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpNativeTypeMemberFormatter.cs index a37f98487..67ba1831d 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpNativeTypeMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpNativeTypeMemberFormatter.cs @@ -4,7 +4,7 @@ class CSharpNativeTypeMemberFormatter : CSharpFullMemberFormatter { public CSharpNativeTypeMemberFormatter(TypeMap map) : base(map) { } - protected override string GetCSharpType (string t) + protected override string GetCSharpType (string t, IAttributeParserContext attributeParserContext = null) { string moddedType = base.GetCSharpType (t); diff --git a/mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs index 471c661b9..21feede9c 100644 --- a/mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs +++ b/mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs @@ -6,5 +6,6 @@ public interface IAttributeParserContext bool IsDynamic(); bool IsNullable(); string GetTupleElementName(); + bool IsNativeInteger(); } } diff --git a/mdoc/mdoc.Test/FormatterTests.cs b/mdoc/mdoc.Test/FormatterTests.cs index fd987decd..607a18198 100644 --- a/mdoc/mdoc.Test/FormatterTests.cs +++ b/mdoc/mdoc.Test/FormatterTests.cs @@ -464,6 +464,25 @@ public void CSharpInitOnlySetterTest(string propertyName, string expectedSignatu Assert.AreEqual(expectedSignature, propertySignature); } + [Test] + public void CSharpNativeIntGenericTypeTest() + { + var type = GetType(typeof(SampleClasses.GenericNativeIntClass<>)); + var typeSignature = formatter.GetDeclaration(type); + Assert.AreEqual("public class GenericNativeIntClass", typeSignature); + } + + [TestCase("Method1", "public (nint,nuint) Method1 (nint a, nuint b, IntPtr c, UIntPtr d);")] + [TestCase("Method2", "public (nint,nuint) Method2 (List a, Dictionary b);")] + [TestCase("Method3", "public (nint,nuint) Method3 ((nint,nuint) a, (nuint,IntPtr) b, (UIntPtr,string) c);")] + [TestCase("Method4", "public (((nint a,IntPtr) b,UIntPtr c) d,(nint e,(nuint f,IntPtr g) h) i) Method4 ();")] + public void CSharpNativeIntMethodTest(string methodName, string expectedSignature) + { + var method = GetMethod(typeof(SampleClasses.NativeIntClass), m => m.Name == methodName); + var methodSignature = formatter.GetDeclaration(method); + Assert.AreEqual(expectedSignature, methodSignature); + } + #region Helper Methods string RealTypeName(string name){ switch (name) { diff --git a/mdoc/mdoc.Test/SampleClasses/NativeIntClass.cs b/mdoc/mdoc.Test/SampleClasses/NativeIntClass.cs new file mode 100644 index 000000000..19fed8996 --- /dev/null +++ b/mdoc/mdoc.Test/SampleClasses/NativeIntClass.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace mdoc.Test.SampleClasses +{ + public class NativeIntClass + { + public (nint, nuint) Method1(nint a, nuint b, IntPtr c, UIntPtr d) + { + return (a + c, b + d); + } + + public (nint, nuint) Method2(List a, Dictionary b) + { + return (a[0], b[0]); + } + + public (nint, nuint) Method3((nint, nuint) a, (nuint, IntPtr) b, (UIntPtr, string) c) + { + return (a.Item1 + b.Item2, b.Item1 + c.Item1); + } + + public (((nint a, IntPtr) b, UIntPtr c) d, (nint e, (nuint f, IntPtr g) h) i) Method4() => throw null; + } + + public class GenericNativeIntClass + { + + } +} \ No newline at end of file From 6a399424a60be5abab36a0630bf675ba7f994b97 Mon Sep 17 00:00:00 2001 From: Min Huang Date: Mon, 14 Mar 2022 16:35:16 +0800 Subject: [PATCH 02/13] update --- mdoc/Mono.Documentation/Updater/AttributeParserContext.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs index c1bf4b3ad..d4cbf98ef 100644 --- a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs +++ b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs @@ -109,7 +109,7 @@ private void ReadNullableAttribute() private void ReadTupleElementNames() { tupleElementNames = ReadCustomAttributeValue( - () => null, + null, Consts.TupleElementNamesAttribute); } @@ -127,7 +127,7 @@ private T[] ReadCustomAttributeValue(Func init, string attributeName) var customAttribute = provider.CustomAttributes.Where(attr => attr.AttributeType.FullName == attributeName).FirstOrDefault(); if (customAttribute != null) { - T[] result = init(); + T[] result = init?.Invoke(); if (customAttribute.HasConstructorArguments) { var constructorArgs = customAttribute.ConstructorArguments[0].Value as CustomAttributeArgument[]; From f8fd0fd0e8fdab849bd5f59643895ed0ac2c6a1f Mon Sep 17 00:00:00 2001 From: Min Huang Date: Mon, 14 Mar 2022 18:01:53 +0800 Subject: [PATCH 03/13] update --- mdoc/Mono.Documentation/Updater/AttributeParserContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs index d4cbf98ef..225ac19fb 100644 --- a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs +++ b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs @@ -87,7 +87,7 @@ public string GetTupleElementName() public bool IsNativeInteger() { - return (nativeIntegerFlags == null || nativeIntegerAttributeIndex >= nativeIntegerFlags.Length) ? false : nativeIntegerFlags[nativeIntegerAttributeIndex++]; + return nativeIntegerFlags != null && nativeIntegerAttributeIndex < nativeIntegerFlags.Length && nativeIntegerFlags[nativeIntegerAttributeIndex++]; } private void ReadDynamicAttribute() From a4194fda23556a4c274011e74ff397c9389dc622 Mon Sep 17 00:00:00 2001 From: Min Huang Date: Mon, 14 Mar 2022 18:12:23 +0800 Subject: [PATCH 04/13] update --- .../Updater/AttributeParserContext.cs | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs index 225ac19fb..91b4c042b 100644 --- a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs +++ b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs @@ -122,21 +122,16 @@ private void ReadNativeIntegerAttribute() private T[] ReadCustomAttributeValue(Func init, string attributeName) { - if (provider != null && provider.HasCustomAttributes) - { - var customAttribute = provider.CustomAttributes.Where(attr => attr.AttributeType.FullName == attributeName).FirstOrDefault(); - if (customAttribute != null) - { - T[] result = init?.Invoke(); - if (customAttribute.HasConstructorArguments) - { - var constructorArgs = customAttribute.ConstructorArguments[0].Value as CustomAttributeArgument[]; - result = constructorArgs?.Select(arg => (T)arg.Value).ToArray(); - } - return result; - } - } - return null; + if (provider == null || !provider.HasCustomAttributes) return null; + + var customAttribute = provider.CustomAttributes.Where(attr => attr.AttributeType.FullName == attributeName).FirstOrDefault(); + + if (customAttribute == null) return null; + + if (!customAttribute.HasConstructorArguments) return init?.Invoke(); + + var constructorArgs = customAttribute.ConstructorArguments[0].Value as CustomAttributeArgument[]; + return constructorArgs?.Select(arg => (T)arg.Value).ToArray(); } } } \ No newline at end of file From 5d92fd9e55d4a667c12e5a83d621aa3a05d50d96 Mon Sep 17 00:00:00 2001 From: Min Huang Date: Mon, 14 Mar 2022 18:39:48 +0800 Subject: [PATCH 05/13] update --- .../Formatters/CSharpFullMemberFormatter.cs | 28 +++++++++---------- .../CSharpNativeTypeMemberFormatter.cs | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs index c1a4c155a..b75f4821a 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs @@ -12,6 +12,12 @@ public class CSharpFullMemberFormatter : MemberFormatter public CSharpFullMemberFormatter() : this(null) {} public CSharpFullMemberFormatter(TypeMap map) : base(map) { } + private static readonly Dictionary nativeIntTypeMap = new Dictionary() + { + { "System.IntPtr", "nint" }, + { "System.UIntPtr", "nuint" }, + }; + public override string Language { get { return "C#"; } @@ -25,7 +31,7 @@ protected override StringBuilder AppendNamespace (StringBuilder buf, TypeReferen return buf; } - protected virtual string GetCSharpType(string t, IAttributeParserContext context = null) + protected virtual string GetCSharpType(string t) { // make sure there are no modifiers in the type string (add them back before returning) string typeToCompare = t; @@ -56,18 +62,6 @@ protected virtual string GetCSharpType(string t, IAttributeParserContext context case "System.Void": typeToCompare = "void"; break; case "System.String": typeToCompare = "string"; break; case "System.Object": typeToCompare = "object"; break; - case "System.IntPtr": - if (context != null && context.IsNativeInteger()) - { - typeToCompare = "nint"; - } - break; - case "System.UIntPtr": - if (context != null && context.IsNativeInteger()) - { - typeToCompare = "nuint"; - } - break; } if (splitType != null) @@ -95,7 +89,13 @@ protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReferenc return base.AppendTypeName (buf, type, context); } - string s = GetCSharpType (t, context); + if (nativeIntTypeMap.TryGetValue(t, out string typeName) && context.IsNativeInteger()) + { + return buf.Append(typeName); + } + + string s = GetCSharpType (t); + if (s != null) { context.NextDynamicFlag(); diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpNativeTypeMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpNativeTypeMemberFormatter.cs index 67ba1831d..a37f98487 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpNativeTypeMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpNativeTypeMemberFormatter.cs @@ -4,7 +4,7 @@ class CSharpNativeTypeMemberFormatter : CSharpFullMemberFormatter { public CSharpNativeTypeMemberFormatter(TypeMap map) : base(map) { } - protected override string GetCSharpType (string t, IAttributeParserContext attributeParserContext = null) + protected override string GetCSharpType (string t) { string moddedType = base.GetCSharpType (t); From 46d47e156e5e2086a8c396f8fa9c7d84df937dee Mon Sep 17 00:00:00 2001 From: Min Huang Date: Mon, 14 Mar 2022 18:40:56 +0800 Subject: [PATCH 06/13] update --- .../Updater/Formatters/CSharpFullMemberFormatter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs index b75f4821a..151610fde 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs @@ -95,7 +95,6 @@ protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReferenc } string s = GetCSharpType (t); - if (s != null) { context.NextDynamicFlag(); From ce3713a7c0f0593cab1cff5c0377a5c0c1ad79c6 Mon Sep 17 00:00:00 2001 From: Min Huang Date: Tue, 15 Mar 2022 12:04:18 +0800 Subject: [PATCH 07/13] update --- .../Updater/AttributeParserContext.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs index 91b4c042b..a472ec10d 100644 --- a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs +++ b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs @@ -108,19 +108,17 @@ private void ReadNullableAttribute() private void ReadTupleElementNames() { - tupleElementNames = ReadCustomAttributeValue( - null, - Consts.TupleElementNamesAttribute); + tupleElementNames = ReadCustomAttributeValue(Consts.TupleElementNamesAttribute); } private void ReadNativeIntegerAttribute() { nativeIntegerFlags = ReadCustomAttributeValue( - () => new bool[] { true }, - Consts.NativeIntegerAttribute); + Consts.NativeIntegerAttribute, + () => new bool[] { true }); } - private T[] ReadCustomAttributeValue(Func init, string attributeName) + private T[] ReadCustomAttributeValue(string attributeName, Func init = null) { if (provider == null || !provider.HasCustomAttributes) return null; From fb882195b9881c70cdf21f49c72b41eaa54c58f2 Mon Sep 17 00:00:00 2001 From: Min Huang Date: Thu, 17 Mar 2022 16:48:43 +0800 Subject: [PATCH 08/13] update --- .../AttributeFormatters/AttributeFormatter.cs | 35 +++++++++++++------ .../Formatters/CSharpFullMemberFormatter.cs | 2 +- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs index b8076d73f..16e2f8bd6 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs @@ -77,15 +77,6 @@ public virtual bool TryGetAttributeString(CustomAttribute attribute, out string return false; } - TypeDefinition attrType = attribute.AttributeType as TypeDefinition; - if (attrType != null && !DocUtils.IsPublic(attrType) - || (FormatterManager.SlashdocFormatter.GetName(attribute.AttributeType) == null) - || Array.IndexOf(IgnorableAttributes, attribute.AttributeType.FullName) >= 0) - { - rval = null; - return false; - } - var fields = new List(); for (int i = 0; i < attribute.ConstructorArguments.Count; ++i) @@ -127,11 +118,33 @@ public virtual string MakeAttributesValueString(object argumentValue, TypeRefere private bool IsIgnoredAttribute(CustomAttribute customAttribute) { + TypeDefinition attrType = customAttribute.AttributeType as TypeDefinition; + + if (attrType == null) return true; + // An Obsolete attribute with a known string is added to all ref-like structs // https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/span-safety.md#metadata-representation-or-ref-like-structs - return customAttribute.AttributeType.FullName == typeof(ObsoleteAttribute).FullName + if (attrType.FullName == typeof(ObsoleteAttribute).FullName && customAttribute.HasConstructorArguments - && customAttribute.ConstructorArguments.First().Value.ToString() == Consts.RefTypeObsoleteString; + && customAttribute.ConstructorArguments.First().Value.ToString() == Consts.RefTypeObsoleteString) + { + return true; + } + + // Expose this attribute in ECMAXML to let ECMA2YML pick up + // https://ceapex.visualstudio.com/Engineering/_workitems/edit/550401 + if (attrType.FullName == Consts.NativeIntegerAttribute) + { + return false; + } + + if (!DocUtils.IsPublic(attrType) || (FormatterManager.SlashdocFormatter.GetName(customAttribute.AttributeType) == null) + || Array.IndexOf(IgnorableAttributes, customAttribute.AttributeType.FullName) >= 0) + { + return true; + } + + return false; } // FIXME: get TypeReferences instead of string comparison? diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs index 151610fde..faabdfa07 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs @@ -163,7 +163,7 @@ protected override StringBuilder AppendSpecialGenericNullableValueTypeName (Stri genArgTypeList.Add (underlyingTypeName); } var genArgList = genInst.GenericArguments.Select((_, index) => string.Format("{0}{1}", genArgTypeList[index], genArgNameList[index] == null ? String.Empty : (" " + genArgNameList[index]))); - buf.Append (string.Join (",", genArgList)); + buf.Append (string.Join (", ", genArgList)); buf.Append (")"); return buf; } From 9b3789c440a837da213365b10ce24948986ef06b Mon Sep 17 00:00:00 2001 From: Min Huang Date: Thu, 17 Mar 2022 16:55:34 +0800 Subject: [PATCH 09/13] update --- .../Updater/Formatters/CSharpFullMemberFormatter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs index faabdfa07..063688556 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs @@ -12,7 +12,7 @@ public class CSharpFullMemberFormatter : MemberFormatter public CSharpFullMemberFormatter() : this(null) {} public CSharpFullMemberFormatter(TypeMap map) : base(map) { } - private static readonly Dictionary nativeIntTypeMap = new Dictionary() + private static readonly Dictionary NativeIntTypeMap = new Dictionary() { { "System.IntPtr", "nint" }, { "System.UIntPtr", "nuint" }, @@ -89,7 +89,7 @@ protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReferenc return base.AppendTypeName (buf, type, context); } - if (nativeIntTypeMap.TryGetValue(t, out string typeName) && context.IsNativeInteger()) + if (NativeIntTypeMap.TryGetValue(t, out string typeName) && context.IsNativeInteger()) { return buf.Append(typeName); } From 3338fa0b3aadaf40756526eeef2dafc37b1e1cdd Mon Sep 17 00:00:00 2001 From: Min Huang Date: Thu, 17 Mar 2022 17:10:05 +0800 Subject: [PATCH 10/13] fix test cases --- mdoc/mdoc.Test/FormatterTests.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mdoc/mdoc.Test/FormatterTests.cs b/mdoc/mdoc.Test/FormatterTests.cs index 607a18198..5bdc07d22 100644 --- a/mdoc/mdoc.Test/FormatterTests.cs +++ b/mdoc/mdoc.Test/FormatterTests.cs @@ -297,7 +297,7 @@ public void CSharpTuple() var member = GetMethod(typeof(NullablesAndTuples), m => m.Name == "TupleReturn"); var formatter = new CSharpFullMemberFormatter(); var sig = formatter.GetDeclaration(member); - Assert.AreEqual("public (int,string) TupleReturn ();", sig); + Assert.AreEqual("public (int, string) TupleReturn ();", sig); } [Test] @@ -425,7 +425,7 @@ public void CSharpTupleNamesTypeTest() { var type = GetType(typeof(SampleClasses.TupleNamesTestClass<,>)); var typeSignature = formatter.GetDeclaration(type); - Assert.AreEqual("public class TupleNamesTestClass : IComparable<(T1,T2)>", typeSignature); + Assert.AreEqual("public class TupleNamesTestClass : IComparable<(T1, T2)>", typeSignature); } [Test] @@ -433,7 +433,7 @@ public void CSharpTupleNamesPropertyTest() { var property = GetProperty(typeof(SampleClasses.TupleNamesTestClass<,>), m => m.Name == "TuplePropertyType"); var propertySignature = formatter.GetDeclaration(property); - Assert.AreEqual("public (int a,int b) TuplePropertyType { get; }", propertySignature); + Assert.AreEqual("public (int a, int b) TuplePropertyType { get; }", propertySignature); } [Test] @@ -441,11 +441,11 @@ public void CSharpTupleNamesFieldTest() { var field = GetField(GetType(typeof(SampleClasses.TupleNamesTestClass<,>)), "TupleField"); var fieldSignature = formatter.GetDeclaration(field); - Assert.AreEqual("public (int a,int b,int c) TupleField;", fieldSignature); + Assert.AreEqual("public (int a, int b, int c) TupleField;", fieldSignature); } - [TestCase("TupleMethod", "public (int a,int,int b) TupleMethod ((int,int) t1, (int b,int c,int d) t2, (int,int) t3);")] - [TestCase("RecursiveTupleMethod", "public ((int a,long b) c,int d) RecursiveTupleMethod ((((int a,long) b,string c) d,(int e,(float f,float g) h) i,int j) t);")] + [TestCase("TupleMethod", "public (int a, int, int b) TupleMethod ((int, int) t1, (int b, int c, int d) t2, (int, int) t3);")] + [TestCase("RecursiveTupleMethod", "public ((int a, long b) c,int d) RecursiveTupleMethod ((((int a, long) b, string c) d,(int e, (float f, float g) h) i, int j) t);")] public void CSharpTupleNamesMethodTest(string methodName, string expectedSignature) { var method = GetMethod(typeof(SampleClasses.TupleNamesTestClass<,>), m => m.Name == methodName); @@ -472,10 +472,10 @@ public void CSharpNativeIntGenericTypeTest() Assert.AreEqual("public class GenericNativeIntClass", typeSignature); } - [TestCase("Method1", "public (nint,nuint) Method1 (nint a, nuint b, IntPtr c, UIntPtr d);")] - [TestCase("Method2", "public (nint,nuint) Method2 (List a, Dictionary b);")] - [TestCase("Method3", "public (nint,nuint) Method3 ((nint,nuint) a, (nuint,IntPtr) b, (UIntPtr,string) c);")] - [TestCase("Method4", "public (((nint a,IntPtr) b,UIntPtr c) d,(nint e,(nuint f,IntPtr g) h) i) Method4 ();")] + [TestCase("Method1", "public (nint, nuint) Method1 (nint a, nuint b, IntPtr c, UIntPtr d);")] + [TestCase("Method2", "public (nint, nuint) Method2 (List a, Dictionary b);")] + [TestCase("Method3", "public (nint, nuint) Method3 ((nint, nuint) a, (nuint, IntPtr) b, (UIntPtr, string) c);")] + [TestCase("Method4", "public (((nint a, IntPtr) b, UIntPtr c) d, (nint e, (nuint f, IntPtr g) h) i) Method4 ();")] public void CSharpNativeIntMethodTest(string methodName, string expectedSignature) { var method = GetMethod(typeof(SampleClasses.NativeIntClass), m => m.Name == methodName); From de501b1202ccbaef891eccf9cbd47eb0c153706a Mon Sep 17 00:00:00 2001 From: Min Huang Date: Thu, 17 Mar 2022 17:27:25 +0800 Subject: [PATCH 11/13] fix test cases --- mdoc/mdoc.Test/FormatterTests.cs | 2 +- mdoc/mdoc.Test/NullableReferenceTypesTests.cs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mdoc/mdoc.Test/FormatterTests.cs b/mdoc/mdoc.Test/FormatterTests.cs index 5bdc07d22..b39d10c4e 100644 --- a/mdoc/mdoc.Test/FormatterTests.cs +++ b/mdoc/mdoc.Test/FormatterTests.cs @@ -445,7 +445,7 @@ public void CSharpTupleNamesFieldTest() } [TestCase("TupleMethod", "public (int a, int, int b) TupleMethod ((int, int) t1, (int b, int c, int d) t2, (int, int) t3);")] - [TestCase("RecursiveTupleMethod", "public ((int a, long b) c,int d) RecursiveTupleMethod ((((int a, long) b, string c) d,(int e, (float f, float g) h) i, int j) t);")] + [TestCase("RecursiveTupleMethod", "public ((int a, long b) c, int d) RecursiveTupleMethod ((((int a, long) b, string c) d, (int e, (float f, float g) h) i, int j) t);")] public void CSharpTupleNamesMethodTest(string methodName, string expectedSignature) { var method = GetMethod(typeof(SampleClasses.TupleNamesTestClass<,>), m => m.Name == methodName); diff --git a/mdoc/mdoc.Test/NullableReferenceTypesTests.cs b/mdoc/mdoc.Test/NullableReferenceTypesTests.cs index 5a166f474..f6cc3b408 100644 --- a/mdoc/mdoc.Test/NullableReferenceTypesTests.cs +++ b/mdoc/mdoc.Test/NullableReferenceTypesTests.cs @@ -36,10 +36,10 @@ public class NullableReferenceTypesTests : BasicFormatterTests?", "NullableTupleOfValueType")] [TestCase("Tuple", "TupleOfNullableValueType")] [TestCase("Tuple?", "NullableTupleOfNullableValueType")] - [TestCase("(int,int)", "ValueTupleOfValueType")] - [TestCase("(int,int)?", "NullableValueTupleOfValueType")] - [TestCase("(int?,int?)", "ValueTupleOfNullableValueType")] - [TestCase("(int?,int?)?", "NullableValueTupleOfNullableValueType")] + [TestCase("(int, int)", "ValueTupleOfValueType")] + [TestCase("(int, int)?", "NullableValueTupleOfValueType")] + [TestCase("(int?, int?)", "ValueTupleOfNullableValueType")] + [TestCase("(int?, int?)?", "NullableValueTupleOfNullableValueType")] [TestCase("ICollection", "InterfaceOfValueType")] [TestCase("ICollection?", "NullableInterfaceOfValueType")] [TestCase("ICollection?", "NullableInterfaceOfNullableValueType")] @@ -83,10 +83,10 @@ public class NullableReferenceTypesTests : BasicFormatterTests?", "NullableTupleOfReferenceType")] [TestCase("Tuple", "TupleOfNullableReferenceType")] [TestCase("Tuple?", "NullableTupleOfNullableReferenceType")] - [TestCase("(string,string)", "ValueTupleOfReferenceType")] - [TestCase("(string,string)?", "NullableValueTupleOfReferenceType")] - [TestCase("(string?,string?)", "ValueTupleOfNullableReferenceType")] - [TestCase("(string?,string?)?", "NullableValueTupleOfNullableReferenceType")] + [TestCase("(string, string)", "ValueTupleOfReferenceType")] + [TestCase("(string, string)?", "NullableValueTupleOfReferenceType")] + [TestCase("(string?, string?)", "ValueTupleOfNullableReferenceType")] + [TestCase("(string?, string?)?", "NullableValueTupleOfNullableReferenceType")] [TestCase("ICollection", "InterfaceOfReferenceType")] [TestCase("ICollection?", "NullableInterfaceOfReferenceType")] [TestCase("ICollection?", "NullableInterfaceOfNullableReferenceType")] From abe001fc5e55d08c0c37e0216d4c660de476789c Mon Sep 17 00:00:00 2001 From: Min Huang Date: Thu, 17 Mar 2022 19:04:50 +0800 Subject: [PATCH 12/13] fix integration test --- .../Formatters/AttributeFormatters/AttributeFormatter.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs index 16e2f8bd6..9bb236674 100644 --- a/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs +++ b/mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs @@ -118,7 +118,7 @@ public virtual string MakeAttributesValueString(object argumentValue, TypeRefere private bool IsIgnoredAttribute(CustomAttribute customAttribute) { - TypeDefinition attrType = customAttribute.AttributeType as TypeDefinition; + var attrType = customAttribute.AttributeType; if (attrType == null) return true; @@ -138,8 +138,9 @@ private bool IsIgnoredAttribute(CustomAttribute customAttribute) return false; } - if (!DocUtils.IsPublic(attrType) || (FormatterManager.SlashdocFormatter.GetName(customAttribute.AttributeType) == null) - || Array.IndexOf(IgnorableAttributes, customAttribute.AttributeType.FullName) >= 0) + var attrTypeDef = attrType as TypeDefinition; + if (attrTypeDef != null && !DocUtils.IsPublic(attrTypeDef) || (FormatterManager.SlashdocFormatter.GetName(attrType) == null) + || Array.IndexOf(IgnorableAttributes, attrType.FullName) >= 0) { return true; } From ead2a55d4805842cfc51617dc0ce61c427754a9c Mon Sep 17 00:00:00 2001 From: Min Huang Date: Fri, 18 Mar 2022 18:30:22 +0800 Subject: [PATCH 13/13] add unit test --- mdoc/mdoc.Test/MDocUpdaterTests.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mdoc/mdoc.Test/MDocUpdaterTests.cs b/mdoc/mdoc.Test/MDocUpdaterTests.cs index 4e4a117c6..6924df61f 100644 --- a/mdoc/mdoc.Test/MDocUpdaterTests.cs +++ b/mdoc/mdoc.Test/MDocUpdaterTests.cs @@ -1,11 +1,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; using System.Xml; using mdoc.Test.SampleClasses; using Mono.Cecil; -using Mono.Cecil.Rocks; using Mono.Collections.Generic; using Mono.Documentation; using Mono.Documentation.Updater; @@ -31,6 +29,16 @@ public void Test_GetCustomAttributes_IgnoredObsoleteAttribute() Assert.IsFalse(formatter.TryGetAttributeString(attributes.First(), out string rval)); } + [Test] + public void Test_GetCustomAttributes_EmitNativeIntegerAttribute() + { + var method = GetMethod(typeof(SampleClasses.NativeIntClass), "Method1"); + static CustomAttribute GetNativeIntegerAttr(ParameterDefinition p) => p?.CustomAttributes.Where(attr => attr.AttributeType.FullName == Consts.NativeIntegerAttribute).FirstOrDefault(); + Assert.IsNotNull(GetNativeIntegerAttr(method.Parameters[0])); + Assert.IsTrue(formatter.TryGetAttributeString(GetNativeIntegerAttr(method.Parameters[0]), out string rval)); + Assert.IsNull(GetNativeIntegerAttr(method.Parameters[2])); + } + [Test] public void Test_GetDocParameterType_CppGenericParameterType_ReturnsTypeWithGenericParameters() {