Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/api-doc-tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMin Huang <huangmin@microsoft.com>2022-03-08 04:28:57 +0300
committerGitHub <noreply@github.com>2022-03-08 04:28:57 +0300
commitc27c019e5a52d897dbb54e15bd645ef693e8bc57 (patch)
tree738e57e055f77bc9c2e726a8e300bde9f87db7c6
parent637f82100ff6ced64a35f1c6ffcc5375a87478a3 (diff)
feat#550401: Support new .net language feature: tuple names (#618)
* Support new .net language feature: tuple names * update test case * update test case * update * updated * update test case * add debug info * update * Remove console log
-rw-r--r--mdoc/Consts.cs1
-rw-r--r--mdoc/Mono.Documentation/Updater/AttributeParserContext.cs22
-rw-r--r--mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs5
-rw-r--r--mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs8
-rw-r--r--mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs1
-rw-r--r--mdoc/mdoc.Test/FormatterTests.cs33
-rw-r--r--mdoc/mdoc.Test/SampleClasses/TupleNamesTestClass.cs20
7 files changed, 87 insertions, 3 deletions
diff --git a/mdoc/Consts.cs b/mdoc/Consts.cs
index 3ef0b936..4d2ef7c3 100644
--- a/mdoc/Consts.cs
+++ b/mdoc/Consts.cs
@@ -49,5 +49,6 @@ 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";
}
}
diff --git a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs
index de9ee35d..e294d7cb 100644
--- a/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs
+++ b/mdoc/Mono.Documentation/Updater/AttributeParserContext.cs
@@ -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,11 @@ namespace Mono.Documentation.Updater
{
private int nullableAttributeIndex;
private int dynamicAttributeIndex;
+ private int tupleNameAttributeIndex;
private ICustomAttributeProvider provider;
private ReadOnlyCollection<bool?> nullableAttributeFlags;
private ReadOnlyCollection<bool> dynamicAttributeFlags;
+ private string[] tupleElementNames;
private AttributeParserContext(ICustomAttributeProvider provider)
{
@@ -20,6 +23,7 @@ namespace Mono.Documentation.Updater
ReadDynamicAttribute();
ReadNullableAttribute();
+ ReadTupleElementNames();
}
private bool ExistsNullableAttribute
@@ -73,6 +77,11 @@ namespace Mono.Documentation.Updater
return false;
}
+ public string GetTupleElementName()
+ {
+ return (tupleElementNames == null || tupleNameAttributeIndex >= tupleElementNames.Length) ? null : tupleElementNames[tupleNameAttributeIndex++];
+ }
+
private void ReadDynamicAttribute()
{
DynamicTypeProvider dynamicTypeProvider = new DynamicTypeProvider(provider);
@@ -88,5 +97,18 @@ namespace Mono.Documentation.Updater
NullableReferenceTypeProvider nullableReferenceTypeProvider = new NullableReferenceTypeProvider(provider);
nullableAttributeFlags = new ReadOnlyCollection<bool?>(nullableReferenceTypeProvider.GetNullableReferenceTypeFlags());
}
+
+ private void ReadTupleElementNames()
+ {
+ if (provider != null && provider.HasCustomAttributes)
+ {
+ var tupleNamesAttr = provider.CustomAttributes.Where(attr => attr.AttributeType.FullName == Consts.TupleElementNamesAttribute).FirstOrDefault();
+ if (tupleNamesAttr != null)
+ {
+ var constructorArgs = tupleNamesAttr.ConstructorArguments.FirstOrDefault().Value as CustomAttributeArgument[];
+ tupleElementNames = constructorArgs?.Select(arg => arg.Value as string).ToArray();
+ }
+ }
+ }
}
} \ No newline at end of file
diff --git a/mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs
index 87aecaa4..71b638fd 100644
--- a/mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs
+++ b/mdoc/Mono.Documentation/Updater/EmptyAttributeParserContext.cs
@@ -26,5 +26,10 @@
{
return false;
}
+
+ public string GetTupleElementName()
+ {
+ return null;
+ }
}
}
diff --git a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs
index 811ff3be..e885df57 100644
--- a/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs
+++ b/mdoc/Mono.Documentation/Updater/Formatters/CSharpFullMemberFormatter.cs
@@ -137,7 +137,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 +149,11 @@ namespace Mono.Documentation.Updater.Formatters
}
var underlyingTypeName = GetTypeName (item, context, appendGeneric, useTypeProjection) + GetTypeNullableSymbol (item, isNullableType);
- genArgList.Add (underlyingTypeName);
+ 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 (")");
-
return buf;
}
diff --git a/mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs b/mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs
index aca6ba21..471c661b 100644
--- a/mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs
+++ b/mdoc/Mono.Documentation/Updater/IAttributeParserContext.cs
@@ -5,5 +5,6 @@
void NextDynamicFlag();
bool IsDynamic();
bool IsNullable();
+ string GetTupleElementName();
}
}
diff --git a/mdoc/mdoc.Test/FormatterTests.cs b/mdoc/mdoc.Test/FormatterTests.cs
index ce1009fe..868def32 100644
--- a/mdoc/mdoc.Test/FormatterTests.cs
+++ b/mdoc/mdoc.Test/FormatterTests.cs
@@ -420,6 +420,39 @@ 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);
+ }
+
#region Helper Methods
string RealTypeName(string name){
switch (name) {
diff --git a/mdoc/mdoc.Test/SampleClasses/TupleNamesTestClass.cs b/mdoc/mdoc.Test/SampleClasses/TupleNamesTestClass.cs
new file mode 100644
index 00000000..29b3a1e6
--- /dev/null
+++ b/mdoc/mdoc.Test/SampleClasses/TupleNamesTestClass.cs
@@ -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();
+ }
+ }
+} \ No newline at end of file