Skip to content

Commit 489be60

Browse files
authored
Merge pull request #622 from mono/develop
bump mdoc to 5.8.8
2 parents 47b7145 + b5f62fc commit 489be60

15 files changed

Lines changed: 271 additions & 31 deletions

mdoc/Consts.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ namespace Mono.Documentation
33
{
44
public static class Consts
55
{
6-
public static string MonoVersion = "5.8.7";
6+
public static string MonoVersion = "5.8.8";
77
public const string DocId = "DocId";
88
public const string CppCli = "C++ CLI";
99
public const string CppCx = "C++ CX";
@@ -49,5 +49,8 @@ public static class Consts
4949
public const string IsByRefLikeAttribute = "System.Runtime.CompilerServices.IsByRefLikeAttribute";
5050
public const string IsReadOnlyAttribute = "System.Runtime.CompilerServices.IsReadOnlyAttribute";
5151
public const string InAttribute = "System.Runtime.InteropServices.InAttribute";
52+
public const string TupleElementNamesAttribute = "System.Runtime.CompilerServices.TupleElementNamesAttribute";
53+
public const string IsExternalInit = "System.Runtime.CompilerServices.IsExternalInit";
54+
public const string NativeIntegerAttribute = "System.Runtime.CompilerServices.NativeIntegerAttribute";
5255
}
5356
}

mdoc/Mono.Documentation/MDocUpdater.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3997,7 +3997,7 @@ public void MakeParameters (XmlElement root, MemberReference member, IList<Param
39973997
xelement.RemoveAttribute(Consts.Index);
39983998
xelement.SetAttribute(Consts.Index, i.ToString());
39993999
xelement.SetAttribute (Consts.FrameworkAlternate, fxaValue);
4000-
4000+
MakeParamsAttributes(xelement, AttributeFormatter.PreProcessCustomAttributes(p.Definition.CustomAttributes), typeEntry, member);
40014001
continue;
40024002
}
40034003
else {

mdoc/Mono.Documentation/Updater/AttributeParserContext.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,30 @@
33
using Mono.Documentation.Util;
44
using System;
55
using System.Collections.ObjectModel;
6+
using System.Linq;
67

78
namespace Mono.Documentation.Updater
89
{
910
public class AttributeParserContext : IAttributeParserContext
1011
{
1112
private int nullableAttributeIndex;
1213
private int dynamicAttributeIndex;
14+
private int tupleNameAttributeIndex;
15+
private int nativeIntegerAttributeIndex;
1316
private ICustomAttributeProvider provider;
1417
private ReadOnlyCollection<bool?> nullableAttributeFlags;
1518
private ReadOnlyCollection<bool> dynamicAttributeFlags;
19+
private string[] tupleElementNames;
20+
private bool[] nativeIntegerFlags;
1621

1722
private AttributeParserContext(ICustomAttributeProvider provider)
1823
{
1924
this.provider = provider;
2025

2126
ReadDynamicAttribute();
2227
ReadNullableAttribute();
28+
ReadTupleElementNames();
29+
ReadNativeIntegerAttribute();
2330
}
2431

2532
private bool ExistsNullableAttribute
@@ -73,6 +80,16 @@ public bool IsNullable()
7380
return false;
7481
}
7582

83+
public string GetTupleElementName()
84+
{
85+
return (tupleElementNames == null || tupleNameAttributeIndex >= tupleElementNames.Length) ? null : tupleElementNames[tupleNameAttributeIndex++];
86+
}
87+
88+
public bool IsNativeInteger()
89+
{
90+
return nativeIntegerFlags != null && nativeIntegerAttributeIndex < nativeIntegerFlags.Length && nativeIntegerFlags[nativeIntegerAttributeIndex++];
91+
}
92+
7693
private void ReadDynamicAttribute()
7794
{
7895
DynamicTypeProvider dynamicTypeProvider = new DynamicTypeProvider(provider);
@@ -88,5 +105,31 @@ private void ReadNullableAttribute()
88105
NullableReferenceTypeProvider nullableReferenceTypeProvider = new NullableReferenceTypeProvider(provider);
89106
nullableAttributeFlags = new ReadOnlyCollection<bool?>(nullableReferenceTypeProvider.GetNullableReferenceTypeFlags());
90107
}
108+
109+
private void ReadTupleElementNames()
110+
{
111+
tupleElementNames = ReadCustomAttributeValue<string>(Consts.TupleElementNamesAttribute);
112+
}
113+
114+
private void ReadNativeIntegerAttribute()
115+
{
116+
nativeIntegerFlags = ReadCustomAttributeValue<bool>(
117+
Consts.NativeIntegerAttribute,
118+
() => new bool[] { true });
119+
}
120+
121+
private T[] ReadCustomAttributeValue<T>(string attributeName, Func<T[]> init = null)
122+
{
123+
if (provider == null || !provider.HasCustomAttributes) return null;
124+
125+
var customAttribute = provider.CustomAttributes.Where(attr => attr.AttributeType.FullName == attributeName).FirstOrDefault();
126+
127+
if (customAttribute == null) return null;
128+
129+
if (!customAttribute.HasConstructorArguments) return init?.Invoke();
130+
131+
var constructorArgs = customAttribute.ConstructorArguments[0].Value as CustomAttributeArgument[];
132+
return constructorArgs?.Select(arg => (T)arg.Value).ToArray();
133+
}
91134
}
92135
}

mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,15 @@ public bool IsNullable()
2626
{
2727
return false;
2828
}
29+
30+
public string GetTupleElementName()
31+
{
32+
return null;
33+
}
34+
35+
public bool IsNativeInteger()
36+
{
37+
return false;
38+
}
2939
}
3040
}

mdoc/Mono.Documentation/Updater/Formatters/AttributeFormatters/AttributeFormatter.cs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,6 @@ public virtual bool TryGetAttributeString(CustomAttribute attribute, out string
7777
return false;
7878
}
7979

80-
TypeDefinition attrType = attribute.AttributeType as TypeDefinition;
81-
if (attrType != null && !DocUtils.IsPublic(attrType)
82-
|| (FormatterManager.SlashdocFormatter.GetName(attribute.AttributeType) == null)
83-
|| Array.IndexOf(IgnorableAttributes, attribute.AttributeType.FullName) >= 0)
84-
{
85-
rval = null;
86-
return false;
87-
}
88-
8980
var fields = new List<string>();
9081

9182
for (int i = 0; i < attribute.ConstructorArguments.Count; ++i)
@@ -127,11 +118,34 @@ public virtual string MakeAttributesValueString(object argumentValue, TypeRefere
127118

128119
private bool IsIgnoredAttribute(CustomAttribute customAttribute)
129120
{
121+
var attrType = customAttribute.AttributeType;
122+
123+
if (attrType == null) return true;
124+
130125
// An Obsolete attribute with a known string is added to all ref-like structs
131126
// https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/span-safety.md#metadata-representation-or-ref-like-structs
132-
return customAttribute.AttributeType.FullName == typeof(ObsoleteAttribute).FullName
127+
if (attrType.FullName == typeof(ObsoleteAttribute).FullName
133128
&& customAttribute.HasConstructorArguments
134-
&& customAttribute.ConstructorArguments.First().Value.ToString() == Consts.RefTypeObsoleteString;
129+
&& customAttribute.ConstructorArguments.First().Value.ToString() == Consts.RefTypeObsoleteString)
130+
{
131+
return true;
132+
}
133+
134+
// Expose this attribute in ECMAXML to let ECMA2YML pick up
135+
// https://ceapex.visualstudio.com/Engineering/_workitems/edit/550401
136+
if (attrType.FullName == Consts.NativeIntegerAttribute)
137+
{
138+
return false;
139+
}
140+
141+
var attrTypeDef = attrType as TypeDefinition;
142+
if (attrTypeDef != null && !DocUtils.IsPublic(attrTypeDef) || (FormatterManager.SlashdocFormatter.GetName(attrType) == null)
143+
|| Array.IndexOf(IgnorableAttributes, attrType.FullName) >= 0)
144+
{
145+
return true;
146+
}
147+
148+
return false;
135149
}
136150

137151
// FIXME: get TypeReferences instead of string comparison?

mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ public class CSharpFullMemberFormatter : MemberFormatter
1212
public CSharpFullMemberFormatter() : this(null) {}
1313
public CSharpFullMemberFormatter(TypeMap map) : base(map) { }
1414

15+
private static readonly Dictionary<string, string> NativeIntTypeMap = new Dictionary<string, string>()
16+
{
17+
{ "System.IntPtr", "nint" },
18+
{ "System.UIntPtr", "nuint" },
19+
};
20+
1521
public override string Language
1622
{
1723
get { return "C#"; }
@@ -25,7 +31,7 @@ protected override StringBuilder AppendNamespace (StringBuilder buf, TypeReferen
2531
return buf;
2632
}
2733

28-
protected virtual string GetCSharpType (string t)
34+
protected virtual string GetCSharpType(string t)
2935
{
3036
// make sure there are no modifiers in the type string (add them back before returning)
3137
string typeToCompare = t;
@@ -83,6 +89,11 @@ protected override StringBuilder AppendTypeName (StringBuilder buf, TypeReferenc
8389
return base.AppendTypeName (buf, type, context);
8490
}
8591

92+
if (NativeIntTypeMap.TryGetValue(t, out string typeName) && context.IsNativeInteger())
93+
{
94+
return buf.Append(typeName);
95+
}
96+
8697
string s = GetCSharpType (t);
8798
if (s != null)
8899
{
@@ -137,7 +148,9 @@ protected override StringBuilder AppendSpecialGenericNullableValueTypeName (Stri
137148
if (genInst.Name.StartsWith ("ValueTuple`"))
138149
{
139150
buf.Append ("(");
140-
var genArgList = new List<string> ();
151+
var genArgTypeList = new List<string> ();
152+
// tuple element names should be traversed before recursion.
153+
var genArgNameList = genInst.GenericArguments.Select(arg => context.GetTupleElementName()).ToList();
141154
foreach (var item in genInst.GenericArguments)
142155
{
143156
var isNullableType = false;
@@ -147,11 +160,11 @@ protected override StringBuilder AppendSpecialGenericNullableValueTypeName (Stri
147160
}
148161

149162
var underlyingTypeName = GetTypeName (item, context, appendGeneric, useTypeProjection) + GetTypeNullableSymbol (item, isNullableType);
150-
genArgList.Add (underlyingTypeName);
163+
genArgTypeList.Add (underlyingTypeName);
151164
}
152-
buf.Append (string.Join (",", genArgList));
165+
var genArgList = genInst.GenericArguments.Select((_, index) => string.Format("{0}{1}", genArgTypeList[index], genArgNameList[index] == null ? String.Empty : (" " + genArgNameList[index])));
166+
buf.Append (string.Join (", ", genArgList));
153167
buf.Append (")");
154-
155168
return buf;
156169
}
157170

@@ -723,7 +736,14 @@ protected override string GetPropertyDeclaration (PropertyDefinition property)
723736
{
724737
if (set_visible != visibility)
725738
buf.Append (' ').Append (set_visible);
726-
buf.Append (" set;");
739+
if (property.SetMethod.ReturnType is RequiredModifierType returnType && returnType.ModifierType.FullName == Consts.IsExternalInit)
740+
{
741+
buf.Append(" init;");
742+
}
743+
else
744+
{
745+
buf.Append(" set;");
746+
}
727747
}
728748
buf.Append (" }");
729749

mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ public interface IAttributeParserContext
55
void NextDynamicFlag();
66
bool IsDynamic();
77
bool IsNullable();
8+
string GetTupleElementName();
9+
bool IsNativeInteger();
810
}
911
}

mdoc/mdoc.Test/FormatterTests.cs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ public void CSharpTuple()
297297
var member = GetMethod(typeof(NullablesAndTuples), m => m.Name == "TupleReturn");
298298
var formatter = new CSharpFullMemberFormatter();
299299
var sig = formatter.GetDeclaration(member);
300-
Assert.AreEqual("public (int,string) TupleReturn ();", sig);
300+
Assert.AreEqual("public (int, string) TupleReturn ();", sig);
301301
}
302302

303303
[Test]
@@ -420,6 +420,69 @@ public void CSharpReadOnlyMemberStructTest(string methodName, string expectedSig
420420
Assert.AreEqual(expectedSignature, methodSignature);
421421
}
422422

423+
[Test]
424+
public void CSharpTupleNamesTypeTest()
425+
{
426+
var type = GetType(typeof(SampleClasses.TupleNamesTestClass<,>));
427+
var typeSignature = formatter.GetDeclaration(type);
428+
Assert.AreEqual("public class TupleNamesTestClass<T1,T2> : IComparable<(T1, T2)>", typeSignature);
429+
}
430+
431+
[Test]
432+
public void CSharpTupleNamesPropertyTest()
433+
{
434+
var property = GetProperty(typeof(SampleClasses.TupleNamesTestClass<,>), m => m.Name == "TuplePropertyType");
435+
var propertySignature = formatter.GetDeclaration(property);
436+
Assert.AreEqual("public (int a, int b) TuplePropertyType { get; }", propertySignature);
437+
}
438+
439+
[Test]
440+
public void CSharpTupleNamesFieldTest()
441+
{
442+
var field = GetField(GetType(typeof(SampleClasses.TupleNamesTestClass<,>)), "TupleField");
443+
var fieldSignature = formatter.GetDeclaration(field);
444+
Assert.AreEqual("public (int a, int b, int c) TupleField;", fieldSignature);
445+
}
446+
447+
[TestCase("TupleMethod", "public (int a, int, int b) TupleMethod ((int, int) t1, (int b, int c, int d) t2, (int, int) t3);")]
448+
[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);")]
449+
public void CSharpTupleNamesMethodTest(string methodName, string expectedSignature)
450+
{
451+
var method = GetMethod(typeof(SampleClasses.TupleNamesTestClass<,>), m => m.Name == methodName);
452+
var methodSignature = formatter.GetDeclaration(method);
453+
Assert.AreEqual(expectedSignature, methodSignature);
454+
}
455+
456+
[TestCase("Property1", "public int Property1 { get; set; }")]
457+
[TestCase("Property2", "public int Property2 { get; init; }")]
458+
[TestCase("Property3", "public int Property3 { get; protected init; }")]
459+
[TestCase("Item", "public int this[int index] { get; init; }")]
460+
public void CSharpInitOnlySetterTest(string propertyName, string expectedSignature)
461+
{
462+
var property = GetProperty(typeof(SampleClasses.InitOnlySetter), p => p.Name == propertyName);
463+
var propertySignature = formatter.GetDeclaration(property);
464+
Assert.AreEqual(expectedSignature, propertySignature);
465+
}
466+
467+
[Test]
468+
public void CSharpNativeIntGenericTypeTest()
469+
{
470+
var type = GetType(typeof(SampleClasses.GenericNativeIntClass<>));
471+
var typeSignature = formatter.GetDeclaration(type);
472+
Assert.AreEqual("public class GenericNativeIntClass<nint>", typeSignature);
473+
}
474+
475+
[TestCase("Method1", "public (nint, nuint) Method1 (nint a, nuint b, IntPtr c, UIntPtr d);")]
476+
[TestCase("Method2", "public (nint, nuint) Method2 (List<nint> a, Dictionary<int,nuint> b);")]
477+
[TestCase("Method3", "public (nint, nuint) Method3 ((nint, nuint) a, (nuint, IntPtr) b, (UIntPtr, string) c);")]
478+
[TestCase("Method4", "public (((nint a, IntPtr) b, UIntPtr c) d, (nint e, (nuint f, IntPtr g) h) i) Method4 ();")]
479+
public void CSharpNativeIntMethodTest(string methodName, string expectedSignature)
480+
{
481+
var method = GetMethod(typeof(SampleClasses.NativeIntClass), m => m.Name == methodName);
482+
var methodSignature = formatter.GetDeclaration(method);
483+
Assert.AreEqual(expectedSignature, methodSignature);
484+
}
485+
423486
#region Helper Methods
424487
string RealTypeName(string name){
425488
switch (name) {

mdoc/mdoc.Test/MDocUpdaterTests.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
using System.Collections.Generic;
22
using System.IO;
33
using System.Linq;
4-
using System.Reflection;
54
using System.Xml;
65
using mdoc.Test.SampleClasses;
76
using Mono.Cecil;
8-
using Mono.Cecil.Rocks;
97
using Mono.Collections.Generic;
108
using Mono.Documentation;
119
using Mono.Documentation.Updater;
@@ -31,6 +29,16 @@ public void Test_GetCustomAttributes_IgnoredObsoleteAttribute()
3129
Assert.IsFalse(formatter.TryGetAttributeString(attributes.First(), out string rval));
3230
}
3331

32+
[Test]
33+
public void Test_GetCustomAttributes_EmitNativeIntegerAttribute()
34+
{
35+
var method = GetMethod(typeof(SampleClasses.NativeIntClass), "Method1");
36+
static CustomAttribute GetNativeIntegerAttr(ParameterDefinition p) => p?.CustomAttributes.Where(attr => attr.AttributeType.FullName == Consts.NativeIntegerAttribute).FirstOrDefault();
37+
Assert.IsNotNull(GetNativeIntegerAttr(method.Parameters[0]));
38+
Assert.IsTrue(formatter.TryGetAttributeString(GetNativeIntegerAttr(method.Parameters[0]), out string rval));
39+
Assert.IsNull(GetNativeIntegerAttr(method.Parameters[2]));
40+
}
41+
3442
[Test]
3543
public void Test_GetDocParameterType_CppGenericParameterType_ReturnsTypeWithGenericParameters()
3644
{

mdoc/mdoc.Test/NullableReferenceTypesTests.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ public class NullableReferenceTypesTests : BasicFormatterTests<CSharpMemberForma
3636
[TestCase("Tuple<int,int>?", "NullableTupleOfValueType")]
3737
[TestCase("Tuple<int?,int?>", "TupleOfNullableValueType")]
3838
[TestCase("Tuple<int?,int?>?", "NullableTupleOfNullableValueType")]
39-
[TestCase("(int,int)", "ValueTupleOfValueType")]
40-
[TestCase("(int,int)?", "NullableValueTupleOfValueType")]
41-
[TestCase("(int?,int?)", "ValueTupleOfNullableValueType")]
42-
[TestCase("(int?,int?)?", "NullableValueTupleOfNullableValueType")]
39+
[TestCase("(int, int)", "ValueTupleOfValueType")]
40+
[TestCase("(int, int)?", "NullableValueTupleOfValueType")]
41+
[TestCase("(int?, int?)", "ValueTupleOfNullableValueType")]
42+
[TestCase("(int?, int?)?", "NullableValueTupleOfNullableValueType")]
4343
[TestCase("ICollection<int>", "InterfaceOfValueType")]
4444
[TestCase("ICollection<int>?", "NullableInterfaceOfValueType")]
4545
[TestCase("ICollection<int?>?", "NullableInterfaceOfNullableValueType")]
@@ -83,10 +83,10 @@ public class NullableReferenceTypesTests : BasicFormatterTests<CSharpMemberForma
8383
[TestCase("Tuple<string,string>?", "NullableTupleOfReferenceType")]
8484
[TestCase("Tuple<string?,string?>", "TupleOfNullableReferenceType")]
8585
[TestCase("Tuple<string?,string?>?", "NullableTupleOfNullableReferenceType")]
86-
[TestCase("(string,string)", "ValueTupleOfReferenceType")]
87-
[TestCase("(string,string)?", "NullableValueTupleOfReferenceType")]
88-
[TestCase("(string?,string?)", "ValueTupleOfNullableReferenceType")]
89-
[TestCase("(string?,string?)?", "NullableValueTupleOfNullableReferenceType")]
86+
[TestCase("(string, string)", "ValueTupleOfReferenceType")]
87+
[TestCase("(string, string)?", "NullableValueTupleOfReferenceType")]
88+
[TestCase("(string?, string?)", "ValueTupleOfNullableReferenceType")]
89+
[TestCase("(string?, string?)?", "NullableValueTupleOfNullableReferenceType")]
9090
[TestCase("ICollection<string>", "InterfaceOfReferenceType")]
9191
[TestCase("ICollection<string>?", "NullableInterfaceOfReferenceType")]
9292
[TestCase("ICollection<string?>?", "NullableInterfaceOfNullableReferenceType")]

0 commit comments

Comments
 (0)