Merge pull request #622 from mono/develop

bump mdoc to 5.8.8
This commit is contained in:
Min Huang 2022-03-24 10:36:37 +08:00 коммит произвёл GitHub
Родитель 47b71458e9 b5f62fcd16
Коммит 489be60c6a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
15 изменённых файлов: 271 добавлений и 31 удалений

Просмотреть файл

@ -3,7 +3,7 @@ namespace Mono.Documentation
{
public static class Consts
{
public static string MonoVersion = "5.8.7";
public static string MonoVersion = "5.8.8";
public const string DocId = "DocId";
public const string CppCli = "C++ CLI";
public const string CppCx = "C++ CX";
@ -49,5 +49,8 @@ namespace Mono.Documentation
public const string IsByRefLikeAttribute = "System.Runtime.CompilerServices.IsByRefLikeAttribute";
public const string IsReadOnlyAttribute = "System.Runtime.CompilerServices.IsReadOnlyAttribute";
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";
}
}

Просмотреть файл

@ -3997,7 +3997,7 @@ namespace Mono.Documentation
xelement.RemoveAttribute(Consts.Index);
xelement.SetAttribute(Consts.Index, i.ToString());
xelement.SetAttribute (Consts.FrameworkAlternate, fxaValue);
MakeParamsAttributes(xelement, AttributeFormatter.PreProcessCustomAttributes(p.Definition.CustomAttributes), typeEntry, member);
continue;
}
else {

Просмотреть файл

@ -3,6 +3,7 @@ using Mono.Cecil;
using Mono.Documentation.Util;
using System;
using System.Collections.ObjectModel;
using System.Linq;
namespace Mono.Documentation.Updater
{
@ -10,9 +11,13 @@ namespace Mono.Documentation.Updater
{
private int nullableAttributeIndex;
private int dynamicAttributeIndex;
private int tupleNameAttributeIndex;
private int nativeIntegerAttributeIndex;
private ICustomAttributeProvider provider;
private ReadOnlyCollection<bool?> nullableAttributeFlags;
private ReadOnlyCollection<bool> dynamicAttributeFlags;
private string[] tupleElementNames;
private bool[] nativeIntegerFlags;
private AttributeParserContext(ICustomAttributeProvider provider)
{
@ -20,6 +25,8 @@ namespace Mono.Documentation.Updater
ReadDynamicAttribute();
ReadNullableAttribute();
ReadTupleElementNames();
ReadNativeIntegerAttribute();
}
private bool ExistsNullableAttribute
@ -73,6 +80,16 @@ namespace Mono.Documentation.Updater
return false;
}
public string GetTupleElementName()
{
return (tupleElementNames == null || tupleNameAttributeIndex >= tupleElementNames.Length) ? null : tupleElementNames[tupleNameAttributeIndex++];
}
public bool IsNativeInteger()
{
return nativeIntegerFlags != null && nativeIntegerAttributeIndex < nativeIntegerFlags.Length && nativeIntegerFlags[nativeIntegerAttributeIndex++];
}
private void ReadDynamicAttribute()
{
DynamicTypeProvider dynamicTypeProvider = new DynamicTypeProvider(provider);
@ -88,5 +105,31 @@ namespace Mono.Documentation.Updater
NullableReferenceTypeProvider nullableReferenceTypeProvider = new NullableReferenceTypeProvider(provider);
nullableAttributeFlags = new ReadOnlyCollection<bool?>(nullableReferenceTypeProvider.GetNullableReferenceTypeFlags());
}
private void ReadTupleElementNames()
{
tupleElementNames = ReadCustomAttributeValue<string>(Consts.TupleElementNamesAttribute);
}
private void ReadNativeIntegerAttribute()
{
nativeIntegerFlags = ReadCustomAttributeValue<bool>(
Consts.NativeIntegerAttribute,
() => new bool[] { true });
}
private T[] ReadCustomAttributeValue<T>(string attributeName, Func<T[]> init = 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();
}
}
}

Просмотреть файл

@ -26,5 +26,15 @@
{
return false;
}
public string GetTupleElementName()
{
return null;
}
public bool IsNativeInteger()
{
return false;
}
}
}

Просмотреть файл

@ -77,15 +77,6 @@ namespace Mono.Documentation.Updater.Formatters
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<string>();
for (int i = 0; i < attribute.ConstructorArguments.Count; ++i)
@ -127,11 +118,34 @@ namespace Mono.Documentation.Updater.Formatters
private bool IsIgnoredAttribute(CustomAttribute customAttribute)
{
var attrType = customAttribute.AttributeType;
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;
}
var attrTypeDef = attrType as TypeDefinition;
if (attrTypeDef != null && !DocUtils.IsPublic(attrTypeDef) || (FormatterManager.SlashdocFormatter.GetName(attrType) == null)
|| Array.IndexOf(IgnorableAttributes, attrType.FullName) >= 0)
{
return true;
}
return false;
}
// FIXME: get TypeReferences instead of string comparison?

Просмотреть файл

@ -12,6 +12,12 @@ namespace Mono.Documentation.Updater.Formatters
public CSharpFullMemberFormatter() : this(null) {}
public CSharpFullMemberFormatter(TypeMap map) : base(map) { }
private static readonly Dictionary<string, string> NativeIntTypeMap = new Dictionary<string, string>()
{
{ "System.IntPtr", "nint" },
{ "System.UIntPtr", "nuint" },
};
public override string Language
{
get { return "C#"; }
@ -25,7 +31,7 @@ namespace Mono.Documentation.Updater.Formatters
return buf;
}
protected virtual string GetCSharpType (string t)
protected virtual string GetCSharpType(string t)
{
// make sure there are no modifiers in the type string (add them back before returning)
string typeToCompare = t;
@ -83,6 +89,11 @@ namespace Mono.Documentation.Updater.Formatters
return base.AppendTypeName (buf, type, context);
}
if (NativeIntTypeMap.TryGetValue(t, out string typeName) && context.IsNativeInteger())
{
return buf.Append(typeName);
}
string s = GetCSharpType (t);
if (s != null)
{
@ -137,7 +148,9 @@ namespace Mono.Documentation.Updater.Formatters
if (genInst.Name.StartsWith ("ValueTuple`"))
{
buf.Append ("(");
var genArgList = new List<string> ();
var genArgTypeList = new List<string> ();
// tuple element names should be traversed before recursion.
var genArgNameList = genInst.GenericArguments.Select(arg => context.GetTupleElementName()).ToList();
foreach (var item in genInst.GenericArguments)
{
var isNullableType = false;
@ -147,11 +160,11 @@ namespace Mono.Documentation.Updater.Formatters
}
var underlyingTypeName = GetTypeName (item, context, appendGeneric, useTypeProjection) + GetTypeNullableSymbol (item, isNullableType);
genArgList.Add (underlyingTypeName);
genArgTypeList.Add (underlyingTypeName);
}
buf.Append (string.Join (",", genArgList));
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 (")");
return buf;
}
@ -723,7 +736,14 @@ namespace Mono.Documentation.Updater.Formatters
{
if (set_visible != visibility)
buf.Append (' ').Append (set_visible);
buf.Append (" set;");
if (property.SetMethod.ReturnType is RequiredModifierType returnType && returnType.ModifierType.FullName == Consts.IsExternalInit)
{
buf.Append(" init;");
}
else
{
buf.Append(" set;");
}
}
buf.Append (" }");

Просмотреть файл

@ -5,5 +5,7 @@
void NextDynamicFlag();
bool IsDynamic();
bool IsNullable();
string GetTupleElementName();
bool IsNativeInteger();
}
}

Просмотреть файл

@ -297,7 +297,7 @@ namespace mdoc.Test
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]
@ -420,6 +420,69 @@ namespace mdoc.Test
Assert.AreEqual(expectedSignature, methodSignature);
}
[Test]
public void CSharpTupleNamesTypeTest()
{
var type = GetType(typeof(SampleClasses.TupleNamesTestClass<,>));
var typeSignature = formatter.GetDeclaration(type);
Assert.AreEqual("public class TupleNamesTestClass<T1,T2> : IComparable<(T1, T2)>", typeSignature);
}
[Test]
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);
}
[Test]
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);
}
[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);
var methodSignature = formatter.GetDeclaration(method);
Assert.AreEqual(expectedSignature, methodSignature);
}
[TestCase("Property1", "public int Property1 { get; set; }")]
[TestCase("Property2", "public int Property2 { get; init; }")]
[TestCase("Property3", "public int Property3 { get; protected init; }")]
[TestCase("Item", "public int this[int index] { get; init; }")]
public void CSharpInitOnlySetterTest(string propertyName, string expectedSignature)
{
var property = GetProperty(typeof(SampleClasses.InitOnlySetter), p => p.Name == propertyName);
var propertySignature = formatter.GetDeclaration(property);
Assert.AreEqual(expectedSignature, propertySignature);
}
[Test]
public void CSharpNativeIntGenericTypeTest()
{
var type = GetType(typeof(SampleClasses.GenericNativeIntClass<>));
var typeSignature = formatter.GetDeclaration(type);
Assert.AreEqual("public class GenericNativeIntClass<nint>", typeSignature);
}
[TestCase("Method1", "public (nint, nuint) Method1 (nint a, nuint b, IntPtr c, UIntPtr d);")]
[TestCase("Method2", "public (nint, nuint) Method2 (List<nint> a, Dictionary<int,nuint> 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) {

Просмотреть файл

@ -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 @@ namespace mdoc.Test
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()
{

Просмотреть файл

@ -36,10 +36,10 @@ namespace mdoc.Test
[TestCase("Tuple<int,int>?", "NullableTupleOfValueType")]
[TestCase("Tuple<int?,int?>", "TupleOfNullableValueType")]
[TestCase("Tuple<int?,int?>?", "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<int>", "InterfaceOfValueType")]
[TestCase("ICollection<int>?", "NullableInterfaceOfValueType")]
[TestCase("ICollection<int?>?", "NullableInterfaceOfNullableValueType")]
@ -83,10 +83,10 @@ namespace mdoc.Test
[TestCase("Tuple<string,string>?", "NullableTupleOfReferenceType")]
[TestCase("Tuple<string?,string?>", "TupleOfNullableReferenceType")]
[TestCase("Tuple<string?,string?>?", "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<string>", "InterfaceOfReferenceType")]
[TestCase("ICollection<string>?", "NullableInterfaceOfReferenceType")]
[TestCase("ICollection<string?>?", "NullableInterfaceOfNullableReferenceType")]

Просмотреть файл

@ -0,0 +1,20 @@
namespace mdoc.Test.SampleClasses
{
public class InitOnlySetter
{
public int Property1 { get; set; }
public int Property2 { get; init; }
public int Property3 { get; protected init; }
public int this[int index]
{
get
{
throw null;
}
init
{
throw null;
}
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
using System.ComponentModel;
namespace System.Runtime.CompilerServices
{
[EditorBrowsable(EditorBrowsableState.Never)]
internal class IsExternalInit { }
}

Просмотреть файл

@ -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<nint> a, Dictionary<int, nuint> 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<nint>
{
}
}

Просмотреть файл

@ -0,0 +1,20 @@
using System;
namespace mdoc.Test.SampleClasses
{
public class TupleNamesTestClass<T1, T2> : IComparable<ValueTuple<T1, T2>>
{
public (int a, int b) TuplePropertyType { get; }
public (int a, int b, int c) TupleField;
public (int a, int, int b) TupleMethod((int, int) t1, (int b, int c, int d) t2, ValueTuple<int, int> t3) => (t1.Item1, t2.b, t3.Item2);
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) => (t.d.b, t.j);
public int CompareTo((T1, T2) other)
{
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -2,7 +2,7 @@
<package >
<metadata>
<id>mdoc</id>
<version>5.8.7</version>
<version>5.8.8</version>
<title>mdoc</title>
<authors>Microsoft</authors>
<owners>Microsoft</owners>